ESP32をWi-Fiに繋げる

ESP32をWi-Fiに繋げる

ESP32をWi-Fiに繋げてHello World

これをやりたいが為にESP32をチョイスしたと言っても過言ではないです。
Wi-Fiに繋げて、後はESP32を電池で動かせれば言うことなし。
さっそく自宅のWi-Fiに接続してみます。
Wi-Fi経由でLチカさせましょう。

まずESP32のWi-Fiですが以下のモードがあります。

  • ステーション
    ESP32からWi-Fiアクセスポイントに接続しに行きます。
  • アクセスポイント
    ESP32自身がアクセスポイントになって接続を受け付けます。
  • ステーション + アクセスポイント
  • 近接認識ネットワーク (NAN)
    近くにいるデバイスと相互接続できます。Wi-Fi Aware

上記以外にもWIFI_IF_MAXというモードがあるのですが、こちらは調べてもよくわかりませんでした。
とりあえず ステーション で自宅のWi-Fiに接続してみます。

ソース

Wi-Fiに接続してWebサーバーを起動。
Webサーバーは「Hello World」を表示するだけの簡単なものです。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_http_server.h"

// Wi-Fiの暗号化モードは WPA2-PSK AES (WPA2ならいいのかも)
#define WIFI_SSID "mySSID"     // 自分のWi-FiのSSID
#define WIFI_PASS "myPASS"     // 自分のWi-Fiのパスワード

static EventGroupHandle_t wifi_event_group;     // イベント
static esp_netif_t *netif_tcpstack;             // TCP/IPスタック
static httpd_handle_t server;                   // Webサーバー

// Wi-Fi接続イベントハンドラ
static void connect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    xEventGroupSetBits(wifi_event_group, BIT0);   // FreeRTOSイベントグループ BIT0 をON        
}

// Wi-Fi切断イベントハンドラ
static void disconnect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    esp_wifi_connect();   // 切断されたら再接続
    xEventGroupClearBits(wifi_event_group, BIT0); // FreeRTOSイベントグループ CONNECTED_BITをOFF
}

// Wi-Fi初期化
void wifi_init_station() {
    wifi_event_group = xEventGroupCreate();     // FreeRTOSイベントグループ初期化

    // Wi-Fi初期化
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    // Wi-Fi設定/開始
    esp_netif_inherent_config_t esp_netif_config = {
        .flags = ESP_NETIF_FLAG_GARP | ESP_NETIF_DHCP_CLIENT | ESP_NETIF_FLAG_MLDV6_REPORT | ESP_NETIF_FLAG_EVENT_IP_MODIFIED,
        .mac = { },
        .ip_info = NULL,
        .get_ip_event = IP_EVENT_STA_GOT_IP,
        .lost_ip_event = IP_EVENT_STA_LOST_IP,
        .if_key = "WIFI_STA_DEF",
        .if_desc = "sta",
        .route_prio = 128,
        .bridge_info = NULL
    };
    netif_tcpstack = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
    ESP_ERROR_CHECK(esp_wifi_set_default_wifi_sta_handlers());
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());

    // イベントハンドラ登録
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, NULL));                     // Wi-Fiのアクセスポイント(AP)からIPを取得
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, NULL));   // Wi-Fiステーション切断

    // Wi-Fi APへ接続
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
            .scan_method = WIFI_ALL_CHANNEL_SCAN,
            .sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
            .threshold.rssi = -127,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        }
    };
    ESP_LOGI("Wi-Fi", "Connecting to %s...", wifi_config.sta.ssid);
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    esp_err_t ret = esp_wifi_connect();     // Wi-Fi APへ接続
    if (ret != ESP_OK) {
        ESP_LOGE("Wi-Fi", "WiFi connect failed! ret:%x", ret);
        ESP_ERROR_CHECK(ret);
    }

    // Wi-Fi接続待ち ( FreeRTOSのインベントグループ(wifi_event_group) の BIT0 が true になるまで待ちます )
    xEventGroupWaitBits(wifi_event_group, BIT0, false, true, portMAX_DELAY);

    // Wi-Fi接続完了、IPアドレス取得完了。取得したIPアドレスをログに出力します。
    ESP_LOGI("Wi-Fi", "Connected to %s", esp_netif_get_desc(netif_tcpstack));
    esp_netif_ip_info_t ip;
    ESP_ERROR_CHECK(esp_netif_get_ip_info(netif_tcpstack, &ip));
    ESP_LOGI("Wi-Fi", "IP Address: " IPSTR, IP2STR(&ip.ip));
}

// GET "/" ハンドラ
esp_err_t get_root(httpd_req_t *req) {
    const char resp[] = "<h1>Hello World</h1>";
    httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
    return ESP_OK;
}

// URLマップ "/"
httpd_uri_t root = {
    .uri      = "/",
    .method   = HTTP_GET,
    .handler  = get_root,
    .user_ctx = NULL
};

// Webサーバー開始
void start_webserver(void)
{
    server = NULL;
    httpd_config_t conf = HTTPD_DEFAULT_CONFIG();
    // Webサーバー開始
    if (httpd_start(&server, &conf) == ESP_OK) {
        ESP_LOGI("Web", "Server start");
        // URLマップハンドラ登録
        httpd_register_uri_handler(server, &root);
    }
}

// Webサーバー停止
void stop_webserver() {
    if (server) {
        httpd_stop(server);
        server = NULL;
    }
}

// シャットダウンハンドラ
static void app_shutdown(void) {
    // Webサーバー停止
    stop_webserver();

    // イベントハンドラ解放
    ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler));
    ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler));

    // Wi-Fi切断
    esp_wifi_disconnect();

    // Wi-Fi停止/設定初期状態
    esp_err_t err = esp_wifi_stop();
    if (err == ESP_ERR_WIFI_NOT_INIT) {
        return;
    }
    ESP_ERROR_CHECK(err);
    ESP_ERROR_CHECK(esp_wifi_deinit());
    ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(netif_tcpstack));
    esp_netif_destroy(netif_tcpstack);
    netif_tcpstack = NULL;
}

void app_main(void)
{
    nvs_flash_init();     // Flash初期化  (お約束のようなもの)

    // シャットダウンハンドラ, esp_restart関数で再起動される前に呼び出されます
    ESP_ERROR_CHECK(esp_register_shutdown_handler(&app_shutdown));

    wifi_init_station();  // Wi-Fi初期化

    if (xEventGroupGetBits(wifi_event_group) & BIT0) {
        // 接続成功ならWebサーバー起動
        start_webserver();
    }
}

はい、長いですね。
Wi-Fi接続部分が長いだけで特に面倒なところはない気がします。
これでモニタに表示されたIPアドレスで、http://192.168.0.10/ とかでアクセスすれば Hello World と表示されます。


ソースファイルの分割とHTMLのソースをフラッシュに置く方法調べましょう。

コメント

このブログの人気の投稿

(真)ESP32の開発環境をVSCodeで作る

ESP32にmicroSD接続

ESP32でデバッグ