Hey folks, I’m having some fun with the Badger2040, using it as a temperature display for our Axolotl tank with a 1-wire thermometer thingy and CircuitPython. Works great when displaying a static temperature but I decided I wanted to display a graph of past temperatures.
I’m doing this by appending the values to a list, and then popping the first item when the list gets too long. Then I loop through the list and draw a bar for each item in the list. I’m adding these to a group (along with some other elements) and then displaying the whole thing.
The code works… to a point. After a few minutes I get the following error:
Traceback (most recent call last):
File "code.py", line 86, in <module>
File "/lib/adafruit_display_shapes/rect.py", line 47, in __init__
MemoryError: memory allocation failed, allocating 5120 bytes
I looked into how to clean up appropriately, and I’m using group.remove() at the end of each loop but still I eventually run out of memory.
I have a feeling I’m just doing something stupid or missing a key peice of knowledge to make this work. Does anyone have any suggestions? (alternatively is there a way to automatically “reboot” the device when it runs out of memory?
This is my horrible code if you want to take a look:
Cheers for the help :)
import board
import displayio
import time
import adafruit_imageload
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
from adafruit_display_shapes.rect import Rect
from adafruit_onewire.bus import OneWireBus
import adafruit_ds18x20
import gc
# time between refreshes (default 15 mins)
# delay = 60 * 15
delay = 3
# define the bar width, spacing and number of elements
bar_width = 15
bar_spacing = 1
bar_num = 5
# setup the DS18B20 one wire temp sensor
ow_bus = OneWireBus(board.SCL)
devices = ow_bus.scan()
ds18b20 = adafruit_ds18x20.DS18X20(ow_bus, devices[0])
# setup the display
display = board.DISPLAY
palette = displayio.Palette(1)
palette[0] = 0xFFFFFF
WHITE = 0xFFFFFF
BLACK = 0x000000
# WHAT THE FONT?
font1 = bitmap_font.load_font("/fonts/Fredoka-75.bdf")
font2 = bitmap_font.load_font("/fonts/Fredoka-32.bdf")
# this is an array for temp values
temp_array = []
# this is where we put all the stuff we want to display
group = displayio.Group()
# set background
background = Rect(0, 0, display.width, display.height, fill=WHITE, outline=WHITE)
# load an image
image1, palette = adafruit_imageload.load("/images/axolotl1.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
image2, palette = adafruit_imageload.load("/images/axolotl2.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
print("\n\n\n\n\nLoading AxOS...")
# Loop forever so you can enjoy your message
while True:
x = 0;
# update temperature
temp = '{0:0.0f}'.format(ds18b20.temperature)
# add the current temp to the storage array
temp_array.append(int(temp))
# Set text, font, and color
text1 = str(temp) + 'ºc'
# add the images depending on temp
if int(temp) > 15 and int(temp) < 20:
text2 = "Temp OK!"
pic = displayio.TileGrid(image1, pixel_shader=palette, x=168, y=0)
else:
text2 = "Temp BAD!"
pic = displayio.TileGrid(image2, pixel_shader=palette, x=168, y=0)
# just for debugging
print(text1, text2)
# Create the title and subtitle labels
text1 = label.Label(font1, text=text1, color=BLACK, scale=1, x=5, y=30, scale=1)
text2 = label.Label(font2, text=text2, color=BLACK, scale=1, x=5, y=82, scale=1)
# sexy background square
background = Rect(0, 0, display.width, display.height, fill=WHITE, outline=WHITE)
# Create the display group and append objects to it
group.append(background)
group.append(pic)
group.append(text1)
group.append(text2)
# when the array gets too long, pop it off
if(len(temp_array) > bar_num):
temp_array.pop(0)
# loop through the temperatures array
for onetemp in temp_array:
# fananagle the numbers to make sure things don't break
if onetemp > 2:
onetemp = round(onetemp / 1.5)
if onetemp < 1:
onetemp = 1
# position the bar at the bottom vertically
y = display.height - onetemp
bar = Rect(x, y, bar_width, onetemp, fill=BLACK, outline=BLACK)
group.append(bar)
x = x+bar_width+bar_spacing
# Show the group and refresh the screen to see the result
display.show(group)
display.refresh()
# hang on a cotton picking minute
time.sleep(delay)
# tidy up (saves memory?)
group.remove(bar)
group.remove(background)
group.remove(pic)
group.remove(text1)
group.remove(text2)
gc.collect()
pass