Has anyone implemented a hardware-based PWM input to measure pulse width? #17460
Replies: 3 comments
-
The PWM has a limitation regarding the achievable resolution (2^16) |
Beta Was this translation helpful? Give feedback.
-
What are the lengths of the pulses in question? Basic things can be done with just interrupts. For high performance the PIO is very attractive, as mentioned by @GitHubsSilverBullet . The PIO can be programmed directly from MicroPython. |
Beta Was this translation helpful? Give feedback.
-
This script uses the PIO to measure period and mark/space: # Measure a pulse train with PIO
from machine import Pin, PWM
from rp2 import PIO, StateMachine, asm_pio
import time
@rp2.asm_pio(set_init=rp2.PIO.IN_LOW, autopush=True, push_thresh=32)
def period():
wrap_target()
set(x, 0)
wait(0, pin, 0) # Wait for pin to go low
wait(1, pin, 0) # Low to high transition
label('low_high')
jmp(x_dec, 'next') [1] # unconditional
label('next')
jmp(pin, 'low_high') # while pin is high
label('low') # pin is low
jmp(x_dec, 'nxt')
label('nxt')
jmp(pin, 'done') # pin has gone high: all done
jmp('low')
label('done')
in_(x, 32) # Auto push: SM stalls if FIFO full
wrap()
@rp2.asm_pio(set_init=rp2.PIO.IN_LOW, autopush=True, push_thresh=32)
def mark():
wrap_target()
set(x, 0)
wait(0, pin, 0) # Wait for pin to go low
wait(1, pin, 0) # Low to high transition
label('low_high')
jmp(x_dec, 'next') [1] # unconditional
label('next')
jmp(pin, 'low_high') # while pin is high
in_(x, 32) # Auto push: SM stalls if FIFO full
wrap()
pin16 = Pin(16, Pin.IN, Pin.PULL_UP)
sm0 = rp2.StateMachine(0, period, in_base=pin16, jmp_pin=pin16)
sm0.active(1)
sm1 = rp2.StateMachine(1, mark, in_base=pin16, jmp_pin=pin16)
sm1.active(1)
pwm = PWM(Pin(17))
pwm.freq(1000)
pwm.duty_u16(0xffff // 3)
# Clock is 125MHz. 3 cycles per iteration, so unit is 24.0ns
def scale(v):
return (1 + (v ^ 0xffffffff)) * 24e-6 # Scale to ms
while True:
period = scale(sm0.get())
mark = scale(sm1.get())
print(period, mark, mark/period)
time.sleep(0.2)
``
Link pins 16 and 17 to run the demo. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I want to measure the width of a pulse. MP does not currently have any support for using channel B of the PWM as an input for pulse width measurement. Are there any implementations out there for doing that with direct register access? I also need to use two other PWM channels as outputs and I don't want to collide with the MP PWM class (similar to how setting the inversion bit on a GPIO using direct register access can be overwritten by the GPIO Pin class).
Beta Was this translation helpful? Give feedback.
All reactions