Week 11 β Networking and Communications
This week is about networking and communication between microcontroller nodes.
The objective is to learn wire and wireless communication.
AI prompt: "Can you give me my avatar an animated landscape image (I don't want realistic image)- where in I am in my week 11 of fab academy - "networking and communication" and I am trying I2C protocol, Bluetooth and Meshtastic LoRA communication. PLease use the attached images as reference and make avatar."
Assignment Overview
- Send a message between two projects
- Design, build, and connect wired or wireless node(s) with network or bus addresses and local input &/or output device(s)
| Day | Activity | Status |
|---|---|---|
| Thursday | Week Planning π , LAB Activity π and Documentation π | Completed |
| Class - Wire and Wireless Communications | Completed | |
| Friday | LAB Activity π - Charlieplexing (ATTiny 1624) Debugging and Power-up | completed |
| Saturday | LAB Activity π - I2C communication between XIAO ESP32C6 and Charlieplexing (ATTiny 1624) | Completed |
| Sunday | Documentation π | Completed |
| Monday | LAB Activity π - I2C hub design and milling | In progress |
| Reflection and Learnings π‘ | Pending | |
| Complete Documentation - Regional Review π | In progress | |
| Tuesday | Regional Review π¨βπ«π¬ | Pending |
| Lab Activity π - Design π - LoRA with Meshtastic | Pending | |
| Watch Prof. Neilβs 2025 Lectures πΊ | Pending | |
| Wednesday | Go the Extra Mile - On Final ProjectβοΈ | Pending |
| NuEval - Final Documentation π | Pending | |
| Make instagram Reel π¬π | Pending |
Group Assignment
The group assignment was to communicate between any 2 projects already made. For the assignment purpose, we communicated between
Individual Assignment
Connect multiple nodes, there needs to be an address, can be a network address or bus address, connect nodes, connect two processor I make, or connect to phone, there has to be an address that I need ot talk to it, and local input going and coming into the network and output.
I2C Communication
I used I2C communication between XIAO ESP32C6 and ATtiny 1426 microcontroller, to connect multiple I2C nodes I designed and milled I2C hub to that I can connect other sensors such as GY-BMI160 6DOF and MAX30102 in future and test it out.
For this assignment propose, I have connected a pulse sensors as local input and charlieplexing as output device. The pulse sensor is an analog sensor and which is connected to XIAO ESP32C6 and ATtiny 1426 is driving charlieplexing LEDs in Multiplexing operation.
What Went Wrong - I2C Hub / Junction
I reversed / mirrored the I2C pin-out in the schematics, which resulted in wiring mismatch using standard I2C female-to-female wire.
What I Learned - I2C Hub / Junction
Always use standard wire sequence in the I2C connector, even though the connector in on top layer or on bottom layer always keep Pin 1 GND, Pin 2 - 3V3, Pin 3- SDA. and PIN 4 - SCL. Following this will always be correct because the connector can only get inserted in one direction, it has two grooves on the top of the connector which matches with the slots on the matting connector.
I2C communication between Two Nodes
Below I used two nodes one is XIAO ESP32C6 and one is ATtiny1624. I have Push button on XIAO ESP32C6 connected to D8 Pin which is active high and I have Status LED at pin PA5 on ATtiny1624 board. Thus the in this I2C communication when I press the button on XIAO ESP32C6 board the LED on the ATtiny1624 will blink.
// ESP32C6
#include
#define SUB_ADDR 0x08 // Address of ATtiny (must match slave)
#define BUTTON_PIN D8 // D8 pin where button is connected
void setup() {
Serial.begin(115200);
// Start serial monitor for debugging
pinMode(BUTTON_PIN, INPUT);
// Configure button pin as INPUT (NO internal pull-up/pull-down)
// External 10k pull-down handles default LOW state
// Default = LOW, pressed = HIGH
Wire.begin(22, 23);
// Initialize I2C (SDA=22, SCL=23)
Serial.println("ESP32 Main Ready");
}
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
// Read button state
Wire.beginTransmission(SUB_ADDR);
// Start communication with slave
if (buttonState == HIGH) {
// Button pressed
Wire.write(1);
// Send value '1' β turn LED ON
Serial.println("Button Pressed β LED ON");
}
else {
// Button released
Wire.write(0);
// Send value '0' β turn LED OFF
Serial.println("Button Released β LED OFF");
}
Wire.endTransmission();
// End I2C transmission
delay(100);
// Small delay to avoid flooding I2C bus
}
// ATtiny1624
#include
#define SUB_ADDR 0x08 // Must match Main
#define LED_PIN PIN_PA5 // PA5
volatile uint8_t receivedData = 0;
// Store incoming data (volatile because used in interrupt)
void receiveEvent(int howMany) {
// This function runs automatically when data is received
if (Wire.available()) {
receivedData = Wire.read();
// Read incoming byte
}
}
void setup() {
pinMode(LED_PIN, OUTPUT);
// Set LED pin as output
Wire.begin(SUB_ADDR);
// Initialize as I2C slave
Wire.onReceive(receiveEvent);
// Register function to run when data arrives
}
void loop() {
if (receivedData == 1) {
digitalWrite(LED_PIN, HIGH);
// Turn LED ON
}
else {
digitalWrite(LED_PIN, LOW);
// Turn LED OFF
}
}
I2C communication between Three Nodes
Now My Instructor Saheen asked me to add one more node and to the I2C communication. First, I added another XIAO ESP32C6 to as Subordinate and made three micro-controller network.
Network functioning is when I short-press (less than 0.5 sec) button on main micro-controller (XIAO ESP32C6) the status LED on Subordinate 1 (ATtiny1624) will flash twice and when I long-press (more than 0.5 sec) button on main microcontroller (XIAO ESP32C6) the status LED on Subordinate 2 (XIAO ESP32C6) will flash twice.
| Device | Controller | Button | Status LED | I2C Pins |
|---|---|---|---|---|
| Main | XIAO ESP32C6 | D8 (Active High) | D7 | SDA β D4 SCL β D5 |
| Subordinate 1 | ATtiny1624 | - | PA5 | SCL β PB0 SDA β PB1 |
| Subordinate 2 | XIAO ESP32C6 | D3 (Active Low) | D0 | SDA β D4 SCL β D5 |
#include // Include I2C library
#define BUTTON_PIN D8 // Button connected to D8 (Active HIGH)
#define LED_PIN D7 // LED connected to D7
#define SUB1_ADDR 0x08 // I2C address of Subordinate 1 (ATtiny)
#define SUB2_ADDR 0x09 // I2C address of Subordinate 2 (ESP32)
unsigned long pressStart = 0; // Stores time when button was pressed
bool prevState = LOW; // Stores previous button state for edge detection
void setup() {
pinMode(BUTTON_PIN, INPUT); // Button uses external pull-down β no internal pull-up
pinMode(LED_PIN, OUTPUT); // LED pin set as output
Wire.begin(22, 23); // Initialize I2C as Main β SDA=22, SCL=23
Serial.begin(115200); // Serial monitor for debugging
}
void loop() {
bool state = digitalRead(BUTTON_PIN); // Read current button state
// Detect button press (LOW β HIGH transition)
if (state && !prevState) {
pressStart = millis();
// Record time when button was pressed
}
// Detect button release (HIGH β LOW transition)
if (!state && prevState) {
unsigned long duration = millis() - pressStart; // Calculate how long button was held
if (duration < 500) {
// SHORT PRESS (<500ms)
sendCommand(SUB1_ADDR, 1); // Send command 1 to Subordinate 1
Serial.println("SHORT PRESS β Sub1");
}
else {
// LONG PRESS (>500ms)
sendCommand(SUB2_ADDR, 2); // Send command 2 to Subordinate 2
Serial.println("LONG PRESS β Sub2");
}
}
prevState = state; // Update previous state for next loop iteration
}
// ββ Function to send I2C command βββββββββββββ
void sendCommand(uint8_t addr, uint8_t cmd) {
Serial.print("Sending to: ");
Serial.println(addr);
Wire.beginTransmission(addr); // Start communication with given address
Wire.write(cmd); // Send command byte
Wire.endTransmission(); // End transmission β actually sends data
}
#include
#define LED_PIN PIN_PA5 // PA5 pin where LED is connected
#define I2C_ADDR 0x08 // I2C address for this device
volatile uint8_t command = 0; // Stores received command (volatile β used in interrupt)
// ββ I2C Receive Callback βββββββββββββββββββ
void receiveEvent(int howMany) {
if (Wire.available()) {
command = Wire.read(); // Read incoming command byte
}
}
void setup() {
pinMode(LED_PIN, OUTPUT); // Set LED pin as output
Wire.begin(I2C_ADDR); // Initialize as I2C Subordinate
Wire.onReceive(receiveEvent); // Register callback when data is received
}
void loop() {
if (command == 1) {
// If command is 1 β blink LED
blinkTwice(); // Call blink function
command = 0; // Reset command after execution
}
}
// ββ Blink LED twice ββββββββββββββββββββββββ
void blinkTwice() {
for (int i = 0; i < 2; i++) {
digitalWrite(LED_PIN, HIGH); // Turn LED ON
delay(200); // Keep it ON for 200ms
digitalWrite(LED_PIN, LOW); // Turn LED OFF
delay(200); // Keep it OFF for 200ms
}
}
#include
#define LED_PIN D2 // LED connected to D0
#define I2C_ADDR 0x09 // I2C address for this device
volatile uint8_t command = 0; // Stores received command
// ββ I2C Receive Callback βββββββββββββββββββ
void receiveEvent(int len) {
Serial.println("Data received!");
while (Wire.available()) {
command = Wire.read();
Serial.print("Command = ");
Serial.println(command);
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT); // Set LED pin as output
Wire.begin((uint8_t)I2C_ADDR); // Initialize as I2C Subordinate // Wire.begin(I2C_ADDR, 22, 23);
Wire.setClock(100000);
Wire.onReceive(receiveEvent); // Register receive callback
}
void loop() {
while (Wire.available()) {
command = Wire.read(); // Read incoming command byte
Serial.println(command);
if (command == 2) {
// If command is 2 β blink LED
blinkTwice();
command = 0; // Reset after execution
delay(10); // allow system to stabilize
}
}
}
// ββ Blink LED twice ββββββββββββββββββββββββ
void blinkTwice() {
for (int i = 0; i < 2; i++) {
digitalWrite(LED_PIN, HIGH); // LED ON
delay(200);
digitalWrite(LED_PIN, LOW); // LED OFF
delay(200);
}
}
Testing the I2C Network
After flashing code is all three microcontroller, I connected them with the I2C hub that I made for testing at the short press of button on Main XIAO ESP32C6 the onboard status LED of Subordinate 1 - ATtiny1624 blinked twice however at the long press of button on main XIAO ESP32C6 the status LED of Subordinate 2 - XAIO ESP32C6 did not blinked.
What Went Wrong --> Subordinate 2: XIAO ESP32C6
XIAO ESP32C6 does not work as Subordinate!
What I Learned --> Debugging
I am not able to resolve this issue yet but diving into this issue resolution - I learned below things.
Hardware Checks
- I2C connection / connecter pin sequence [GND, 3V3, SDA, SCL]- Checked
- Only One pull-up resistors between 3V3 and SDA in network - Checked
- Only One pull-up resistors between 3V3 and SCL in network - Checked
- Voltage between Supply and GND which is 3.3 V - Checked
- All nodes in network has common ground - Checked
- Status LED connection on ubordinate 2: XIAO ESP32C6 - Checked
- Replaced the Subordinate 2 with another XIAO ESP32C6, still not working- Checked
Software Checks
- Main code -> confirmed that long press is actually triggered - Checked
Serial.println("LONG PRESS TRIGGERED"); - Main code -> confirmed command is sent - Checked
Serial.print("Sending to: ");Serial.println(addr);
- Subordinate 2 -> added "Serial.println" inside Subordinate 2 - No response in serial print
Serial.println("Data received!"); - Address of Subordinate in Main confirmed - Checked
#define SUB2_ADDR 0x09
- Subordinate 2 address confirmed - Checked
#define I2C_ADDR 0x09
- Run I2C Scanner - Subordinate 2 XIAO ESP32C6 is not sending its Address 0X09
#include
void setup() {
Serial.begin(115200); // Start serial monitor
Wire.begin(22, 23); // Initialize I2C as Main (SDA=22, SCL=23)
Serial.println("\nI2C Scanner Starting...");
}
void loop() {
byte error, address;
int count = 0;
Serial.println("Scanning..."); // Scan all possible I2C addresses (1 to 126)
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address); // Try to communicate with this address
error = Wire.endTransmission(); // 0 = success (device responded)
if (error == 0) {
Serial.print("Found device at 0x");
if (address < 16) Serial.print("0"); // Formatting for single digit hex
Serial.println(address, HEX); // Print address in HEX
count++;
}
}
if (count == 0) {
Serial.println("No I2C devices found\n");
} else {
Serial.println("Scan complete\n");
}
delay(2000); // Wait 2 seconds before next scan
}
My Finding : This issue persist with all XIAO ESP32C6 boards that I checked. The same board works as Main however it does not work as Subordinate in the network.
Thus, I replaced the Subordinate 2 with ATtiny1624 and I was able to communicate between three nodes. Below is the network details and the arduino code.
| Device | Controller | Button | Status LED | I2C Pins |
|---|---|---|---|---|
| Main | XIAO ESP32C6 | D8 (Active High) | D7 | SDA β D4 SCL β D5 |
| Subordinate 1 | ATtiny1624 | - | PA5 | SCL β PB0 SDA β PB1 |
| Subordinate 2 | ATtiny1624 | - | PA3 | SDA β PB0 SCL β PB1 |
#include
#define LED_PIN PIN_PA3 // PA5 pin where LED is connected
#define I2C_ADDR 0x09 // I2C address for this device
volatile uint8_t command = 0; // Stores received command (volatile β used in interrupt)
// ββ I2C Receive Callback βββββββββββββββββββ
void receiveEvent(int howMany) {
if (Wire.available()) {
command = Wire.read(); // Read incoming command byte
}
}
void setup() {
pinMode(LED_PIN, OUTPUT); // Set LED pin as output
Wire.begin(I2C_ADDR); // Initialize as I2C Subordinate
Wire.onReceive(receiveEvent); // Register callback when data is received
}
void loop() {
if (command == 2) {
// If command is 2 β blink LED
blinkTwice(); // Call blink function
command = 0; // Reset command after execution
}
}
// ββ Blink LED twice ββββββββββββββββββββββββ
void blinkTwice() {
for (int i = 0; i < 2; i++) {
digitalWrite(LED_PIN, HIGH); // Turn LED ON
delay(200); // Keep it ON for 200ms
digitalWrite(LED_PIN, LOW); // Turn LED OFF
delay(200); // Keep it OFF for 200ms
}
}