ESP系マイコンにはお手軽な無線通信方式であるESP-NOWが用意されています。

ESP-NOWはwifi通信のベンダー領域を使い,お互いのMACアドレス (Media Access Control address) を指定して1対1,1対多などの通信ができる仕様になっていて,一度に送れるデータは250バイトまでです。


まずは手持ちのSeeed Studio XIAO ESP32C3を2台使い,ESP-NOWで1対1通信を試してみました。

隣り合わせにしているので,アンテナは付けていません。






・Arduino IDE環境での設定と注意点


1) ESP32 ボードを2.0.17などのバージョンに下げる



ボードのバージョンが3.x.xでは Seeed Studio XIAO 本家のサンプルコードなどでもコンパイルエラーが出ました。

どうもSDカードのライブラリの時のように何か互換の無い変更がされているようです,,。

以前のバージョンにすると,立ち上げ時にしつこく「バージョンアップがあります」と出ますが無視しています(^^;;;;;;。



2) 受信側のマイコンのMACアドレスを調べる

いろいろな方法があるようですが,ESP32は何かプログラムをダウンロードすると出力にMACアドレスが表示されますので,これをメモしています。



ESP32では表示されているMACアドレスがベースになるようです。
ESP-NOWには普通はこのまま使えます。

wifi STAモード (ステーションモード):ベースそのまま
wifi APモード (アクセスポイントモード):ベース+1
Bluetooth:ベース+2
だそうです(未確認)。

なお,ESP-NOWではすべての相手に送れるブロードキャストアドレスもあり,送信コードのテストなどには便利かもしれません。
ブロードキャストアドレス:(ff:ff:ff:ff:ff:ff)



・動作確認

コンパイルエラーの赤文字出力を幾度も乗り越えて(^^;;;;;;
下記にメモしているシンプルな送信,受信プログラムを走らせたところです。

向かって右側が送信側の送信状態を確認するモニタ,左が受信側で受信したデータのモニタ出力です。





・参考
How to: ESP-Nowで超お手軽デバイス間無線通信 (Zenn)
 ESP-NOWについて,またプログラム作成の流れなどをとても分かりやすく解説されています(^^)。


送信側プログラムです

/* XIAO_ESP32C3 ESP-NOW Sender Code test1 */

#include <WiFi.h>
#include <esp_now.h>

// Set Receiver_Address (MAC Address)
uint8_t Receiver_Address[] = {0x58, 0x8c, 0x81, 0x--, 0x--, 0x--};


// Create a struct_message called myData
typedef struct {
   char a[32];
   int b;
} struct_message;

struct_message myData;


// create peer_info
esp_now_peer_info_t peerInfo;


// callback function will be executed when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
   Serial.print("\r\nLast Packet Send Status:\t");
   Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}


void setup() {

   // Initialize Serial
   Serial.begin(115200);

   // Set device as Wi-Fi Station mode
   WiFi.mode(WIFI_STA);

   // Init ESP-NOW
   if (esp_now_init() != ESP_OK) {
       Serial.println("Error initializing ESP-NOW");
       return;
   }

   // Set a callback_function that will be executed when data is sent
   esp_now_register_send_cb(OnDataSent);

   // Set peer_Info
   memcpy(peerInfo.peer_addr, Receiver_Address, 6); // Set receiver address
   peerInfo.channel = 0;       // Set channel 0
   peerInfo.encrypt = false;   // No encryption
   
   if (esp_now_add_peer(&peerInfo) != ESP_OK){  // add peer node and Error check
       Serial.println("Failed to add peer");
       return;
   }

} // setup end


void loop() {

   // Insert test_data into myData
   strcpy(myData.a, "Hello from XIAO C3");
   myData.b = random(1, 20);
   
   // Send data
   esp_now_send(Receiver_Address, (uint8_t *) &myData, sizeof(myData));
   
   delay(2000);

} // loop end





受信側プログラムです

/* XIAO_ESP32C3 Receiver Code test1 */

#include <WiFi.h>
#include <esp_now.h>


// Create a struct_message called myData
typedef struct {
   char a[32];
   int b;
} struct_message;

struct_message myData;


// callback function will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
 memcpy(&myData, incomingData, sizeof(myData));
 Serial.print("Bytes received: ");
 Serial.println(len);
 Serial.print("Char: ");
 Serial.println(myData.a);
 Serial.print("Int: ");
 Serial.println(myData.b);
}


void setup() {
 // Initialize Serial
 Serial.begin(115200);
 
 // Set device as Wi-Fi Station mode
 WiFi.mode(WIFI_STA);

 // Init ESP-NOW
 if (esp_now_init() != ESP_OK) {
   Serial.println("Error initializing ESP-NOW");
   return;
 }
 
 // Set a callback_function that will be executed when data is received
 esp_now_register_recv_cb(OnDataRecv);

} // setup end


void loop() {

} // loop end