11. Networking and Communications¶
Group Assignment¶
Two Projects Communication¶
Hero Shot¶
Summary¶
This week, we worked on implementing I2C communication between two microcontrollers: a RP2040 (acting as the master) and an ESP32 (acting as the slave).
We configured the I2C communication so that the RP2040 sends messages to the ESP32, which processes the data and forwards it to another RP2040. Additionally, we integrated WiFi communication between the ESP32 units to enable communication over a network. In this setup, one ESP32 receives data from the RP2040 via I2C and then transmits it over WiFi to another ESP32, which passes it to the second RP2040.
We also troubleshooted issues such as incorrect data type conversions (notably with Wire.write()
) and ensured proper data formatting for reliable communication.
Work Process Detail¶
🔄 Comparison of Communication Protocols: UART vs I²C vs SPI¶
Feature | UART | I²C | SPI |
---|---|---|---|
Wires Required | 2 (TX, RX) | 2 (SDA, SCL) | 4 (MOSI, MISO, SCK, SS) |
Speed | Up to 1 Mbps (standard); varies by implementation | Up to ~3.4 MHz (Fast Mode Plus / High Speed Mode) | Typically 10–50+ MHz |
Complexity | Simple, point-to-point | Moderate; needs addressing, start/stop conditions, ACK/NACK handling | Higher; more pins, but straightforward full-duplex communication |
Device Support | 1:1 communication | Supports multiple devices via unique addresses on shared bus | Supports multiple devices using separate SS lines |
Data Direction | Bi-directional (half/full-duplex) | Bi-directional on SDA | Full-duplex with separate MOSI and MISO lines |
Clock Signal | No (asynchronous) | Yes (SCL line) | Yes (SCK line) |
Master-Slave | Not strictly defined | Yes (1 master, multiple slaves) | Yes (1 master, multiple slaves) |
Power Consumption | Low | Lower at idle; open-drain lines with pull-up resistors | Higher at high speed, but more power-efficient during fast data transfers |
Pin Efficiency | High | Very high—only 2 pins for many devices | Lower—requires more pins, especially with multiple slaves |
Range | Short to medium (typically under 15 meters) | Short (usually under 1 meter) | Very short (under 1 meter) |
Error Checking | Optional parity bit | Built-in ACK/NACK mechanism | None inherently; must be implemented in software |
Use Case Suitability | Serial communication between two devices (e.g., PC ↔ microcontroller) | Great for low-speed sensors, RTCs, EEPROMs, small OLEDs | Best for high-speed peripherals like displays, ADCs, SD cards |
Multi-master Support | No | Yes (but rarely used) | No |
🔧 Uploading Code to XIAO ESP32-C3 Using Arduino IDE¶
✅ Step 1: Install ESP32 Board Support
- Open Arduino IDE.
- Go to File → Preferences.
- In the “Additional Boards Manager URLs” field, add:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
If you have other URLs there, separate them with a comma.
-
Click OK.
-
Go to Tools → Board → Boards Manager.
- Search for
esp32
and install “esp32 by Espressif Systems” (install the latest version).
✅ Step 2: Select the XIAO ESP32-C3 Board
- Go to Tools → Board and select:
XIAO_ESP32C3
If not visible, scroll or search after installing the ESP32 core.
- Go to Tools → Port and choose the correct COM port for the board.
✅ Step 3: Uploading Code (Tips)
- If the upload fails, double-press the RESET button on the XIAO ESP32-C3.
- The onboard LED should start pulsing — it’s now in bootloader mode.
- Then click Upload again.
Test Example
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println("Hello from XIAO ESP32-C3!");
delay(1000);
}
I2C Communication Protocol¶
XIAO RP2040 —> XIAO ESP32-C3
This section explains how to connect an XIAO RP2040 to the XIAO ESP32-C3 using the I²C communication protocol.
Wiring:¶
The XIAO ESP32-C3 matches the XIAO RP2040’s logic level.
XIAO ESP32-C3 | XIAO RP2040 Pin |
---|---|
VCC | 3V3 |
GND | GND |
SDA | D4 |
SCL | D5 |
💡 Note: On the XIAO RP2040, the default I²C pins are: - SDA → D4
- SCL → D5
Code:¶
XIAO ESP32-C3 Transmitter
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(); // Default SDA = D4, SCL = D5 on XIAO ESP32-C3
}
void loop() {
Wire.beginTransmission(0x08); // Slave address
// Send the string byte by byte
const char* msg = "Hello from ESP32-C3!";
while (*msg) {
Wire.write(*msg); // Write each character as a byte
msg++;
}
Wire.endTransmission();
Serial.println("Sent to RP2040");
delay(1000);
}
XIAO RP2040 Receiver
#include <Wire.h>
void receiveEvent(int bytes) {
while (Wire.available()) {
char c = Wire.read();
Serial.print(c);
}
Serial.println();
}
void setup() {
Serial.begin(115200);
Wire.begin(0x08); // RP2040 as slave at address 0x08
Wire.onReceive(receiveEvent); // Callback on data received
}
void loop() {
}
Multi-Protocol Communication Between RP2040 and ESP32 Using I2C and WiFi¶
RP2040_1 --(I2C)--> ESP32_1 --(WiFi)--> ESP32_2 --(I2C)--> RP2040_2
Concept¶
- RP2040_1 (Master) → sends a message to ESP32_1 (Slave) over I2C
- ESP32_1 (WiFi Client) → sends that message over WiFi to ESP32_2 (WiFi Server)
- ESP32_2 (Master) → sends that message to RP2040_2 (Slave) over I2C
This is fully possible and works as intended.
Simple Flow¶
Step | Action |
---|---|
1 | RP2040_1 sends text via I2C to ESP32_1 |
2 | ESP32_1 connects over WiFi to ESP32_2 and sends message |
3 | ESP32_2 receives WiFi message and sends it via I2C to RP2040_2 |
4 | RP2040_2 receives message and prints it |
Programming Hints¶
🟢 RP2040_1 (I2C Master)¶
#include <Wire.h>
void setup() {
Wire.begin();
}
void loop() {
const char* message = "Hello FAB25!";
Wire.beginTransmission(0x08); // Address of ESP32_1
Wire.write((const uint8_t*)message, strlen(message));
Wire.endTransmission();
delay(5000);
}
🟢 ESP32_1 (I2C Slave + WiFi Client)¶
#include <WiFi.h>
#include <Wire.h>
String i2cMessage = "";
void receiveI2C(int bytes) {
while (Wire.available()) {
i2cMessage += (char)Wire.read();
}
}
void setup() {
Wire.begin(0x08); // I2C Slave address
Wire.onReceive(receiveI2C);
WiFi.begin("ESP32_SERVER", "12345678");
while (WiFi.status() != WL_CONNECTED) delay(500);
}
void loop() {
if (i2cMessage.length() > 0) {
WiFiClient client;
if (client.connect("192.168.4.1", 80)) {
client.println(i2cMessage);
client.stop();
i2cMessage = "";
}
}
}
🟢 ESP32_2 (WiFi Server + I2C Master)¶
#include <WiFi.h>
#include <Wire.h>
WiFiServer server(80);
void setup() {
Wire.begin();
WiFi.softAP("ESP32_SERVER", "12345678");
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (client) {
String data = client.readStringUntil('\n');
Wire.beginTransmission(0x09); // Address of RP2040_2
Wire.write((const uint8_t*)data.c_str(), data.length());
Wire.endTransmission();
client.stop();
}
}
🟢 RP2040_2 (I2C Slave)¶
#include <Wire.h>
void receiveI2C(int bytes) {
while (Wire.available()) {
char c = Wire.read();
Serial.print(c);
}
}
void setup() {
Serial.begin(115200);
Wire.begin(0x09); // I2C Slave address
Wire.onReceive(receiveI2C);
}
void loop() {
delay(100);
}
Learning Outcome¶
- Mastered I2C communication setup between RP2040 and ESP32 microcontrollers.
- Addressed data type conversions and ensured compatibility between devices.
- Successfully integrated WiFi communication alongside I2C.
- Enhanced troubleshooting and debugging skills related to data transfer and protocol compatibility.
- Gained deeper understanding of serial communication protocols (I2C & WiFi) in embedded systems and their combined use for complex applications.