Supported Targets | ESP32 |
---|
ESP32-MeshKit-Button 是基于 ESP-WIFI-MESH 的智能开关,包含配网、升级和设备联动等功能,它将帮助您更好地了解 ESP-WIFI-MESH 在超低功耗场景下的使用情况。ESP32-MeshKit-Button 仅作为子节点连入 ESP-WIFI-MESH,因此需要配合 ESP32-MeshKit-Light 使用。在运行本示例之前请先详细阅读 ESP32-MeshKit 指南。在编译本示例前请先阅读本文档的最后一部分:唤醒按键检测。
ESP32-MeshKit-Button 开发板硬件资源主要包括:
- 主控单元:ESP32 SoC
- 供电单元:Mini USB 供电口和外接电池供电口
- 调试单元:ESP-Prog 调试器接口
- 控制单元:4 个按键
- 显示单元:4 个 RGB LED
建立 ESP-WIFI-MESH 网络,您需要:
硬件 | 数量 |
---|---|
ESP32-MeshKit-Button 开发板 | 1 |
ESP32-MeshKit-Light | 至少 1 个 |
ESP-Prog 调试器(调试用,非必须) | 1 |
200 mAh 锂电池(可通过 Mini USB 供电,非必须) | 1 |
由于 ESP32-MeshKit-Button 不可作为根节点,需要配合使用 ESP32-MeshKit-Light 加入 ESP-WIFI-MESH 网络,请确保 Mesh 网络中至少有一个 ESP32-MeshKit-Light 设备。在使用 ESP32-MeshKit-Button 之前,先启动 ESP32-MeshKit-Light,并完成配网组网。
更多建立 ESP-WIFI-MESH 网络详情,请参照 ESP32-MeshKit 指南。
可以通过下面两种方式中的任意一种进行配网
将 ESP32-MeshKit-Button 靠近 ESP32-MeshKit-Light 后, 长按任意一个按键 5 秒, LED 绿色闪烁, 表明设备已经完成配网和设置完成默认的关联事件
注: 如果需要修改默认的关联事件,请连接 Mini USB 并使用 APP 进行修改
-
将 ESP32-MeshKit-Button 连接 Mini USB,LED 黄色闪烁,表明设备已进入配网状态。若设备需要重新配网,同时长按任意两个键 5 秒将重置设备;
-
根据 ESP-WIFI-MESH App 提示,点击
加入网络
将设备添加到 Mesh 网络; -
配网完成后,ESP32-MeshKit-Button 出现在已添加设备列表中,其 LED 将停止闪烁(由黄色闪烁变为黄色常亮),等待与 ESP32-MeshKit-Light 关联。
注:
- ESP32-MeshKit-Button 仅作为子节点,必须配合其他 ESP32-MeshKit 设备进行使用;
- ESP32-MeshKit-Button 需要通过添加设备的方法加入配网,不支持单独配网。
![]() 加入网络 |
![]() 配网成功 |
-
添加设备配⽹成功后,在 ESP-WIFI-MESH App 中打开已添加设备列表,长按 ESP32-MeshKit-Button 设备;
-
在弹出框中选择
自动化
,然后选择关联的方式及设备,点击右上角的√
; -
通过拖放的方式为每一个按键绑定关联的事件,点击右上角的
√
完成关联。设备端的 LED 将显示充电的状态(由黄色变成蓝色或蓝色闪烁)。
![]() 选择自动化 |
![]() 选择关联的方式 |
![]() 选择关联的设备 |
![]() 绑定关联的事件 |
请点击此处观看 ESP32-MeshKit-Button 演示视频。
-
ESP32-MeshKit-Button 若连接 Mini USB,当按键触发时处于 ESP-WIFI-MESH 模式。在此模式下,可以对设备进行配网、绑定、升级和控制。
-
ESP32-MeshKit-Button 若未连接 Mini USB 而使用电池供电时,设备处于 ESP-NOW 模式。在此模式下,ESP32 芯片会断开电源,仅在按下按键时重新启动,芯片发送完控制指令后立即断开电源。
指示灯颜色 | USB 接口 | 状态 |
---|---|---|
黄色(慢闪) | 已连接 | 进入配网模式,未组网 |
黄色(快闪) | 已连接 | 已配置,正在组网 |
黄色(常亮) | 已连接 | 已组网但未绑定 |
蓝色(闪烁) | 已连接 | 已组网且已绑定,正在充电 |
蓝色(常亮) | 已连接 | 已组网且已绑定,充电完成 |
红色(闪烁) | 已连接 | 已组网且已绑定,电量不足 |
熄灭 | 未连接 | 进入省电模式,按键可正常工作 |
绿色(按下任意按键) | 已连接/未连接 | 按键被触发,设备已配置 |
黄色(闪烁一次) | 已连接 | 按键被触发,设备未配置 |
从绿色变成黄色 | 未连接 | 按键被触发,设备已配置,但未绑定 |
从绿色变为黄色闪烁 | 已连接 | 按键被触发,设备未配置,且未绑定 |
ESP32-MeshKit-Button 上的按键有两种操作⽅式:短按和⻓按。
短按
功能 | 应用场景 |
---|---|
开/关 | 打开/关闭关联的 ESP32-MeshKit-Light。 |
亮度调节 | 随着短按次数增加,灯泡亮度数值依次递增。调节到最大数值后,短按即回到初始数值,依次往复。 |
色温调节 | 随着短按次数增加,灯泡色温数值依次递增。调节到最大数值后,短按即回到初始数值,依次往复。 |
色调调节 | 随着短按次数增加,灯泡色调不断变化,调节完所有色调后,短按即回到初始色调,依次往复。 |
明亮模式 | 灯泡进入明亮模式,发出明亮通透的白光 (H/S/V: 0/0/100)。 |
阅读模式 | 灯泡进入阅读模式,发出柔和、适合阅读的光 (H/S/V: 216/10/100)。 |
温馨模式 | 灯泡进入温馨模式,发出温馨、淡黄色光 (H/S/V: 60/10.2/100)。 |
就寝模式 | 灯泡进入就寝模式,发出色温较暖的黄色光 (H/S/V: 28/63/100)。 |
长按
功能 | 应用场景 |
---|---|
亮度 | 为一对按键绑定亮度事件,长按逐渐增加/降低亮度。 |
色温 | 为一对按键绑定色温事件,长按逐渐升高/降低色温。 |
色调 | 为一对按键绑定色调事件,长按实现前后色调的转换。 |
ESP32-MeshKit-Button 是针对超低功耗的按键方案,设备从断电到完成发包需要 1200 ms 左右的时间。下表列出了 ESP32-MeshKit-Button 在各个运行阶段的电流和时间,电流值为电源供电处 “DCVCC-SUFVCC” 的电流。
运行阶段 | 电流 | 时间 |
---|---|---|
ESP32 芯片断电 | 0.1 uA | 使用电池供电,按键未触发时长 |
唤醒后的启动过程 | 40 mA | 800 ms |
初始化及 ESP-NOW 发包控制 | 60 mA | 400 ms |
根据上述表格,单次按键触发耗电量为 56 mAs (40 mA x 800 ms + 60 mA x 400 ms = 56 mAs),且考虑到芯片断电时硬件电路也有耗电,因而 200 mAh 的电源可以支持约 10,000 次控制(200 mAh x 3600 / 56 mAs ≈ 12800 - 芯片断电时硬件电路耗电量)。
注:以下方面同样体现出功耗优势
- 数据传输:ESP32-MeshKit-Button 作为 ESP-WIFI-MESH 子节点设备,从启动到组网成功需要的时间大约为 500 ms 左右,因为设备在配置完成后,使用 ESP-NOW 进行数据传输,而 ESP-NOW 是基于数据链路层的无连接协议,所以省去设备连接的时间;
- 检测时间:在
bootloader
增加了按键检测,无需等待芯片完全启动;bootloader
启动时间:清除bootloader
日志,减少bootloader
的启动时间。
ESP32-MeshKit-Button 使用外接电池供电的情况下,由于 ESP32 芯片断电到唤醒后的启动过程需要 800 ms,如果在芯片完全启动后再检测按键触发,将无法获取短按的操作,因此需要在 bootloader
中加入按键检测。
您需要在 esp-idf/components/bootloader/subproject/main/bootloader_start.c
文件中加入下列检测代码,并在 call_start_cpu0()
函数中调用硬件初始化函数 bootloader_init()
之后用调用 button_bootloader_trigger()
。
#include "soc/gpio_periph.h"
void button_bootloader_trigger()
{
#define RTC_SLOW_MEM ((uint32_t*) (0x50000000)) /*!< RTC slow memory, 8k size */
#define BUTTON_GPIO_LED_BLUE (14)
#define BUTTON_GPIO_KEY0 (39)
#define BUTTON_GPIO_KEY1 (34)
#define BUTTON_GPIO_KEY2 (32)
#define BUTTON_GPIO_KEY3 (35)
#define BUTTON_KEY_NUM (4)
typedef struct {
uint32_t gpio_num;
uint32_t status;
bool push;
bool release;
int backup_tickcount;
} button_key_t;
bool key_press_flag = false;
button_key_t button_key[BUTTON_KEY_NUM] = {
{.gpio_num = BUTTON_GPIO_KEY0},
{.gpio_num = BUTTON_GPIO_KEY1},
{.gpio_num = BUTTON_GPIO_KEY2},
{.gpio_num = BUTTON_GPIO_KEY3},
};
for (int i = 0; i < BUTTON_KEY_NUM; ++i) {
gpio_pad_select_gpio(button_key[i].gpio_num);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[button_key[i].gpio_num]);
}
uint32_t tm_start = esp_log_early_timestamp();
do {
for (int i = 0; !key_press_flag && i < BUTTON_KEY_NUM; ++i) {
if (GPIO_INPUT_GET(button_key[i].gpio_num)) {
ets_delay_us(10 * 1000);
}
button_key[i].push = GPIO_INPUT_GET(button_key[i].gpio_num);
key_press_flag |= button_key[i].push;
ESP_LOGI(TAG, "gpio_num: %d, level: %d", button_key[i].gpio_num, button_key[i].push);
}
} while (!key_press_flag && 30 > (esp_log_early_timestamp() - tm_start));
if (key_press_flag) {
gpio_pad_select_gpio(BUTTON_GPIO_LED_BLUE);
GPIO_OUTPUT_SET(BUTTON_GPIO_LED_BLUE, 1);
ESP_LOGI(TAG, "There is a button pressed");
}
memcpy(RTC_SLOW_MEM, button_key, sizeof(button_key_t) * BUTTON_KEY_NUM);
}