OpenMV cam stops working after 20-30 minutes

Hi,

I’ve been having a great time using an OpenMV H7 for an AprilTags application. Unfortunately I’m running into a problem, though, where the camera works perfectly for about 20-30 minutes and then stops sending out data. I saw another thread with a similar problem where the suggestion was to re-flash the firmware, and I’ll give that a try tomorrow, but in the meantime I wondered if there was anything obvious about my code that could be causing problems.

It’s a slightly modified version of one of the AprilTags examples; I drag a set_windowing area around the VGA space so I can look for tags throughout the FOV.

Thanks for any help!

# Code Composer Apriltags
#
# Based on "AprilTags Example" that came with the camera
#
# 0.01: Hello world
# 0.02: Working on moving the subwindow around to scan for tags
# 0.03: It works!  Taking out the debug print() commands
# 0.04: New track layout to support both card orientations
#

import sensor, image, time, math

sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.VGA) # we run out of memory if the resolution is much bigger...
sensor.set_hmirror(True)
sensor.set_vflip(True)
sensor.set_windowing(0,0,160, 200)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False)  # must turn this off to prevent image washout...
sensor.set_auto_whitebal(False)  # must turn this off to prevent image washout...
#clock = time.clock()

# Note! Unlike find_qrcodes the find_apriltags method does not need lens correction on the image to work.

# The apriltag code supports up to 6 tag families which can be processed at the same time.
# Returned tag objects will have their tag family and id within the tag family.

tag_families = 0
#tag_families |= image.TAG16H5 # comment out to disable this family
#tag_families |= image.TAG25H7 # comment out to disable this family
#tag_families |= image.TAG25H9 # comment out to disable this family
#tag_families |= image.TAG36H10 # comment out to disable this family
tag_families |= image.TAG36H11 # comment out to disable this family (default family)
#tag_families |= image.ARTOOLKIT # comment out to disable this family

# What's the difference between tag families? Well, for example, the TAG16H5 family is effectively
# a 4x4 square tag. So, this means it can be seen at a longer distance than a TAG36H11 tag which
# is a 6x6 square tag. However, the lower H value (H5 versus H11) means that the false positve
# rate for the 4x4 tag is much, much, much, higher than the 6x6 tag. So, unless you have a
# reason to use the other tags families just use TAG36H11 which is the default family.

def family_name(tag):
    if(tag.family() == image.TAG16H5):
        return "TAG16H5"
    if(tag.family() == image.TAG25H7):
        return "TAG25H7"
    if(tag.family() == image.TAG25H9):
        return "TAG25H9"
    if(tag.family() == image.TAG36H10):
        return "TAG36H10"
    if(tag.family() == image.TAG36H11):
        return "TAG36H11"
    if(tag.family() == image.ARTOOLKIT):
        return "ARTOOLKIT"

rows = [0, 170, 333]

while(True):
#    clock.tick()
    print("Z")
    track = 0
    index = 0
    for row in rows:
        for step in range(0,5):
            sensor.set_windowing(120*step, row, 160, 184)
            img = sensor.snapshot()
            for tag in img.find_apriltags(families=tag_families): # defaults to TAG36H11 without "families".
#                img.draw_rectangle(tag.rect(), color = (255, 0, 0))
#                img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))
                print_args = (track, index, tag.id(), tag.cx()+120*step, tag.cy()+row, (180 * tag.rotation()) / math.pi)
                print("%d,%d,%d,%d,%d,%f," % print_args, end="")
#                print_args = (tag.id(), tag.cx()+120*step, tag.cy()+row, (180 * tag.rotation()) / math.pi)
#                print("Tag ID %d, x= %d, y= %d, rotation %f (degrees), " % print_args, end="")
                index = index + 1
#            time.sleep(0.5)
        track = (track + 1) % 3
        index = 0

Hi, if you run it in the IDE do you get an exception when it stops working? Typically there should be an error.

Great suggestion, thank you!

The error I get is “Frame capture has timed out”. In a fairly ignorant attempt to work around this, I added a time.sleep() right after set_windowing, and that seems to do the trick. time.sleep(0.1) worked, so currently I’m testing time.sleep(0.05).

Question: is there any more elegant way to do it? I’d like to get tag data from the camera at as high a rate as possible, so I’d love to hear if there are any better ways to do it than by hardcoding delays into the code.

Thank you!

I see what you are trying to do… you are shifting the capture window while the camera is streaming.

We provide the ROI feature for this purpose in find_apriltags(). This will do the job much better. However, I guess you are RAM limited so you are directly controlling the camera output instead?

As for making this more elegant… yeah, generally changing any of the camera settings after streaming is ugly. So, time.sleep() is probably the best thing to do. Basically, when snapshot() is called after you changed settings it starts a whole DMA pipeline and etc. Generally, you want to keep that running without editing settings on the fly per frame.

Aha. Searching for ROI I found this thread:

It looks like that person and I are trying to get to the same place: detect the smallest possible AprilTags in a decent-sized FOV.

I had it running for several hours today with time.sleep(0.1), so that appears to be stable. The resulting data rate is a little on the slow side, but I think I can live with it.

Thanks for your help!

Yeah, so, once the RT1060 comes out. Or if you have an OpenMV Cam H7 Plus, you can just set a full resolution and then use the ROI feature of the function call.