quadrature.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. import machine
  2. from machine import Pin
  3. import sys
  4. class Encoder:
  5. _increment_grid = [[0, -1, 1, None],
  6. [1, 0, None, -1],
  7. [-1, None, 0, 1],
  8. [None, 1, -1, 0]]
  9. @property
  10. def total_change(self):
  11. return self._total_change
  12. def __init__(self, channel_a, channel_b):
  13. self.channel_a = self._configure_channel(channel_a)
  14. self.channel_b = self._configure_channel(channel_b)
  15. self.reset()
  16. def reset(self):
  17. self._previous_value = None
  18. self._total_change = 0
  19. def _irq_cb(self, input_pin):
  20. interrupt_mask = machine.disable_irq()
  21. current_value = (self.channel_a.value() * 2) + self.channel_b.value()
  22. if self._previous_value == None:
  23. self._previous_value = current_value
  24. machine.enable_irq(interrupt_mask)
  25. return
  26. try:
  27. change_amount = self._increment_grid[self._previous_value][current_value]
  28. self._total_change += change_amount
  29. except TypeError:
  30. print('Detected invalid encoder state! Can the system keep up?', file=sys.stderr)
  31. self._previous_value = current_value
  32. machine.enable_irq(interrupt_mask)
  33. def _configure_channel(self, pin):
  34. p = pin if isinstance(pin, Pin) else Pin(pin, Pin.IN, pull=Pin.PULL_UP)
  35. p.irq(self._irq_cb, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING))
  36. return p