ESP32使用按键配网并通过LED指示网络状态

本文介绍了如何在ESP32上通过按键实现长按配网,并通过LED灯显示网络状态。通过添加新文件和修改CMakeList,实现了按键清除配网信息和LED灯的不同状态指示网络连接情况。使用了esp-iot-solution库的button模块检测按键长按,并使用系统定时器控制LED灯的闪烁。当长按按键3秒后,设备会清除配网信息并重启进入等待配网状态,联网过程中LED快闪,连接成功后常亮。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

上面我们已经可以通过 ESPTOUCH 和 Airkiss 给模块配网,并且存储在 nvs 中,重启后仍然可以联网,只是这样仍然不能满足我们实际的应用,这次我们增加按键作为输入,LED作为输出,实现长按按键配网,并可以通过LED指示网络状态。

添加自己的组件

为了让程序结构更加清晰,所以我们在smart_config例程的基础上做了修改,在main文件夹里新建了main.c 、smartconfig_button.c , smartconfig_led.c ,将原来的smartconfig_main.c改为smartconfig_wifi.c,及其对应的.h文件

增加自己的组件
增加文件后,然后将 CMakeList.txt 文件修改为:

idf_component_register(SRCS “iot_button.c” “smartconfig_wifi.c” “smartconfig_button.c” “smartconfig_led.c” “main.c”
INCLUDE_DIRS “.”)

增加按键清除配网信息的功能

这里我们使用了乐鑫官方有个仓库叫做esp-iot-solution,里面有很多常用外设的驱动和物联网场景的实现代码。其中就有一个button模块来实现按键的长按、短按检测,我们将 botton 模块里的 iot_button.c 和 iot_button.h 文件添加到main文件夹中。
然后实现通过 smartconfig_button.c 文件实现长按清除网络信息的功能,具体如下:

//--------------- smartconfig_button.c ---------------//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "iot_button.h"
#include "smartconfig_button.h"
#include "smartconfig_wifi.h"

#define BUTTON_IO_NUM           0   //GPIO0
#define BUTTON_ACTIVE_LEVEL     0   //信号有效电平:低电平

static const char* TAG_BTN = "SMARTCONFIG_BUTTON";

void button_tap_cb(void* arg)
{
    char* pstr = (char*) arg;
    pstr = pstr;
    ESP_LOGI(TAG_BTN, "key tap \n");
}

void button_press_3s_cb(void* arg)
{
    char* pstr = (char*) arg;
    pstr = pstr;
    ESP_LOGI(TAG_BTN,"key 3s long press\n");                    //按键长按,清除配网信息并重启                  
    nvs_handle_t wificonfig_set_handle;
    ESP_ERROR_CHECK( nvs_open("wificonfig",NVS_READWRITE,&wificonfig_set_handle) );
    ESP_ERROR_CHECK( nvs_set_u8(wificonfig_set_handle,"WifiConfigFlag", wifi_unconfiged) );
    ESP_ERROR_CHECK( nvs_commit(wificonfig_set_handle) );
    nvs_close(wificonfig_set_handle);

    ESP_LOGI(TAG_BTN,"Set Restart now.\n");
    esp_restart();
}

void smartconfig_button_init(void)
{
    //配置配网按键
    button_handle_t btn_handle = iot_button_create(BUTTON_IO_NUM, BUTTON_ACTIVE_LEVEL);
    //注册单击事件
    iot_button_set_evt_cb(btn_handle, BUTTON_CB_TAP, button_tap_cb, "TAP");
    //注册 3s 长按事件
    iot_button_add_custom_cb(btn_handle, 3, button_press_3s_cb, NULL);

}

加入配网指示灯

灯的不同状态代表不同的配网状态,设定:慢闪代表未联网,快闪代表正在联网,长亮代表网络已连接。这里会用到ESP32的系统定时器,使用方法也比较简单,创建定时器,开启或者关闭定时器,源码如下:

//--------------- smartconfig_led.c ---------------//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "driver/gpio.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "smartconfig_led.h"
 
#define WIFI_STATUS_LED_GPIO  15

static const char* TAG = "WIFI_STATUS_LED";
static esp_timer_handle_t  smartconfig_led_soft_timer;
 
//定时器回调里实现灯的闪烁
static void periodled_timer_callback(void* arg)
{
    static uint8_t s_LEDToggle  = 0;
    s_LEDToggle = ~s_LEDToggle;

    if(s_LEDToggle)
    {
        gpio_set_level(WIFI_STATUS_LED_GPIO, 1);
    }       
    else
    {
        gpio_set_level(WIFI_STATUS_LED_GPIO, 0);
    }   
}
 
static void handle_smartconfig_led_status(Wifi_Status_t WifiState)
{
    static uint8_t s_WifiDisconnectNotice;
    switch(WifiState)
    {
        case WIFI_DISCONNECT:
            
            if(s_WifiDisconnectNotice == 0)
            {
                ESP_ERROR_CHECK(esp_timer_start_periodic(smartconfig_led_soft_timer, ConnectStatusInterval));
                s_WifiDisconnectNotice = 1;
            }                      
            break;
        case WIFI_CONNECTING:
            //正在联网的时候LED快闪
            if(s_WifiDisconnectNotice == 1)
            {
                ESP_ERROR_CHECK(esp_timer_stop(smartconfig_led_soft_timer));
            }
            ESP_ERROR_CHECK(esp_timer_start_periodic(smartconfig_led_soft_timer, DisconnectStatusInterval));
            break;
        case WIFI_CONNECTED:
            //连上网后LED常亮,并注销软件定时器,减少消耗
            gpio_set_level(WIFI_STATUS_LED_GPIO, 1);
            if(s_WifiDisconnectNotice == 1)
            {               
                ESP_ERROR_CHECK(esp_timer_stop(smartconfig_led_soft_timer));
                ESP_ERROR_CHECK(esp_timer_delete(smartconfig_led_soft_timer));
                s_WifiDisconnectNotice = 0;
            }           
            break;
        default:
            break;
    }
}
 
//LED管脚初始化
void wifi_status_led_init(void)
{
    gpio_config_t smartconfig_IO_conf;
    smartconfig_IO_conf.intr_type = GPIO_PIN_INTR_DISABLE;
    smartconfig_IO_conf.mode = GPIO_MODE_OUTPUT;
    smartconfig_IO_conf.pin_bit_mask = 1 << WIFI_STATUS_LED_GPIO;
    smartconfig_IO_conf.pull_down_en = 0;
    smartconfig_IO_conf.pull_up_en = 0;
    gpio_config(&smartconfig_IO_conf); 
    gpio_set_level(WIFI_STATUS_LED_GPIO, 0); 

     esp_timer_create_args_t periodled_timer_args = {
            .callback = &periodled_timer_callback,
            /* name is optional, but may help identify the timer when debugging */
            .name = "periodled"
    };    
    ESP_ERROR_CHECK(esp_timer_create(&periodled_timer_args, &smartconfig_led_soft_timer));
}
 
//通知网络未连接
void delegate_wifi_disconnect_status(void)
{
    ESP_LOGI(TAG,"Delegate wifi is disconnect\n"); 
    handle_smartconfig_led_status(WIFI_DISCONNECT); 
    
}
//通知网络已连接
void delegate_wifi_connected_status(void)
{
    ESP_LOGI(TAG,"Delegate wifi has connected\n");
    handle_smartconfig_led_status(WIFI_CONNECTED);
    
}
//通知网络正在连接中
void delegate_wifi_connecting_status(void)
{   
    ESP_LOGI(TAG,"Delegate wifi is connecting\n"); 
    handle_smartconfig_led_status(WIFI_CONNECTING);   
}

//--------------- smartconfig_led.h ---------------//
#ifndef __SMARTCONFIG_LED_H__
#define __SMARTCONFIG_LED_H__

#ifdef __cplusplus
extern "C" {
#endif
 
#define ConnectStatusInterval    1000000    //单位为us
#define DisconnectStatusInterval 200000
 
typedef enum{
    WIFI_DISCONNECT = 1,
    WIFI_CONNECTING,
    WIFI_CONNECTED,
}Wifi_Status_t;
 
 
void wifi_status_led_init(void);
void delegate_wifi_disconnect_status(void);
void delegate_wifi_connected_status(void);
void delegate_wifi_connecting_status(void);
 
#ifdef __cplusplus
}
#endif


#endif


主函数

删除 smartconfig_wifi.c 中的 app_main() 函数,在 main.c 中增加如下源码:

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "smartconfig_button.h"
#include "smartconfig_wifi.h"
#include "smartconfig_led.h"


void app_main(void)
{
    ESP_ERROR_CHECK( nvs_flash_init() );
    wifi_status_led_init();
    smartconfig_button_init();

    //initialise_wifi();
    check_wifi_config_in_nvs();
}

实验结果

编译下载程序后,长按 Boot 按键 3S后,就自动清除配网标志位,并自动重启后,重启后就等待配网,同时LED闪烁,等网络连接后,LED指示灯常亮。


纯手写文章,转载请注明出处,谢谢!
如有任何错误,欢迎留言指正!

### ESP32 按键检测去抖动方法 在ESP32应用程序中,为了确保按键信号稳定可靠,通常需要加入消抖处理机制。当机械开关切换状态时,由于物理特性可能会产生瞬态噪声或多次跳变现象,这会影响系统的正常工作。 对于ESP32而言,在不采用中断的方式下可以利用软件延时法来进行简单的按键消抖[^2]。具体做法是在读取到一次变化后的电平之后等待一段时间再重新确认该电平是否仍然保持不变;如果确实如此,则认为是一次有效的按压动作。 下面给出一段基于ESP-IDF框架下的C语言代码示例用于实现上述逻辑: ```c #include "driver/gpio.h" #define KEY_GPIO 0 // 定义使用的IO口编号 #define LED_GPIO 2 // 连接LED灯的IO号 void app_main(void){ /* 初始化 */ gpio_reset_pin(KEY_GPIO); gpio_set_direction(KEY_GPIO, GPIO_MODE_INPUT); // 设置为输入模式 gpio_pullup_en(KEY_GPIO); // 上拉电阻使能 gpio_reset_pin(LED_GPIO); gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT); int last_key_state = HIGH; // 记录上一次的状态,默认高电平即未按下 int current_key_state; bool debounce_flag = false; while (true) { current_key_state = gpio_get_level(KEY_GPIO); // 获取当前按键状态 if (!debounce_flag && (last_key_state != current_key_state)){ vTaskDelay(pdMS_TO_TICKS(20)); // 等待20ms让抖动结束 if(last_key_state != gpio_get_level(KEY_GPIO)){// 再次判断按键状态是否一致 debounce_flag = true; // 如果相同则标记已消除抖动 if(current_key_state == LOW){ // 若此时处于低电平说明被按下 printf("Key Pressed!\n"); // 控制LED翻转 uint8_t level = !gpio_get_level(LED_GPIO); gpio_set_level(LED_GPIO,level); } last_key_state = current_key_state; // 更新最后记录的状态 }else{ continue; // 否则继续循环不做其他事情 } } if(digitalRead(KEY_GPIO)==last_key_state&&debounce_flag==true){// 当再次回到原始状态时表示释放完成 debounce_flag=false; // 清除标志位以便下次触发 } vTaskDelay(pdMS_TO_TICKS(10)); } } ``` 这段程序实现了基本的功能:初始化GPIO端口设置其方向与属性;进入无限循环监听指定引脚上的电压水平改变情况;一旦发现有新的下降沿到来就启动一个短暂延迟过程以过滤掉可能存在的干扰成分;最终只有经过验证确实是有效边沿才会执行相应的操作比如点亮/熄灭连接在同一电路板上的指示灯。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

荻夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值