1

I use MicroPython on my Raspberry Pi Pico and try to display a BLOB coming from an HTTP API on a Waveshare ePaper display. This is my code:

epd = EPD_7in5_B()
epd.Clear()

while(True):
    response = urequests.get('http://<<myRaspiPicoW>>/screenshotCreator/latestImage?blackAndWhite=true&asWaveshareBytes=true')
    if response.status_code == 200:
        epd.buffer_black = response.content
        epd.display()
    else:
        print('Request failed')

    epd.sleep()
    time.sleep(30)

Running this code works pretty nice, but since I want to update the display every couple of minutes, I'm running into an OutOfMemory exception for the second run:

Traceback (most recent call last):
  File "<stdin>", line 283, in <module>
  File "urequests.py", line 20, in content
MemoryError: memory allocation failed, allocating 11520 bytes

The line throwing the exception is epd.buffer_black = response.content. From what I learned about MicroPython I could imagine that response.content is somehow kept in memory after the loop run, so I played around with del response or gc.collect(), but no luck.

The HTTP response content has always a size of 48000 bytes.

I also saw that urequests has the option to access the raw response content. From C# I'm familiar with stream APIs to copy bytes from one array to another. Is there a similar API for bytearray, e. g.:

i = 0
for chunk in response.iter_content(chunk_size=128):
    epd.buffer_black.write(chunk, i * 128)
    i++

So how can I work around this problem, e. g. by freeing memory or using a stream API?

mu88
  • 4,156
  • 1
  • 23
  • 47
  • 2
    You're holding a reference to the 'previous content' in epd.buffer_black while you are collecting the 'current content' - right up to the point at which the assignment to buffer_black is complete: i.e., you will have two lots of content in memory. Do you really need to have buffer_black always set? – Arfur Narf Jul 03 '23 at 17:08
  • Ah you mean I could set `epd.buffer_black` to `None` after `epd.display()`? – mu88 Jul 03 '23 at 17:10
  • 1
    You'll have to tell me! I don't know whether the ePaper thing needs to retain its buffer_black value after the display() call returns. Worth a try, though. (Edited) Oh, I see you did. – Arfur Narf Jul 03 '23 at 22:12

1 Answers1

1

I was able to solve it by resetting the epd.buffer_black after each iteration with an empty bytearray. This is my final code:

epd = EPD_7in5_B()
epd.Clear()
empty_buffer = bytearray(0)

while(True):
    response = urequests.get('http://<<myRaspiPicoW>>/screenshotCreator/latestImage?blackAndWhite=true&asWaveshareBytes=true')
    if response.status_code == 200:
        epd.buffer_black = response.content
        epd.display()
    else:
        print('Request failed')

    epd.sleep()
    epd.buffer_black = empty_buffer
    response = None
    time.sleep(30)

Kudos to @arfur-narf for pointing this out

mu88
  • 4,156
  • 1
  • 23
  • 47