Networking and Communications
What is Networking & Communication
In simple words, networking and communication are all about connecting devices so they can share information. It could be through WiFi, Bluetooth, or other wireless systems.
Component / Aspect | What it Does / Why it's Important |
---|---|
WiFi Module | Helps ESP32 connect wirelessly to a network |
MAC Address | Unique permanent identity of every ESP32 device |
IP Address | Temporary address given to ESP32 when connected to WiFi |
Router / Hotspot | Provides internet connection & assigns IP address |
Web Server | Allows ESP32 to host and display a webpage |
Group Assignment
For the Networking and Communication week, I explored ESP-NOW communication between two ESP32-S3 boards. My goal was to make one ESP send a signal to the other — first just a simple "hello" to check the connection, and then move on to triggering a motor on the receiver side through a button press on the sender.
A. Finding the MAC Address of the Receiver
Before writing the actual sender code, I needed the MAC address of the receiver board. ESP-NOW communication is based on device MAC addresses, so the sender needs to know exactly where to send data.
I uploaded this code to the receiver ESP32-S3 to get its MAC:
#include <WiFi.h>
void setup() {
Serial.begin(115200);
Serial.println(WiFi.macAddress());
}
void loop() {}
I noted down the MAC from the Serial Monitor
B. Checking Communication with “Hello”
I connected both ESP32 boards to different COM ports and uploaded code separately to sender and receiver. This was a simple test — I made the sender send “hello” every 2 seconds, and the receiver printed anything it got.
Sender
#include <WiFi.h>
#include <esp_now.h>
// Structure to send
typedef struct struct_message {
char text[32];
} struct_message;
struct_message myData;
// Replace this with your receiver’s MAC address!
uint8_t broadcastAddress[] = {0xDC, 0xDA, 0x0C, 0x17, 0x81, 0xD4}; // example only
// Callback to check if data was sent successfully
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 station mode for ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(onDataSent);
esp_now_peer_info_t peerInfo = {};
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (!esp_now_is_peer_exist(broadcastAddress)) {
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}
}
void loop() {
strcpy(myData.text, "Hello from Sender!");
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *)&myData, sizeof(myData));
if (result != ESP_OK) {
Serial.println("Error sending the data");
}
delay(2000); // send every 2 seconds
}
Reciever
#include <WiFi.h>
#include <esp_now.h>
typedef struct struct_message {
char text[32];
} struct_message;
struct_message incomingData;
void onDataReceive(const uint8_t *mac, const uint8_t *incomingDataBytes, int len) {
memcpy(&incomingData, incomingDataBytes, sizeof(incomingData));
Serial.print("Received: ");
Serial.println(incomingData.text);
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_recv_cb(onDataReceive);
}
void loop() {
// Nothing here
}
COM port is very important because the initial upload failed due to choosing the wrong port. After selecting the right port, the upload worked successfully.
C. Button Controls Motor
After confirming communication, I added input and output elements. A button on the sender sends a trigger message to the receiver, which activates a motor for one second.
Sender (Button Press to Send Message)
#include <WiFi.h>
#include <esp_now.h>
uint8_t broadcastAddress[] = {0xDC, 0xDA, 0x0C, 0x17, 0x81, 0xD4}; // Replace with Receiver MAC
typedef struct struct_message {
int motorStatus; // 1 = ON, 0 = OFF
} struct_message;
struct_message myData;
const int buttonPin = 2;
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
esp_now_add_peer(&peerInfo);
}
void loop() {
if (digitalRead(buttonPin) == LOW) {
myData.motorStatus = 1;
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
Serial.println("Button Pressed: Motor ON sent");
delay(1000); // Debounce delay
}
}
Receiver (Turn ON Motor when Message Received)
#include <WiFi.h>
#include <esp_now.h>
typedef struct struct_message {
int motorStatus;
} struct_message;
struct_message incomingData;
const int motorPin = 5;
void onDataReceive(const esp_now_recv_info *info, const uint8_t *data, int len) {
memcpy(&incomingData, data, sizeof(incomingData));
Serial.print("Received motorStatus: ");
Serial.println(incomingData.motorStatus);
if (incomingData.motorStatus == 1) {
digitalWrite(motorPin, HIGH);
delay(2000); // Motor ON for 2 sec
digitalWrite(motorPin, LOW);
}
}
void setup() {
Serial.begin(115200);
pinMode(motorPin, OUTPUT);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_recv_cb(onDataReceive);
}
void loop() {
// Nothing here, everything handled in callback
}
Motor Connection to ESP32
Motor Wire Color | Connect To on ESP32 | Notes |
---|---|---|
Red (Power +) | 3.3V or 5V (check motor voltage) | Supplies power to motor |
Black (Ground -) | GND | Common ground connection |
Yellow (Signal) | GPIO pin (e.g., GPIO 5) | Controls motor ON/OFF or PWM |
This table shows the wiring connections between the motor and the ESP32 board for basic control without an external power supply.
What I Learned
-
How to communicate between ESP32 boards without Wi-Fi or Bluetooth pairing.
-
How to get and use MAC addresses for peer-to-peer wireless communication.
-
That esp_now_init() works even without setting WiFi mode explicitly in some cases.
-
How to send messages and control GPIOs based on received data.
-
Common troubleshooting steps like checking ports, using the BOOT button for upload, and validating MAC formatting.
Key Points to Remember
-
Always upload to the right port for each ESP.
-
Use esp_now_peer_info_t correctly when adding the peer.
-
Avoid unnecessary delays inside the loop unless required.
-
Debounce button presses to avoid multiple triggers.
-
Use serial prints for easier debugging during testing.
-
You may not need WiFi.mode(WIFI_STA); explicitly — test first.
Individual Assignment
A. How Connected XIAO ESP32
This was my first step. I came to know that every device has a unique MAC Address like a fingerprint. I used Arduino IDE for this.
Steps I followed:
Step 1: Connected Xiao ESP32 to laptop
Step 2: Opened Arduino IDE → Selected correct board and port
Add ESP32 Board to Arduino IDE Open Arduino IDE → Preferences
In Additional Board Manager URLs,
Go to → Tools → Board → Board Manager
Search for ESP32
Install esp32 by Espressif Systems
code
void setup() {
Serial.begin(115200); // Start Serial at 115200 baud rate
delay(1000); // Wait for Serial to start
Serial.println("Hello from ESP32 Xiao!");
}
void loop() {
Serial.println("Still running...");
delay(1000); // Wait 1 second
}
B. Got MAC Address of Xiao ESP32
While working on networking and communication using Xiao ESP32, I wanted to find out my board's MAC address.
A MAC address is like a unique identity given to every device by the manufacturer. It is really useful while connecting devices in a network or for identification.
Steps I followed:
Step 1: I opened Arduino IDE.
Step 2: Then selected the correct board: Tools → Board → Seeed Xiao ESP32C3
Step 3: After that, I selected the right port: Tools → Port → (My device port)
Library I used:
For getting the MAC address, I didn’t have to install any extra library. The Xiao ESP32 board package already comes with an in-built library called: 'WiFi.h'
This library has a simple function called → WiFi.macAddress() which directly gives the MAC address.
Code
include "WiFi.h"
void setup() { Serial.begin(115200);
// Get MAC address of the ESP32
String macAddress = WiFi.macAddress();
Serial.println("ESP32 MAC Address: " + macAddress);
}
void loop() {
// Nothing to do here
}
Output I got:
Once I uploaded this code and opened the Serial Monitor (baud rate: 115200), I got my MAC address like this:
' DC:DA:0C:17:81:D4 '
Note: This MAC address will be different for every board because each ESP32 device has its own unique MAC.
C. Touch Sensor to Servo Motor Communication using Two ESP32 Boards
For this project, I wanted to create a simple communication system between two ESP32 boards, where one board reads a touch sensor and the other board controls a servo motor based on that input. The idea was to simulate a real-world use case where a physical touch or trigger on one device could cause a movement or response in another—kind of like remote control but wired directly through serial communication .
Initially, I thought it would be easy: just plug in a touch sensor, send the value over Serial, and move the motor. But it turned out to be trickier than expected. I ran into multiple errors, communication issues, and even moments when nothing worked at all.
So, I took a step back, tested each part individually (touch sensor and servo motor), fixed wiring mistakes, changed the code, and slowly figured out how to make it all work together. This documentation captures the entire process—from the first failed attempt to the final working system—while explaining how serial communication between two ESP32s can be used for interactive control.
Initial Plan
Node A (Sender): Touch sensor → detects touch → sends a signal via Serial.
Node B (Receiver): Receives signal → moves a servo motor. It seemed simple: read the touch, send a “1” or “0” over TX/RX, move the servo. But the process wasn’t that straightforward.
First Attempt – Everything in One Go
I began by connecting both ESP32 boards and uploading codes for sensor and servo on each.
But:
-
The servo didn’t move.
-
Serial monitor on Node B showed nothing or repeated “loop running”.
-
Sometimes I got errors like:
multiple definition of 'Serial2' or 'T0' was not declared in this scope.
Troubleshooting
Test Servo Motor Independently
I disconnected everything and just tested if the servo worked with a simple code:
#include <ESP32Servo.h>
Servo myServo;
void setup() {
Serial.begin(115200);
myServo.attach(5); // GPIO 5 (D5)
}
void loop() {
myServo.write(0);
delay(1000);
myServo.write(90);
delay(1000);
myServo.write(180);
delay(1000);
}
Outcome: Servo moved! So I knew the motor and pin were working.
Test Touch Sensor Independently
Next, I tried this code:
void setup() {
Serial.begin(115200);
}
void loop() {
int value = touchRead(T0); // GPIO 4
Serial.println(value);
delay(500);
}
Outcome: I saw numbers drop when I touched the wire. So the sensor was also working
Attempt to Connect Both ESP32s Again
I wrote two new simple codes:
But Still Didn't Work!
-
The receiver showed nothing.
-
I had connected TX to TX and RX to RX — mistake!
-
Then I realized: TX from sender should go to RX of receiver.
Realization – Key Fixes & Learnings
-
At first, the setup didn’t work — touch sensor showed values, but the servo didn’t move.
-
Tested both the touch sensor and the servo individually, and both worked fine.
-
Realized the problem was in communication between the two ESP32 boards.
Fixed the wiring:
-
Connected TX of one ESP to RX of the other.
-
Added a common GND wire between both boards.
-
Saw a Serial2 error in the code — removed extra definitions to solve it.
-
Corrected the touch pin syntax: used touchRead(4) instead of touchRead(T0).
-
Checked and made sure both sender and receiver used the same baud rate (9600).
-
After these changes, the data was received properly, and the servo started moving.
-
Realized that small mistakes in wiring or code can stop the whole system from working.
Final Working Codes
Node A – Sender (Touch Sensor)
void setup() {
Serial.begin(9600);
}
void loop() {
int value = touchRead(T0); // GPIO 4
if (value < 30) {
Serial.println("1");
} else {
Serial.println("0");
}
delay(500);
}
Node B – Receiver (Servo Motor)
#include <ESP32Servo.h>
Servo myServo;
void setup() {
Serial.begin(9600);
myServo.attach(5); // GPIO 5 (D5)
Serial.println("Node B ready");
}
void loop() {
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
Serial.print("Received: ");
Serial.println(input);
if (input == "1") {
myServo.write(90);
} else if (input == "0") {
myServo.write(0);
}
}
}
Hardware Connections Between Two ESP32 Boards
Component | Sender ESP32 (Touch Sensor) | Receiver ESP32 (Servo Motor) |
---|---|---|
Touch Sensor | GPIO 4 | – |
Servo Motor | – | GPIO 5 (or D5) |
TX | GPIO 17 (TX2) | Connect to RX (GPIO 16 / RX2) |
RX | GPIO 16 (RX2) | Connect to TX (GPIO 17 / TX2) |
GND | GND | GND (common ground required) |
3.3V (if needed) | 3.3V (for sensor) | Servo powered externally if needed |
Note:
-
Always connect GND between both ESP32 boards.
-
Use Serial2.begin(9600, SERIAL_8N1, RX, TX); on both side
-
GPIO numbers may vary, so adjust if you use different pins
Final Result
-
Touching the wire changes the sensor value.
-
It sends touch value through UART.
-
The receiver reads it and moves the servo to 90 ,180 or 0 accordingly.
What I Learned
-
Test components individually first.
-
Use ESP32Servo instead of regular Servo.h.
-
Always double-check TX/RX connections (TX → RX, not TX → TX).
-
Match baud rates and use proper Serial.readStringUntil