MatrixPortal Memory Error

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
Tortilla
 
Posts: 31
Joined: Sun Jan 09, 2022 5:03 am

Re: MatrixPortal Memory Error

Post by Tortilla »

dastels wrote:Can you post your code again, making sure the formatting carries over? I want to try with exactly what you have on the board.

Dave
Ok, I hope this shows the formatting:

Code: Select all

"""One panel display using 64 X 32 RGB panel to scroll ESPN game information"""
import gc
import time
import json
from adafruit_datetime import datetime, timedelta
import board
from adafruit_matrixportal.matrixportal import MatrixPortal

Memory_free = gc.mem_free()
print("Total memory free right after importing matrixportal library is", Memory_free)
# import terminalio


USE_24HR_TIME = False
TIME_ZONE_OFFSET = -8  # hours ahead or behind Zulu time, e.g. Pacific is -8
TIME_ZONE_NAME = "PST"
# SCROLL_DELAY = 0.03

#  Create a list of dictionaries for ESPN API's
#  Note that College Baseball doesn't start until mid-February,
#  so NHL Hockey (Sport 1)is displayed for now
SPORTS = [
    {
        "name": "College Baseball",
        "url": "http://site.api.espn.com/apis/site/v2/sports/baseball/college-"
        "baseball/scoreboard",
    },
    {
        "name": "NHL Hockey",
        "url": "http://site.api.espn.com/apis/site/v2/sports/hockey/nhl/scoreboard",
    },
]
current_game = 0
current_sport = 1
sports_data = []


EVENTS_LOCATION = ["events"]
STATUS_LOCATION = ["status", "type", "description"]
BROADCAST_LOCATION = ["competitions", 0, "broadcasts"]
IS_FINAL_LOCATION = ["competitions", 0, "status", "type", "id"]
SCORES_LOCATION = ["competitions", 0, "competitors"]
SCORE_0_LOCATION = ["competitions", 0, "competitors", 0, "score"]
SCORE_1_LOCATION = ["competitions", 0, "competitors", 1, "score"]

months = [
    "Jan",
    "Feb",
    "March",
    "April",
    "May",
    "June",
    "July",
    "Aug",
    "Sept",
    "Oct",
    "Nov",
    "Dec",
]

Memory_free = gc.mem_free()
print("Total memory free right before matrixportal call is", Memory_free)

matrixportal = MatrixPortal(
    url=SPORTS[current_sport]["url"],
    status_neopixel=board.NEOPIXEL,
)


def format_date(iso_formatted_date):
    if iso_formatted_date is None:
        return "When: Unavailable"
    date = datetime.fromisoformat(iso_formatted_date[:-1])
    date += timedelta(hours=TIME_ZONE_OFFSET)

    if USE_24HR_TIME:
        timestring = "%d:%d %s" % (date.hour, date.minute, TIME_ZONE_NAME)
    elif date.hour > 12:
        timestring = "%d:%d pm %s" % (
            abs((date.hour - 12) % 12),
            date.minute,
            TIME_ZONE_NAME,
        )
    else:
        timestring = "%d:%d am %s" % (date.hour, date.minute, TIME_ZONE_NAME)
    return "%s %d, %s" % (months[date.month - 1], date.day, timestring)


def format_score(scores, is_final):
    home_score = scores[0]["score"]
    away_score = scores[1]["score"]
    if not home_score or not away_score:
        return "Unavailable"
    if int(is_final) == 3:
        return "%s - %s" % (home_score, away_score)
    return " "


def format_available(value):
    if value is None:
        return "Unavailable"
    return value


def format_broadcast(value):
    if not value:
        value = "N/A"
    else:
        value = matrixportal.network.json_traverse(value, [0, "names", 0])
    return "Airing on: " + value


def get_game_number():
    return "Game %d of %d" % (current_game + 1, len(sports_data))


def update_labels():
    # Set the labels for the current game data
    matrixportal.set_text(SPORTS[current_sport]["name"], 0, False)
    matrixportal.set_text(sports_data[current_game]["name"], 1, False)
    matrixportal.set_text(sports_data[current_game]["date"], 2, False)
    matrixportal.set_text(sports_data[current_game]["broadcast"], 3, False)
    matrixportal.set_text(sports_data[current_game]["status"], 4, False)
    matrixportal.set_text(get_game_number(), 5, False)
    matrixportal.set_text(sports_data[current_game]["score"], 6)
    # wait 2 seconds for display to complete
    time.sleep(2)


def fetch_sports_data(reset_game_number=True):
    # Fetches and parses data for all games for the current sport
    # pylint: disable=global-statement
    global sports_data, current_game, current_sport
    matrixportal.url = SPORTS[current_sport]["url"]
    sports_data.clear()
    raw_data = json.loads(matrixportal.fetch(auto_refresh=False))
    events = raw_data["events"]
    for event in events:
        game_data = {}
        game_data["name"] = format_available(event["name"])
        game_data["date"] = format_date(event["date"])
        game_data["status"] = "Game status: " + format_available(
            matrixportal.network.json_traverse(event, STATUS_LOCATION)
        )
        game_data["broadcast"] = format_broadcast(
            matrixportal.network.json_traverse(event, BROADCAST_LOCATION)
        )
        scores = matrixportal.network.json_traverse(event, SCORES_LOCATION)
        is_final = matrixportal.network.json_traverse(event, IS_FINAL_LOCATION)
        game_data["score"] = format_score(scores, is_final)
        sports_data.append(game_data)
    if reset_game_number or current_game > len(sports_data):
        current_game = 0
    update_labels()


FONT = "tom-thumb.bdf"
# FONT = terminalio.FONT

# Sports Name
matrixportal.add_text(text_font=FONT, text_position=(5, 3), is_data=False)

# Game Name
matrixportal.add_text(
    text_font=FONT,
    text_wrap=35,
    line_spacing=0.75,
    text_position=(5, 16),
    is_data=False,
)

# Date
matrixportal.add_text(text_font=FONT, text_position=(5, 10), is_data=False)

# Broadcast Information
matrixportal.add_text(text_font=FONT, text_position=(5, 20), is_data=False)

# Game Status
matrixportal.add_text(text_font=FONT, text_position=(5, 25), is_data=False)

# Game Number
matrixportal.add_text(text_font=FONT, text_position=(40, 10), is_data=False)

# Score
matrixportal.add_text(text_font=FONT, text_position=(32, 16), is_data=False)

last_update = time.monotronic()
UPDATE_DELAY = 7
fetch_sports_data()

while True:
    current_sport = 1
    if time.monotonic() > last_update + UPDATE_DELAY:
        current_game += 1
        last_update = time.monotonic()
    if current_game >= len(sports_data):
        fetch_sports_data(False)
        current_game = 0
    update_labels()
    # time.sleep(7)
I know that my code has some functional problems that I was going to be working on if I could get past the Memory Error.

Thanks again for helping with this.

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: MatrixPortal Memory Error

Post by dastels »

OK, with the code you just posted I get

Code: Select all

code.py output:
Total memory free right after importing matrixportal library is 32544
Total memory free right before matrixportal call is 31920
Traceback (most recent call last):
  File "code.py", line 66, in <module>
  File "adafruit_matrixportal/matrixportal.py", line 97, in __init__
  File "adafruit_matrixportal/graphics.py", line 67, in __init__
  File "adafruit_matrixportal/matrix.py", line 192, in __init__
MemoryError:

Code done running
So the MatrixPortal library take sup a BIG chunk, and your code is enough that there's not room to create the MatrixPortal object.

I'm still concerned about the lack of information about the error.

Dave

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: MatrixPortal Memory Error

Post by dastels »

OK, I changed the MatrixPortal instantiation code to:

Code: Select all

try:
    matrixportal = MatrixPortal(
        url=SPORTS[current_sport]["url"],
        status_neopixel=board.NEOPIXEL,
        )
except MemoryError as err:
    print(type(err))
    print(err.args)
    print(err)
and its output is

Code: Select all

<class 'MemoryError'>
()

So it's just a bare MemoryError with no information attached?? I've never seen that before. They're usually an allocation error with information about how much was requested. Dan?

Dave

User avatar
danhalbert
 
Posts: 4649
Joined: Tue Aug 08, 2017 12:37 pm

Re: MatrixPortal Memory Error

Post by danhalbert »

This means there is so little memory left that there was not even room to construct the error message. It does not happen that often. There is an "emergency buffer" but we may not be using it. Sorry that it's so uninformative.

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: MatrixPortal Memory Error

Post by dastels »

Options?

Switch to C++ with protomatter?

Make a build of CP with the MatrixPortal stuff frozen?

??

Dave

User avatar
Tortilla
 
Posts: 31
Joined: Sun Jan 09, 2022 5:03 am

Re: MatrixPortal Memory Error

Post by Tortilla »

dastels wrote:Options?

Switch to C++ with protomatter?

Make a build of CP with the MatrixPortal stuff frozen?

??

Dave
Well, thanks for hanging in there on this. Your output with the MemoryError now exactly matches mine.

I talked to some guys this weekend and the consensus seems to be that my code is just too large for the memory on the Matrix Portal board. I was attempting to take the ESPN game schedule code which was written for the Adafruit MagTag project and create a one-sport schedule board to display game information on an LED display, primarily for college baseball. Obviously with the MagTag, you have buttons to switch sports and scroll to the next game, etc. but I am only interested in displaying the schedule information for one sport, so I thought the Matrix Portal might work. The MagTag has 4 MByte of Flash and 2 MByte of PSRAM versus 512KB flash and 192K of SRAM for the Matrix Portal, so the Matrix Portal just doesn't have the memory.

If the Matrix Portal had more memory, it would be a fantastic display board for these kinds of projects.

Of course, if anyone has some other ideas, I would love to hear them.

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: MatrixPortal Memory Error

Post by dastels »

An ESP32-S2 (4M flash, 2M PSRAM) based MatrixPortal would be nice. Alas, there isn't one. And the Matrix Featherwing doesn't appear to have a version for the ESP32-S2 Feather. Using a Feather nRF52840 (1MB flash and 256KB SRAM) https://www.adafruit.com/product/4062 + the matching Matrix Featherwing https://www.adafruit.com/product/4702 and an Airlift Featherwing https://www.adafruit.com/product/4264 would do a good job of it (as long as the wings don't conflict).

Again, you can always switch to C++/Arduino.

Dave

User avatar
Tortilla
 
Posts: 31
Joined: Sun Jan 09, 2022 5:03 am

Re: MatrixPortal Memory Error

Post by Tortilla »

dastels wrote:An ESP32-S2 (4M flash, 2M PSRAM) based MatrixPortal would be nice. Alas, there isn't one. And the Matrix Featherwing doesn't appear to have a version for the ESP32-S2 Feather. Using a Feather nRF52840 (1MB flash and 256KB SRAM) https://www.adafruit.com/product/4062 + the matching Matrix Featherwing https://www.adafruit.com/product/4702 and an Airlift Featherwing https://www.adafruit.com/product/4264 would do a good job of it (as long as the wings don't conflict).

Again, you can always switch to C++/Arduino.

Dave
I'm definitely considering the Arduino. Thanks.

User avatar
MakerMelissa
 
Posts: 375
Joined: Wed Jun 05, 2013 2:10 am

Re: MatrixPortal Memory Error

Post by MakerMelissa »

This library was always on the large size and it or dependent libraries have likely grown since it was first written. As Dan mentioned, you should make sure you are using .mpy files. If you're still having issues, we may need to freeze a library into CircuitPython.

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: MatrixPortal Memory Error

Post by dastels »

I can confirm the error with fresh MPY files.

Dave

User avatar
MakerMelissa
 
Posts: 375
Joined: Wed Jun 05, 2013 2:10 am

Re: MatrixPortal Memory Error

Post by MakerMelissa »

Thank you Dave. You may also be able to remove any libraries from lib that appear in https://github.com/adafruit/circuitpyth ... ain/frozen to shave off a little of the memory used such as busdevice and esp32spi.

User avatar
dastels
 
Posts: 15656
Joined: Tue Oct 20, 2015 3:22 pm

Re: MatrixPortal Memory Error

Post by dastels »

I added modules to lib in response to import errors, and esp32spi was one of those.

Dave

User avatar
MakerMelissa
 
Posts: 375
Joined: Wed Jun 05, 2013 2:10 am

Re: MatrixPortal Memory Error

Post by MakerMelissa »

Ok, thanks. That's helpful to know.

User avatar
Tortilla
 
Posts: 31
Joined: Sun Jan 09, 2022 5:03 am

Re: MatrixPortal Memory Error

Post by Tortilla »

MakerMelissa wrote:This library was always on the large size and it or dependent libraries have likely grown since it was first written. As Dan mentioned, you should make sure you are using .mpy files. If you're still having issues, we may need to freeze a library into CircuitPython.
Yes, all of my library files are .mpy and they are the latest version.

User avatar
Tortilla
 
Posts: 31
Joined: Sun Jan 09, 2022 5:03 am

Re: MatrixPortal Memory Error

Post by Tortilla »

MakerMelissa wrote: If you're still having issues, we may need to freeze a library into CircuitPython.
That would be great. I would rather not give up on my project if it might still be able to work.

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”