Basic Timer Question

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
Andrew1234
Posts: 20
Joined: Sat Oct 16, 2021 3:58 pm

Basic Timer Question

Post by Andrew1234 » Thu Mar 03, 2022 6:21 pm

I am using a pyboard and trying to figure out how to use the timer. I expect the below code to use Timer 1 and call function 'light' at the rate of once per second, and so I expect the LED(4) to toggle each second. The actual result is that the blue LED toggles state once. Can someone tell me why, and how to correct the code?

Code: Select all

def light(led):
    led.toggle()

import pyb 
led = pyb.LED(4)

tim = pyb.Timer(1, freq=1)    # freq in Hz
tim.callback(light(led))

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Basic Timer Question

Post by dhylands » Thu Mar 03, 2022 6:40 pm

You're passing the results of calling light(led) (which is None) to callback, instead of passing the function light to callback.

Use this instead: tim.callback(light)

The light callback needs to take a single argument, which is the timer its associated with. So you'll either need to make led be a global or perhaps make the callback be a method that's part of a class.

Here's an example that uses a class: https://github.com/dhylands/upy-example ... eat_irq.py and a variant that uses a regular function (much like what you were trying to do): https://github.com/dhylands/upy-example ... _irq_fn.py

It also occured to me that you could so this with a closure, by coding it like this:

Code: Select all

def light(led):
    def light_callback(tim):
        led.toggle()
    return light_callback

tim = pyb.Timer(1, freq=1)
tim.callback(light(led))

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Basic Timer Question

Post by dhylands » Thu Mar 03, 2022 6:58 pm

Here's a link to my tested example using a closure:
https://github.com/dhylands/upy-example ... closure.py

It looks like tick needs to be a global. I couldn't get it to work as a local to the light function (I suspect that this is a microptyonism).

Andrew1234
Posts: 20
Joined: Sat Oct 16, 2021 3:58 pm

Re: Basic Timer Question

Post by Andrew1234 » Thu Mar 03, 2022 9:27 pm

Hi Dave
I adjusted the code based on your response and the example you provided as below:

Code: Select all

import pyb

def light(tim):
    led = pyb.LED(4)
    led.toggle()

tim = pyb.Timer(1, freq=10)    # freq in Hz
tim.callback(light)     
This now works as expected. I left led as a local variable for now.

I'm a little confused about the function light needing a parameter of the timer object. Is this just the way to properly connect the callback to the function?

Regards
Andy

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Basic Timer Question

Post by dhylands » Fri Mar 04, 2022 6:04 pm

Andrew1234 wrote:
Thu Mar 03, 2022 9:27 pm
Hi Dave
I adjusted the code based on your response and the example you provided as below:

Code: Select all

import pyb

def light(tim):
    led = pyb.LED(4)
    led.toggle()

tim = pyb.Timer(1, freq=10)    # freq in Hz
tim.callback(light)     
This now works as expected. I left led as a local variable for now.

I'm a little confused about the function light needing a parameter of the timer object. Is this just the way to properly connect the callback to the function?
It allows the same timer callback to be used for multiple timers, and the callback can then distinguish which timer its being called for.

It turns out you can do something similar by using a callback method inside a class and create what's know as a "bound function", which is what this example does: https://github.com/dhylands/upy-example ... eat_irq.py

Post Reply