Week 11 - Networking and Communications

This week we have the following tasks to complete:

  • design, build, and connect wired or wireless node(s) with network or bus addresses and local input &/or output device(s)
  • send a message between two projects

Group Assignment

The weekly group assignment can be accessed here. For that Matthias and I used our Xiao ESP32C3 to control the brightness from the Neopixel connected to the other Xiao.

Serial Communication

To get a first impression with communication I hooked up a XIAO ESP32-C3 and used the serial monitor to receive messages from the XIAO and also send messages to the XIAO with the following code:

After using just one XIAO and communicated with them I used a second Xiao and let them communicate with each other.

ESP Now

The base idea is to get a XIAO ESP32-C3 as an remote with some rotary encoder as input devices and an indicator led that represent the color of the led strips. The receiver is an esp32-C3 WRoom dev kit 3 which controlled two RGB LED-strips and some LED-spots with some MOSFET's with a MOSFET driver. The PCB from the receiver already exist, this is also why I will use a this specific board and not another one like a XIAO ESP32-C3. I designed the receiver a few months ago before I know about the FabInventory and its handy MOSFET's that can directly controlled with a microcontroller.
To get a better idea how to use ESP now I looked up the documentation from Espressif and also for further information and understanding I looked up at Seedstudio's example and at Randomnerdstutorial.

I followed the instructions to get the MAC Address of both ESP32 boards and used the following code:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/get-change-esp32-esp8266-mac-address-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.  
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>                                           // include wifi library to activate and use wifi from the ESP32-C3 chip
#include <esp_wifi.h>                                       // include esp wifi library to read out the MAC Address from the ESP32-C3 chip

void readMacAddress(){                                      // function to read out the MAC Address
  uint8_t baseMac[6];                                       // initialize a 6 byte array to store the chars from the MAC Address
  esp_err_t ret = esp_wifi_get_mac(WIFI_IF_STA, baseMac);   // read out MAC Address im Station mode
  if (ret == ESP_OK) {                                      // if it was possible to read out a MAC Address it will sent to the serial monitor in a formation like xx:xx:xx:xx:xx:xx, where every x is replaced by a letter or digit
    Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                  baseMac[0], baseMac[1], baseMac[2],
                  baseMac[3], baseMac[4], baseMac[5]);
  } else {                                                  // if it was not possible to read out a MAC Address it will sent to the serial monitor an error message
    Serial.println("Failed to read MAC address");
  }
}

void setup(){
  Serial.begin(115200);                                     // initialize serial communication with a baudrate of 115200

  WiFi.mode(WIFI_STA);                                      // ESP is set in to station mode and not into access point
  WiFi.STA.begin();                                         // start the Wifi in station mode, probably not need it and optional but I'm not sure
}

void loop(){
  Serial.print("[DEFAULT] ESP32 Board MAC Address: ");      // this lines are original in the void setup function which didn't give me anything out, it just send a message to the serial monitor
  readMacAddress();                                         // this lines are original in the void setup function which didn't give me anything out, call up the readMacAddress function 
}

After flashing the XIAO ESP32-C3 I opened the Serial Monitor in the Arduino IDE and note down the Mac Address. I tried to repeated this for the ESP32-Wrover-E module but for some reasons my PC's could recognized the board, so I designed a small adapter pcb to use a XIAO ESP32-C3 on the footprint of the ESP32-Wrover-E module. I firstly wanted to use the Wrover module because it was already used in the receiver part of the project but after I encounter the connection problem I switched to an XIAo ESP32-C3.

XIAO 1: ec:da:3b:be:68:10
XIAO 2: ec:da:3b:be:74:1c

With this information I can setup the ESP-Now connection. For that I followed further the instruction from Random Nerds Tutorials to setup the ESP-now. Beginning with the transmitter with the following code:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <esp_now.h>                                                // include ESP-NOW library to use ESP-Now
#include <WiFi.h>                                                   // include wifi library to activate and use wifi from the ESP32-C3 chip

uint8_t broadcastAddress[] = {0xEC, 0xDA, 0x3B, 0xBE, 0x68, 0x1C};  // replaced with the receiver XIAO's MAC Address that I read out earlier it set up the broadcast MAC Address

typedef struct struct_message {                                     // Structure example to send data that must match the receiver structure
  char a[32];
  int b;
  float c;
  bool d;
} struct_message;

struct_message myData;                                              // Create a struct_message called myData

esp_now_peer_info_t peerInfo;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {                  // callback function which tracks if data is sent
  Serial.print("\r\nLast Packet Send Status:\t");                                         // send a message to a serial monitor
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");  // send a message to a serial monitor if the delivery of the data was a success or if it fails
}

void setup() {
  Serial.begin(115200);                             // initialize serial communication with a baudrate of 115200
  WiFi.mode(WIFI_STA);                              // ESP is set in to station mode and not into access point

  if (esp_now_init() != ESP_OK) {                   // initialize ESP-NOW
    Serial.println("Error initializing ESP-NOW");   // if the ESP encounter any setup errors it will send a error message to a serial monitor
    return;                                         // exit function
  }

  esp_now_register_send_cb(OnDataSent);               // after a successful initialization of ESP-NOW it will call up the OnDataSent function from earlier

  memcpy(peerInfo.peer_addr, broadcastAddress, 6);  // Register another XIAO to peer with
  peerInfo.channel = 0;                             // set peer chanel to 0, multiple channels are possible to make sure that they are no interference
  peerInfo.encrypt = false;                         // don't encrypt the transmit messages

  if (esp_now_add_peer(&peerInfo) != ESP_OK){       // function to send a MAC Address to the receiver to add a peer 
    Serial.println("Failed to add peer");           // send an error message to the serial monitor if the connection setup failed
    return;                                         // exit function
  }
}

void loop() {
  strcpy(myData.a, "THIS IS A CHAR");                                                     // set values to send
  myData.b = random(1,20);
  myData.c = 1.2;
  myData.d = false;

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); // send message via ESP-NOW

  if (result == ESP_OK) {                                                                 // send positive message to a serial monitor if the transmit was successful
    Serial.println("Sent with success");
  }
  else {                                                                                  // send error message to a serial monitor if the transmit was not successful
    Serial.println("Error sending the data");
  }
  delay(2000);                                                                            // set a delay between sending messages
}

After this I setup the receiver XIAO with the following code:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/  
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/

#include <esp_now.h>                                                          // include ESP-NOW library to use ESP-Now
#include <WiFi.h>                                                             // include wifi library to activate and use wifi from the ESP32-C3 chip

typedef struct struct_message {                                               // Structure example to send data that must match the transmitter structure
    char a[32];
    int b;
    float c;
    bool d;
} struct_message;

struct_message myData;                                                        // Create a struct_message called myData

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {  // callback function that will be executed when data is received
  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);
  Serial.print("Float: ");
  Serial.println(myData.c);
  Serial.print("Bool: ");
  Serial.println(myData.d);
  Serial.println();
}

void setup() {
  Serial.begin(115200);                                                       // initialize serial communication with a baudrate of 115200
  WiFi.mode(WIFI_STA);                                                        // ESP is set in to station mode and not into access point

  if (esp_now_init() != ESP_OK) {                                             // initialize ESP-NOW
    Serial.println("Error initializing ESP-NOW");                             // if the ESP encounter any setup errors it will send a error message to a serial monitor
    return;                                                                   // exit function
  }                 

  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));                    // after a successful initialization of ESP-NOW it will call up the OnDataRecv function from earlier to get a package information about the received data
}

void loop() {

}

The next step is to test if the setup works, which I did with two ArduinoIDE serial monitors in different windows with different com ports.

After this I added step by step one rotary encoder and the status Neopixels to the receiver and after it all four rotary encoders. The Neopixels act as an indicator so I could already test with the receiver if the rotary encoder work.

What I learn this week

  • SoftwareSerial Library is to big for the Attiny412
  • The XIAO ESP32-C3 is most of the time enough for everything you need and allows to easily communicate wirelessly with other XIAO ESP32-C3.

What I want to improve next week

Design Files


To create this page, I used ChatGPT to check my syntax and grammar.

Copyright 2025 < Benedikt Feit > - Creative Commons Attribution Non Commercial

Source code hosted at gitlab.fabcloud.org