Memory allocation error - comments!?!
Memory allocation error - comments!?!
To date I've been using an OpenMV cam with no SD card. The program I've written started returning allocation errors, but I was able to just squeeze it in under the limit. And then I commented the code. Comments bumped me over the limit!? This doesn't seem right. But I confirmed line by line that the only difference was adding comments. Bizzare.
So I added a SD card. When trying to load the program with comments (larger), the IDE freezes/hangs. This proceeded to brick the OpenMV cam - it was recovered through a firmware re-flash and internal file system erase. Upon attempting to re-run my script via the IDE, I got the same results.
The SD card functions as an extension of the file system, correct? In other words, adding the SD card should enable me to run larger programs, correct? If so, any idea what I am doing wrong?
This is a basic 16gb SD card formatted to FAT32.
Thanks,
Chris
So I added a SD card. When trying to load the program with comments (larger), the IDE freezes/hangs. This proceeded to brick the OpenMV cam - it was recovered through a firmware re-flash and internal file system erase. Upon attempting to re-run my script via the IDE, I got the same results.
The SD card functions as an extension of the file system, correct? In other words, adding the SD card should enable me to run larger programs, correct? If so, any idea what I am doing wrong?
This is a basic 16gb SD card formatted to FAT32.
Thanks,
Chris
Re: Memory allocation error - comments!?!
Hmm, so it seems like I can save the program to the openMV cam and run it as is, but I can't run it through the IDE. Does this make sense? Any workarounds? Debugging will be somewhat annoying if I can't use the IDE.
Note that when I connect the OpenMV to my computer, the drive pops up with ~15gb of space, so it seems like the uSD card is being recognized.
Note that when I connect the OpenMV to my computer, the drive pops up with ~15gb of space, so it seems like the uSD card is being recognized.
Re: Memory allocation error - comments!?!
Um, so, the script is compiled by the camera. The camera firmware parses the script line by line and turns it into a byte array that uses heap memory.
Anyway, um, have you tried aggressively "del object" and gc.collect() and you don't need something? You have to do this once you start running out of ram so as to control heap fragmentation.
Anyway, um, have you tried aggressively "del object" and gc.collect() and you don't need something? You have to do this once you start running out of ram so as to control heap fragmentation.
Nyamekye,
Re: Memory allocation error - comments!?!
I'm not familiar with del_object and gc_collect, so no, I'm not doing this. My program is pretty simple, its just a bit long, honestly I'm surprised I'm having a memory allocation problem.
Why would it work if I save direct to the camera, but not work when using the IDE?
Why would it work if I save direct to the camera, but not work when using the IDE?
- iabdalkader
- Posts: 1292
- Joined: Sun May 24, 2015 3:53 pm
Re: Memory allocation error - comments!?!
Saving the script to cam strips comments and white space (and yes even comments take memory, they have to be stored somewhere, right ?) using an SD card won't help. Also, when connected to the IDE, the camera may need more memory.type11969 wrote: ↑Thu Nov 01, 2018 3:59 pmI'm not familiar with del_object and gc_collect, so no, I'm not doing this. My program is pretty simple, its just a bit long, honestly I'm surprised I'm having a memory allocation problem.
Why would it work if I save direct to the camera, but not work when using the IDE?
Re: Memory allocation error - comments!?!
Please bear with me, I am only somewhat okay at programming in C. So I am used to a precompiler - comments take no space, etc.
So, to confirm, the SD card will not help with memory allocation errors, correct?
So, to confirm, the SD card will not help with memory allocation errors, correct?
- iabdalkader
- Posts: 1292
- Joined: Sun May 24, 2015 3:53 pm
Re: Memory allocation error - comments!?!
No it will not, the script is loaded in memory, parsed, executed etc... You should avoid too many small allocations (causes memory fragmentation) and also use del <obj>, to free some memory, this may help.
Re: Memory allocation error - comments!?!
Okay, so I am taking a series of small images - color analysis on defined portions of an image. Should I run a del img command? Or simply run a gc.collect() at the end of the function where I analyze the image? Apologies if this is a basic question, still trying to navigate python. Appreciate the help.
-Chris
-Chris
- iabdalkader
- Posts: 1292
- Joined: Sun May 24, 2015 3:53 pm
Re: Memory allocation error - comments!?!
del img just before the line that fails to alloc will help. GC will try to collect memory before failing. If all fails, post the script and I'll try to optimize it.type11969 wrote: ↑Thu Nov 01, 2018 7:40 pmOkay, so I am taking a series of small images - color analysis on defined portions of an image. Should I run a del img command? Or simply run a gc.collect() at the end of the function where I analyze the image? Apologies if this is a basic question, still trying to navigate python. Appreciate the help.
-Chris
Re: Memory allocation error - comments!?!
Is there a way to reliably test which line is causing the allocation failure?
- iabdalkader
- Posts: 1292
- Joined: Sun May 24, 2015 3:53 pm
Re: Memory allocation error - comments!?!
Really? Thanks, sorry, I completely missed that. I was focused on the bytes that couldn't be allocated.
Re: Memory allocation error - comments!?!
Hmm, this is the error I'm getting, no reference to a code line:
MemoryError: memory allocation failed, allocating 3242 bytes
MicroPython v1.9.4-4510-g23e8457de on 2018-06-29; OPENMV3 with STM32F765
Any ideas?
MemoryError: memory allocation failed, allocating 3242 bytes
MicroPython v1.9.4-4510-g23e8457de on 2018-06-29; OPENMV3 with STM32F765
Any ideas?
Re: Memory allocation error - comments!?!
If you have time/are willing to take a look at my code for memory optimization opportunities, feedback will be appreciated. Please be kind, I generally code in C, and I'm not that great at it anyway.
Note that if I take this code and remove the comments, it will fit. But barely. If I add any more functionality, I hit the memory error again.
And yes, I am barely using the functionality of the OpenMV cam, but it is perfect for what I need it to do (color analysis). Unfortunately I can't use your canned LAB-based image analytics, this is why I am averaging pixels across a ROI.
Note that if I take this code and remove the comments, it will fit. But barely. If I add any more functionality, I hit the memory error again.
And yes, I am barely using the functionality of the OpenMV cam, but it is perfect for what I need it to do (color analysis). Unfortunately I can't use your canned LAB-based image analytics, this is why I am averaging pixels across a ROI.
Code: Select all
import sensor, image, time, pyb
from pyb import I2C, delay, ExtInt, Pin, Timer
global systemState #increments state
systemState = 0x00
#flag toggled in ISR when start button is pressed
startButtonPressFlag = 0
#keeps track of the start button state - used to keep tabs on a long press to handle a user-forced reset condition
isStartBtnPressed = 0
#keeps track of the time that the start button is depressed
startBtnPressDuration = 0
#used in each state to keep track of timed events
sysClockDuration = 0
#indicates if the arm motor is on or off
isArmMotorOn = 0
#indicates if the power up state is complete - the system then waits for user input
isPwrUpComplete = 0
#indicates if the cleaning pump is on or off
isClnPumpComplete = 0
#indicates if the urine pump is on or off
isUrnPumpComplete = 0
#indicates if the test chamber is filled or not
isChamberFilled = 0
#indicates if the urine hold duration (in the test chamber) is complete
isHoldComplete = 0
#indicates if the drain in the urine accumulator is open or not
isDrainOpen = 0
#indicates if the urine pre-drain interval is complete (mid-stream urine is used for analysis_
hasPreDrainOccured = 0
#indicates if the colormetric test is complete or not
isColormetricComplete = 0
#indicates if the collector arm is home or not
isArmHome = 0
#used in each state to initialize the state as needed
init = 0
#used during i2c transactions
snd_data = bytearray(1)
recv_data = bytearray(1)
#variable updated during colormetric tests to reflect the range of interest being analyzed in the image
roi = (0,0,0)
#clock used for timing button events
buttonClock = time.clock()
#interrupt handler - only used to handle button presses (currently)
def intHandler():
global startButtonPressFlag
global isStartBtnPressed
global startBtnPressBuration
global systemState
if startButtonPressFlag == 1:
#if the start pin is high (switch is NC) and the flag is low, the button is pressed
if startButtonPin.value() == 1 and isStartBtnPressed == 0:
isStartBtnPressed = 1
buttonClock.tick()
extIntStart.enable()
#else if the pin is high and the flag is asserted, look at the button timer
elif startButtonPin.value() == 1 and isStartBtnPressed == 1:
startBtnPressDuration = buttonClock.avg()
#if the button is held for longer than interval, a forced reset is issued
if startBtnPressDuration > 2000:
systemState = 0x08
buttonClock.reset()
startButtonPressFlag = 0
#if the pin is low and the flag is asserted, the button is released
elif startButtonPin.value() == 0 and isStartBtnPressed == 1:
isStartBtnPressed = 0
buttonClock.reset()
startButtonPressFlag = 0
extIntStart.enable()
#camera initialization routine
def cameraInit():
sensor.reset() # Reset and initialize the sensor.
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565
sensor.set_framesize(sensor.VGA) # Set frame size to VGA
sensor.set_brightness(0) #+/-3
sensor.set_saturation(0) #+/-3
sensor.set_contrast(0) #+/-3
sensor.set_auto_gain(False, -10) #gain_db
sensor.set_auto_exposure(False, 15000) #exposure time
sensor.set_quality(100)
#start button ISR
def startbuttonISR(line):
global startButtonPressFlag
startButtonPressFlag = 1
extIntStart.disable()
def runArmOut():
snd_data[0] = 0xFD
i2c.mem_write(snd_data, 0x64, 0, timeout=2000, addr_size=8) #arm motor
#function which drives the urine collection arm back towards the home position
def runArmBack():
snd_data[0] = 0xFE
i2c.mem_write(snd_data, 0x64, 0, timeout=2000, addr_size=8) #arm motor
#stops the urine collection arm
def stopArm():
snd_data[0] = 0x00
i2c.mem_write(snd_data, 0x64, 0, timeout=2000, addr_size=8) #arm motor
#pumps urine in to the test chamber
def pumpFluidIn():
snd_data[0] = 0xFE
i2c.mem_write(snd_data, 0x63, 0, timeout=2000, addr_size=8) #pump motor
def pumpFluidOut():
snd_data[0] = 0xFD
i2c.mem_write(snd_data, 0x63, 0, timeout=2000, addr_size=8) #pump motor
#stops the urine pump
def stopPump():
snd_data[0] = 0x00
i2c.mem_write(snd_data, 0x63, 0, timeout=2000, addr_size=8) #pump motor
#opens the drain in the urine collection chamber (accumulator)
def openDrain():
snd_data[0] = 0xF7
i2c.mem_write(snd_data, 0x20, 0, timeout=2000, addr_size=8) #output expander
def closeDrain():
snd_data[0] = 0xFF
i2c.mem_write(snd_data, 0x20, 0, timeout=2000, addr_size=8) #output expander
#enables the cleaning pump
def cleanActive():
cleanPumpPin.high()
def cleanInactive():
cleanPumpPin.low()
#used to write the results of the colormetric analysis
def uartWrite(rAvg, gAvg, bAvg, result):
uart.write("%d"%rAvg)
uart.write(",")
uart.write("%d"%gAvg)
uart.write(",")
uart.write("%d"%bAvg)
uart.write(",")
uart.write("%d"%result)
uart.write("\n\r")
def analyzeVitC(gAvg):
if gAvg>=168:
return 0
elif gAvg>=160:
return 50
elif gAvg>=150:
return 100
elif gAvg>=134:
return 200
elif gAvg>=119:
return 300
elif gAvg>=94:
return 500
elif gAvg>=76:
return 700
elif gAvg>=58:
return 1000
else:
return 2000
def analyzeB7(gAvg):
if gAvg>=185:
return 20
if gAvg>=177:
return 15
if gAvg>=170:
return 10
elif gAvg>=162:
return 5
else:
return 0
def analyzeMag(gAvg):
if gAvg>=185:
return 0
if gAvg>=177:
return 50
if gAvg>=170:
return 250
elif gAvg>=162:
return 450
else:
return 1500
def analyzePH(gAvg):
if gAvg>=168:
return 0
elif gAvg>=160:
return 5
elif gAvg>=150:
return 5.5
elif gAvg>=134:
return 6
elif gAvg>=119:
return 6.5
elif gAvg>=94:
return 7
elif gAvg>=76:
return 7.5
elif gAvg>=58:
return 8
else:
return 8.5
def analyzeSG(gAvg):
if gAvg>=168:
return 1000
elif gAvg>=160:
return 1005
elif gAvg>=150:
return 1010
elif gAvg>=134:
return 1015
elif gAvg>=119:
return 1020
elif gAvg>=94:
return 1025
else:
return 1030
def analyzeColor(gAvg):
if gAvg>=168:
return 1
elif gAvg>=160:
return 2
elif gAvg>=150:
return 3
elif gAvg>=134:
return 4
elif gAvg>=119:
return 5
elif gAvg>=94:
return 6
elif gAvg>=84:
return 7
else:
return 8
def analyzeArea(roi):
cameraInit() #initialize the camera
sensor.set_windowing(roi) #specify the region of interest
sensor.skip_frames(time = 2000) # Wait for settings take effect.
img = sensor.snapshot() # Take a picture and return the image.
delay(100)
rAvg = 0
gAvg = 0
bAvg = 0
#sum the pixels in the range of interest
for x in range(roi[2]):
for y in range(roi[3]):
pixel = img.get_pixel(x, y, rgbtuple=True)
#delay(10)
rAvg = rAvg+pixel[0];
gAvg = gAvg+pixel[1];
bAvg = bAvg+pixel[2];
#average the pixels
rAvg = rAvg/(roi[2]*roi[3])
gAvg = gAvg/(roi[2]*roi[3])
bAvg = bAvg/(roi[2]*roi[3])
del img #img is no longer needed
gc.collect #collect the garbage
rgbAverage = (rAvg, gAvg, bAvg)
return rgbAverage
#Initialization
uart = pyb.UART(1, 115200, timeout_char = 1000) #pin 0 = RX, pin 1 = TX - used for comms of the results
#pin 2 - not used
portExpInt = pyb.Pin('P3', pyb.Pin.IN) #not currently used
startButtonPin = pyb.Pin('P4', pyb.Pin.IN) #start button pin - currently NC
homeButtonPin = pyb.Pin('P5', pyb.Pin.IN) #note, home switch is NC
magProxPin = pyb.Pin('P6', pyb.Pin.IN) #magnet proximity switch - hall effect sensor
i2c = I2C(4) # create on bus 4 - pin 7 = SCL, pin 8 = SDA
i2c = I2C(4, I2C.MASTER) # create and init as a master
i2c.init(I2C.MASTER, baudrate=100000)
cleanPumpPin = pyb.Pin('P9', pyb.Pin.OUT_PP)
display_led = pyb.LED(1)
green_led = pyb.LED(2)
blue_led = pyb.LED(3)
red_led = pyb.LED(4)
extIntStart = pyb.ExtInt(startButtonPin, pyb.ExtInt.IRQ_RISING_FALLING, pyb.Pin.PULL_NONE, startbuttonISR)
#make sure everything is off upon startup
stopArm()
stopPump()
cleanPumpPin.low()
closeDrain()
green_led.off()
blue_led.off()
red_led.on() #swapped polarity - must confirm
display_led.off() #swapped polariy
sysClock = time.clock() #initialize system clock
while(True):
#if the button press flag is issued, run the interrupt handler
if startButtonPressFlag == 1:
intHandler()
if systemState == 0x00: #Power up state
if init == 0: #Initialization
init = 1
sysClock.tick()
red_led.off() #red LED on, boot up in progress, note swapped polarity
else:
sysClockDuration = sysClock.avg()
if isPwrUpComplete == 0:
#if power up is not complete, look at the home pin - if 6000ms elapses and the arm still isn't home, go to an error state
if homeButtonPin.value() == 0 and sysClockDuration<6000: #ARM_RETURN_MAX_DURATION
#if the home pin indicates that the arm isn't home, send it home
if isArmMotorOn == 0:
isArmMotorOn = 1
runArmBack()
elif homeButtonPin.value() == 0 and sysClockDuration>=6000: #ARM_RETURN_MAX_DURATION
systemState = 0x08 #error state
init = 0
sysClock.reset()
stopArm()
elif homeButtonPin.value() == 1:
isArmMotorOn = 0
stopArm()
isPwrUpComplete = 1
else:
red_led.on() #swapped polarity
green_led.on() #green LED - ready for user input
#waiting for start button press
if isStartBtnPressed == 1:
systemState = 0x01 #sweep state
init = 0
isPwrUpComplete = 0
sysClock.reset()
#Timing for sweeping the arm out
elif systemState == 0x01:
if init == 0:
init = 1
sysClock.tick()
#send arm out
runArmOut()
red_led.on() #red and green on - amber - filling
else:
sysClockDuration = sysClock.avg()
#arm is in position
if sysClockDuration >= 1500 and homeButtonPin.value() == 0: #ARM_SWEEP_OUT_DURATION
stopArm()
init = 0
sysClock.reset()
systemState = 0x02 #urine collect state
#arm never left - error
elif sysClockDuration >= 1200 and homeButtonPin.value() == 1: #ARM_SWEEP_OUT_DURATION
stopArm()
init = 0
sysClock.reset()
systemState = 0x08 #error state
#Timing for urine collection
elif systemState == 0x02:
if init == 0:
init = 1
sysClock.tick()
else:
sysClockDuration = sysClock.avg()
#if 7000ms elapses without a mag sensor toggle - error
if sysClockDuration >=7000 and hasPreDrainOccured == 0: #MAX_COLLECT_DURATION
init = 0
sysClock.reset()
systemState = 0x08 #error state
#if the mag sensor toggles and pre-draining hasn't completed yet, open the drain
elif magProxPin.value() == 0 and hasPreDrainOccured == 0:
sysClock.reset()
sysClock.tick()
openDrain()
hasPreDrainOccured = 1
#close the drain after time has elapsed
elif hasPreDrainOccured == 1 and sysClockDuration >=300 and sysClockDuration < 350:
closeDrain()
#when the mag sensor is toggled again (or if it is maintained) - move state
elif magProxPin.value() == 0 and hasPreDrainOccured == 1 and sysClockDuration >=350:
init = 0
hasPreDrainOccured = 0
sysClock.reset()
systemState = 0x03
red_led.off()
green_led.off()
blue_led.on() #blue LED on - urine collected, pumping to chamber
#timing to sweep the arm back while pumping urine in to the test chamber
elif systemState == 0x03:
if init == 0:
init = 1
sysClock.tick()
runArmBack()
pumpFluidIn()
else:
sysClockDuration = sysClock.avg()
#if the arm doesn't return in 6000ms - issue an error
if sysClockDuration >= 6000: #ARM_RETURN_MAX_DURATION
init = 0
sysClock.reset()
systemState = 0x08 #error state
stopArm()
stopPump()
#stop the arm once the home switch is toggled
elif homeButtonPin.value() == 1 and isArmHome == 0:
stopArm()
isArmHome = 1
#stop the pump after the pre-determined time
if sysClockDuration >= 2500 and isUrnPumpComplete == 0: #URINE_PUMPING_DURATION
isUrnPumpComplete = 1
stopPump()
#After the urine has been held in the test chamber for the allotted time, move to the next state
if isArmHome == 1 and isUrnPumpComplete == 1 and sysClockDuration >= (4500): #URINE_PUMPING_DURATION + URINE_HOLD_DURATION
init = 0
isArmHome = 0
isUrnPumpComplete = 0
sysClock.reset()
red_led.on()
green_led.on() #amber - processing urine
blue_led.off()
#Perform color test while urine is in the chamber
roi = (511, 443, 32, 27) #ROI COLOR - must be updated
RGBaverage = analyzeArea (roi)
#apply scaling factor to RGB data - placeholder
result = analyzeColor(RGBaverage[1])
uart.write("TEST_BEGIN\n\r")
uart.write("COLOR,")
uart.write(RGBaverage[0], RGBaverage[1], RGBaverage[2], result)
systemState = 0x04
elif systemState == 0x04: #drain urine
if init == 0:
init = 1
sysClock.tick()
pumpFluidOut()
openDrain()
else:
sysClockDuration = sysClock.avg()
#turn off pump after elapsed interval
if sysClockDuration >= 4500 and isUrnPumpComplete == 0: #URINE_DRAINING_DURATION
isUrnPumpComplete = 1
stopPump()
#close the drain after the elapsed interval
elif sysClockDuration >= (6500) and isUrnPumpComplete == 1: #URINE_DRAINING_DURATION + ACCUMULATOR_DRAINING_DURATION
closeDrain()
init = 0
isUrnPumpComplete = 0
sysClock.reset()
systemState = 0x05
elif systemState == 0x05: #pre-clean state - flush the collector and the accumulator
if init == 0:
init = 1
sysClock.tick()
cleanActive()
else:
sysClockDuration = sysClock.avg()
#run the cleaning pump for the alotted time
if sysClockDuration >= 3000 and isClnPumpComplete == 0: #CLEANING_FILL_DURATION
isClnPumpComplete = 1
cleanInactive()
#Let the cleaning solution sit in the accumulator for a bit, then drain
elif sysClockDuration >= (7000) and isClnPumpComplete == 1 and isDrainOpen == 0: #CLEANING_FILL_DURATION + CLEANING_HOLD_DURATION
isDrainOpen = 1
openDrain()
#close the drain after the alotted time
elif sysClockDuration >= (9000) and isDrainOpen == 1: #CLEANING_FILL_DURATION + CLEANING_HOLD_DURATION + ACCUMULATOR_DRAINING_DURATION
closeDrain()
init = 0
isClnPumpComplete = 0
isDrainOpen = 0
sysClock.reset()
systemState = 0x06
elif systemState == 0x06: #colormetric analysis
if init == 0:
init = 1
sysClock.tick()
else:
sysClockDuration = sysClock.avg()
if isColormetricComplete == 0:
for i in range (0,4): #step through the 5x regions of interest that can be analyzed right away
if i==0:
roi = (53, 391, 35, 33) #ROI ASCORBIC ACID
elif i==1:
roi = (150, 408, 37, 32) #ROI MAGNESIUM
elif i==2:
roi = (345, 417, 32, 36) #ROI PH
elif i==3:
roi = (444, 414, 27, 33) #ROI SG
RGBaverage = analyzeArea (roi)
result = 0
if i==0:
result = analyzeVitC(RGBaverage[1])
uart.write("Vitamin C,")
elif i==1:
result = analyzeMag(RGBaverage[1])
uart.write("Magnesium,")
elif i==2:
result = analyzePH(RGBaverage[1])
uart.write("PH,")
elif i==3:
result = analyzeSG(RGBaverage[1])
uart.write("SG,")
uartWrite(RGBaverage[0], RGBaverage[1], RGBaverage[2], result)
isColormetricComplete = 1
sysClock.reset()
sysClock.tick()
else:
if sysClockDuration>=450000: #B7_WAIT_DURATION - this is about 13 minutes - timekeeping is not great
roi = (258, 80, 26, 41) #ROI B7 - may need to be tweaked
RGBaverage = analyzeArea (roi)
result = analyzeB7(RGBaverage[1])
uart.write("B7,")
uartWrite(RGBaverage[0], RGBaverage[1], RGBaverage[2], result)
uartWrite("TEST_END\n\r")
init = 0
isColormetricComplete = 0
sysClock.reset()
systemState = 0x07 #move to final cleaning step
red_led.off()
green_led.on() #green - processing complete
blue_led.off()
elif systemState == 0x07: #final clean
if init == 0:
init = 1
sysClock.tick()
cleanActive()
else:
sysClockDuration = sysClock.avg()
#run the cleaning pump for the specified duration
if sysClockDuration >= 3000 and isClnPumpComplete == 0: #CLEANING_FILL_DURATION
isClnPumpComplete = 1
cleanInactive()
pumpFluidIn()
#use the urine pump to pump cleaning fluid in to the test chamber
elif sysClockDuration >= (5750) and isClnPumpComplete == 1 and isChamberFilled == 0: #CLEANING_FILL_DURATION + CLEANING_PUMPING_DURATION
isChamberFilled = 1
stopPump()
#hold the cleaning solution in the test chamber
elif sysClockDuration >= (9750) and isChamberFilled == 1 and isHoldComplete == 0: #CLEANING_FILL_DURATION + CLEANING_HOLD_DURATION + CLEANING_PUMPING_DURATION
isHoldComplete = 1
pumpFluidOut()
openDrain()
#drain the fluid from the test chamber
elif sysClockDuration >= (15750) and isHoldComplete == 1: #CLEANING_FILL_DURATION + CLEANING_HOLD_DURATION + CLEANING_PUMPING_DURATION + CLEANING_DRAINING_DURATION
closeDrain()
stopPump()
init = 0
isClnPumpComplete = 0
isChamberFilled = 0
isHoldComplete = 0
sysClock.reset()
systemState = 0x00 #return to power up
elif systemState == 0x08: #error state
red_led.off() #note polarity shift
green_led.off()
blue_led.off()
#sweep arm back until the home switch toggles
runArmBack()
while homeButtonPin.value() == 0:
delay(20)
stopArm()
pumpFluidOut()
openDrain()
delay(4000)
closeDrain()
stopPump()
cleanActive()
delay(3000)
cleanInactive()
pumpFluidIn()
delay(5550)
stopPump()
delay(4000)
pumpFluidOut()
openDrain()
delay(10000)
stopPump()
closeDrain()
systemState = 0x00
delay(20)
Re: Memory allocation error - comments!?!
That's so much code...
Um, can you point just post the lines that have issues? Where you allocate a lot of RAM?
Um, can you point just post the lines that have issues? Where you allocate a lot of RAM?
Nyamekye,
Re: Memory allocation error - comments!?!
Sorry. Honestly I'm not sure what is the root cause of the RAM allocation issue. If I had to guess, I'd say it was here:
I call this function 6 times in the code. Should I be using gc.collect and del differently?
Code: Select all
def analyzeArea(roi):
cameraInit() #initialize the camera
sensor.set_windowing(roi) #specify the region of interest
sensor.skip_frames(time = 2000) # Wait for settings take effect.
img = sensor.snapshot() # Take a picture and return the image.
delay(100)
rAvg = 0
gAvg = 0
bAvg = 0
#sum the pixels in the range of interest
for x in range(roi[2]):
for y in range(roi[3]):
pixel = img.get_pixel(x, y, rgbtuple=True)
#delay(10)
rAvg = rAvg+pixel[0];
gAvg = gAvg+pixel[1];
bAvg = bAvg+pixel[2];
#average the pixels
rAvg = rAvg/(roi[2]*roi[3])
gAvg = gAvg/(roi[2]*roi[3])
bAvg = bAvg/(roi[2]*roi[3])
del img #img is no longer needed
gc.collect #collect the garbage
rgbAverage = (rAvg, gAvg, bAvg)
return rgbAverage
Re: Memory allocation error - comments!?!
Try this:
Also, note that you can wrap things in try: except: blocks if the error happens randomly and just retry. You don't have to make sure it always succeeds.
So, keep in mind in python everything is a memory alloc. So, the im.get_pixel call returns a tuple which is allocated on the heap.
Code: Select all
def analyzeArea(roi):
cameraInit() #initialize the camera
sensor.set_windowing(roi) #specify the region of interest
sensor.skip_frames(time = 2000) # Wait for settings take effect.
img = sensor.snapshot() # Take a picture and return the image.
delay(100)
rAvg = 0
gAvg = 0
bAvg = 0
#sum the pixels in the range of interest
for x in range(roi[2]):
for y in range(roi[3]):
pixel = img.get_pixel(x, y, rgbtuple=True)
#delay(10)
rAvg = rAvg+pixel[0];
gAvg = gAvg+pixel[1];
bAvg = bAvg+pixel[2];
del pixel
gc.collect()
#average the pixels
rAvg = rAvg/(roi[2]*roi[3])
gAvg = gAvg/(roi[2]*roi[3])
bAvg = bAvg/(roi[2]*roi[3])
del img #img is no longer needed
gc.collect() #collect the garbage
rgbAverage = (rAvg, gAvg, bAvg)
return rgbAverage
So, keep in mind in python everything is a memory alloc. So, the im.get_pixel call returns a tuple which is allocated on the heap.
Nyamekye,
Re: Memory allocation error - comments!?!
Thanks, definitely a change in my way of thinking. I'll give the del pixel a shot, and do some digging on the try: except: blocks - never heard of this.
-Chris
-Chris
Re: Memory allocation error - comments!?!
Note, you can just use our LAB color code and convert the returned value to RGB...
Nyamekye,
Re: Memory allocation error - comments!?!
Do you have a canned conversion back to RGB? I took a look at doing this, and it seemed like much less code to just pull the RGB data and average directly (vs converting LAB to RGB). Different story if you guys already coded this.
Re: Memory allocation error - comments!?!
Yeah, http://docs.openmv.io/library/omv.image ... lab_to_rgb - been there for a while...
Nyamekye,
Re: Memory allocation error - comments!?!
well that was dumb miss on my part - thanks
Return to “Technical Discussion”
Who is online
Users browsing this forum: No registered users and 0 guests