11. Networking and Communications¶
Hero Shot!
Group Assignment¶
You can find more details on our lab site: TechWorks - Networking and Communications
Learning Outcomes:¶
- Understand the differences between communication protocols: UART, I²C, SPI
- Apply these protocols in real embedded systems
- Evaluate their pros and cons based on project requirements
Overview of Communication Protocols¶
UART¶
- Universal Asynchronous Receiver-Transmitter
- Uses two wires (TX and RX)
- No clock signal — devices must agree on the baud rate
- Used for simple serial communication between two devices
I²C¶
- Inter-Integrated Circuit
- Uses two lines: SDA (data) and SCL (clock)
- Allows multiple slave devices with unique addresses
- Slower but requires fewer pins and supports multi-master
SPI¶
- Serial Peripheral Interface
- Uses four lines: MOSI, MISO, SCK, SS (chip select)
- Faster communication than I²C
- Ideal for high-speed sensors and displays but uses more GPIOs
🔄 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 |
💡 Summary: - UART: Great for simple two-device serial communication. - I²C: Best when you want to connect many devices with minimal wiring. - SPI: Preferred for high-speed and high-performance communication, especially for displays and storage devices.
UART Communication Protocol¶
XIAO RP2040 —> Arduino Uno¶
I started by connecting the Arduino Uno R3 and the XIAO RP2040. Since the Arduino works at 5V and the XIAO at 3.3V, I needed a voltage divider circuit to avoid damaging the XIAO.
Voltage Divider Circuit¶
Designed in Altium Designer:
- Install: 1x3 header footprint from JLCPCB.
- Calculate resistor values R1 “”1k”” and R2 “1k+1k” to divide 5V into 3.3V.
- Simulate and fabricate using MODS as done in Electronics Production Week
Images:
Testing the voltage divider using a multimeter:
Wiring: Arduino Uno —> XIAO RP2040¶
UART Code:¶
Arduino_Transmitter_UART
#include <SoftwareSerial.h> //to create another serial port on different pins.
SoftwareSerial ArduinoSerial(10, 11); // RX, TX
void setup() {
Serial.begin(9600);
ArduinoSerial.begin(9600);
Serial.println("Arduino ready");
}
void loop() {
ArduinoSerial.println("Hello from Arduino!");
delay(1000);
}
XIAO_Reciver_UART
void setup() {
// Start serial communication on both Serial (for debug) and Serial1 (for UART)
Serial.begin(9600); // Serial monitor
Serial1.begin(9600); // UART communication with Arduino Uno
}
void loop() {
// Check if data is available on Serial1 (connected to Arduino)
if (Serial1.available()) {
// Read data from Serial1 and send it to Serial monitor
String data = Serial1.readString();
Serial.println("Received: " + data);
}
}
Communication Test:¶
I²C Communication Protocol¶
OLED Display with Arduino Uno “For Testing”¶
Wiring:¶
- VCC → 5V
- GND → GND
- SDA → A4
- SCL → A5
Code:¶
Used
Adafruit_SSD1306
andAdafruit_GFX
libraries to initialize and print to the OLED. I used the ssd1306_128x64_i2c example provided in the Arduino IDE.
- Install Libraries:
-
Open the Library Manager and install:
Adafruit SSD1306
Adafruit GFX
-
Open Example:
-
Navigate to:
File > Examples > Adafruit SSD1306 > ssd1306_128x64_i2c
-
Set Board:
- Select board: Arduino Uno
-
Choose the correct COM port
-
Upload and Run
OLED Address Check
#include <Wire.h>
void setup() {
Wire.setSDA(6); // GPIO6 = D4
Wire.setSCL(7); // GPIO7 = D5
Wire.begin();
Serial.begin(9600);
while (!Serial); // Wait for serial to be ready
Serial.println("\nI2C Scanner");
}
void loop() {
byte error, address;
int nDevices = 0;
Serial.println("Scanning...");
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
}
delay(5);
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(2000);
}
SSd1306 OLED Check
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
Serial.begin(9600);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println(F("SSD1306 Test"));
display.display();
}
void loop() {}
XIAO RP2040 —> OLED Display¶
This section explains how to connect an SSD1306-based OLED display to the XIAO RP2040 using the I²C communication protocol.
Wiring:¶
Ensure your OLED display operates at 3.3V (to match the XIAO RP2040’s logic level).
OLED Pin | 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:¶
Included OLED initialization, I²C address setup, and message display.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // No reset pin
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Wire.setSDA(4); // SDA on D4
Wire.setSCL(5); // SCL on D5
Wire.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Infinite loop if display not found
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 10);
display.println(F("Hello XIAO!"));
display.display();
}
void loop() {}
Conclusion¶
Understanding the communication protocols UART, I²C, and SPI is essential for embedded systems. Choosing between I²C and SPI depends on your speed, wiring, and complexity requirements. For displays, I²C is simple and effective for basic OLEDs, while SPI is better for high-performance displays requiring fast data throughput.
Files
Electronics
Codes