Quantcast
Viewing all articles
Browse latest Browse all 5273

General • Re: Help Needed: Achieving Long Delays with PIO for Pump Control on Raspberry Pi Pico

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

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
They key thing is that the pump turns on and off after the debounce period once the switch has settled.

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.
:)
Thank you so very much for all the help!

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



Viewing all articles
Browse latest Browse all 5273

Trending Articles