關於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\n",
        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接口

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM