11. Networking and Communications¶
This week, I explored how microcontrollers can communicate with each other using different protocols.
Understanding the basics¶
What is Networking and Communications?
Networking and Communications refers to how devices are connected to each other and how through wired or wireless communication they exchange data.
UART¶
UART (Universal Asynchronous Receiver/Transmitter) is a hardware communication protocol used to transmit data asynchronously — without a clock signal.It requires only two lines: TX (Transmit) and RX (Receive). This is commonly used between microcontrollers and modules like Bluetooth, GPS, etc.
USART¶
USART (Universal Synchronous/Asynchronous Receiver/Transmitter) is an extension of UART that supports both asynchronous and synchronous communication.
SERCOM¶
- SERCOM (Serial Communication Interface) is found in microcontrollers like those from Atmel (e.g., SAMD21). SERCOM modules are flexible — they can be configured as UART, SPI, or I2C, depending on project needs.
PIO¶
- PIO (Programmable I/O) is Specific to the RP2040 microcontroller. It allows users to create custom peripheral behavior using software-defined state machines.
Asynchronized Serial Communication¶
Asynchronized Serial Communication means data is transmitted without a shared clock signal. Instead, both sender and receiver agree on a baud rate (speed), and data is framed with start and stop bits for proper synchronization.
- RS232: RS232 is used for simple device-to-device communication.
- RS422: RS422 supports longer distances and multiple receivers, ideal for industrial settings.
- RS485: RS485 is great for multi-device networks, making it suitable for building automation and industrial LANs.
Serial Communication Standards
Standard | Communication Type | Direction | Devices Supported | Max Distance |
---|---|---|---|---|
RS232 | Point-to-Point | Full Duplex | 1-to-1 | ~15 meters |
RS422 | Point-to-Multipoint | Full Duplex | 1 transmitter, up to 10 receivers | ~1200 meters |
RS485 | Multi-Point (LAN) | Half Duplex | Multiple transmitters & receivers | ~1200 meters |
Synchronized Serial Communication¶
Synchronized Serial Communication involves the exchange of data between devices using a shared clock signal. This ensures both sender and receiver are perfectly synchronized, making data transfer faster and more reliable compared to asynchronous communication.
Two common synchronous communication protocols are:
Serial Peripheral Interface (SPI)
- A fast communication method used for short distances.
- Needs 4 wires: MOSI, MISO, SCK, and SS/CS.
- One Master can talk to many Slaves using separate select lines
I2C (Inter-Integrated Circuit)
- Uses just 2 wires: SDA (data) and SCL (clock).
- One Master can talk to many Slaves using unique addresses.
- Slower than SPI but more efficient for connecting multiple devices.
Individual Assignment¶
Arduino to Arduino (I2C)¶
I reffred to Autodesk Instructables I2C Between Arduinos by Cornela to get a better understanding of how it works.
What is I2C? I2C (Inter-Integrated Circuit) is a two-wire communication protocol that allows multiple devices to communicate with a microcontroller over the same bus. It uses:
- SDA (Serial Data Line) for data transfer
- SCL (Serial Clock Line) for synchronization
How It Works
- The Master sends a command to the Slave using I2C.
- The Slave listens at a particular I2C address and takes action.
- In this example, when the Master sends
1
, the Slave turns ON an LED. When it sends0
, the LED turns OFF.
Wire connections
Connection Description | Master Arduino Pin | Slave Arduino Pin |
---|---|---|
I2C Data Line | A4 (SDA) | A4 (SDA) |
I2C Clock Line | A5 (SCL) | A5 (SCL) |
Common Ground | GND | GND |
LED for Output (Slave) | — | Digital Pin 12 → GND |
Code
Uploading the master code
Uploading the slave code
Note: Remember to check your ports before uploading the code
Master Code
#include <Wire.h>
int slaveAddress = 9; // Slave I2C address (same as in the slave code)
void setup() {
// Start the I2C communication as master
Wire.begin();
// Start the serial communication for debugging
Serial.begin(9600);
delay(1000); // Wait for Serial to initialize
}
void loop() {
// Send a command to the slave to blink the LED
Wire.beginTransmission(slaveAddress);
Wire.write('1'); // Send the command '1' to make the slave blink the LED
Wire.endTransmission();
// Print to Serial Monitor
Serial.println("Sent command to blink LED");
// Wait 2 seconds before sending the next command
delay(2000);
}
Slave Code
#include <Wire.h>
int LED = 12; // Pin for the LED
int x = 0; // Variable to store received data
void setup() {
// Define the LED pin as Output
pinMode(LED, OUTPUT);
// Start the I2C Bus as Slave with address 9
Wire.begin(9);
// Attach the receive function to handle I2C communication
Wire.onReceive(receiveEvent);
// Start serial communication for debugging
Serial.begin(9600);
}
void receiveEvent(int bytes) {
x = Wire.read(); // Read the byte sent from the master
}
void loop() {
// Print the received value to Serial Monitor for debugging
Serial.print("Received value: ");
Serial.println(x);
// If the value received is '1', blink the LED every 1 second
if (x == '1') {
digitalWrite(LED, HIGH); // Turn the LED on
delay(1000); // Wait for 1 second
digitalWrite(LED, LOW); // Turn the LED off
delay(1000); // Wait for 1 second
}
// Optional: Small delay to avoid overloading the Serial Monitor
delay(100);
}
Successful LED Blink
Once the code was uploaded the LED blinked, confirming that the I2C communication was working properly. The setup was stable and successfully demonstrated how two Arduinos can communicate using just two data lines.
Xiao RP2040 to Arduino UNO (I2C)¶
While working on this assignment, I referred to Siddharth Agarwal's documentation
From his documentation, I understood:
- RP2040 to RP2040 does not work due to a bug in the chip itself
- When connecting RP2040 to anything else, to be cautious of the voltage difference.
He quoted a valuable insight from our mentor Jesal sir's that
“One has to be careful here, since the XIAO operates at 3.3 V while the Uno operates at 5 V. The I2C connection operates at whatever the Master is operating at. So the XIAO being the Primary or Master would work for the Uno but not the other way !”
For this I will be using the board that I made during week 8
Wiring Connection
XIAO RP2040 | Arduino UNO | Description |
---|---|---|
D4 (SDA) | A4 (SDA) | I2C Data Line |
D5 (SCL) | A5 (SCL) | I2C Clock Line |
GND | GND | Common Ground |
— | Pin 12 + GND | LED connected on UNO |
Code
Uploading the master code
Uploading the slave code
Master Code for Xaio
#include <Wire.h>
int slaveAddress = 9; // The address of the Arduino Uno (slave)
void setup() {
// Start the I2C communication as master
Wire.begin();
// Start the serial communication for debugging
Serial.begin(9600);
delay(1000); // Wait for Serial to initialize
}
void loop() {
// Send a command to the slave to blink the LED
Wire.beginTransmission(slaveAddress);
Wire.write('1'); // Send the command '1' to make the slave blink the LED
Wire.endTransmission();
// Print to Serial Monitor
Serial.println("Sent command to blink LED");
// Wait 2 seconds before sending the next command
delay(2000);
}
Slave Code for Arduino
#include <Wire.h>
int LED = 12; // Pin for the LED
int x = 0; // Variable to store received data
void setup() {
// Define the LED pin as Output
pinMode(LED, OUTPUT);
// Start the I2C Bus as Slave with address 9
Wire.begin(9);
// Attach the receive function to handle I2C communication
Wire.onReceive(receiveEvent);
// Start serial communication for debugging
Serial.begin(9600);
}
void receiveEvent(int bytes) {
x = Wire.read(); // Read the byte sent from the master
}
void loop() {
// Print the received value to Serial Monitor for debugging
Serial.print("Received value: ");
Serial.println(x);
// If the value received is '1', blink the LED every 1 second
if (x == '1') {
digitalWrite(LED, HIGH); // Turn the LED on
delay(1000); // Wait for 1 second
digitalWrite(LED, LOW); // Turn the LED off
delay(1000); // Wait for 1 second
}
// Optional: Small delay to avoid overloading the Serial Monitor
delay(100);
}
Promblem faced: The slave was not responding at all. It was showing error in the code
How I fixed it: I forgot to call Wire.onReceive() in the slave code! After setting the receive callback properly, everything worked.
Final Working
Esp 32 to Esp 32¶
The ESP32 is a low-cost, low-power system-on-chip (SoC) with integrated Wi-Fi and Bluetooth capabilities. It is widely used in IoT (Internet of Things) projects due to its versatile features
Pinout
The ESP32 has many pins used for different purposes such as GPIO (General Purpose Input/Output), power supply, and communication interfaces. Below is a simplified pinout of the ESP32.
Key Pins on the ESP32:
-
GPIO Pins (0 to 39): These are the general-purpose input/output pins.
-
3V3 (3.3V): This pin provides 3.3V output.
-
5V: Provides 5V output.
-
GND: Ground pin.
-
EN (Enable): Used to enable or reset the ESP32.
-
TX/RX (UART): Pins used for serial communication.
-
SDA/SCL (I2C): Pins for I2C communication.
-
MOSI/MISO (SPI): Pins for SPI communication.
-
Analog Pins (ADC): For analog signals.
Setting up the IDE
In order to program the ESP 32 we need to download the necessary drivers. You can download them by go to [Silicon Labs] (https://www.silabs.com/developer-tools/usb-to-uart-bridge-vcp-drivers) site. We use a USB to UART bridge. Most ESP32 boards have the CP210x chip (made by Silicon Labs) built in. This chip helps the computer communicate with the ESP32 using USB. Without downloading the driver yoursystem might not be able to detect the board.
I instalied the Universal windows driver and ran the program on my computer.
Board setup on Arduino IDE
Next I opened up Arduino IDE and went to Preferences under File.
Over there, under Additional Boards Manager URL I added the following link: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
After that I went to Tools>Board>Board Manager and then sercah for esp32.
And then install the Arduino ESP32 boards
After installation You’ll now be able to select ESP32 boards under: Tools > Board > ESP32 Arduino> ESP32C3 Dev Module
I wanted to test if my ESP32 was working. I wrote a basic Blink code to turn ON/OFF the built-in LED on GPIO 2.
Code
#define LED_BUILTIN 2 // Use the correct GPIO if your board uses a different one
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
delay(1000); // wait for a second
}
After uploading the code I got on error.
To solve this:
-
I cross checked the port made sure the correct COM port was selected.
-
Some ESP32 boards require holding the BOOT button while uploading. I pressed and held the BOOT button right when the upload started, and released it once the uploading progress bar began. But even that didn't work,
After this, the issue still persisted. I still need to figure out whether it’s a problem with the USB cable or if there's an issue with the board itself and I'm still debugging it.
Group Assignment¶
Exercise files¶
Below are the files for:
Arduino to Arduino: Master code
Arduino to Arduino: Slave code