MicroPython在树莓派Pico循环更新电子纸时出现内存不足问题
Raspberry Pi Pico MicroPython 电子纸显示屏内存溢出问题解决
问题场景
在Raspberry Pi Pico上使用MicroPython,通过HTTP API拉取BLOB数据并显示在Waveshare 7.5寸B型电子纸显示屏。首次运行正常,但循环更新时第二次触发内存溢出错误。
原代码:
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)
错误信息
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
无效尝试
- 使用
del response删除响应对象 - 调用
gc.collect()强制垃圾回收
解决方案
方案1:使用流API逐块写入(推荐)
核心思路是避免一次性加载整个响应到内存,而是逐块读取并写入预分配的电子纸缓冲区,降低内存峰值占用。
修改后代码:
import gc import time import urequests from waveshare_epd import EPD_7in5_B # 请根据实际导入路径调整 epd = EPD_7in5_B() epd.Clear() # 预分配固定大小的缓冲区(7.5寸B型电子纸的黑色缓冲区大小为11520字节) BUFFER_SIZE = 11520 epd.buffer_black = bytearray(BUFFER_SIZE) while True: response = urequests.get('http://<<myRaspiPicoW>>/screenshotCreator/latestImage?blackAndWhite=true&asWaveshareBytes=true') if response.status_code == 200: offset = 0 # 逐块读取响应内容,写入缓冲区 while True: chunk = response.raw.read(128) # 每次读取128字节 if not chunk: break chunk_len = len(chunk) # 通过切片赋值将chunk写入缓冲区对应位置 epd.buffer_black[offset:offset+chunk_len] = chunk offset += chunk_len epd.display() else: print('Request failed') # 显式关闭响应,释放底层连接资源 response.close() # 删除引用并强制垃圾回收 del response gc.collect() epd.sleep() time.sleep(30)
方案2:优化内存回收逻辑
如果无法使用流API,可通过主动清空缓冲区引用+强制GC确保内存释放:
import gc import time import urequests from waveshare_epd import EPD_7in5_B 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 = None gc.collect() # 再赋值新内容 epd.buffer_black = response.content epd.display() else: print('Request failed') response.close() del response gc.collect() epd.sleep() time.sleep(30)
关键说明
- 预分配缓冲区:方案1中提前创建固定大小的
bytearray,避免每次赋值新的bytes对象产生内存碎片。 - 流读取:
response.raw.read()直接读取HTTP响应流,无需将整个BLOB加载到内存,大幅降低内存占用。 - 显式资源释放:必须调用
response.close()关闭HTTP连接,否则底层套接字资源会持续占用内存,导致GC无法回收。
内容的提问来源于stack exchange,提问作者mu88
相关产品推荐
相关产品推荐

