In tutti gli esempi finora proposti, abbiamo utilizzato il chip esp32 in STAtion Mode, ovvero come client che si collega ad una rete wifi esistente. In un precedente articolo ho spiegato in dettaglio come interagiscono i vari componenti del framework esp-idf per stabilire la connessione e l’uso degli eventi per sincronizzare i vari tasks del nostro programma.
Oggi vedremo come configurare il chip esp32 per creare una propria rete wifi, in maniera simile ad un access point. Tale modalità prende infatti il nome di SoftAP.
Indirizzamento IP
Ogni dispositivo collegato ad una rete IP deve avere un proprio indirizzo univoco. E’ possibile assegnare l’indirizzo in maniera statica, o affidarsi ad un servizio (DHCP, Dynamic Host Configuration Protocol – Protocollo di configurazione dinamica dei dispositivi) che li assegna in maniera dinamica. Il servizio DHCP ha il vantaggio di non richiedere – a chi si collega ad una rete – di conoscere a priori la configurazione corretta da applicare (indirizzo IP, maschera di rete, gateway…); per questo normalmente il dispositivo che gestisce la rete offre anche un server DHCP:
Anche il framework esp-idf include un server DHCP. Per poterlo rendere disponibile nella nuova rete wifi che andremo a creare dobbiamo:
[checklist]
- fermare il servizio in caso sia già in esecuzione – tcpip_adapter_dhcps_stop()
- configurare in maniera statica l’interfaccia di rete del chip esp32 – tcpip_adapter_set_ip_info()
- avviare il servizio – tcpip_adapter_dhcps_start()
[/checklist]
Per assegnare l’indirizzo 192.168.10.1/24 (/24 corrisponde ad una maschera di rete 255.255.255.0) ed eseguire il server DHCP dobbiamo quindi:
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)); tcpip_adapter_ip_info_t info; memset(&info, 0, sizeof(info)); IP4_ADDR(&info.ip, 192, 168, 10, 1); IP4_ADDR(&info.gw, 192, 168, 10, 1); IP4_ADDR(&info.netmask, 255, 255, 255, 0); ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info)); ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); |
SoftAP
Possiamo ora configurare la modalità SoftAP del chip esp32.
Per prima cosa inizializziamo l’event handler (vedremo in seguito quali eventi sono disponibili in questa modalità):
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); |
Quindi configuriamo lo stack wifi in modalità access point, con configurazione di default memorizzata nella memoria RAM:
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); |
I parametri di configurazione dell’access point sono disponibili nella struct wifi_ap_config_t:
- ssid è il nome (Service Set Identifier) della rete
- password è la password per il collegamento alla rete (se la modalità di autenticazione la prevede, vedi sotto)
- ssid_len è la lunghezza (in caratteri) della stringa ssid – può essere lasciata a 0 se tale stringa è null-terminated
- channel è il canale di trasmissione
- authmode indica la modalità di autenticazione, vedi sotto
- ssid_hidden consente di nascondere la rete non trasmettendo il suo SSID in broadcast
- max_connection è il numero di dispositivi collegati contemporaneamente (max 4)
- beacon_intereval indica l’intervallo tra la trasmissione di un beacon frame e il successivo
Una volta configurati i parametri, vanno applicati con il metodo esp_wifi_set_config(). Nell’esempio pubblicato su Github, tutti i parametri sono configurabili tramite menuconfig:
wifi_config_t ap_config = { .ap = { .ssid = CONFIG_AP_SSID, .password = CONFIG_AP_PASSWORD, .ssid_len = 0, .channel = CONFIG_AP_CHANNEL, .authmode = CONFIG_AP_AUTHMODE, .ssid_hidden = CONFIG_AP_SSID_HIDDEN, .max_connection = CONFIG_AP_MAX_CONNECTIONS, .beacon_interval = CONFIG_AP_BEACON_INTERVAL, }, }; ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); |
Infine avviamo lo stack wifi con:
ESP_ERROR_CHECK(esp_wifi_start()); |
Eventi
3 gli eventi principali che sono disponibili in modalità access point:
[checklist]
- SYSTEM_EVENT_AP_START, quando lo stack ha completato il processo di avvio (iniziato con esp_wifi_start)
- SYSTEM_EVENT_AP_STACONNECTED, quando un nuovo dispositivo si collega all’access point
- SYSTEM_EVENT_AP_STADISCONNECTED, quando un dispositivo si disconnette
[/checklist]
Nell’esempio di questo post gli eventi sono notificati tramite diversi event bits:
case SYSTEM_EVENT_AP_START: printf("Access point started\n"); break; case SYSTEM_EVENT_AP_STACONNECTED: xEventGroupSetBits(event_group, STA_CONNECTED_BIT); break; case SYSTEM_EVENT_AP_STADISCONNECTED: xEventGroupSetBits(event_group, STA_DISCONNECTED_BIT); break; |
Authentication modes
La modalità SoftAP del chip esp32 supporta diverse modalità di autenticazione:
open configura una rete wifi senza alcuna modalità di autenticazione, mentre le altre modalità implementano qualche forma di sicurezza, da quelle più “deboli” (WEP, ormai facilmente violabile) a quelle più sicure (WPA2). Personalmente utilizzo sempre la modalità WPA2_PSK che offre elevata sicurezza e autenticazione tramite password (PSK = PreShared Key, chiave di sicurezza condivisa).
Elenco dispositivi connessi
E’ possibile ottenere un elenco dei dispositivi connessi all’access point con il metodo esp_wifi_ap_get_sta_list() che aggiorna una struct di tipo wifi_sta_list_t:
wifi_sta_list_t wifi_sta_list; memset(&wifi_sta_list, 0, sizeof(wifi_sta_list)); ESP_ERROR_CHECK(esp_wifi_ap_get_sta_list(&wifi_sta_list)); |
Per ottenere i parametri IP (ad esempio l’indirizzo) delle varie stations si può quindi utilizzare il metodo tcpip_adapter_get_sta_list():
tcpip_adapter_sta_list_t adapter_sta_list; memset(&adapter_sta_list, 0, sizeof(adapter_sta_list)); ESP_ERROR_CHECK(tcpip_adapter_get_sta_list(&wifi_sta_list, &adapter_sta_list)); for(int i = 0; i < adapter_sta_list.num; i++) { tcpip_adapter_sta_info_t station = adapter_sta_list.sta[i]; printf("%d - mac: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x - IP: %s\n", i + 1, station.mac[0], station.mac[1], station.mac[2], station.mac[3], station.mac[4], station.mac[5], ip4addr_ntoa(&(station.ip))); } |
Demo
(sottotitoli in italiano disponibili)
Thanks for this tutorial.
The main.c compiles and I user menuconfig to set the values.
But If I start the program my wroom32 keeps rebooting telling me the following error:
ESP_ERROR_CHECK failed: esp_err_t 0xb at 0x400df854
0x400df854: app_main at /home/roland/Roboter/esp32/esp32-tutorial/12_accesspoint/main/./main.c:168 (discriminator 1)
file: “/home/roland/Roboter/esp32/esp32-tutorial/12_accesspoint/main/./main.c” line 168
func: app_main
expression: esp_wifi_set_config(WIFI_IF_AP, &ap_config)
Backtrace: 0x400868ac:0x3ffb88f0 0x40086c29:0x3ffb8910 0x400df854:0x3ffb8930 0x400d0ce2:0x3ffb8a00
0x400868ac: invoke_abort at /home/roland/Roboter/esp32/esp-idf/components/esp32/./panic.c:547
0x40086c29: _esp_error_check_failed at /home/roland/Roboter/esp32/esp-idf/components/esp32/./panic.c:559
0x400df854: app_main at /home/roland/Roboter/esp32/esp32-tutorial/12_accesspoint/main/./main.c:168 (discriminator 1)
0x400d0ce2: main_task at /home/roland/Roboter/esp32/esp-idf/components/esp32/./cpu_start.c:334
Rebooting…
What am I doing wrong?
could you possibly provide me with a working sdkconfig file
Thank you
Hi, it usually means that you’re using wrong parameters when configuring the AP… for example a password too short for the encryption method you chose.
Really good stuff!!!
but I want to do make this possible by configuring it with Arduino IDE
Hi! My tutorials are about using only the official IDF but you can find many articles on the Internet related to esp32+arduino…
Thanks for the great information. Maybe you already have a demo for APSTA but I was not able to locate it on your site. I would like to configure one ESP32 as SoftAP + Station P2P and then another ESP32 in Station mode to connect to the first ESP’s AP. Hope you can point me in the direction.
Thanks again
Hi Brian, I’m working on it, meanwhile you can use the esp32 forum: some users already posted example about that mode.
Hi Luca
too good tutorial. Wounder why no tutorial on ADC. And how we can make the output of ADC linear. Will be very helpful for sensor interface.
Hi, I’m working on a tutorial about ADC, meanwhile you can read some threads in the esp32 forum.
commento giusto:
ESP_ERROR_CHECK failed: esp_err_t 0xb at 0x40103848
0x40103848: app_main at /home/orcim/esp/_work/_luca_dentella/esp32-tutorial/12_accesspoint/main/./main.c:188 (discriminator 1)
file: “/home/orcim/esp/_work/_luca_dentella/esp32-tutorial/12_accesspoint/main/./main.c” line 188
func: app_main
expression: esp_wifi_set_config(WIFI_IF_AP, &ap_config)
Backtrace: 0x40087618:0x3ffba9d0 0x4008797d:0x3ffba9f0 0x40103848:0x3ffbaa10 0x400d0e53:0x3ffbab10
0x40087618: invoke_abort at /home/orcim/esp/esp-idf/components/esp32/./panic.c:553
0x4008797d: _esp_error_check_failed at /home/orcim/esp/esp-idf/components/esp32/./panic.c:565
0x40103848: app_main at /home/orcim/esp/_work/_luca_dentella/esp32-tutorial/12_accesspoint/main/./main.c:188 (discriminator 1)
0x400d0e53: main_task at /home/orcim/esp/esp-idf/components/esp32/./cpu_start.c:406
Rebooting…
ets Jun 8 2016 00:22:57
ciao, normalmente quell’errore indica che qualche parametro in ap_config non è valido… di solito la password non soddisfa i criteri di sicurezza (lunghezza…) dello standard (WEP, WPA…) che hai scelto.
Hi, Luca! Nice Tutorial.
Can I write the default password in the Kconfig file?
Hi Brian, you can include it in your program (using #define) if you want
Hi, Luca!
So I implemented sucessfully this tutorial in my own ESP32 but for some reason it seems to reboot when a station connects or disconnects from it. do you have some ideas? Thank you again for your awesome work
Brian, are you running my exact code?
I had to add the following code before calling esp_wifi_init() API in main.c, otherwise this API returns error code 0x1101 and esp32 keeps rebooting.
:: Code Added before esp_wifi_init() ::
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 );
Thanks! The new version of the framework (3.0) changed the behaviour of esp_wifi_init() and now you have to call the nvs_flash_init() explicitly.
Ciao Luca, davvero i miei complimenti per il lavoro che stai facendo. Non avrei mai pensato di affrontare IDF senza aver trovato i tuoi tutorial. Dopo aver letto i primi 3 “episodi” non sono riuscito a resistere alla tentazione di acquistare una dev board ESP32.
Non vedo l’ora che arrivi.
Posso chiederti se sia possibile configurare le due interfacce (una in STA mode e l’altra in AP mode), in modo da averle contemporaneamente attive?
Grazie
Ciao Claudio, si puoi configurare il chip in WIFI_MODE_APSTA, avendo a disposizione sia una interfaccia di tipo STAtion che una di tipo AP. In questo thread trovi anche un esempio di come fare… buon divertimento!
Ciao Luca grazie per i tuoi tutorial, volevo chiederti io ho due esp32 , volevo che uno sia access point e uno client, al client vorrei collegare un potenziometro, al server un led che varierà intensità in base all’informazione inviata dal client (cioè dal potenziometro)
ciao, la tua domanda è “si può fare”? sicuramente… tra i miei tutorial trovi tutto (AP, HTTP server, HTTP client…)
Ciao Luca,
sto provando a installare la toolchain (e l’IDF) su Raspberry PI3. Purtroppo non riesco a trovare una soluzione già compilata, ed il processo di build a partire dai sorgenti è talmente onerosa che non si completa mai e manda in overtemperature l’RPI3.
Tu potresti indicarmi qualche link da cui scaricare toolchain per RPI3?
Ho provato da un link indicato da Mr. Kolban in un suo tutorial YouTube, tuttavia credo sia superato non funziona.
Ti ringrazio. Saluti
ciao Claudio, purtroppo non avendo un Pi3 non mi sono mai interessato della cosa… ho visto che ci sono le istruzioni “from skretch” e che qualcuno è riuscito a seguirle proprio per la Pi3.
Simple question: When I use ESP32 in AP_STA mode, after create a AP by softAP(), can the station part as a client connect to this AP (AP’s network) ?
Or in short, Can STA connect to its own AP in a ESP32 in AP_STA mode?
don’t think so, but you can try
Dear Luca,
I use this example with a esp-wrover-kit. I get the following error:
Guru Meditation Error: Core 0 panic’ed (InstrFetchProhibited). Exception was un
handled.
Core 0 register dump:
PC : 0x00000000 PS : 0x00060730 A0 : 0x800ea851 A1 : 0x3f
fc0bf0
A2 : 0x00000000 A3 : 0x00000037 A4 : 0xffffffa5 A5 : 0x3f
fc0d78
A6 : 0x0000000c A7 : 0x00000000 A8 : 0x800f82d4 A9 : 0x3f
fc0be0
A10 : 0x3ffb9cb0 A11 : 0x00000037 A12 : 0xffffffa5 A13 : 0x3f
fc0c84
A14 : 0x0000b500 A15 : 0x0000b500 SAR : 0x00000010 EXCCAUSE: 0x00
000014
EXCVADDR: 0x00000000 LBEG : 0x4000c349 LEND : 0x4000c36b LCOUNT : 0xff
ffffff
Backtrace: 0x00000000:0x3ffc0bf0 0x400ea84e:0x3ffc0c10 0x400ebb3f:0x3ffc0cf0 0x4
0104b81:0x3ffc0d10 0x400874ce:0x3ffc0d60 0x4008c919:0x3ffc0da0
0x400ea84e: hostap_input at ??:?
0x400ebb3f: ap_rx_cb at ??:?
0x40104b81: ppRxPkt at ??:?
0x400874ce: ppTask at ??:?
Any idea of what is poing on?
Best Regard and tnaks in advance.
Asepi.
Dear Luca, thanks for sharing this nice tutorial.
In my app I would like to configure one device as the master, using softAP, and allows multiple other devices to automatically connect to this AP.
– In you code you mentioned the limit is 4 devices that could connect to one AP, is this a real limit ?
– Once connected, I’d like the AP to send a trigger to the different connected devices to start performing a task synchronized on all devices.
I was thinking about creating a mobile app also connected to the AP, and when user click a button on the app, a signal is sent to all connected devices, do you think this is possible ?
Thanks
Salve. E’ possibile usare una scheda esp32-cam, configurandola come access point, per poi connettersi ad essa con uno smartphone/pc e visualizzare lo stream ripreso dalla telecamera? In giro ho visto che si può visualizzare lo stream solo se esp32-cam e smartphone/pc sono collegati alla stessa rete wifi. Ma se nel posto in cui mi trovo non c’è una rete wifi a cui connettersi nè posso abilitare il tethering hospot da cellulare, come si potrebbe visualizzare lo stream video? Si può creare un AP wifi con la esp32-cam e connetterci lo smartphone/pc. per visualizzare lo streaming?Grazie
Salve! Si è possibile, qui un esempio.
CIao Luca,
sto utilizzando ESP32-S2-MINI-1 come Access Point, mi capita che effettui una duplicazione degli indirizzi che assegna a 5 diverse IPCAM, sto utilizzando release/v2.1.0.0_esp32s2 .
non l’ho trovato tra i bug della release ne in generale su internet, ma mi capita in maniera ripetuta e certa, tu hai evidenza di questa problematica?
Grazie,
Antonio
Ciao Antonio: no, non mi è mai capitato di imbattermi in questo problema di IP dupplicati. Stai usando il framework per Arduino?
no, direttamente l’esp32 pilotato tramite seriale da stm32, senza librerie aggiuntive, ma nel firmware riavviamo spesso esp32 qualora vi siano problemi con qualche ipcam e questo porta ad avere ip duplicati perchè nel firmware esp32 probabilmente non fa associazione tra mac e ip, o la perde al riavvio