ESP32 (6) – How to connect to a wifi network

luca 16/01/2017 6

In this post I’m going to show you how to connect to a wifi network.

The esp-idf framework includes a wifi driver that manages the wifi interface of the esp32 chip. The driver exposes API calls the programmer can use to interact with it; you’ve already used some of those APIs in my previous 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());

The driver is executed in parallel with the main program and communicates with it using events:

esp32-wifi02

In the main program you have to define a function that will be the event handler, i.e. a function called by the wifi driver every time it has to notify a new event:

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

then you have to tell the framework the name of your function:

ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));

The list of the events the framework may generate is included in the esp_event.h file. The events related to the wifi driver when working in station mode have SYSTEM_EVENT_STA as name prefix:

esp32-wifi03

The connection to a wifi network follows this flow diagram:

esp32-wifi04

  • the main program configures and starts the driver via API calls
  • after having completed its internal tasks, the driver notifies that it has successfully started triggering the event SYSTEM_EVENT_STA_START
  • the event handler, once received that event, can call the esp_wifi_connect() API to ask the driver to connect to the network specified during the configuration phase
  • when the connection is completed and after having obtained a valid IP address (if the DHCP service is used), the driver triggers the event SYSTEM_EVENT_STA_GOT_IP
  • now the event handler can inform the main program that the connection has been completed

Tasks synchronization

In the process described above, the main program waits for the connection to be completed before executing its own instructions. It’s therefore important to understand how to synchronize the different elements: the main program, the event handler and the wifi driver. FreeRTOS offers different ways to make the tasks communicate: one of the simplest is via events. Events, in FreeRTOS, are managed using event groups and event bits.

Event bits are similar to flags,  visible to the different tasks:

  • the programmer can create as many event bits as he needs
  • tasks can activate (set) o deactivate (clear) the different bits
  • a task can pause its execution waiting for one of more bits to be set

Event bits are grouped into event groups, each of them usually contains 8 event bits. Event bits in an event group are numbered depending on their “position” (BIT0, BIT1…):

esp32-wifi05

The program

The complete program is available in my Github repository. Let’s review the main sections:

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

The program defines an event group (wifi_event_group) and an event bit (CONNECTED_BIT). In the app_main() the event group is created using the FreeRTOS xEventGroupCreate() method.

#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));

The configuration of the wifi network starts with the definition of two constants: the SSID name and the password (WIFI_SSID e WIFI_PASS). The constants are then used to initialize the wifi_config struct; struct which is then passed as parameter to the esp_wifi_set_config method.

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;

The event handler manages the different events triggered by the wifi driver as explained above. In particular, once the connection is established (STA_GOT_IP event), sets the CONNECTED_BIT event bit. On the contrary, in case of disconnection it clears the same event bit.

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

The main task pauses its execution until the connection to the wifi network is perfomed, waiting for the CONNECTED_BIT bit to be set. The portMAX_DELAY constant will cause the task to block indefinitely (without a timeout).

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));

When the connection is established, the main task prints out the network parameters (IP address, netmask and gateway). The TCPIP_ADAPTER_IF_STA constant represents (see tcpip_adapter.h) the network interface of the esp32 chip when working in station mode.

Here’s a screenshot of the program in execution:

esp32-wifi06

To make its output clearer, I turned off the default logging of the wifi driver with the instruction:

esp_log_level_set("wifi", ESP_LOG_NONE);

and disabled the buffering for the standard output:

setvbuf(stdout, NULL, _IONBF, 0);

6 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?

    • lind 26/04/2017 at 12:07 - Reply

      Hi, I had the same problem, commenting the line :
      //setvbuf(stdout, NULL, _IONBF, 0);
      solved the problem for me

      • luca 26/04/2017 at 12:57 - Reply

        Thanks! It solved also for me… I’m going to fix all the examples in the repository

Leave A Response »

This website uses cookies to ensure you get the best experience on our website 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