ESP32 (18) – Access Point

by luca
26 comments

In all the examples so far, we used the esp32 chip in STAtion Mode, that is as a client which connects to an existing wifi network. In a previous article I explained in details how the different components of the esp-idf framework interact to establish the connection and how to use events to syncronize the tasks of your program.

Today you’ll learn how to configure the esp32 chip to publish its own wifi network, similar to an access point. This mode is indeed named SoftAP.

IP addressing

Every device connected to an IP network must have its unique address. You can statically assign the address or leverage a network service (DHCP, Dynamic Host Configuration Protocol) that dynamically assigns them. The main advantage in using the DHCP service is that you don’t need to know in advance – when connecting to a network – the correct settings to apply (IP address, netmask, gateway…); this is the reason why normally the device which manages the network also offers a DHCP server:

ap-05

The esp-idf framework does include a DHCP server. To use it in the network you’re going to create, you have to:

[checklist]

  • stop the service if it’s already running – tcpip_adapter_dhcps_stop()
  • statically configure the network interface of the esp32 chip – tcpip_adapter_set_ip_info()
  • start the service – tcpip_adapter_dhcps_start()

[/checklist]

The esp-idf framework uses two different interfaces depending if the esp32 chip is in station mode or in SoftAP mode (TCPIP_ADAPTER_IF_STA e TCPIP_ADAPTER_IF_AP). Make sure you’re configuring the correct one based on the mode you’re planning to use.

For example, to assign the address 192.168.10.1/24 (/24 corresponds to 255.255.255.0 netmask) and run the DHCP server:

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

Now you can configure the SoftAP mode for the esp32 chip.

First initialize the event handler (later I’ll list the events that are available when working in this mode):

ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));

Then configure the wifi stack in access point mode, with the default settings and RAM storage:

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

The different settings for the AP mode are available in the wifi_ap_config_t struct:

ap-01

  • ssid is the name (Service Set Identifier) of the network
  • password is the password you have to specify to connect to the network (if the authentication mode requires it, see below)
  • ssid_len is the length (in characters) of the ssid string – you can set it to zero if the string is null-terminated
  • channel is the transmission channel
  • authmode is the authentication mode, see paragraph below
  • ssid_hidden allows to “hide” the network not broadcasting its SSID
  • max_connection is the maximum number of concurrent connections (max 4)
  • beacon_intereval is the transmission interval for beacon frames

Once configured, you have to apply struct using the esp_wifi_set_config() method. In the example I published on Github, all the parameters can be configured via menuconfig:

ap-02

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

Finally start the wifi stack with:

ESP_ERROR_CHECK(esp_wifi_start());

Events

Three are the main events available when working in access point mode:

[checklist]

  • SYSTEM_EVENT_AP_START, when the stack completed the start process (after esp_wifi_start)
  • SYSTEM_EVENT_AP_STACONNECTED, when a new device connects to the access point
  • SYSTEM_EVENT_AP_STADISCONNECTED, when a device disconnects

[/checklist]

ap-03

In the example, the events are notified using different 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

In SoftAP mode, the esp32 chip supports different authentication modes:

ap-04

open configures a wifi network with no authentication, while all the other modes offer some security, from the “weak” ones (WEP, now easily hackable) to the strongest ones (WPA2). Personally, I always use the WPA2_PSK mode, which offers high security and authentication, using a shared password (PSK = PreShared Key).

Some authentication modes require a minimum password length. In particular, WPA and WPA2 require a password at least 8 characters long; if you specify a password too short, the esp_wifi_set_config method will return an error.

List the connected devices

You can get the list of the devices connected to the access point with the esp_wifi_ap_get_sta_list() method, which updates a wifi_sta_list_t struct:

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

To obtain the IP settings (for example the address) of the different stations, you can then use the tcpip_adapter_get_sta_list() method:

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

[youtube id=”ARiX_H0sH4Y” width=”600″ height=”350″]

Related Posts

26 comments

Roland Tuesday July 11th, 2017 - 07:51 PM

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

Reply
luca Wednesday July 12th, 2017 - 08:51 AM

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.

Reply
rahul Tuesday July 25th, 2017 - 09:26 AM

Really good stuff!!!
but I want to do make this possible by configuring it with Arduino IDE

Reply
luca Wednesday July 26th, 2017 - 07:37 AM

Hi! My tutorials are about using only the official IDF but you can find many articles on the Internet related to esp32+arduino…

Reply
Brian Monday October 9th, 2017 - 08:43 PM

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

Reply
luca Tuesday October 10th, 2017 - 12:42 PM

Hi Brian, I’m working on it, meanwhile you can use the esp32 forum: some users already posted example about that mode.

Reply
satme Monday October 16th, 2017 - 03:35 PM

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.

Reply
luca Tuesday October 17th, 2017 - 08:23 AM

Hi, I’m working on a tutorial about ADC, meanwhile you can read some threads in the esp32 forum.

Reply
loris Sunday October 29th, 2017 - 11:46 AM

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

Reply
luca Monday October 30th, 2017 - 08:45 AM

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.

Reply
Brian M Saturday November 25th, 2017 - 09:34 AM

Hi, Luca! Nice Tutorial.
Can I write the default password in the Kconfig file?

Reply
luca Saturday November 25th, 2017 - 02:46 PM

Hi Brian, you can include it in your program (using #define) if you want

Reply
Brian M Monday November 27th, 2017 - 11:51 PM

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

Reply
luca Tuesday November 28th, 2017 - 02:05 PM

Brian, are you running my exact code?

Reply
Waseem Sunday December 10th, 2017 - 12:00 AM

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

Reply
luca Sunday December 10th, 2017 - 05:03 PM

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.

Reply
Claudio Wednesday January 31st, 2018 - 07:32 PM

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

Reply
luca Thursday February 1st, 2018 - 11:40 AM

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!

Reply
And Monday February 26th, 2018 - 10:17 PM

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)

Reply
luca Tuesday February 27th, 2018 - 09:17 AM

ciao, la tua domanda è “si può fare”? sicuramente… tra i miei tutorial trovi tutto (AP, HTTP server, HTTP client…)

Reply
Claudio Wednesday March 7th, 2018 - 07:46 AM

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

Reply
luca Thursday March 8th, 2018 - 03:43 PM

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.

Reply
James Tang Saturday July 14th, 2018 - 05:49 AM

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?

Reply
luca Monday July 16th, 2018 - 07:51 AM

don’t think so, but you can try

Reply
asepi Tuesday January 8th, 2019 - 08:23 AM

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.

Reply
jerome Tuesday January 15th, 2019 - 10:59 AM

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

Reply

Leave a Comment