diff --git a/pio/pio_pwmin.py b/pio/pio_pwmin.py new file mode 100644 index 0000000..138056d --- /dev/null +++ b/pio/pio_pwmin.py @@ -0,0 +1,96 @@ +from machine import Pin, PWM +from rp2 import PIO, StateMachine, asm_pio +from time import sleep, ticks_ms, ticks_diff + +pwm_out = PWM(Pin(16)) + +pwm_out.freq(100) +pwm_out.duty_u16((2**16-1)//2) + +@asm_pio() +def pwmin(): + pull(block) # wait for activation by doing a blocking pull on the input + mov(x, invert(null)) # invert(null) = Max. 32 Bit value + + wait(1, pin, 0) # wait for a full PWM cycle to start measurement + wait(0, pin, 0) # wait for pin to be low + + label("count_low") + jmp(pin, "out_low") # jump to output if pin is high + jmp(x_dec, "count_low") # jump back to count loop, decrement X + label("out_low") + + mov(isr, x) # move x into ISR for outputting low counter of PWM signal + push(noblock) # push into fifo + + label("count_high") + jmp(x_dec, "next") # count down X, jump to next instruction + label("next") + jmp(pin, "count_high") # as long as the pin is high, jump back up to continue countdown + + mov(isr, x) # move x into ISR for outputting the total period of the signal + push(noblock) # push into fifo + irq(0) + +base_frq = 100_000_000 +sm = rp2.StateMachine(0, pwmin, freq=base_frq, jmp_pin=Pin(16), in_base=Pin(16)) +sm.active(1) + +''' +W A R N I N G + +This example code will hang, if no PWM signal is present, +e.g. when the PWM is at 0% or 100% duty cycle. + +''' +def readPwm(sm): + # Send data to start measurement + sm.put(0) + + low = sm.get() + total = sm.get() + + # Convert to duration + low = 2**32 - 1 - low + total = 2**32 - 1 - total + + # Total is in ticks, based on base_frq. + # Due to the code, it counts by 1 for every 2 clock cycles + period = total / base_frq * 2 + + return { + "period":period, + "duty_low":low/total, + "duty":1.0-(low/total), + "freq":1/period + } + +print("PWMIn Selfcheck") + +for f in [100, 200, 500, + 1_000, 2_000, 5_000, + 10_000, 20_000, 50000, + 100_000, 200_000, 500_000]: + for d in [0.1, 0.25, 0.5, 0.75, 0.9]: + # Set new output + pwm_out.freq(f) + pwm_out.duty_u16(int((2**16-1)*d)) + + # Wait a bit + sleep(0.5) + + read = readPwm(sm) + diff_freq = abs(read["freq"]-f) + diff_duty = abs(read["duty"]-d) + + if (diff_freq <= f*0.01) and (diff_duty < 0.01): + print("{} Hz / {} duty OK".format(f, d)) + else: + print("{} Hz / {} duty OUTSIDE LIMITS ---------".format(f, d)) + + print("\t{:.2f} Hz / {:.2f} duty cycle measured".format(read["freq"], read["duty"])) + + print("\tDiff: {:.2f} Hz".format(diff_freq)) + print("\tDiff: {:.2%} of freq".format(abs(1.0-read["freq"]/f))) + print("\tDiff: {:.2%} duty cycle".format(diff_duty)) + print("")
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: