[ESP32]:如何在micropython中添加C库

[ESP32]:如何在micropython中添加C库

本文将描述如何在micropython中添加一个基于c语言的led模块。

1.编写c驱动

选择一个目录:examples/usercmodule,建立对应的驱动文件hw_led

.
├── cexample
│   ├── examplemodule.c
│   ├── micropython.cmake
│   └── micropython.mk
├── cppexample
│   ├── example.cpp
│   ├── examplemodule.c
│   ├── examplemodule.h
│   ├── micropython.cmake
│   └── micropython.mk
├── hw_led
│   ├── hw_led.c
│   └── hw_led.cmake
├── micropython.cmake
└── subpackage
    ├── micropython.cmake
    ├── micropython.mk
    ├── modexamplepackage.c
    ├── qstrdefsexamplepackage.h
    └── README.md

照着usercmodule里面的micropython.cmake添加编译脚本:

add_library(hw_led INTERFACE)

target_sources(hw_led INTERFACE
    ${CMAKE_CURRENT_LIST_DIR}/hw_led.c
)

target_include_directories(hw_led INTERFACE
    ${CMAKE_CURRENT_LIST_DIR}
)
target_link_libraries(usermod INTERFACE hw_led)

编写led驱动程序,包括初始化,开关。

#include "py/runtime.h"
#include "py/mphal.h"
#include "driver/gpio.h"

static int gpio_num = -1;

void hw_led_init(int num)
{
    gpio_config_t io_conf = {
        .mode = GPIO_MODE_OUTPUT,
        .intr_type = GPIO_INTR_DISABLE,
        .pin_bit_mask = (1ULL << num),
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .pull_up_en = GPIO_PULLUP_DISABLE,
    };
    gpio_num = num;
    gpio_config(&io_conf);
}

void hw_led_on(void)
{
    gpio_set_level(gpio_num, 1);
}

void hw_led_off(void)
{
    gpio_set_level(gpio_num, 0);
}

static mp_obj_t led_init_func(mp_obj_t num)
{
    int num_int = mp_obj_get_int(num);
    hw_led_init(num_int);
    return mp_const_none;
}

static MP_DEFINE_CONST_FUN_OBJ_1(led_init_obj, led_init_func);

static mp_obj_t led_on_func(void)
{
    hw_led_on();
    return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_0(led_on_obj, led_on_func);

static mp_obj_t led_off_func(void)
{
    hw_led_off();
    return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_0(led_off_obj, led_off_func);


static const mp_rom_map_elem_t led_module_globals_table[] = {
    { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_led) },
    { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&led_init_obj) },
    { MP_ROM_QSTR(MP_QSTR_on)  , MP_ROM_PTR(&led_on_obj)   },
    { MP_ROM_QSTR(MP_QSTR_off) , MP_ROM_PTR(&led_off_obj)  },
};
static MP_DEFINE_CONST_DICT(led_module_globals, led_module_globals_table);


// Define module object.
const mp_obj_module_t led_module = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t *)&led_module_globals,
};

// Register the module to make it available in Python.
MP_REGISTER_MODULE(MP_QSTR_led, led_module);

有几个值得注意的地方:

  1. MP_DEFINE_CONST_FUN_OBJ_1:代表函数只有一个形参。如果是MP_DEFINE_CONST_FUN_OBJ_0,就代表没有形参。
  2. MP_QSTR_led:代表我们的模块名字叫led。

2.编译与烧录:

首先进入esp32的目录中:

/home/yanke/project/micropython/micropython/ports/esp32

编译代码:

➜  esp32 git:(master)make USER_C_MODULES=../../../examples/usercmodule/hw_led/hw_led.cmake

注意这里一定是三个…/。或者使用绝对路径,因为编译命令并不是在当前目录。

烧录代码:

 python -m esptool --chip esp32 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 4MB --flash_freq 40m 0x1000 build-ESP32_GENERIC/bootloader/bootloader.bin 0x8000 build-ESP32_GENERIC/partition_table/partition-table.bin 0x10000 build-ESP32_GENERIC/micropython.bin

这个编译指令会直接指定/dev/ttyUSB0

3.测试

在这里插入图片描述

<think>首先,用户的问题是:“我想在ESP32上使用MicroPython时,如何扩展或添加新的函数到MicroPython中”。这涉及到在MicroPython添加自定义函数或扩展。 根据系统指令: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 参考站内引用: - 引用[1]: 提到为MicroPython固件添加自定义模块。 - 引用[2]: 提到MicroPython支持加载存储在文件系统上的自定义模块。 - 引用[3]: 提到MicroPython自带了驱动函数,如DHT11的measure()函数。 用户的问题是如何在ESP32MicroPython环境中添加自定义函数或扩展。我需要基于这些引用构建回答。 关键点: - 添加自定义模块可以通过修改固件或使用文件系统加载模块。 - MicroPython支持内置模块和文件系统模块。 回答结构: 1. **理解需求**:解释添加自定义函数的两种主要方式。 2. **步骤**:提供逐步指导。 3. **示例**:给出一个简单的例子。 4. **注意事项**:讨论性能、限制等。 5. **相关问题**:生成相关问题。 生成相关问题: - 基于主题,生成2-3个相关问题。 使用引用: - 在回答中自然地添加引用标识,如[^1]。 完整回答: - 以中文回复。 - 确保LaTeX正确:如果有数学表达式,使用$...$或$$...$$。 用户问题中没有数学表达式,所以可能不需要LaTeX。但指令说所有行内数学表达式必须使用$...$,所以如果有的话,就用。 在回答中: - 可能没有数学,但如果有变量或代码,就正常处理。 最终回答结构: 1. 介绍:简要解释添加自定义函数的方法。 2. 方法一:通过文件系统添加模块(动态加载)。 3. 方法二:通过修改固件添加模块(静态)。 4. 示例:给出一个简单的代码示例。 5. 注意事项:如性能、兼容性等。 6. 相关问题:列出2-3个相关问题。</think>### 如何为ESP32MicroPython环境添加自定义函数或扩展ESP32上使用MicroPython时,添加自定义函数或扩展可以通过两种主要方式实现:**动态加载文件系统模块**和**静态修改固件**。这两种方法都基于MicroPython模块化设计,允许开发者根据需要扩展功能。下面我将逐步解释这两种方法,并提供示例和注意事项,确保回答真实可靠。参考引用内容,MicroPython支持通过文件系统加载自定义模块[^2],也支持通过固件修改添加内置模块[^1]。 #### 1. **理解添加自定义函数的基本原理** - MicroPython模块系统分为内置模块(编译时集成)和文件系统模块(运行时加载)。自定义函数可以通过创建新模块来实现。 - 关键点: - **文件系统模块**:适合快速开发和测试,将函数保存在.py文件中,然后通过`import`加载。优点是简单灵活,但性能可能受限(如执行速度较慢)[^2]。 - **固件修改**:将函数编译进MicroPython固件,成为内置模块。优点是性能高(直接访问硬件),但需要重新编译和烧录固件[^1]。 - 在ESP32上,文件系统通常使用`flash`或SD卡存储模块文件,而固件修改需基于MicroPython源代码。 #### 2. **方法一:通过文件系统动态加载自定义模块(推荐初学者)** 这是最简单的方法,无需修改固件。步骤如下: - **步骤1: 创建自定义函数文件** - 在ESP32的文件系统中(如通过串口工具或WebREPL上传),创建一个.py文件,例如`my_functions.py`。 - 在文件中定义您的自定义函数。例如,添加一个简单的温度转换函数: ```python # my_functions.py def celsius_to_fahrenheit(celsius): """将摄氏度转换为华氏度""" return (celsius * 9/5) + 32 # 使用行内数学表达式,例如转换公式: $F = \frac{9}{5}C + 32$ ``` - 这里,行内数学表达式如$F = \frac{9}{5}C + 32$用于说明公式逻辑。 - **步骤2: 上传文件到ESP32** - 使用工具如`ampy`、`rshell`或WebREPL将`my_functions.py`上传到ESP32的文件系统根目录(例如`/`或`/lib`)。 - 示例命令(使用ampy): ```bash ampy --port /dev/ttyUSB0 put my_functions.py ``` - **步骤3:MicroPython中导入和使用** - 连接到ESP32的REPL(如通过串口),导入模块并调用函数: ```python import my_functions temp_c = 25 temp_f = my_functions.celsius_to_fahrenheit(temp_c) print(f"25°C 等于 {temp_f}°F") # 输出: 25°C 等于 77.0°F ``` - **优点**:快速迭代,无需重新烧录固件;适合小型项目或测试[^2]。 - **缺点**:函数执行速度慢于内置模块,且文件系统操作可能增加内存开销。 #### 3. **方法二:通过修改固件静态添加内置模块(适合高级用户)** 如果您需要高性能或直接硬件访问(如操作GPIO),可以将函数编译进MicroPython固件。参考引用[^1],这涉及修改源代码并重新编译。 - **步骤1: 获取MicroPython源代码** - 克隆MicroPythonESP32端口仓: ```bash git clone https://github.com/micropython/micropython.git cd micropython/ports/esp32 ``` - 确保安装依赖工具(如ESP-IDF)。 - **步骤2: 添加自定义模块代码** - 在`modules`目录下创建新文件,例如`mymodule.c`,定义函数和模块结构。示例代码: ```c #include "py/runtime.h" // 定义自定义函数 STATIC mp_obj_t my_add(mp_obj_t a_obj, mp_obj_t b_obj) { mp_int_t a = mp_obj_get_int(a_obj); mp_int_t b = mp_obj_get_int(b_obj); return mp_obj_new_int(a + b); // 简单加法函数,例如数学表达式: $a + b$ } STATIC MP_DEFINE_CONST_FUN_OBJ_2(my_add_obj, my_add); // 定义模块方法表 STATIC const mp_rom_map_elem_t mymodule_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&my_add_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mymodule_globals, mymodule_globals_table); // 定义模块对象 const mp_obj_module_t mymodule_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mymodule_globals, }; MP_REGISTER_MODULE(MP_QSTR_mymodule, mymodule_module); ``` - **步骤3: 修改编译配置** - 在`ports/esp32/boards`中选择您的ESP32板型(如`GENERIC`),编辑`mpconfigboard.mk`文件,添加模块: ```makefile USER_C_MODULES = $(BUILD)/../../modules ``` - 确保在`main.c`中注册模块MicroPython会自动处理)。 - **步骤4: 编译和烧录固件** - 编译固件: ```bash make clean make BOARD=GENERIC ``` - 烧录到ESP32(使用esptool): ```bash esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash 0x1000 build-GENERIC/firmware.bin ``` - **步骤5:MicroPython中使用内置模块** - 重启ESP32,在REPL中直接导入: ```python import mymodule result = mymodule.add(3, 5) print(result) # 输出: 8 ``` - **优点**:性能高,适合资源敏感操作(如传感器驱动)[^3]。 - **缺点**:过程复杂,需要C语言技能;每次修改需重新编译。 #### 4. **注意事项和最佳实践** - **性能考虑**:MicroPythonESP32上资源有限(内存和CPU)。文件系统模块适合简单函数,但复杂逻辑(如实时数据处理)应优先用固件方法[^1][^3]。 - **兼容性**:确保自定义函数与MicroPython版本兼容。ESP32的常见问题包括内存溢出,建议使用`gc.collect()`管理内存。 - **调试技巧**:使用`print()`调试文件系统模块;固件模块可通过JTAG调试。 - **引用示例**:如引用[^3]所示,MicroPython已封装了类似DHT11的驱动函数(`dht.measure()`),您可以参考其设计模式封装自己的函数。 - **安全提示**:修改固件时备份原固件;避免在关键应用中使用未测试模块。 #### 5. **相关问题** 为了深入理解MicroPython的扩展机制,以下是几个相关问题: 1. 在ESP32上,如何优化MicroPython自定义模块的性能以减少内存使用? 2. MicroPython固件编译过程中常见错误有哪些?如何解决? 3. 如何将自定义MicroPython模块打包为,以便在多个项目中复用? 通过上述方法,您可以灵活地为ESP32MicroPython环境添加自定义功能。如果您有具体函数需求(如硬件驱动),我可以提供更针对性的代码示例! [^1]: 在使用MicroPython的过程中,我们可以通过import导入各种各样的,非常的方便。但有的时候我们想要使用的功能在这些中找不到,又或者是某些功能因MicroPython的性能受限,这个时候就需要为MicroPython固件添加自定义模块了。 [^2]: esp32c3开发micropython环境下的函数和。此外,"Plus any modules on the filesystem" 意味着除了内置模块外,MicroPython还支持加载存储在文件系统上的自定义模块。这使得开发者可以根据需要扩展MicroPython的功能。 [^3]: 基于ESP32+MicroPython+阿里云平台+微信小程序的课设项目。对于MicroPython来说,使用该模块来检测环境的温湿度相较于c语言来说变得异常简单,因为它自带了DHT11的驱动函数,并且封装好了只需要调用即可。上述代码dht中就包含了DHT11的测量函数measure(),只需对其引用使用一个变量来存储函数的和返回值便可得到对应的温湿度信息,最后将其封装成一个函数,供其它工程进行调用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值