You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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. 预分配缓冲区:方案1中提前创建固定大小的bytearray,避免每次赋值新的bytes对象产生内存碎片。
  2. 流读取:response.raw.read()直接读取HTTP响应流,无需将整个BLOB加载到内存,大幅降低内存占用。
  3. 显式资源释放:必须调用response.close()关闭HTTP连接,否则底层套接字资源会持续占用内存,导致GC无法回收。

内容的提问来源于stack exchange,提问作者mu88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 01:57:42