Zmiana wersji lub uaktualnienie ESP-IDF
Rodzina układów ESP32 wciąż się rozbudowuje, a za zmianami podąża również środowisko ESP-IDF. W kolejnych wersjach uwzględniana jest obsługa nowszych modeli ESP32, oferujących często całkiem nowe możliwości. Także samo środowisko podlega zmianom – poprzez modernizowanie wersji bibliotek: usuwanie błędów i optymalizację procedur. Nowe aplikacje użytkownika warto zatem pisać używając najświeższych stabilnych wersji środowiska ESP-IDF, z kolei drobne poprawki starszych aplikacji mogą wymagać tej wersji ESP-IDF, w której zostały napisane. W przypadku pracy z edytorem opartym o Eclipse, pobranie nowej wersji środowiska lub przełączenie na inną wersję można wykonać klikając opcję Espressif → Download and Configure ESP-IDF. Wyświetli się plansza podobna do tej z rysunku 1.
Zaznaczając opcję Use an existing ESP-IDF directory from file system możemy wskazać katalog z wcześniej pobranymi wersjami ESP-IDF. Jedną z nich będzie można ustawić jako aktywną i używaną w procesie kompilacji programów użytkownika. Jeżeli opcja pozostanie niezaznaczona, można wybrać wersję środowiska do pobrania z sieci spod adresu https://dl.espressif.com/dl/idf-eclipse-plugin/updates/latest/. Pliki wersji po pobraniu zostaną rozpakowane do wskazanego folderu i mogą być użyte jako aktywna wersja ESP-IDF.
Standard Wi-Fi w modułach rodziny ESP32
Starsze warianty ESP32 mogą pracować jako Wi-Fi (standard 802.11 b/g/n) o następujących parametrach:
- prędkość do 150 Mb/s,
- obsługa wielu połączeń (do 255),
- tryby pracy: stacja, punkt dostępowy, mieszany.
Nowe układy (np. ESP32-S3) są przystosowane do standardu Wi-Fi 6 802.11 b/g/n/ax, który od starszej wersji różni się:
- prędkością do 300 Mb/s,
- standardem szyfrowania WPA3,
- niższym zużyciem energii.
Nowy standard Wi-Fi 6 jest kompatybilny ze starszymi wersjami Wi-Fi.
Tryb stacji
Praca w trybie stacji oznacza, że moduł ESP32 może po zalogowaniu łączyć się z innymi uczestnikami lokalnej sieci Wi-Fi. Jest to sytuacja pokazana na rysunku 2. Lokalną sieć tworzy w tym przykładzie router oraz dwa inne urządzenia działające w trybie stacji: komputer PC i telefon. Moduł ESP32, po uwierzytelnieniu się właściwym hasłem, otrzymuje swój numer IP przydzielony przez router. Od tego momentu staje się widoczny w ramach sieci lokalnej – może za pośrednictwem routera łączyć się z pozostałymi uczestnikami sieci i wymieniać dane. Prosty program pokazany na kolejnych listingach zademonstruje kroki niezbędne do tego, aby moduł – pracując w trybie stacji – stał się osiągalny w ramach sieci.
Na początku, co widać na listingu 1, włączamy wszystkie pliki nagłówkowe bibliotek, które będą używane w dalszej części programu. Zamiast „twój ssid” i „twoje hasło” trzeba wpisać rzeczywistą nazwę sieci – do której moduł ma się podłączyć – oraz hasło.
#include <string.h> //obsługa ciągów znaków
#include "freertos/FreeRTOS.h" //dla operacji rtos: delay,mutexs,semphrs
#include "esp_system.h" //dla funkcji esp_err_t
#include "esp_wifi.h" //dla funkcji i operacji Wi-Fi
#include "esp_log.h" //dla wyświetlania logów
#include "esp_event.h" //dla obsługi zdarzeń Wi-Fi
#include "nvs_flash.h" //dla obsługi pamięci nieulotnej
#include "lwip/err.h" //obsługa błędów lwip
#include "lwip/sys.h" //aplikacje systemowe dla lwip
const char *your_ssid = "twój ssid";
const char *your_pass = "twoje hasło";
int retry_num=0;
Listing 1. Pliki nagłówkowe oraz najważniejsze stałe i zmienne używane do obsługi Wi-Fi
Na listingu 2 pokazano, jak utworzyć procedurę obsługi zdarzeń (są to różne sytuacje, w tym przypadku występujące podczas włączania modułu ESP32 do sieci). Przykładem zdarzenia może być start trybu stacji, podłączenie do sieci, uzyskanie numeru IP czy też odłączenie od sieci. Gdy któraś z wymienionych sytuacji wystąpi, wywołana zostanie funkcja obsługi z przekazanym w parametrze event_id identyfikatorem zdarzenia. Dzięki identyfikatorowi wiadomo, które zdarzenie wymaga obsługi w danym momencie. W analizowanym przykładzie najczęściej będzie to tylko wysłanie komunikatu, który wyświetli się na monitorze portu szeregowego przez polecenie printf. W przypadku zdarzenia WIFI_EVENT_STA_DISCONNECTED będzie to podejmowana 5 razy próba nawiązania połączenia.
if (event_id == WIFI_EVENT_STA_START)
{
printf ( "ŁĄCZENIE Z WIFI....\n" );
}
else if (event_id == WIFI_EVENT_STA_CONNECTED)
{
printf ( "Wi-Fi POŁĄCZONE\n" );
}
else if (event_id == WIFI_EVENT_STA_DISCONNECTED)
{
printf ( "Utracono połączenie Wi-Fi\n" );
if (retry_num< 5 ){esp_wifi_connect();retry_num++; printf ( "Ponowna próba połączenia...\n" );}
}
else if (event_id == IP_EVENT_STA_GOT_IP)
{
printf ( "Wi-Fi ma adres IP...\n\n" );
}
}
Listing 2. Procedura obsługi zdarzeń
Listing 3 zawiera główną procedurę realizującą podłączenie modułu ESP32 – pracującego w trybie stacji – do wybranej sieci Wi-Fi. Poszczególne kroki opatrzono zwięzłymi opisami w komentarzach. Najpierw przeprowadzane są niezbędne konfiguracje, włączane obsługi zdarzeń, tworzona struktura zadeklarowanych wcześniej stałych zawierających nazwę sieci i hasło dostępu. Na końcu funkcji wifi_connection() wywoływane są procedury podłączeniowe. Listing 4 pokazuje funkcję main() łączącą wszystko razem.
esp_netif_init(); //inicjalizacja interfejsu sieciowego
esp_event_loop_create_default(); //włączenie obsługi zdarzeń
esp_netif_create_default_wifi_sta(); //konfiguracja struktury danych dla interfejsu
//stacji Wi-Fi
wifi_init_config_t wifi_initiation = WIFI_INIT_CONFIG_DEFAULT(); //struktura wifi_init_config
//z wartościami domyślnymi
esp_wifi_init(&wifi_initiation); //inicjacja wifi warościami domyślnymi
esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL); //tworzenie rejestru obsługi zdarzeń dla Wi-Fi
esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler,NULL); //tworzenie rejestru obsługi zdarzeń dla
//zdarzenia IP
wifi_config_t wifi_configuration ={ //struktura wifi_configuration dla nazwy sieci
//i hasła
.sta= {
.ssid = "",
.password= "",
}
};
strcpy((char*)wifi_configuration.sta.ssid,your_ssid); //kopiowanie do struktury łańcuchów znaków
strcpy((char*)wifi_configuration.sta.password,your_pass);
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_configuration); //konfiguracja po zdarzeniu //ESP_IF_WIFI_STA
esp_wifi_start(); //start połączenia
esp_wifi_set_mode(WIFI_MODE_STA); //wybranie trybu pracy stacja
esp_wifi_connect(); //łączenie z wykorzystaniem podanych ssid
//i pass
printf( "wifi_init_softap finished. SSID:%s password:%s",your_ssid,your_pass);
}
Listing 3. Główna procedura realizująca podłączenie modułu ESP32 do sieci Wi-Fi w trybie stacji
nvs_flash_init(); //inicjacja pamięci do przechowywania konfiguracji Wi-Fi
wifi_connection();
}
Listing 4. Funkcja main programu
Po kompilacji programu i wgraniu do pamięci ESP32, układ zaczyna szukać sieci o podanej w stałej your_ssid nazwie i próbuje się do niej zalogować. W przypadku sukcesu nadawany jest modułowi numer IP. W monitorze można podejrzeć komunikaty generowane podczas tego procesu, podobne do tych widocznych na rysunku 3. Z komunikatu logu wynika, że router dodał moduł ESP32 pracujący w trybie stacji do sieci – i nadał mu numer IP 192.168.0.192.
Przykładowa procedura oparta została na materiale dostępnym tutaj [1].
Tryb punktu dostępowego
Tryb punktu dostępowego w dokumentacji nosi nazwę soft Acces Point (softAP). Pracując w tym trybie ESP32 tworzy lokalną sieć Wi-Fi, do której mogą się podłączać urządzenia będące stacjami Wi-Fi. Utworzona sieć umożliwia podłączonym stacjom komunikację i wymianę danych pomiędzy sobą, przy skorzystaniu z pośrednictwa softAP. Taką konfigurację zaprezentowano na rysunku 4. Trzy stacje: komputer PC, telefon oraz moduł ESP32 podłączone są do sieci utworzonej przez inny moduł ESP32, pracujący jako softAP.
Na kolejnych listingach pokazano składowe programu demonstrującego, jak przy pomocy modułu ESP32 utworzyć w pełni funkcjonalny softAP.
Na listingu 5 wyliczone zostały wszystkie potrzebne pliki nagłówkowe.
#include "freertos/FreeRTOS.h" //dla operacji rtos: delay,mutexs,semphrs
#include "freertos/task.h" //dla operacji rtos: task
#include "esp_system.h" //dla funkcji esp_err_t
#include "esp_wifi.h" //dla funkcji i operacji Wi-Fi
#include "esp_event.h" //dla obsługi zdarzeń Wi-Fi
#include "esp_log.h" //dla wyświetlania logów
#include "nvs_flash.h" //dla obsługi pamięci nieulotnej
#include "lwip/err.h" //lwip kody błędów
#include "lwip/sys.h" //lwip system
Listing 5. Pliki nagłówkowe używane w drugim programie testowym
Listing 6 zawiera deklaracje kluczowych ustawień tworzonej sieci Wi-Fi. Do EXAMPLE_ESP_WIFI_SSID przypisujemy nazwę sieci, np. „esp32_moja_siec”, a do EXAMPLE_ESP_WIFI_PASS – hasło logowania.
#define EXAMPLE_ESP_WIFI_PASS "hasło_do_twojej_sieci"
#define EXAMPLE_ESP_WIFI_CHANNEL 1 //kanał radiowy twojej sieci
#define EXAMPLE_MAX_STA_CONN 4 //maksymalna ilość stacji w twojej sieci Wi-Fi
static const char *TAG = "wifi softAP"; //znacznik logu
Listing 6. Najważniejsze stałe i zmienne używane do obsługi Wi-Fi w trybie softAP
Na listingu 7 można obejrzeć przykładową procedurę obsługi zdarzeń Wi-Fi. Obsługiwane są dwa zdarzenia: WIFI_EVENT_AP_STACONNECTED (zdarzenie podłączenia do sieci nowej stacji), a także WIFI_EVENT_AP_STADISCONNECTED (zdarzenie odłączenia stacji od sieci).
int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
Listing 7. Przykładowa procedura obsługi zdarzeń Wi-Fi w trybie softAP
Na listingu 8 pokazana została funkcja wifi_init_softap(), inicjalizująca Wi-Fi ESP32 w trybie softAP. Ostatni listing 9 zawiera główną funkcję main() programu.
{
ESP_ERROR_CHECK(esp_netif_init()); //inicjalizacja interfejsu sieciowego
ESP_ERROR_CHECK(esp_event_loop_create_default()); //włączenie obsługi zdarzeń
esp_netif_create_default_wifi_ap(); //konfiguracja struktury danych dla interfejsu AP Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); //struktura cfg z wartościami domyślnymi
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); //inicjacja wifi wartościami domyślnymi
//tworzenie rejestru obsługi zdarzeń
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
//inicjacja trybu Wi-Fi softAP
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}
Listing 8. Ciało funkcji inicjalizującej moduł Wi-Fi do pracy w trybie softAP
{
//Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
wifi_init_softap();
}
Listing 9. Główna funkcja programu obsługującego tryb softAP
Na rysunku 5 pokazano zrzut ekranu z komunikatami wysyłanymi do terminala przez moduł ESP32 z uruchomionym przykładowym oprogramowaniem. Moduł działa w trybie softAP i tworzy sieć o nazwie „ESP32-softAP” zabezpieczoną hasłem „1234567890ab”. Do sieci podłączona jest jedna stacja, której przydzielono numer IP: 192.168.4.2.
Przykładowa procedura oparta została na materiale dostępnym tutaj [2].
Ryszard Szymaniak, EP
Odniesienia: