Skip to content

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 sends 0, 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

Xiao RP2040 to Arduino UNO: Master code

Xiao RP2040 to Arduino UNO: Slave code