combine two functions into one

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
soggycashew
Posts: 55
Joined: Sat Sep 18, 2021 10:21 pm

combine two functions into one

Post by soggycashew » Sun Oct 31, 2021 4:25 am

Hello, I have two functions that get called at the same time and want to combone them BUT one uses a timer
and and the other loops 5 times and stops.

I want the led/buzzer and on/off led to run until I press a button, as it is now the button doesnt do anything untill
the loop is finished then it will stop the blink_buzz

the two are called using:

Code: Select all

tim.init(freq=2, mode=Timer.PERIODIC, callback=blink_buzz) 
blink_lcd()
Two functions:

Code: Select all

def blink_buzz(timer):
    global led_red
    global buzzer
    led_red.toggle()
    buzzer.toggle()

def blink_lcd():
    for i in range(5): #flash LCD 5 times
        lcd.display_off()  #Turns off LCD
        utime.sleep(0.5) #Pause
        lcd.display_on()  #Turns on LCD
        utime.sleep(0.5) #Pause

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: combine two functions into one

Post by pythoncoder » Sun Oct 31, 2021 11:22 am

Welcome to the world of asynchronous coding. You need to learn uasyncio (official docs) and unofficial tutorial. Once you've grasped the concepts, tasks like this are easy - and you don't need a timer.
Peter Hinch
Index to my micropython libraries.

soggycashew
Posts: 55
Joined: Sat Sep 18, 2021 10:21 pm

Re: combine two functions into one

Post by soggycashew » Sun Oct 31, 2021 3:15 pm

@pythoncoder I got them to work together but how do you stop the looping? when using the timer I just used tim.deinit() from a button.

initialize the functions:

Code: Select all

uasyncio.run(incomplete_cycle())
The functions:

Code: Select all

async def blink_lcd(delay):
    while True:
         led_red.toggle()
         buzzer.toggle()
         await uasyncio.sleep(delay)
        
async def incomplete_cycle():
    uasyncio.create_task(blink_lcd(0.2))
    
    while True:
        lcd.display_off()  #Turns off LCD
        await uasyncio.sleep_ms(500)  #Wait 1/2 sec
        lcd.display_on()  #Turns on LCD
        await uasyncio.sleep_ms(500)  #Wait 1/2 sec

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: combine two functions into one

Post by pythoncoder » Sun Oct 31, 2021 5:41 pm

Well done for picking it up quickly. The simplest approach is to cancel the task: see my tutorial. Other ways are to use an Event or to test a global variable.
Peter Hinch
Index to my micropython libraries.

soggycashew
Posts: 55
Joined: Sat Sep 18, 2021 10:21 pm

Re: combine two functions into one

Post by soggycashew » Sun Oct 31, 2021 7:08 pm

@pythoncoder I read your GitHub cancel documentation and I'm not quite getting it... Do I need to create another async def as my main and call both from main like:

Called using:

Code: Select all

uasyncio.run(incomplete_cycle())

Code: Select all

async def blink_led(delay):
    while True:
         led_red.toggle()
         await uasyncio.sleep(delay)
        
async def blink_lcd(): 
    while True:
        lcd.display_off()  #Turns off LCD
        await uasyncio.sleep_ms(500)  #Wait 1/2 sec
        lcd.display_on()  #Turns on LCD
        await uasyncio.sleep_ms(500)  #Wait 1/2 sec
        
async def incomplete_cycle():
    task1 = uasyncio.create_task(blink_led())
    task2 = uasyncio.create_task(blink_lcd())
    await uasyncio.sleep(10)
    print('Quitting')
    task1.cancel()
    task2.cancel()
    await uasyncio.sleep_ms(1000)
    print('Done')
But im still confused on how I can cancel it from a button? I am also getting an error when trying to run the code so I really dont know what its doing

File "<stdin>", line 217, in <module>
TypeError: function takes 1 positional arguments but 0 were given

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: combine two functions into one

Post by pythoncoder » Mon Nov 01, 2021 11:49 am

Your blink_led function requires an argument so this line will fail:

Code: Select all

    task1 = uasyncio.create_task(blink_led())
Peter Hinch
Index to my micropython libraries.

soggycashew
Posts: 55
Joined: Sat Sep 18, 2021 10:21 pm

Re: combine two functions into one

Post by soggycashew » Mon Nov 01, 2021 6:02 pm

Peter maybe I'm going about this wrong, what I'm trying to do is have my LCD flash on and off while the buzzer beeps and a LED blinks all simultaneously from a sensor press until I can push a reset button to stop it.

Using a timer allowed me to do this because I could stop the timer from a button press but the issue was I couldn't get the LCD to blank at the same time unless I used a separate function in only let it blink five times after that I was allowed to push the reset button to stop the buzzer and the LED

How would you go about doing this?

User avatar
curt
Posts: 25
Joined: Thu Jul 29, 2021 3:52 am
Location: Big Lake, Alaska

Re: combine two functions into one

Post by curt » Tue Nov 02, 2021 4:31 am

This code isn't ready to release but I thought it might be useful:

https://github.com/ctimmer/iot-logger/t ... emperature

For testing:
Using powercontrol.py, remove all classes except Globals and PlugInTemplate.
Remove references to the display.

Code: Select all

#----
#---- PlugIn control set up
#----
global_data = Globals (poll_ms=100)            # 0.10 second poll

#----
#---- plugin poll array - determines which plugin''s are polled and polling order
#----
poll_array = [
    #ReadInput (global_data) ,           # Button input, turns on or off
    #LedDisplay (global_data) ,          # LED blink
    #Buzzer (global_data) ,                 # buzzer on/off
    PlugInTemplate (global_data)       # demo
    ]

#----
#---- Start polling
#----
try :
    while global_data.running () :
        for plugin in poll_array :     # poll each plugin
            plugin.poll_it ()
        global_data.poll_wait ()       # wait for next poll cycle
except : #Exception as e :
    print ("poll_it: exception")
    #print (e)
finally :
    print ("Poll_It: completed")

#----
#---- plugin shutdown
#----
print ("plugins shutdown")
for plugin in poll_array :
    #print ("mod shutdown", plugin.__class__)
    try :
        plugin.shutdown ()
    except :
        print ("plugin shutdown", plugin.__class__, "exception")
Notice that no timers are used.
The poll_ms parameter determines how often the poll loop is executed
PlugInTemplate shows the way to configure how often the plug in is active
self.global_data.message_set provides communication between the plugins

Sorry for the lack of documentation but this is in development. Feel free to ask any questions

Curt

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: combine two functions into one

Post by pythoncoder » Tue Nov 02, 2021 8:09 am

@soggycashew I'm having some trouble understanding your problem. If you're saying that you want to guarantee the LCD state when the task is cancelled, this can be done by trapping the cancellation exception as described in my tutorial. To interface to a pushbutton, use the Switch or Pushbutton classes documented here. The switch callback can issue the task cancel command.
Peter Hinch
Index to my micropython libraries.

Post Reply