Alarm callback function not executing



  • Instead of using sleep commands, I'm trying to use alarms to control how long a solenoid valve is open. However, the alarm is not calling the function that closes the valve. These are DC latching solenoids, so solON applies voltage to the solenoid for 25 ms, solOFF applies reverse polarity to close the valve. I don't get any errors, but the valve never closes if I use solAction. The solON and solOFF functions work fine by themselves. I don't think my "duration" variable is getting to the alarm.

    def solON(valve):
        valve[0].value(0)
        sleep_ms(closed_time)
        valve[0].value(1)
        print('open')
    
    def solOFF(valve):
        valve[1].value(0)
        sleep_ms(closed_time)
        valve[1].value(1)
        print('close')
    
    
    def solAction(valve, duration):
        irrigate_alarm = Timer.Alarm(lambda x: solOFF(valve), duration)
        solON(valve)
    

    0_1531681307150_fd8ceb81-9bda-4cf3-a2be-44db6f559c99-image.png



  • @robert-hh It turns out the "periodic=False" attribute is all it needed. Works fine now.



  • @jmpratt I do no get your problem. If I take your script, let#s call it valve.py, run:

    from valve import *
    solAction(mist, 2)
    

    Then it seems to work as expected. I get a message "open", and after 2 seconds the message "close".
    Which firmware version are you using. At the REPL prompt, push Ctrl-B, or run:
    import uos;uos.uname()
    Are you sure that the scrpt is loaded to your device permanently?
    Pymakr sometimes fools people about it.



  • @robert-hh Thanks. I should have posted my whole module. I have two valves, drip_line & mist. I want to be able to specify the valve and time each time I call the function. I still don't understand why the callback doesn't execute.

    from machine import Pin, Timer
    from utime import sleep_ms
    
    # define relay close time in milliseconds
    closed_time = 25
    
    #  define control pins
    valve1 = [5, 6] #[open_pin, close_pin]
    valve2 = [19, 20]
    inputs = ['in1', 'in2', 'in3', 'in4'] # relay board input labels
    
    pins = valve1 + valve2
    
    #init control pin, set all as output high (relay inactive)
    for i, j in zip(pins, inputs):
        command1 = "%s=Pin('P%s', mode=Pin.OUT)" % (j,str(i))
        command2 ="%s.value(1)" %(j)
        exec(command1)
        exec(command2)
    
    drip_line = [in1, in2] # [open_pin, close_pin]
    mist = [in3, in4]
    
    def solON(valve):
        valve[0].value(0)
        sleep_ms(closed_time)
        valve[0].value(1)
        print('open')
    
    def solOFF(valve):
        valve[1].value(0)
        sleep_ms(closed_time)
        valve[1].value(1)
        print('close')
    
    
    def solAction(valve, duration):
        irrigate_alarm = Timer.Alarm(lambda x: solOFF(valve), duration)
        solON(valve)```


  • @jmpratt I added a few lines to you code, and it runs well.

    from machine import Timer, Pin
    from utime import sleep_ms
    
    pins=[Pin("P10", Pin.OUT), Pin("P11", Pin.OUT)]
    closed_time = 25
    
    
    def solON(valve):
        valve[0].value(0)
        sleep_ms(closed_time)
        valve[0].value(1)
        print('open')
    
    def solOFF(valve):
        valve[1].value(0)
        sleep_ms(closed_time)
        valve[1].value(1)
        print('close')
    
    
    def solAction(valve, duration):
        irrigate_alarm = Timer.Alarm(lambda x: solOFF(valve), duration, periodic=False)
        solON(valve)
    
    def run(time):
        solAction(pins, time)
    

    If the script is e.g. called valve.py, executing import valve and then valve.run(1) performs as expected.


 

Pycom on Twitter