【雕爷学编程】MicroPython手册之 ESP32 特定端口库 esp32.idf_heap_info(capabilities)

在这里插入图片描述

MicroPython是为了在嵌入式系统中运行Python 3编程语言而设计的轻量级版本解释器。与常规Python相比,MicroPython解释器体积小(仅100KB左右),通过编译成二进制Executable文件运行,执行效率较高。它使用了轻量级的垃圾回收机制并移除了大部分Python标准库,以适应资源限制的微控制器。

MicroPython主要特点包括:
1、语法和功能与标准Python兼容,易学易用。支持Python大多数核心语法。
2、对硬件直接访问和控制,像Arduino一样控制GPIO、I2C、SPI等。
3、强大的模块系统,提供文件系统、网络、图形界面等功能。
4、支持交叉编译生成高效的原生代码,速度比解释器快10-100倍。
5、代码量少,内存占用小,适合运行在MCU和内存小的开发板上。
6、开源许可,免费使用。Shell交互环境为开发测试提供便利。
7、内置I/O驱动支持大量微控制器平台,如ESP8266、ESP32、STM32、micro:bit、掌控板和PyBoard等。有活跃的社区。

MicroPython的应用场景包括:
1、为嵌入式产品快速构建原型和用户交互。
2、制作一些小型的可 programmable 硬件项目。
3、作为教育工具,帮助初学者学习Python和物联网编程。
4、构建智能设备固件,实现高级控制和云连接。
5、各种微控制器应用如物联网、嵌入式智能、机器人等。

使用MicroPython需要注意:
1、内存和Flash空间有限。
2、解释执行效率不如C语言。
3、部分库函数与标准版有差异。
4、针对平台优化语法,订正与标准Python的差异。
5、合理使用内存资源,避免频繁分配大内存块。
6、利用原生代码提升速度关键部位的性能。
7、适当使用抽象来封装底层硬件操作。

总体来说,MicroPython让Python进入了微控制器领域,是一项重要的创新,既降低了编程门槛,又提供了良好的硬件控制能力。非常适合各类物联网和智能硬件的开发。
在这里插入图片描述

MicroPython的esp是指针对ESP8266和ESP32芯片的MicroPython固件和相关软件库。ESP8266和ESP32是一类广泛应用于物联网和嵌入式系统的低成本、低功耗的Wi-Fi和蓝牙模块。MicroPython的esp为这两种芯片提供了高级的脚本编程环境,使开发者能够使用Python语言进行快速原型设计和开发。

ESP8266:是一款低成本、低功耗的Wi-Fi模块/芯片,由Espressif Systems开发。它内置了TCP/IP协议栈,可以用于连接互联网,并具备较强的处理能力。MicroPython的esp提供了针对ESP8266的固件和相关软件库,使开发者可以使用MicroPython语言进行ESP8266应用的开发。

ESP32:是Espressif Systems推出的一款高度集成的Wi-Fi和蓝牙模块/芯片,与ESP8266相比,它具备更强大的处理能力、更多的外设接口和更多的内存。MicroPython的esp也提供了针对ESP32的固件和相关软件库,使开发者可以使用MicroPython语言进行ESP32应用的开发。

MicroPython的esp固件:是专门针对ESP8266和ESP32芯片的MicroPython固件版本。这些固件经过了针对性的优化,使得它们可以在ESP8266和ESP32上运行,并提供了与硬件交互、网络通信和外设控制等功能的API。

软件库:MicroPython的esp还提供了一系列与ESP8266和ESP32硬件相关的软件库,用于简化和加速开发过程。这些软件库提供了丰富的功能接口,涵盖了Wi-Fi、蓝牙、GPIO(通用输入输出)、I2C、SPI、PWM等常用的硬件和通信协议,使开发者可以方便地访问和控制硬件资源。
在这里插入图片描述

MicroPython 的 esp32.idf_heap_info(capabilities) 是一个用于查询 ESP-IDF 堆内存区域的信息的函数。该函数返回一个列表,每个元素是一个四元组,表示一个堆的总字节数、空闲字节数、最大空闲块和最小空闲值。该函数需要一个参数 capabilities,表示要查询的堆的能力。

MicroPython 的 esp32.idf_heap_info(capabilities) 的主要特点有:

可以实现 ESP32 查询不同类型的堆内存区域的使用情况,从而监控内存的分配和释放。
可以根据不同的应用场景,选择合适的堆能力,例如 MALLOC_CAP_8BIT 表示可以单字节访问的内存,MALLOC_CAP_EXEC 表示可以执行代码的内存等。
可以与其他模块或功能结合使用,实现多种内存相关的应用。

MicroPython 的 esp32.idf_heap_info(capabilities) 的应用场景有:

案例1:内存显示:利用 ESP32 开发板、OLED 显示屏等组件,利用 MicroPython 的 esp32.idf_heap_info(capabilities) 函数来实现一个内存显示,可以在 OLED 显示屏上显示 ESP-IDF 堆内存区域的总大小、空闲大小和使用率,并根据用户的选择来切换不同的堆能力。以下是部分代码示例::

# 导入 esp32 模块
import esp32
# 导入 OLED 模块
import ssd1306
# 导入按键模块
from machine import Pin

# 定义 OLED 引脚号和尺寸
OLED_SCL_PIN = 22
OLED_SDA_PIN = 21
OLED_WIDTH = 128
OLED_HEIGHT = 64

# 定义按键引脚号和状态
KEY_PIN = 4
KEY_ON = 0
KEY_OFF = 1

# 创建 OLED 对象并初始化
oled = ssd1306.SSD1306_I2C(OLED_WIDTH, OLED_HEIGHT, machine.I2C(scl=machine.Pin(OLED_SCL_PIN), sda=machine.Pin(OLED_SDA_PIN)))
oled.fill(0)
oled.text("Memory Display", 0 ,0)
oled.show()

# 创建按键对象并初始化,设置为上拉输入模式,并注册中断回调函数,触发方式为下降沿(按下)
key = Pin(KEY_PIN, Pin.IN, Pin.PULL_UP)
key.irq(lambda pin: change_cap(), trigger=Pin.IRQ_FALLING)

# 定义一个全局变量,用于存储当前的堆能力,初始值为 MALLOC_CAP_8BIT
cap = esp32.MALLOC_CAP_8BIT

# 定义一个函数,用于查询 ESP-IDF 堆内存区域的信息,并转换为总大小、空闲大小和使用率
def read_mem():
    global cap
    # 调用 esp32.idf_heap_info(cap) 函数,获取堆信息列表
    info_list = esp32.idf_heap_info(cap)
    # 初始化总大小、空闲大小和使用率为零
    total_size = 0
    free_size = 0
    usage_rate = 0
    # 遍历堆信息列表,累加每个堆的总大小和空闲大小
    for info in info_list:
        total_size += info[0]
        free_size += info[1]
    # 如果总大小不为零,则计算使用率(百分比)
    if total_size != 0:
        usage_rate = (total_size - free_size) * 100 / total_size
    # 返回总大小、空闲大小和使用率字符串
    return "{:.2f} KB".format(total_size / 1024), "{:.2f} KB".format(free_size / 1024), "{:.2f} %".format(usage_rate)

# 定义一个函数,用于在 OLED 上显示 ESP-IDF 堆内存区域的信息,并根据用户的选择来切换不同的堆能力
def show_mem():
    # 调用 read_mem 函数,获取总大小、空闲大小和使用率字符串
    total_str, free_str, usage_str = read_mem()
    # 在 OLED 上显示内存信息
    oled.fill(0)
    oled.text("Memory Display", 0 ,0)
    oled.text("Total: " + total_str, 0 ,16)
    oled.text("Free: " + free_str, 0 ,32)
    oled.text("Usage: " + usage_str, 0 ,48)
    oled.show()

# 定义一个函数,用于切换堆能力,并重新显示内存信息
def change_cap():
    global cap
    # 根据当前的堆能力,切换到下一个堆能力(8BIT -> EXEC -> DEFAULT -> 8BIT)
    if cap == esp32.MALLOC_CAP_8BIT:
        cap = esp32.MALLOC_CAP_EXEC
    elif cap == esp32.MALLOC_CAP_EXEC:
        cap = esp32.MALLOC_CAP_DEFAULT
    elif cap == esp32.MALLOC_CAP_DEFAULT:
        cap = esp32.MALLOC_CAP_8BIT
    else:
        return
    # 调用 show_mem 函数,重新显示内存信息
    show_mem()

# 定义一个循环,用于调用 show_mem 函数,并延迟一秒钟
while True:
    show_mem()
    time.sleep(1)

案例2:内存优化:利用 ESP32 开发板、网络模块等组件,利用 MicroPython 的 esp32.idf_heap_info(capabilities) 函数来实现一个内存优化,可以根据 ESP-IDF 堆内存区域的使用情况,动态调整网络缓冲区的大小,从而提高网络性能。以下是部分代码示例::

# 导入 esp32 模块
import esp32
# 导入网络模块
import network

# 定义网络缓冲区的最小值和最大值(单位为字节)
MIN_BUFFER_SIZE = 1024
MAX_BUFFER_SIZE = 16384

# 创建 WLAN 对象并初始化,设置为 STA 模式,并连接到指定的 SSID 和密码
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("SSID", "PASSWORD")

# 定义一个函数,用于根据 ESP-IDF 堆内存区域的使用情况,动态调整网络缓冲区的大小
def buffer_optimize():
    # 调用 esp32.idf_heap_info(esp32.MALLOC_CAP_8BIT) 函数,获取可以单字节访问的堆信息列表
    info_list = esp32.idf_heap_info(esp32.MALLOC_CAP_8BIT)
    # 初始化空闲大小和最大空闲块为零
    free_size = 0
    max_free_block = 0
    # 遍历堆信息列表,累加每个堆的空闲大小,并找出最大空闲块
    for info in info_list:
        free_size += info[1]
        if info[2] > max_free_block:
            max_free_block = info[2]
    # 如果空闲大小小于最小缓冲区大小,则表示内存不足,无法调整缓冲区大小,返回 False
    if free_size < MIN_BUFFER_SIZE:
        return False
    # 如果最大空闲块大于最大缓冲区大小,则表示内存充足,可以将缓冲区大小设置为最大值,返回 True
    if max_free_block > MAX_BUFFER_SIZE:
        wlan.set_buffer_size(MAX_BUFFER_SIZE)
        return True
    # 否则,表示内存有限,可以将缓冲区大小设置为最大空闲块的一半,返回 True
    else:
        wlan.set_buffer_size(max_free_block // 2)
        return True

# 定义一个循环,用于每隔一分钟调用 buffer_optimize 函数,并打印结果
while True:
    result = buffer_optimize()
    if result:
        print("Buffer size optimized.")
    else:
        print("Buffer size cannot be optimized.")
    time.sleep(60)

案例3:实现内存释放的功能

# 导入 esp32 模块
import esp32
# 导入 gc 模块
import gc

# 定义内存释放的阈值(单位为字节)
FREE_THRESHOLD = 10240

# 定义一个函数,用于检测 ESP-IDF 堆内存区域的空闲大小,并根据阈值决定是否执行垃圾回收
def memory_release():
    # 调用 esp32.idf_heap_info(esp32.MALLOC_CAP_8BIT) 函数,获取可以单字节访问的堆信息列表
    info_list = esp32.idf_heap_info(esp32.MALLOC_CAP_8BIT)
    # 初始化空闲大小为零
    free_size = 0
    # 遍历堆信息列表,累加每个堆的空闲大小
    for info in info_list:
        free_size += info[1]
    # 如果空闲大小小于阈值,则表示内存不足,执行垃圾回收
    if free_size < FREE_THRESHOLD:
        gc.collect()
        print("Memory released.")

# 定义一个循环,用于每隔一分钟调用 memory_release 函数,并打印结果
while True:
    memory_release()
    time.sleep(60)

案例4:打印堆内存信息

import esp32

info = esp32.idf_heap_info()
print(info)

直接打印出ESP-IDF 堆内存的总容量和可用内存等信息。

案例5:检测内存泄:

import esp32, gc

last_free = esp32.idf_heap_info()['available'] 
gc.collect()
used = last_free - esp32.idf_heap_info()['available']

if used > 1000:
  print('Memory leak detected!')

通过对比两次获取的 free heap,可以检测是否存在内存泄漏。

案例6:动态内存分配

import esp32

heap_info = esp32.idf_heap_info() 
if heap_info['available'] > 50000:
  alloc_large_buffer()
else:
  print('Memory too low!')

根据当前可用堆内存的大小,决定是否执行大内存分配。这些例子展示了esp32.idf_heap_info()提供的堆内存信息可以用于调试、检测内存泄漏和动态内存管理。

案例7:打印ESP32的总堆内存信息:

import esp32

heap_info = esp32.idf_heap_info(esp32.IDF_HEAP_INFO_ALL)
print("Total heap size: {} bytes".format(heap_info["total_bytes"]))
print("Free heap size: {} bytes".format(heap_info["free_bytes"]))
print("Largest free block: {} bytes".format(heap_info["largest_free_block"]))

在这个示例中,我们使用esp32.idf_heap_info()函数来获取ESP32的堆内存信息。通过传递esp32.IDF_HEAP_INFO_ALL作为参数,我们获取所有可用的堆内存信息。然后,我们打印输出总堆大小、可用堆大小和最大空闲块的大小。

案例8:检查ESP32的堆内存使用情况:

import esp32

heap_info = esp32.idf_heap_info(esp32.IDF_HEAP_INFO_INTERNAL)
free_bytes = heap_info["free_bytes"]

if free_bytes < 1024:
    print("Low memory warning!")
else:
    print("Memory is sufficient.")

在这个示例中,我们使用esp32.idf_heap_info()函数获取ESP32的内部堆内存信息。我们只关注可用堆内存的大小,并将其存储在free_bytes变量中。然后,我们进行一个简单的判断,如果可用堆内存小于1024字节(1KB),则打印输出低内存警告,否则打印输出内存充足的信息。

案例9:优化内存使用:

import esp32

# 执行一些内存密集型操作...

heap_info_before = esp32.idf_heap_info(esp32.IDF_HEAP_INFO_INTERNAL)
# 执行一些内存密集型操作...

heap_info_after = esp32.idf_heap_info(esp32.IDF_HEAP_INFO_INTERNAL)
memory_saved = heap_info_before["free_bytes"] - heap_info_after["free_bytes"]
print("Memory saved: {} bytes".format(memory_saved))

在这个示例中,我们使用esp32.idf_heap_info()函数来比较内存操作前后的堆内存信息,以计算内存节省量。首先,我们获取内存操作前的内部堆内存信息,并存储在heap_info_before变量中。然后,我们执行一些内存密集型操作。接着,我们获取内存操作后的内部堆内存信息,并存储在heap_info_after变量中。通过比较两次堆内存信息中的可用堆内存大小,我们计算出节省的内存量,并打印输出。

这些示例展示了esp32.idf_heap_info(capabilities)函数的实际应用。它可以帮助您了解ESP32的堆内存使用情况,并根据需要进行内存管理和优化操作。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41659040/article/details/132918623