Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
products:laboratory_iot_c:exp35 [2024/11/16 11:14] – создано labuser30products:laboratory_iot_c:exp35 [2024/11/16 11:46] (текущий) – [Программный код эксперимента] labuser30
Строка 23: Строка 23:
 ==== Программный код эксперимента ==== ==== Программный код эксперимента ====
  
-<file python Exp35[enable_line_numbers="2", start_line_numbers_at="1"]> +<file arduino Exp35.ino[enable_line_numbers="2", start_line_numbers_at="1"]> 
-from time import sleep_ms, ticks_ms +#include <LCDI2C_Multilingual.h>
-from machine import I2C, Pin +
-from esp8266_i2c_lcd import I2cLcd +
-_init()+
  
-DEFAULT_I2C_ADDR 0x3F Или 0x27 в зависимости от модели микросхемы на плате+#define ENC_A 13 
 +#define ENC_B 12   
 +#define DEFAULT_I2C_ADDR 0x3F // Или 0x27 в зависимости от твоей платы IoT
  
-encA = Pin(13Pin.IN) +LCDI2C_Generic lcd(DEFAULT_I2C_ADDR162)
-encB = Pin(12Pin.IN)+
  
-states = ( +bool states[4][2] { 
-    (0,0)+  {0,0}
-    (1,0)+  {1,0}
-    (1,1)+  {1,1}
-    (0,1) +  {0,1} 
-)+};
  
-old_state = 0+bool value_a = 0
 +bool value_b = 0;
  
-count = 0+int count = 0
 +int state = 0; 
 +int state_old = 0;
  
 +void printLcd(int number) {
 +  lcd.clear();
 +  lcd.print(number);
 +}
  
-def print_lcd(data): +int index(bool a, bool b){ 
-    lcd.clear() +  for (int i = 0; i < 4; i++){ 
-    lcd.putstr(str(data))+    if (states[i][0] == a and states[i][1] == b
 +      return i; 
 +    } 
 +  } 
 +  return -1; 
 +}
  
 +void setup() {
 +  Serial.begin(9600);
 +  lcd.init(); 
 +  lcd.setBacklight(0); 
 +  pinMode(ENC_A, INPUT);
 +  pinMode(ENC_B, INPUT);         
 +}
 + 
 +void loop() {   
 +  value_a = digitalRead(ENC_A);
 +  value_b = digitalRead(ENC_B);
  
-i2c I2C(scl=Pin(5)sda=Pin(4), freq=400000) +  state index(value_avalue_b);
-lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, 2, 16) +
-lcd.backlight_on()+
  
- +  if ((state state_old == 1) or (state == 0 and state_old == 3)) { 
-while True: +    count++; 
-    value_a = encA.value(+    Serial.println("+"); 
-    value_b = encB.value(+    printLcd(count); 
- +    state_old state; 
-    current_state = states.index((value_a, value_b)) +  } 
-     +  else if ((state state_old == -1)  or (state == 3 and state_old == 0)) { 
-    if (current_state  old_state == 1) or (current_state == 0 and old_state == 3): +    count--; 
-        count += 1 +    Serial.println("-"); 
-        print('+'); +    printLcd(count); 
-        print_lcd(count) +    state_old state; 
-        old_state current_state +  } 
-    elif (current_state  old_state == -1)  or (current_state == 3 and old_state == 0): +}
-        count -= 1 +
-        print('-'); +
-        print_lcd(count) +
-        old_state current_state+
 </file> </file>
  
 Описываем возможные состояния конечного автомата: Описываем возможные состояния конечного автомата:
-<code python[enable_line_numbers="2", start_line_numbers_at="11"]> +<code python[enable_line_numbers="2", start_line_numbers_at="9"]> 
-states = ( +bool states[4][2] { 
-    (0,0)+  {0,0}
-    (1,0)+  {1,0}
-    (1,1)+  {1,1}
-    (0,1) +  {0,1} 
-)+};
 </code> </code>
-Список из 4 элементов. В каждом элементе первая цифра это состояние сигнала A, вторая — сигнала B.+Двумерный массив 4×2Первая цифра это состояние сигнала A, вторая — сигнала B.
 Номер состояния — это индекс элемента списка. Логика переключения состояний автомата простая — состояние может смениться только на соседнее: состояние 0 на 1, 1 на 2, 2 на 3, 3 на 0. И в обратном направлении. Состояние не может измениться "перескочив" через другое. Эту логику мы опишем в программе далее. Номер состояния — это индекс элемента списка. Логика переключения состояний автомата простая — состояние может смениться только на соседнее: состояние 0 на 1, 1 на 2, 2 на 3, 3 на 0. И в обратном направлении. Состояние не может измениться "перескочив" через другое. Эту логику мы опишем в программе далее.
  
-В переменной ''old_state'' будем хранить последнее состояние конечного автомата, чтобы  понимать какое состояние было и какое у него теперь будет.+В переменной ''state_old'' будем хранить последнее состояние конечного автомата, чтобы  понимать какое состояние было и какое у него теперь будет.
  
 В основном цикле программы мы получаем данные о текущем состоянии линий А и B: В основном цикле программы мы получаем данные о текущем состоянии линий А и B:
-<code python[enable_line_numbers="2", start_line_numbers_at="34"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="46"]> 
-    value_a = encA.value() +  value_a = digitalRead(ENC_A); 
-    value_b = encB.value()+  value_b = digitalRead(ENC_B);
 </code> </code>
  
-И определяем номер состояния конечного автомата, соответствующего такому состоянию А и B: +И определяем номер состояния конечного автомата, соответствующего такому состоянию А и B с помощью написанной нами функцией ''index()''
-<code python[enable_line_numbers="2", start_line_numbers_at="37"]> +<code python[enable_line_numbers="2", start_line_numbers_at="49"]> 
-    current_state states.index((value_a, value_b))+  state = index(value_a, value_b);
 </code> </code>
  
-Формируем список с состояниями А и ''(value_a, value_b)'' и  +Функция ''index(a, b)'' принимает два параметра типа ''bool'', осуществляет поиск соответствующего элемента в массиве states и возвращает индекс найденного элемента. Ключевое слово ''return'' прерывает работу функции и возвращает указанное после него значение. 
-с помощью оператора ''index'' мы получаем индекс такого состояния в ''states''.+ 
 +<code arduino[enable_line_numbers="2", start_line_numbers_at="46"]> 
 +int index(bool a, bool b){ 
 +  for (int i = 0; i < 4; i++){ 
 +    if (states[i][0] == a and states[i][1] == b) { 
 +      return i; 
 +    } 
 +  } 
 +  return -1; 
 +
 +</code>  
 + 
 +Зачем же нужна строка ''return -1;'' в конце функции, если в цикле ''for'' в любом случае будет найден и возвращен индекс? Компилятор не на столько умный и не знает об этом, но для всех функций обязательно возвращение значения, иначе программа не скомпилируется. Поэтому мы возвращаем заведомо нереальное значение, т.к. в нашем случае строка  ''return -1;'' никогда не будет выполнена
  
-Теперь мы знаем индекс только что измеренного состояния линий. А индекс последнего состояния конечного автомата хранится в переменной ''old_state''. Теперь нам нужно понять можем ли мы из состояния записанного в ''old_state'' переключиться в новое состояние, индекс которого мы определили и записали в ''current_state''.+Теперь мы знаем индекс только что измеренного состояния линий. А индекс последнего состояния конечного автомата хранится в переменной ''state_old''. Теперь нам нужно понять можем ли мы из состояния записанного в ''state_old'' переключиться в новое состояние, индекс которого мы определили и записали в ''state''.
  
-<code python[enable_line_numbers="2", start_line_numbers_at="39"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="51"]> 
-if (current_state  old_state == 1) or (current_state == 0 and old_state == 3):+  if ((state state_old == 1) or (state == 0 and state_old == 3)) {
 </code> </code>
  
-Если индекс нового состояния на 1 больше старого или, если новое состояние 0, а старое 3, то регистрируем переход в новое состояние. Переводим конечный автомат в новое состояние ''old_state current_state''. Увеличиваем на 1 счетчик ''count'', печатаем + в терминал и отображаем счетчик на дисплее.+Если индекс нового состояния на 1 больше старого или, если новое состояние 0, а старое 3, то регистрируем переход в новое состояние. Переводим конечный автомат в новое состояние ''state_old state''. Увеличиваем на 1 счетчик ''count'', печатаем + в терминал и отображаем счетчик на дисплее.
  
 Аналогично для вращения в обратную сторону. Если индекс состояния уменьшился на один, то производим аналогичные действия. Аналогично для вращения в обратную сторону. Если индекс состояния уменьшился на один, то производим аналогичные действия.
  
 Когда ты запустишь эту программу в конструкторе, то увидишь, что значение на дисплее всегда меняется сразу на 2 и в терминале появляется по два + или -. Дело в том, что наш энкодер имеет фиксацию положений (при вращении ощущаются толчки). И эта фиксация осуществляется не в каждом состоянии, а через один. Таким образом от щелчка до щелчка энкодер проходит 2 состояния. Поэтому и число изменяется на 2. Когда ты запустишь эту программу в конструкторе, то увидишь, что значение на дисплее всегда меняется сразу на 2 и в терминале появляется по два + или -. Дело в том, что наш энкодер имеет фиксацию положений (при вращении ощущаются толчки). И эта фиксация осуществляется не в каждом состоянии, а через один. Таким образом от щелчка до щелчка энкодер проходит 2 состояния. Поэтому и число изменяется на 2.