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

luca 16/01/2017 14

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

14 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

  3. Rodolfo 24/05/2017 at 13:46 - Reply

    Hello Luca,

    Thank for your guides! I’m planning to follow them all :)

    I’m having a problem with this one. I downloaded your code from Github and I have the following errors:

    const int CONNECTED_BIT = BIT0; // BIT0 could not be resolved

    tcpip_adapter_ip_info_t ip_info; // tcpip_adapter_ip_info_t could not be resolved

    I tried including #include “tcpip_adapter.h” (Path and Symbols, GNU C, add the folder tcpip_adapter under components) and adding a #include “tcpip_adapter.h” in the main. But the include is also not resolved.

    I tried also rebuilding the index. But still the same problem.

    Any advice? Thanks!!

    • luca 25/05/2017 at 15:02 - Reply

      Hi Rodolfo, this is strange… I can compile the example with the latest framework. For example I include esp_event_loop.h, which includes esp_event.h which includes tcpip_adapter.h that defines tcpip_adapter_ip_info_t. Are you sure your esp-idf repository is updated and complete?

      • Rodolfo 29/05/2017 at 10:09 - Reply

        Now it’s even stranger. I erased part of the code that was directly using tcpip functions and left esp_event_loop. Now it compiles… When seeing esp_event.h, there is a warning saying that the include is not found. But it’s not an error. I’m using the latest esp-idf on OSX. Maybe it’s a good idea to reinstall everything again. Will keep you posted. Thanks

  4. Kartik Sikka 22/07/2017 at 16:59 - Reply

    Hi luca ,
    I have been reading your posts on ESP 32 , they are amazing .

    I have one question that , form where do you collect the info to write the code ?

    I want to write my own code for ESP 32 for some application , How do I proceed ?

    • luca 24/07/2017 at 09:15 - Reply

      Hi, my sources are the official documentation, the official forum (esp32.com) and many tutorials/videos other makers publish everyday on the Internet!

  5. Emilio 15/09/2017 at 09:23 - Reply

    Hi,
    congrats for the great job and your dedication to this!!
    I guess the code should compile using Arduino IDE, if so, it halts in setup() at “configure the wifi connection and start the interface” with error: C99 designator ‘ssid’ outside aggregate initializer.
    The only thing I did is copy/paste in the IDE added void loop() and changed the main to setup().
    Is it correct?
    Thanks again.

    • luca 16/09/2017 at 15:58 - Reply

      Hi Emilio, this code (and in general my tutorials) are not meant to be used with Arduino IDE but with the official esp-idf framework.

Leave A Response »

Click here to cancel reply.

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