Timer Callback Can't Be Stopped

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
Some_Intern_Coder
Posts: 4
Joined: Tue Jul 05, 2022 8:11 am

Timer Callback Can't Be Stopped

Post by Some_Intern_Coder » Tue Jul 05, 2022 8:30 am

Hey all, first time posting around here.

I was working on a small project with the pyboard 1.1 that requires using timer interrupts. And these interrupts should be controlled externally over REPL. I have 2 files, one of them will get loaded onto the pyboard to define the timer and interrupts, the other file is what I run on my PC to control the REPL and manipulate the data I receive over REPL.

The file that gets loaded into pyboard (pyb_test.py):

Code: Select all

import pyb
import utime
import micropython

# Initialize the interrupt timer and the LED to indicate the state

led = pyb.LED(2)

pulse_max = 250000
pulse_min = 250000
stop = False
#############################
# Set up the pins and pulse timer
pin_a = pyb.Pin('X1', pyb.Pin.AF_PP, pull=pyb.Pin.PULL_NONE, af=pyb.Pin.AF1_TIM2)
pin_b = pyb.Pin('X2', pyb.Pin.AF_PP, pull=pyb.Pin.PULL_NONE, af=pyb.Pin.AF1_TIM2)

pulse = pyb.Timer(2, prescaler=0, period=5000000)
pulse_channel = pulse.channel(1, pyb.Timer.ENC_A)
#############################
tim = pyb.Timer(4)
tim.init(freq=2)

def tick(tim):
    global led
    global pulse
    global pulse_max
    global pulse_min

    mypulse = pulse.counter()
    mytime = utime.ticks_us()
    print(mypulse, mytime)  # Return the pulse and time ticks
    if mypulse >= pulse_max:
        pulse_max = mypulse
    if mypulse <= pulse_min:
        pulse_min = mypulse
    print(pulse_max, pulse_min)
    led.toggle()  # toggle the LED

def start_pyb():
    tim.callback(lambda t: tick(tim))  # Start the interrupt timer


def stop_pyb():
    pyb.Timer(4).callback(None)
    pyb.Timer(4).deinit()
    pyb.LED(2).off()


def initposcounter(value):
    global pulse
    pulse.counter(value)


def get_pulse_minmax():
    global pulse_max
    global pulse_min
    print("abcdef")
    print(pulse_max, pulse_min)

initposcounter(250000)

And the file I use on the PC:

Code: Select all

import pyboard
import time

# Initialize PyBoard and connect in REPL mode
pyb = pyboard.Pyboard('COM10')
pyb.enter_raw_repl()
# Execute the file that reports the pulse and time ticks
pyb.execfile('pyb_test.py')
pyb.exec("start_pyb()")
# Read the reported values 50 times (50 for min and max and 50 for the position and time tick)
for a in range(100):
    print(pyb.read_until(1, b'\r\n', 3))

pyb.exec("stop_pyb()")
print("here")

# Exit REPL and close the connection
pyb.exit_raw_repl()
pyb.close()
When I run the code, I see the outputs on the console, but when the program reaches line pyb.exec("stop_pyb()") , the program just hangs without doing anything and I have to force stop the program. The LED on the pyboard also does not turn off.

What can I do to solve this issue? I have tried quite a lot of things, but it seems like once I start the callback, I can't do anything else with the pyboard until I do a soft reset.

Many thanks in advance.

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

Re: Timer Callback Can't Be Stopped

Post by dhylands » Thu Jul 07, 2022 11:33 pm

I think that pyb.exec only expects to be called once.

The first thing it does is read until it gets a > but all it gets is the output from your timer.

If you replace the

Code: Select all

pyb.exec('stop_pyb()')
with

Code: Select all

pyb.serial.write(b'stop_pyb()')
then it will execute the stop_pyb() and things work as expected.

Some_Intern_Coder
Posts: 4
Joined: Tue Jul 05, 2022 8:11 am

Re: Timer Callback Can't Be Stopped

Post by Some_Intern_Coder » Mon Jul 11, 2022 4:17 pm

Thank you very much for the answer. The python script on the pc now runs without hanging, but the pyboard LED does not stop blinking. Could it be that I am doing something wrong?

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

Re: Timer Callback Can't Be Stopped

Post by dhylands » Wed Jul 13, 2022 7:42 pm

Sorry, my fault. When you're in the raw repl the commands don't get executed until a Control-D is received.

So try changing the pyb.serial.write to look like this instead:

Code: Select all

pyb.serial.write(b'stop_pyb()\r\x04')

Some_Intern_Coder
Posts: 4
Joined: Tue Jul 05, 2022 8:11 am

Re: Timer Callback Can't Be Stopped

Post by Some_Intern_Coder » Thu Jul 14, 2022 7:07 am

Thanks a BUNCH! It now works perfectly fine. My only gripe with it is that this is not really documented anywhere. It would be actually nice to include such instructions maybe in the pyboard specific part of MicroPython documentation. Or is it that I was just blind and did not/could not find the right place to look for it? :) Thanks a lot again.

PrimeTime416
Posts: 1
Joined: Thu Feb 01, 2018 12:42 am

Re: Timer Callback Can't Be Stopped

Post by PrimeTime416 » Wed Jul 20, 2022 7:43 pm

I had somewhat of a similar issue https://github.com/micropython/micropython/issues/8934:

Hello I was wonders if there is lag when de-initialising the timer at faster PERIODs < 5ms; in my application I require the faster period, please let me know if this is expected? If said behaviour expected I suppose I can use the counter_en return value to stop my code as needed? Thanks Team.

Code: Select all

`from machine import Timer, freq
print(freq()) # get the current frequency of the CPU
freq(240000000) # set the CPU frequency to 240 MHz
print(freq())

count = 0
timeX = Timer(1)

def timer_callback(t):
print(t)
global count
print(count)
count += 1
if (count == 50):
timeX.deinit()
timeX.init(mode=Timer.PERIODIC, period=5, callback=timer_callback)`

Lag: Count should stop at 49 but goes to 53 when period=5
Image

Good: Works great stops at 49 for period=10
Image

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Timer Callback Can't Be Stopped

Post by Roberthh » Wed Jul 20, 2022 8:12 pm

Probably the print statements in the callback take too long, which causes a few callback events to queue up. You can also write t.deinit() in the callback function, since the argument t is the timer object. See also my response at https://github.com/micropython/micropython/issues/8934.

Some_Intern_Coder
Posts: 4
Joined: Tue Jul 05, 2022 8:11 am

Re: Timer Callback Can't Be Stopped

Post by Some_Intern_Coder » Thu Jul 21, 2022 6:12 am

Thanks for the info on that topic as well. Neither am I using that fast of a callback frequency, nor do I need it. But what makes me curious is the fact that prints being that slow. And the transmission over the serial interface taking that long. Definitely something worth keeping in mind for future projects and applications.

Post Reply