Yep; you've got it.
The below seems to do what's wanted though I am not sure about the polarities of the actual hardware. Disconnect the switch if using the code as it makes the input pin an output and we don't want to destroy the Pico.
In this case it keeps one delay in 'y' and the other in 'osr'. Same as before, load one of those into 'x' and that's the decrementing debounce counter.Code:
# ***************************************************************************# * *# * PIO Pump Control PioDelayTest4.py *# * *# ***************************************************************************from machine import Pinfrom rp2 import PIO, StateMachine, asm_pioimport time# .-------------------------------------------------------------------------.# | Configuration |# `-------------------------------------------------------------------------'TESTING = TrueSWITCH_PIN = 18PUMP_PIN = 21DELAY_FULL = 10 # Must register as full for 10 secondsDELAY_EMPTY = 15 # Must register as empty for 15 seconds# .-------------------------------------------------------------------------.# | Initialise hardware |# `-------------------------------------------------------------------------'switch = Pin(SWITCH_PIN, Pin.IN, Pin.PULL_UP)pump = Pin(PUMP_PIN, Pin.OUT, value=0)# .-------------------------------------------------------------------------.# | PIO program for controlling pump |# `-------------------------------------------------------------------------'@asm_pio(set_init=[PIO.OUT_LOW])def Delay(TESTING=TESTING): pull(block) # DELAY_FULL = pull(); // Uses 'y' mov(y, osr) # # pull(block) # DELAY_EMPTY = pull(); // USes 'osr' # wrap_target() # repeat { # # // Tank is empty. Switch going high for # // 'DELAY_FULL' period means it's full. # mov(x, y) # x = DELAY_FULL; label("loop_empty") # repeat { jmp(x_dec, "dec_empty") # x = x - 1; label("dec_empty") # # jmp(pin, "pin_empty") # if (switchValue() == 0) { mov(x, y) # x = DELAY_FULL; label("pin_empty") # } # jmp(not_x, "done_empty") # } until (x == 0); jmp("loop_empty") # # label("done_empty") # // Tank is full. Turn the pump on. # set(pins, 1) # SetPump(ON); # if TESTING: # if (TESTING) { mov(isr, invert(null)) # ReportPump(ON); push(noblock) # } # # // Tank is full. Keep emptying until the # // switch goes low for 'DELAY_EMPTY' # // period which means it is empty. # mov(x, osr) # x = DELAY_EMPTY; label("loop_full") # repeat { jmp(x_dec, "dec_full") # x = x - 1; label("dec_full") # # jmp(pin, "pin_full") # if (switchValue() == 1) { jmp("pin_done") # label("pin_full") # mov(x, osr) # x = DELAY_EMPTY; label("pin_done") # } # jmp(not_x, "done_full") # } until (x == 0); jmp("loop_full") # # label("done_full") # // Tank is empty. Turn the pump off. # set(pins, 0) # SetPump(OFF); # if TESTING: # if (TESTING) { mov(isr, null) # ReportPump(OFF); push(noblock) # } # wrap() # } forever;# .-------------------------------------------------------------------------.# | Set the PIO program running |# `-------------------------------------------------------------------------'hz = 1_000_000sm = rp2.StateMachine(0, Delay, freq=hz, jmp_pin=switch, set_base=pump)sm.active(1)sm.put(DELAY_FULL * ((hz // 4) - 3)) # Set debounce delay for fullsm.put(DELAY_EMPTY * ((hz // 5) - 3)) # Set debounce delay for empty# .-------------------------------------------------------------------------.# | Test everything works |# `-------------------------------------------------------------------------'if TESTING: # Report what's going when we control the switch and monitor what's going # on in the PIO lastTime = 0 def Report(msg): global lastTime t = time.time() s = (t // 1) % 60 m = (t // 60) % 60 h = (t // 3600) % 24 if lastTime == 0 : elapsed = "" else : elapsed = "+{}".format(t - lastTime) lastTime = t print("{:02}:{:02}:{:02} {:<4} {:<40} Switch = {} Pump = {}".format( h,m,s, elapsed, msg, switch.value(), pump.value())) def Pause(t): while t > 0: while sm.rx_fifo(): n = sm.get() if n == 0 : Report("Pump turned off") else : Report("Pump turned on") time.sleep(0.1) t -= 0.1 # Report configuration print("") print("Switch GPIO pin : {}".format(SWITCH_PIN)) print("Pump GPIO pin : {}".format(PUMP_PIN)) print("Full debounce : {:,} seconds".format(DELAY_FULL)) print("Empty debounce : {:,} seconds".format(DELAY_EMPTY)) print("") # Control the switch under program control switch = Pin(SWITCH_PIN, Pin.OUT, value=0) while True: Report("Tank is empty, but filling") Pause(5) switch.value(1) # Tank is full Report("Tank has filled") Pause(1) switch.value(0) # Bounce the switch Report("Switch bounced") Pause(1) switch.value(1) Report("Settled as filled") Pause(DELAY_FULL) # Takes time for PIO to agree it's full Pause(20) # It takes 20 seconds of pumping to empty switch.value(0) # Tank is empty Report("Tank has emptied") Pause(2) switch.value(1) # Bounce the switch Report("Switch bounced") Pause(2) switch.value(0) Report("Settled as emptied") Pause(DELAY_EMPTY) # Takes time for PIO to agree it's empty Pause(15) # Wait 15 seconds before repeating test print("") lastTime = 0
They key thing is that the pump turns on and off after the debounce period once the switch has settled.Code:
Switch GPIO pin : 18Pump GPIO pin : 21Full debounce : 10 secondsEmpty debounce : 15 seconds19:27:53 Tank is empty, but filling Switch = 0 Pump = 019:27:58 +5 Tank has filled Switch = 1 Pump = 019:27:59 +1 Switch bounced Switch = 0 Pump = 019:28:00 +1 Settled as filled Switch = 1 Pump = 019:28:10 +10 Pump turned on Switch = 1 Pump = 119:28:30 +20 Tank has emptied Switch = 0 Pump = 119:28:32 +2 Switch bounced Switch = 1 Pump = 119:28:34 +2 Settled as emptied Switch = 0 Pump = 119:28:49 +15 Pump turned off Switch = 0 Pump = 0
If the polarities are right, then simply setting 'TESTING=False' and adjusting the DELAY_FULL and DELAY_EMPTY times should make it work as desired
Why thanks so much! I haven't gone through it yet, but the switch seems to be bouncing even without anything connected to that pin, so perhaps I've been fighting hardware issues all along without realizing it. All these examples have been a great source of learning and I certainly feel a lot more confident in being able to work through the issue now, at the very least. Image may be NSFW.
Clik here to view.

And of course just as I'm learning things they go and announce a Pico 2, with updated PIO hardware!
Statistics: Posted by Darkhand — Thu Aug 08, 2024 5:08 pm