How to receive UART data in timer callback function?

I am trying to receive UART data in timer callback function.here is my code:

# Hello World Example
#
# Welcome to the OpenMV IDE! Click on the green run arrow button below to run the script!

import sensor, image, time, pyb, struct

sensor.reset()                      # Reset and initialize the sensor.
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QVGA)   # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 2000)     # Wait for settings take effect.
clock = time.clock()                # Create a clock object to track the FPS.


##初始化串口
uart = pyb.UART(1, 115200, timeout_char=1000)                         # i使用给定波特率初始化
uart.init(115200, bits=8, parity=None, stop=1, timeout_char=1000) # 使用给定参数初始化

res=1

def uart_call_back_(t):
    global uart
    if uart.any():
        res=uart.read()
        res = struct.unpack('B', res)
        res = hex(res)
        res = int(res)
        if res == 0xaf:
            pyb.LED(1).toggle()
            print('succes')
    return

tim = pyb.Timer(4)              # create a timer object using timer 4  使用定时器4创建一个定时器对象
tim.init(freq=1000)                # trigger at 2Hz 以2Hz触发
tim.callback(uart_call_back_)

def snshot():
    #clock.tick()                    # Update the FPS clock.
    img = sensor.snapshot()         # Take a picture and return the image.
    
    #print(clock.fps())              # Note: OpenMV Cam runs about half as fast when connected
                                    # to the IDE. The FPS should increase once disconnected.

while(True):
    snshot()

But I got error like this:
uncaught exception in Timer(4) interrupt handler
MemoryError:

It seem that have not enough memory.
I also try to call the “uart_call_back_” function in main loop instead of as a callback function of timer.but it mean I can’t deal my data in time,because i have to process my photo data in mean loop.
what can i do to solve this problem? :sob:

If you read the documentation you have to call MicroPython.schedule() to run the code later outside of the interrupt. There’s a large section in the documentation that explains what you can and cannot do in interrupts. You cannot allocate memory or using floating point operations in them.

micropython is not c, not asm, and micropython interrrupt function is very poor .
forget uart in callback.
i think check any() is better.

That’s not true at all.

If you write any interrupt code in C you will know that you can never allocate memory in them or use floating point operations. The rules that you have to follow in asm/C are the same.

thank for answer,I still can’t receive data in callback function.but in my surpise, receiving data in main loop is good enough for my current application.

when i was using MicroPython.schedule() in my timer callback function like this:

def uart_call_back_(t):
    global uart
    if uart.any():
        res=uart.read()
        res = struct.unpack('B', res)
        res = hex(res)
        res = int(res)
        if res == 0xaf:
            pyb.LED(1).toggle()
            print('succes')
    return

def timercallback(tim):
    micropython.schedule(uart_call_back_, tim)


tim = pyb.Timer(4)              # create a timer object using timer 4  使用定时器4创建一个定时器对象
tim.init(freq=1000)                # trigger at 2Hz 以2Hz触发
tim.callback(timercallback)

i got error like this:>>> uncaught exception in Timer(4) interrupt handler
RuntimeError:
I want to know if i called the MicroPython.schedule() to run in a wrong way.the documentation mentions this error( micropython – access and control MicroPython internals — MicroPython 1.20 documentation (openmv.io)),but i still don’t know how to solve this problem.

Hi, uh, yeah, generally I wouldn’t try to receive data in a call back or etc. That’s really just for setting a flag.

So, the way code like this works is that the interrupt/callback just should do a very simple operation. The main loop then checks that flag and does something based on it.

Generally, you want your code to be non-blocking and the main loop to be checking all cases and etc. Interrupts just help you make something happen more quickly than the main loop getting to it.

As for the error. Hmmm, code looks right. However, the errors are less verbose inside the interrupt callback to save stack space. If you call the timercallback function in your main code just once you’ll see what the actual error is.

thank you for your patient answer :smiling_face: