| Master The ESP32 WiFi: ESPNow |
| Written by Harry Fairhead and Mike James | ||||
| Monday, 08 December 2025 | ||||
Page 2 of 3
We now need to create a program, ESPNOWTransmitter, that sends data to the receiver and this is very slightly more difficult. It starts off in the same way by starting the WiFi without making a connection: void app_main(void)
{
esp_event_loop_create_default();
nvs_flash_init();
esp_netif_init();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_set_channel(3, WIFI_SECOND_CHAN_NONE);
esp_wifi_start();
Notice that this ESP32 is also set to channel 3. Now we initialize ESP Now and register a send callback: int err = esp_now_init();
err = esp_now_register_send_cb(
The main difference between this program and ESPNowReceive is that we need to setup a peer struct: esp_now_peer_info_t peer = {
.peer_addr = {0x08, 0xB6, 0x1F,
This is where you have to enter the MAC address of the receiving ESP32. If you run ESPNowReceive, you can read the MAC address and enter it into this program. Now we add the peer: err = esp_now_add_peer(&peer); and send some data: uint8_t data[] = {1, 2, 3, 4, 5, 6};
err = esp_now_send(NULL, data, 6);
If the first parameter is NULL the data is sent to all of the peers that we have included in the list. If the first parameter is a MAC address the the data is only sent to that device. You can have up to 20 unencrypted peers set at any time. If you run this program, folder ESPNOWtransmitter, while the previous program is running you will see: 8 B6 1F 29 BE 7C I (663) ESPNOW: espnow [version: 2.0] init If you want to use encryption, set the peer.encrypt field to true and set the lmk field to the 128-bit key to use. Of course, both the sending and receiving devices have to use the same key and the receiving device has to add the sending device as a peer. A receiving device with no peers set can only receive broadcast packets and unencrypted packets addressed to it. Different pairs of devices can use different keys up to a maximum of six. The problem to be solved is how to distribute or agree upon a key. If you want to broadcast a message to all ESP32s listening on the same channel, you can do so using the broadcast MAC address FF,FF,FF,FF,FF,FF. This address has to be added as a peer and you also have to specify its address in the send function: esp_now_peer_info_t broadcast = {
.peer_addr = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
.encrypt = false};
err = esp_now_add_peer(&broadcast);
uint8_t data[] = {1, 2, 3, 4, 5, 6};
err = esp_now_send(broadcast.peer_addr,data,6);
printf("error= %x\n", err);
Also notice that due to the difficulty of managing keys, you cannot broadcast an encrypted message. The broadcast mechanism can be the key to distributing the MAC address. To enable this one of the ESP32s needs to broadcast a “Join” message which contains its MAC address. Any new ESP32s can receive the Join message, extract the MAC address and then send its MAC address back to the broadcasting ESP32. It can then extract the MAC address and be added to the peer list.
You can see that, using mechanisms like this, it is fairly easy to build up a network of peers that can exchange data in a very general way. Full Listing Receive#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "string.h"
#include "esp_now.h"
static void example_espnow_recv_cb(const esp_now_recv_info_t *recv_info, const uint8_t *data, int len)
{
for (int i = 0; i < len; i++)
{
printf("%2X", data[i]);
}
printf("\n");
fflush(stdout);
}
void app_main(void)
{
esp_event_loop_create_default();
nvs_flash_init();
esp_netif_init();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_set_channel(3,WIFI_SECOND_CHAN_NONE);
esp_wifi_start();
uint8_t mac[6];
esp_wifi_get_mac(ESP_IF_WIFI_STA, mac);
for (int i = 0; i < 6; i++)
{
printf("%2X ", mac[i]);
}
printf("\n");
esp_now_init();
esp_now_register_recv_cb(example_espnow_recv_cb);
while (true)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
};
}
|
||||
| Last Updated ( Monday, 08 December 2025 ) |
