Это старая версия документа!


Эксперимент 35. Конечные автоматы

Коне́чный автома́т — абстрактный автомат, число возможных внутренних состояний которого конечно. Если говорить проще, то с помощью конечного автомата описываются состояния какого либо объекта и переходы между этими состояниями. Например, светофор можно описать с помощью конечного автомата.

Видно, что из состояния 1 (красного сигнала) светофор может перейти только в состояние 2 (красный + желтый), означающий скорое включение зеленого. Из состояния 2 светофор может перейти только в состояние 3 (зеленый сигнал). После зеленого всегда идет желтый сигнал (состояние 4), который сменяется красным (состояние 1). Главное, что у данного конечного автомата есть 4 состояния и мы знаем из какого состояния в какое он может переходить.

Конечные автоматы иногда очень полезны для описания состояний электроники. Возьмем тот же инкрементальный энкодер. Снова посмотрим на график сигналов от него:

По графику видно, что состояния у энкодера не меняются хаотично. Они меняются только последовательно. Если крутить ручку в одну сторону, то состояния сменяются 0-1-2-3-0…, а если в другую, то 0-3-2-1-0…

Зная это мы можем отфильтровывать ложные показания из-за дребезга контактов и точно отслеживать импульсы. Попробуем обрабатывать сигналы энкодера с помощью конечного автомата.

Схема эксперимента

Рисунок 1. Электрическая принципиальная схема эксперимента

Рисунок 2. Монтажная схема эксперимента

Программный код эксперимента

Exp35
  1. from time import sleep_ms, ticks_ms
  2. from machine import I2C, Pin
  3. from esp8266_i2c_lcd import I2cLcd
  4. _init()
  5.  
  6. DEFAULT_I2C_ADDR = 0x3F
  7.  
  8. encA = Pin(13, Pin.IN)
  9. encB = Pin(12, Pin.IN)
  10.  
  11. states = (
  12. (1,1),
  13. (0,1),
  14. (0,0),
  15. (1,0)
  16. )
  17.  
  18. old_state = 0
  19.  
  20. count = 0
  21.  
  22.  
  23. def print_lcd(data):
  24. lcd.clear()
  25. lcd.putstr(str(data))
  26.  
  27.  
  28. i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
  29. lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, 2, 16)
  30. lcd.backlight_on()
  31.  
  32.  
  33. while True:
  34. value_a = encA.value()
  35. value_b = encB.value()
  36.  
  37. current_state = states.index((value_a, value_b))
  38.  
  39. if (current_state - old_state == 1) or (current_state == 0 and old_state == 3):
  40. count += 1
  41. if not (count % 2):
  42. print('+');
  43. print_lcd(int(count/2))
  44. old_state = current_state
  45. elif (current_state - old_state == -1) or (current_state == 3 and old_state == 0):
  46. count -= 1
  47. if not (count % 2):
  48. print('-');
  49. print_lcd(int(count/2))
  50. old_state = current_state