From 564fafd6d5be604e7edbd6b2914f93986105ec89 Mon Sep 17 00:00:00 2001 From: Sandor Attila Gerendi Date: Sat, 13 Feb 2021 21:14:11 +0200 Subject: [PATCH 1/3] Create pio_quadrature_encoder.py Example that is using StateMachine to offload quadrature encoder pooling. --- examples/rp2/pio_quadrature_encoder.py | 99 ++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 examples/rp2/pio_quadrature_encoder.py diff --git a/examples/rp2/pio_quadrature_encoder.py b/examples/rp2/pio_quadrature_encoder.py new file mode 100644 index 0000000000..2fa38e8a12 --- /dev/null +++ b/examples/rp2/pio_quadrature_encoder.py @@ -0,0 +1,99 @@ +""" +This implementation offloads the quadrature sensor continuous pooling to the StateMachine pio_quadrature, +pio_quadrature will detect state changes and push the values then raises an interrupt that is handled by +encoder_state_changed_irq_handler + +encoder_state_changed_irq_handler was inspired from +https://electronics.stackexchange.com/questions/360637/quadrature-encoder-most-efficient-software-implementation + +""" + +from machine import Pin +from rp2 import PIO, StateMachine +import utime +import array + + +state_look_up_table = array.array("b", [ + #Direction = 1 + 0, # 00 to 00 + -1, # 00 to 01 + +1, # 00 to 10 + +2, # 00 to 11 + + +1, # 01 to 00 + 0, # 01 to 01 + +2, # 01 to 10 + -1, # 01 to 11 + + -1, # 10 to 00 + +2, # 10 to 01 + 0, # 10 to 10 + +1, # 10 to 11 + + +2, # 11 to 00 + +1, # 11 to 01 + -1, # 11 to 10 + 0, # 11 to 11 + + #Direction = 0 + 0, # 00 to 00 + -1, # 00 to 01 + +1, # 00 to 10 + -2, # 00 to 11 + + +1, # 01 to 00 + 0, # 01 to 01 + -2, # 01 to 10 + -1, # 01 to 11 + + -1, # 10 to 00 + -2, # 10 to 01 + 0, # 10 to 10 + +1, # 10 to 11 + + -2, # 11 to 00 + +1, # 11 to 01 + -1, # 11 to 10 + 0, # 11 to 11 + ]) + + +counter = 0 +direction = 0 +lut_index = 0 + +def encoder_state_changed_irq_handler(sm): + global counter, direction, lut_index + lut_index |= sm.get() & 3 + counter += state_look_up_table[lut_index] + if state_look_up_table[lut_index] != 0: + direction = 1 if (state_look_up_table[lut_index] > 0) else 0 + lut_index = ((lut_index << 2) & 0b1100) | (direction << 4) + + +@rp2.asm_pio() +def pio_quadrature(in_init=rp2.PIO.IN_LOW): + wrap_target() + label("again") + in_(pins, 2) + mov(x, isr) + jmp(x_not_y, "push_data") + mov(isr, null) + jmp("again") + label("push_data") + push() + irq(block, rel(0)) + mov(y, x) + wrap() + + + +sm = StateMachine(0, pio_quad, freq=160000, in_base=Pin(2)) +sm.irq(encoder_state_changed_irq_handler) +sm.exec("set(y, 99)") # add a last value for y that would be always different then the input +sm.active(1) + +while True: + utime.sleep(2) + print(counter) From 5366ead756cc04a322be6e0196b3e444052156e8 Mon Sep 17 00:00:00 2001 From: Sandor Attila Gerendi Date: Tue, 28 Dec 2021 12:01:48 +0200 Subject: [PATCH 2/3] Fixes missing import and botched refactoring reported by robert-hh --- examples/rp2/pio_quadrature_encoder.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/rp2/pio_quadrature_encoder.py b/examples/rp2/pio_quadrature_encoder.py index 2fa38e8a12..7945b3410b 100644 --- a/examples/rp2/pio_quadrature_encoder.py +++ b/examples/rp2/pio_quadrature_encoder.py @@ -9,6 +9,7 @@ https://electronics.stackexchange.com/questions/360637/quadrature-encoder-most-e """ from machine import Pin +import rp2 from rp2 import PIO, StateMachine import utime import array @@ -89,7 +90,7 @@ def pio_quadrature(in_init=rp2.PIO.IN_LOW): -sm = StateMachine(0, pio_quad, freq=160000, in_base=Pin(2)) +sm = StateMachine(0, pio_quadrature, freq=160000, in_base=Pin(2)) sm.irq(encoder_state_changed_irq_handler) sm.exec("set(y, 99)") # add a last value for y that would be always different then the input sm.active(1) From c79be30ca661194d50fb1dc5a4af70aef50d29f4 Mon Sep 17 00:00:00 2001 From: Sandor Attila Gerendi Date: Thu, 30 Dec 2021 17:50:12 +0200 Subject: [PATCH 3/3] Cater for the case where another state change occurs while the ISR is running. Thank you peterhinch --- examples/rp2/pio_quadrature_encoder.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/rp2/pio_quadrature_encoder.py b/examples/rp2/pio_quadrature_encoder.py index 7945b3410b..cc6cf2ec51 100644 --- a/examples/rp2/pio_quadrature_encoder.py +++ b/examples/rp2/pio_quadrature_encoder.py @@ -66,11 +66,12 @@ lut_index = 0 def encoder_state_changed_irq_handler(sm): global counter, direction, lut_index - lut_index |= sm.get() & 3 - counter += state_look_up_table[lut_index] - if state_look_up_table[lut_index] != 0: - direction = 1 if (state_look_up_table[lut_index] > 0) else 0 - lut_index = ((lut_index << 2) & 0b1100) | (direction << 4) + while sm.rx_fifo(): + lut_index |= sm.get() & 3 + counter += state_look_up_table[lut_index] + if state_look_up_table[lut_index] != 0: + direction = 1 if (state_look_up_table[lut_index] > 0) else 0 + lut_index = ((lut_index << 2) & 0b1100) | (direction << 4) @rp2.asm_pio()