๐ Fab Academy: Week 11 - Networking and Communications
This week for networking I connected 2 ESP32-S3 boards and made them communicate wirelessly.
๐ง I soldered header pins onto the ESP32 boards so that I can attach components onto it.
๐ค Then I worked with ChatGPT to learn how to code and network between the boards.
Group Assignment
The networking of 2 different projects was done in the second spiral of my weekly assignment where I got the MAC address of one board and used it to communicate with another ESP32. You can find it here.
My learning from this was, its better to not connect 2 boards to your laptop simulataneously while uploading code. Upload the code on one board, disconnect it and then do the next. Connect them to power after the fact. This was the least buggiest way that I found to network between the 2 boards I used.
๐งญ Step 1: Getting the MAC Address
๐ The first step was to get the MAC address for one board.
๐งช It took a couple of tries to get the code just right but then it worked!
The working code:
#include <WiFi.h>
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA); // Set to Station mode
delay(1000);
Serial.print("MAC Address: ");
Serial.println(WiFi.macAddress());
}
void loop() {}

๐ฌ I had the MAC address for the receiver.
๐ฃ๏ธ Step 2: Saying Hello
๐ก I used this MAC address to do a simple serial print code that made them say hello to each other, to establish a connection.
Sender Code:
#include <WiFi.h>
#include <esp_now.h>
uint8_t peerAddress[] = {0x74, 0x4D, 0xBD, 0x97, 0x65, 0xFC};
String incomingMsg;
unsigned long lastSent = 0;
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
incomingMsg = "";
for (int i = 0; i < len; i++) {
incomingMsg += (char)data[i];
}
Serial.print("Received: ");
Serial.println(incomingMsg);
}
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_recv_cb(OnDataRecv);
esp_now_register_send_cb(OnDataSent);
esp_now_peer_info_t peerInfo = {};
memcpy(peerInfo.peer_addr, peerAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (!esp_now_is_peer_exist(peerAddress)) {
esp_now_add_peer(&peerInfo);
}
}
void loop() {
if (millis() - lastSent > 1000) {
const char *msg = "Hello from A";
esp_now_send(peerAddress, (uint8_t *)msg, strlen(msg));
lastSent = millis();
}
}
Reciever code:
#include <WiFi.h>
#include <esp_now.h>
String incomingMsg;
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
incomingMsg = "";
for (int i = 0; i < len; i++) {
incomingMsg += (char)data[i];
}
Serial.print("Received: ");
Serial.println(incomingMsg);
// Add sender as peer before replying
if (!esp_now_is_peer_exist(info->src_addr)) {
esp_now_peer_info_t peerInfo = {};
memcpy(peerInfo.peer_addr, info->src_addr, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
esp_now_add_peer(&peerInfo);
}
const char *reply = "Hello from B";
esp_now_send(info->src_addr, (uint8_t *)reply, strlen(reply));
}
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.disconnect();
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_recv_cb(OnDataRecv);
esp_now_register_send_cb(OnDataSent);
}
void loop() {
// Waiting for incoming messages...
}
Output from this transmission.
๐ก Step 3: Blinking the Onboard LED
๐จ Next, I built upon this code to make an onboard LED blink .
๐งฉ It was a task to figure out which pin the built-in LED was on, but I got it eventually!
Code for a simple LED blink:
#ifndef LED_BUILTIN
#define LED_BUILTIN 38 // fallback if not defined
#endif
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
Development for Final project!
I am going to use ESP32s as my main board for my final project, It will be used for controlling the gas release and trigger the plasma pulse from the glove. I have strated tinkering and I will post updates when I have breakthroughs!
code:
#include <esp_now.h>
#include <WiFi.h>
#include <ESP32Servo.h>
Servo myServo;
typedef struct struct_message {
int xVal;
} struct_message;
struct_message receivedData;
void onReceive(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
memcpy(&receivedData, incomingData, sizeof(receivedData));
int angle = map(receivedData.xVal, 0, 4095, 0, 180);
myServo.write(angle);
Serial.print("Received X: ");
Serial.print(receivedData.xVal);
Serial.print(" | Mapped Angle: ");
Serial.println(angle);
}
void setup() {
Serial.begin(115200);
myServo.attach(0); // D0 = GPIO 0
WiFi.mode(WIFI_STA);
WiFi.disconnect();
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW Init Failed");
return;
}
esp_now_register_recv_cb(&onReceive);
}
void loop() {
// nothing here; waiting for joystick input
}
#include <esp_now.h>
#include <WiFi.h>
#define JOYSTICK_X_PIN 0 // D0 -> GPIO 0
uint8_t receiverMac[] = {0x74, 0x4D, 0xBD, 0x97, 0x65, 0xFC}; // Updated MAC
typedef struct {
int xVal;
} JoystickData;
JoystickData dataToSend;
void setup() {
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
Serial.println("Transmitter MAC: " + WiFi.macAddress());
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW Init Failed");
return;
}
// Register peer
esp_now_peer_info_t peerInfo = {};
memcpy(peerInfo.peer_addr, receiverMac, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (!esp_now_add_peer(&peerInfo)) {
Serial.println("Failed to add peer");
} else {
Serial.println("Peer added");
}
// Read Joystick X only
pinMode(JOYSTICK_X_PIN, INPUT);
}
void loop() {
dataToSend.xVal = analogRead(JOYSTICK_X_PIN);
esp_now_send(receiverMac, (uint8_t*)&dataToSend, sizeof(dataToSend));
Serial.print("Sent X: ");
Serial.println(dataToSend.xVal);
delay(100); // Adjust as needed
}
I also tried using text prompts like 'open' and 'close sent wirelessly, between the two ESP32's. If you are using ChatGPT to generate the code for this it will first give a code like this:
#include <WiFi.h>
void setup() {
Serial.begin(115200);
Serial.println("Receiver MAC Address:");
Serial.println(WiFi.macAddress());
}
void loop() {}
This is a code to get your IP address, use this code instead:
#include <WiFi.h>
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA); // Important: Set to station mode (no Wi-Fi connection)
delay(1000);
Serial.println("ESP32-S3 MAC Address:");
Serial.println(WiFi.macAddress()); // This is the MAC you'll use for ESP-NOW
}
void loop() {}
After discarding a lot of outdated libraries, I finally got a set of code that works hand in hand. Using the MAC address that I had gotten from my reciever. these are the code files:
#include <esp_now.h>
#include <WiFi.h>
// Replace with your receiver's MAC address
uint8_t receiverMAC[] = { 0x74, 0x4D, 0xBD, 0x97, 0x65, 0xFC };
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println("ESP-NOW Sender Ready. Type 'open' or 'close' and press Enter.");
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed!");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_peer_info_t peerInfo = {};
memcpy(peerInfo.peer_addr, receiverMAC, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}
void loop() {
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd == "open" || cmd == "close") {
const char *msg = cmd.c_str();
esp_now_send(receiverMAC, (uint8_t *)msg, strlen(msg) + 1);
Serial.print("Command sent: ");
Serial.println(cmd);
} else {
Serial.println("Invalid command. Use: open / close");
}
}
}
#include <esp_now.h>
#include <WiFi.h>
#include <ESP32Servo.h> // Make sure this library is installed
Servo myServo;
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
String cmd = String((char *)incomingData);
cmd.trim();
Serial.print("Received from MAC: ");
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",
info->src_addr[0], info->src_addr[1], info->src_addr[2],
info->src_addr[3], info->src_addr[4], info->src_addr[5]);
Serial.println(macStr);
Serial.print("Command: ");
Serial.println(cmd);
if (cmd == "open") {
myServo.write(90); // Open position
} else if (cmd == "close") {
myServo.write(0); // Close position
}
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println("ESP-NOW Receiver Ready");
myServo.setPeriodHertz(50); // Set frequency to 50Hz
myServo.attach(10); // GPIO 10 (D10)
myServo.write(0); // Initial position: closed
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
// Nothing here
}
The setup of the 2 ESP's
This is the link for the ChatGPT spiral that I followed.