ESP32 (6) – Collegamento ad una rete wifi

luca 16/01/2017 4

In questo post vi mostrerò come effettuare il collegamento ad una rete wifi.

Il framework esp-idf include un driver wifi che si occupa della gestione dell’interfaccia wifi del modulo esp32. Tale driver mette a disposizione delle API che il programma può utilizzare; alcune di queste API le abbiamo già viste nel precedente tutorial:

ESP_ERROR_CHECK(esp_wifi_init(&wifi_config));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());

Il driver wifi viene eseguito in parallelo al programma principale e comunica con questo tramite eventi:

esp32-wifi02

Nel programma principale dobbiamo definire una funzione che farà da event handler, ovvero che sarà chiamata dal driver wifi ogni volta che un nuovo evento deve essere notificato:

static esp_err_t event_handler(void *ctx, system_event_t *event)
{...}

dobbiamo quindi indicare al framework il nome di tale funzione:

ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));

L’elenco dei diversi eventi generati dal framework è presente nel file esp_event.h. Per quanto riguarda il driver wifi in modalità station, gli eventi sono quelli con prefisso SYSTEM_EVENT_STA:

esp32-wifi03

Il collegamento ad una rete wifi avviene secondo questo flusso logico:

esp32-wifi04

  • il programma principale effettua delle chiamate API per configurare ed avviare il driver
  • terminate le attività interne, il driver notifica che l’avvio è avvenuto con successo tramite l’evento SYSTEM_EVENT_STA_START
  • l’event handler, una volta ricevuta la notifica di avvio del driver, può eseguire l’API esp_wifi_connect() per chiedere al driver il collegamento alla rete wifi specificata in fase di configurazione
  • una volta effettuato il collegamento e ottenuto un indirizzo IP (se utilizziamo il servizio DHCP), il driver lo notifica tramite l’evento SYSTEM_EVENT_STA_GOT_IP
  • ora l’event handler può informare il programma principale che il collegamento alla rete è avvenuto con successo

Sincronizziamo i tasks

Il processo descritto sopra prevede che il programma principale aspetti l’avvenuto collegamento alla rete wifi prima di eseguire le sue attività. E’ quindi necessario capire come sincronizzare i diversi elementi coinvolti: programma principale, event handler e driver wifi. Similmente a quanto abbiamo già visto, FreeRTOS mette a disposizione del programmatore un sistema di eventi per fare comunicare i diversi tasks. La gestione degli eventi in FreeRTOS avviene tramite event groupsevent bits.

Possiamo immaginare gli event bits come delle “bandiere” (flags) visibili dai diversi tasks:

  • il programmatore può definire un numero arbitrario di event bits
  • i task possono alzare (set) o abbassare (clear) i diversi bits
  • i task possono interrompere la loro esecuzione aspettando che uno o più bit siano attivati

Infine gli event bits sono raggruppati in event groups, ognuno dei quali normalmente contiene 8 event bits. Gli event bits all’interno di un event group sono nominati in base alla loro “posizione” (BIT0, BIT1…):

esp32-wifi05

Il programma

Il programma completo si trova nel mio repository Github. Commentiamo le parti principali:

static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
[...]
wifi_event_group = xEventGroupCreate();

Il programma definisce un event group (wifi_event_group) e un event bit (CONNECTED_BIT). All’interno di app_main() tale event group viene creato utilizzando il metodo xEventGroupCreate() di FreeRTOS.

#define WIFI_SSID "MYSSID"
#define WIFI_PASS "MYPASSWORD"
[...]
wifi_config_t wifi_config = {
  .sta = {
    .ssid = WIFI_SSID,
    .password = WIFI_PASS,
  },
};
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));

La configurazione della rete wifi avviene tramite la definizione di due costanti (WIFI_SSID e WIFI_PASS). Tali costanti sono poi utilizzate per creare la struttura wifi_config, struttura che viene passata come parametro al metodo esp_wifi_set_config.

static esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch(event->event_id) {
 
  case SYSTEM_EVENT_STA_START:
    esp_wifi_connect();
    break;
  case SYSTEM_EVENT_STA_GOT_IP:
    xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
    break;  
  case SYSTEM_EVENT_STA_DISCONNECTED:
    xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
    break;

L’event handler gestisce i diversi eventi generati dal driver wifi come illustrato sopra. In particolare, una volta stabilita la connessione (evento STA_GOT_IP), attiva l’event bit CONNECTED_BIT; al contrario in caso di disconnessione disattiva (clear) tale event bit.

xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);

Il task principale (main_task) si mette in pausa fino al completamento della connessione alla rete wifi attendendo l’attivazione del bit CONNECTED_BIT. La costante portMAX_DELAY indica che l’attesa deve avvenire per un tempo indefinito.

tcpip_adapter_ip_info_t ip_info;
ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
printf("IP Address:  %s\n", ip4addr_ntoa(&ip_info.ip));
printf("Subnet mask: %s\n", ip4addr_ntoa(&ip_info.netmask));
printf("Gateway:     %s\n", ip4addr_ntoa(&ip_info.gw));

Una volta stabilita la connessione, il task principale visualizza i parametri di rete (indirizzo IP, netmask e gateway). La costante TCPIP_ADAPTER_IF_STA rappresenta (vedi file tcpip_adapter.h) l’interfaccia di rete quando il chip esp32 è in modalità station.

Ecco uno screenshot del programma in esecuzione:

esp32-wifi06

Per rendere l’output più chiaro, ho spento il logging di default del driver wifi con l’istruzione:

esp_log_level_set("wifi", ESP_LOG_NONE);

e disabilitato il buffering di standard output:

setvbuf(stdout, NULL, _IONBF, 0);

4 Comments »

  1. rudi ;-) 16/01/2017 at 11:47 - Reply

    hi

    nice post!
    hope we read more of this art from you.

    best wishes
    rudi ;-)

    • luca 17/01/2017 at 14:00 - Reply

      Thanks Rudi, it’s great to read you here: I followed your posts on the official forum! I’m going to post a tutorial every week, a lot of peripherals in this little chip ;)

  2. Andrew 17/01/2017 at 02:18 - Reply

    Somehow your code from github doesn’t work on my ESP32. The program is simple and straightforward, thanks for all those details… but it throws ‘Guru Meditation Error of type LoadProhibited occurred on core 0. Exception was unhandled.’ My other WiFi programs work fine though.

    • luca 17/01/2017 at 13:55 - Reply

      Hi Andew… very strange: I’ve just compiled the example again and it runs fine on my ESP32 board. Are you using the release 1.0 of the framework or is it updated with the latest commits?

Leave A Response »

Questo sito usa i cookie per poterti offrire una migliore esperienza di navigazione maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi