zoukankan      html  css  js  c++  java
  • 关于esp32的省电模式的WiFi连接

      对于ESP32,其作为一款集成了2.4GHz WiFi和蓝牙双模块的单芯片,所有基于wifi和蓝牙开发是学习esp32的重要一环,今天WiFi原理和网络结构 可以点击链接进行详细的了解,这里就不做详细的叙述了,本文重点讲解省电模式下的WiFi是如何连接上路由器的,重点是相关API接口和编程方法的介绍。本文源码地址在:esp-idf/examples/wifi/power_save里。源码完成了对ESP32的低功耗模式的设置,并通过menuconfig将接入点AP的名称和密码赋值给ESP32,使ESP32作为一个站点STA接入到接入点AP(即路由器)中。

    PART1:

    定义基本参数

    /*set the ssid and password via "make menuconfig"*/
    #define DEFAULT_SSID CONFIG_WIFI_SSID
    #define DEFAULT_PWD CONFIG_WIFI_PASSWORD
    
    #if CONFIG_POWER_SAVE_MODEM
    #define DEFAULT_PS_MODE WIFI_PS_MODEM
    #elif CONFIG_POWER_SAVE_NONE
    #define DEFAULT_PS_MODE WIFI_PS_NONE
    #else
    #define DEFAULT_PS_MODE WIFI_PS_NONE
    #endif /*CONFIG_POWER_SAVE_MODEM*/

     这里首先将AP端的名称和密码赋值给ESP32,使ESP32可以连接上接入点AP,这里的CONFIG_WIFI_SSID和CONFIG_WIFI_PASSWORD即为路由器端的名称和密码,他们在源码中是看不到的,它们的定义是在Kconfig.projbuild中定义的,我们可以通过make menconfig对其进行赋值。具体操作如下:

    选择Example Configuration后

        在WIFI SSID和WIFI Password中分别将路由器的名称和密码赋值给ESP32。

      (当然,你也可以不通过menucofig而对ESP32直接进行赋值)

      紧随其后的便是对ESP32工作模式的设置,同样,其也可以通过menuconfig进行设置。

    PART2:

    进程打印函数

    static const char *TAG = "power_save";
    
    
    static esp_err_t event_handler(void *ctx, system_event_t *event)
    {
        switch(event->event_id) {
        case SYSTEM_EVENT_STA_START:
        ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START");
        ESP_ERROR_CHECK(esp_wifi_connect());
        break;
        case SYSTEM_EVENT_STA_GOT_IP:
        ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP");
        ESP_LOGI(TAG, "got ip:%s
    ",
            ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
            break;
        case SYSTEM_EVENT_STA_DISCONNECTED:
        ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED");
        ESP_ERROR_CHECK(esp_wifi_connect());
        break;
        default:
            break;
        }
        return ESP_OK;
    }

       本部分主要是将ESP32的工作信息,打印出来,对返回的任务通知进行switch分析,如果连接上了,就打印sta_start消息,并再次执行esp_err_t esp_wifi_connect void 将ESP32 WiFi站连接到AP,第二次得到返回任务通知SYSTEM_EVENT_STA_GOT_IP,并调用  ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));将数字IP地址转换为十进制点ASCII表示法。,此时显示连接到的AP的IP和MAC地址。

    如果没有连接上AP,同样会一直执行esp_err_t esp_wifi_connect( void ),直到将ESP32 WiFi站连接到AP为止。

    PART3:

    WIFI设置和耗电设置

    /*init wifi as sta and set power save mode*/
    static void wifi_power_save(void)
    {
        tcpip_adapter_init();
        ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
        
        wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
        ESP_ERROR_CHECK(esp_wifi_init(&cfg));
        wifi_config_t wifi_config = {
        .sta = {
            .ssid = DEFAULT_SSID,
            .password = DEFAULT_PWD
        },
        };
        ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
        ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
        ESP_ERROR_CHECK(esp_wifi_start());
    
        ESP_LOGI(TAG, "esp_wifi_set_ps().");
        esp_wifi_set_ps(DEFAULT_PS_MODE);
    }

       wifi_power_save首先调用 tcpip_adapter_init();函数对底层库的TCP/IP协议进行调用,然后检测esp_event_loop_init是否初始化完成。

    之后便是进行wifi的设置,首先用esp_wifi_init(&cfg)对WIFI的内存空间进行设置,初始化WiFi Alloc资源为WiFi驱动,如WiFi控制结构,RX / TX缓冲区,WiFi NVS结构等,此WiFi也启动WiFi任务。(注意;在调用所有其他WiFi API之前,必须先调用此API)

    然后设置ESP32 STA或AP的配置。

     wifi_config_t wifi_config = {
        .sta = {                        
            .ssid = DEFAULT_SSID,              //设置要连接的AP的接入点名称和密码
            .password = DEFAULT_PWD
        },
        };
    (注意
    1.只有当指定的接口被启用时,才能调用这个API,否则API会失败
    2.对于站配置,bssid_set需要为0; 只有当用户需要检查AP的MAC地址时,才需要1。
    3. ESP32仅限一个通道,因此在软AP +站模式下,软AP将自动调整其通道与ESP32站的通道相同。)

     通过esp_wifi_set_mode(WIFI_MODE_STA)将WiFi操作模式设置为站,软AP或站+软AP,默认模式为软AP模式。

    esp_wifi_set_config设置ESP32 STA或AP的配置。

    最后通过esp_wifi_start()根据当前配置启动WiFi,

    并通过 esp_wifi_set_ps(DEFAULT_PS_MODE);设置当前节电类型。

    PART4:

    APP_main函数

    void app_main()
    {
        // Initialize NVS
        esp_err_t ret = nvs_flash_init();
        if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
            ESP_ERROR_CHECK(nvs_flash_erase());
            ret = nvs_flash_init();
        }
        ESP_ERROR_CHECK( ret );
    
        wifi_power_save();
    }

     app_main函数主要是对NVS完成基本的初始化操作(关于NVS,可以在ESP32汇总中进行详细了解),保证数据的缓存空间,然后调用 wifi_power_save();函数完成WIFI设置。

    PART5:

    实验现象

       程序烧写完成后,打开minicom,可以看到如下的打印信息

    打开windows的cmd(这里笔记本和ESP32接入的是同一个AP),对AP分配的ESP32的IP进行ping操作,观察能否PING通。操作结果如下:

    至此,基于省电模式的WIFI链接就设计完成了。

    PART6:编程详情

       

       一旦ESP32已经设置了站点配置细节,其中包括SSID和password,我们准备好连接到目标访问点后。 功能 esp_wifi_connect() 将形成的连接。你连接了后ESP32中的任何内容都不会阻塞,同样也不会影响到这个功能。

        在一段时间以后,当其实际的连接起来后,我们会看到两个回调事件发生, 首先是 SYSTEM_EVENT_STA_CONNECTED 表明我们有连接到接入点。 第二个事件是 SYSTEM_EVENT_STA_GOT_IP 其表示我们已经被DHCP服务器分配了一个IP地址。只有这样我们才能真正参与通讯。如果我们正在使用静态IP地址,那么我们只会看到连接的事件。

       我们从接入点断开连接时,我们将看到一个SYSTEM_EVENT_STA_DISCONNECTED 事件。从先前连接的 断开接入点我们调用esp_wifi_disconnect()完成,

        关于与接入点连接的进一步考虑是自动连接的想法。 有一个布尔标志存储在闪存中指示ESP32是否应尝试自动连接到最后一个使用的接入点。 如果设置为true,那么之后在设备启动后,你无需调用任何API函数,它将尝试连接到最后使用的接入点。  这是一个

    方便选项,但是我更喜欢关闭。 通常我想在我的设备中进行控制来确定是否自动连接,是否自动连接,我们可以通过调用esp_wifi_set_auto_connect()。

        另外,当我们连接到接入点时,我们的设备正在成为一个station。 连接到接入点AP不是自动的,意味着我们现在有一个IP地址。 我们坚持必须从DHCP服务器请求已建立的IP地址。 这可能需要几秒。在某些情况下,我们可以让设备请求特定的IP。 这可以更快的连接时间。 如果我们指定数据,我们也需要提供DNS信息,如果我们需要连接到DNS服务器的名字解析度。

    这是分配给我们一个特定IP地址的逻辑片段:
    #include <lwip / sockets.h>
     
    //我们希望我们的设备拥有的IP地址。
    #define DEVICE_IP“192.168.1.99”
     
    //我们希望发送数据包的网关地址
    //这通常是我们的接入点。#define DEVICE_GW “192.168.1 1”
     
    //网络掩码规范。
    #define DEVICE_NETMASK“255.255.255.0”
     
    //我们希望连接的接入点的身份。
    #define AP_TARGET_SSID“RASPI3”
     
    //我们需要提供给接入点进行授权的密码。
    #define AP_TARGET_PASSWORD“password”
    
     
     
    esp_err_t wifiEventHandler(void * ctx,system_event_t * event)
    {
    返回ESP_OK;
    }
     
     
    //代码片段在这里...
    nvs_flash_init();
    tcpip_adapter_init();
     
    tcpip_adap ter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
    tcpip_adapter_ip_info_t ipInfo;
     
    inet_pton(AF_INET,DEVICE_IP,&ipInfo.ip);
    inet_pton(AF_INET,DEVICE_GW,&ipInfo.gw);
    inet_pton(AF_INET,DEVICE_NETMASK,&ipInfo.netmask);
    tcpip_ada pter_set_ip_info(TCPIP_ADAPTER_IF_STA,&ipInfo);
     
    ESP_ERROR_CHECK(esp_event_loop_init(wifiEventHandler,NULL));
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_ST ORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    wifi_config_t sta_config = {
    .sta = {
    .ssid = AP_TARGET_SSID,
    .password = AP_TARGET_PASSWORD,
    .bssid_set = 0
    }
    };
    ESP_ERROR_CHECK(esp_wifi_set_config(WI FI_IF_STA,&sta_config));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_connect());

    作为接入点AP

        到目前为止,我们只将ESP32作为了接入接入点的WiFi站

        但它也具有作为一个接入点使其他WiFi设备(站)连接的能力 。为了成为一个接入点,我们需要定义允许其他的SSID设备来区分我们的网络。 这个SSID可以被标记为为hidden, 如果我们不希望它在扫描中找到。 另外我们还要提供认证方式当台站希望与我们联系时,将使用该功能。 这是用来允许

    的,实际的将ES32实例作为接入点AP请看下一篇文章

    ESP32作为接入点AP

            

    相关知识:wifi相关的API接口

  • 相关阅读:
    LeetCode 264. Ugly Number II
    LeetCode 231. Power of Two
    LeetCode 263. Ugly Number
    LeetCode 136. Single Number
    LeetCode 69. Sqrt(x)
    LeetCode 66. Plus One
    LeetCode 70. Climbing Stairs
    LeetCode 628. Maximum Product of Three Numbers
    Leetcode 13. Roman to Integer
    大二暑假周进度报告03
  • 原文地址:https://www.cnblogs.com/noticeable/p/7524522.html
Copyright © 2011-2022 走看看