[Diao Ye Learns Programming] MicroPython Manual ESP32 Specific Port Library esp32.idf_heap_info(capabilities)

Insert image description here

MicroPython is a lightweight version of the interpreter designed for running the Python 3 programming language in embedded systems. Compared with regular Python, the MicroPython interpreter is small (only about 100KB) and is compiled into a binary Executable file to run, resulting in higher execution efficiency. It uses a lightweight garbage collection mechanism and removes most of the Python standard library to accommodate resource-constrained microcontrollers.

The main features of MicroPython include:
1. The syntax and functions are compatible with standard Python, making it easy to learn and use. Supports most core syntax of Python.
2. Directly access and control hardware, control GPIO, I2C, SPI, etc. like Arduino.
3. Powerful module system, providing file system, network, graphical interface and other functions.
4. Support cross-compilation to generate efficient native code, which is 10-100 times faster than the interpreter.
5. The amount of code is small and the memory usage is small. It is suitable for running on MCU and development boards with small memory.
6. Open source license, free to use. The Shell interactive environment provides convenience for development and testing.
7. The built-in I/O driver supports a large number of microcontroller platforms, such as ESP8266, ESP32, STM32, micro:bit, control board and PyBoard, etc. There is an active community.

MicroPython application scenarios include:
1. Rapidly build prototypes and user interactions for embedded products.
2. Make some small programmable hardware projects.
3. As an educational tool, it helps beginners learn Python and IoT programming.
4. Build smart device firmware to achieve advanced control and cloud connectivity.
5. Various microcontroller applications such as Internet of Things, embedded intelligence, robots, etc.

Things to note when using MicroPython:
1. Memory and Flash space are limited.
2. The explanation and execution efficiency is not as good as C language.
3. Some library functions are different from the standard version.
4. Optimize the syntax for the platform and correct the differences with standard Python.
5. Use memory resources rationally and avoid frequently allocating large memory blocks.
6. Use native code to improve the performance of speed-critical parts.
7. Use abstraction appropriately to encapsulate underlying hardware operations.

Generally speaking, MicroPython brings Python into the field of microcontrollers, which is an important innovation that not only lowers the programming threshold but also provides good hardware control capabilities. It is very suitable for the development of various types of Internet of Things and intelligent hardware.
Insert image description here

MicroPython's esp refers to the MicroPython firmware and related software libraries for ESP8266 and ESP32 chips. ESP8266 and ESP32 are a class of low-cost, low-power Wi-Fi and Bluetooth modules widely used in IoT and embedded systems. MicroPython's esp provides an advanced scripting environment for both chips, allowing developers to use the Python language for rapid prototyping and development.

ESP8266: It is a low-cost, low-power Wi-Fi module/chip developed by Espressif Systems. It has a built-in TCP/IP protocol stack, can be used to connect to the Internet, and has strong processing capabilities. MicroPython's esp provides firmware and related software libraries for ESP8266, allowing developers to use MicroPython language to develop ESP8266 applications.

ESP32: It is a highly integrated Wi-Fi and Bluetooth module/chip launched by Espressif Systems. Compared with ESP8266, it has more powerful processing power, more peripheral interfaces and more memory. MicroPython's esp also provides firmware and related software libraries for ESP32, allowing developers to use MicroPython language to develop ESP32 applications.

MicroPython's esp firmware: It is a MicroPython firmware version specifically for ESP8266 and ESP32 chips. These firmwares have been specifically optimized to run on ESP8266 and ESP32, and provide APIs for hardware interaction, network communication, and peripheral control.

Software libraries: MicroPython's esp also provides a series of software libraries related to ESP8266 and ESP32 hardware to simplify and accelerate the development process. These software libraries provide a rich set of functional interfaces, covering commonly used hardware and communication protocols such as Wi-Fi, Bluetooth, GPIO (General Purpose Input and Output), I2C, SPI, and PWM, allowing developers to easily access and control hardware resources.
Insert image description here

MicroPython's esp32.idf_heap_info(capabilities) is a function used to query the information of the ESP-IDF heap memory area. This function returns a list, each element is a four-tuple representing the total number of bytes, the number of free bytes, the maximum free block, and the minimum free value of a heap. This function requires a parameter capabilities, indicating the capabilities of the heap to be queried.

The main features of MicroPython's esp32.idf_heap_info(capabilities) are:

ESP32 can be implemented to query the usage of different types of heap memory areas to monitor memory allocation and release.
You can choose the appropriate heap capability according to different application scenarios. For example, MALLOC_CAP_8BIT represents memory that can be accessed by a single byte, MALLOC_CAP_EXEC represents memory that can execute code, etc.
Can be used in combination with other modules or functions to implement a variety of memory-related applications.

The application scenarios of MicroPython's esp32.idf_heap_info(capabilities) are:

Case 1: Memory display: Use ESP32 development board, OLED display and other components, and use MicroPython's esp32.idf_heap_info(capabilities) function to implement a memory display. The total size of the ESP-IDF heap memory area can be displayed on the OLED display. Free size and usage, and switch different heap capabilities according to user choice. Here are some code examples::

# 导入 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)

Case 2: Memory optimization: Use ESP32 development board, network module and other components, and use MicroPython's esp32.idf_heap_info(capabilities) function to implement a memory optimization. The network buffer can be dynamically adjusted according to the usage of the ESP-IDF heap memory area. size, thereby improving network performance. Here are some code examples::

# 导入 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)

Case 3: Implementing the function of memory release

# 导入 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)

Case 4: Print heap memory information

import esp32

info = esp32.idf_heap_info()
print(info)

Directly print out information such as the total capacity and available memory of the ESP-IDF heap memory.

Case 5: Detecting memory leaks:

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!')

By comparing the free heap obtained twice, you can detect whether there is a memory leak.

Case 6: Dynamic memory allocation

import esp32

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

Depending on the size of the currently available heap memory, decide whether to perform large memory allocation. These examples demonstrate that the heap memory information provided by esp32.idf_heap_info() can be used for debugging, detecting memory leaks, and dynamic memory management.

Case 7: Print the total heap memory information of 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"]))

In this example, we use esp32.idf_heap_info()a function to get the heap memory information of the ESP32. By passing esp32.IDF_HEAP_INFO_ALLas parameter we get all available heap memory information. We then print out the total heap size, free heap size, and the size of the largest free block.

Case 8: Check the heap memory usage of 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.")

In this example, we use esp32.idf_heap_info()a function to get the ESP32’s internal heap memory information. We only focus on the size of the available heap memory and store it in free_bytesa variable. Then, we make a simple judgment. If the available heap memory is less than 1024 bytes (1KB), a low memory warning will be printed, otherwise a message indicating that there is sufficient memory will be printed.

Case 9: Optimize memory usage:

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))

In this example, we use esp32.idf_heap_info()a function to compare heap memory information before and after a memory operation to calculate memory savings. First, we obtain the internal heap memory information before the memory operation and store it in heap_info_beforea variable. Then we perform some memory intensive operations. Next, we obtain the internal heap memory information after the memory operation and store it in heap_info_aftera variable. By comparing the available heap memory size in the two heap memory information, we calculate the amount of memory saved and print it out.

These examples show the esp32.idf_heap_info(capabilities) function in action. It can help you understand the heap memory usage of your ESP32 and perform memory management and optimization operations as needed.

Insert image description here

Guess you like

Origin blog.csdn.net/weixin_41659040/article/details/132918623