Skip to content

11. Networking and Communications

This week I worked on communication between two microcontrollers.

Weekly Objectives

  • individual assignment:
  • design, build, and connect wired or wireless node(s)
  • with network or bus addresses and local input &/or output device(s)

  • group assignment:

  • send a message between two projects

Group Assignment

In this week group assignment, Elle and I figured out how to connect her servo with my sensor. I designed the board and soldered components onto the board. You can find our full group documentation here.

TFT Touch Screen

Since my final project requires te use of TFT screen, I decided to use TFT screen for this week. During weekend I followed Connor Cruz’s Documentation and downloaded the library Connor used.

Next I asked ChatGPT to help me with the wiring according to the example code. I used XIAO Rp2040 for this.

I then successfully uploaded an example code from the tutorial.

Since it was really late that night, I decide to leave the rest of it till the next day. In order to put the screen back to its box, I took off the wires from the screen.

The Tragedy of my TFT Screen

The next day, when I tried to connect the wires to the screen according to the picture I took the day before, the TFT dsiplay suddenly started to smoke once I plugged in power. I immediately cut the power off but the TFT Screen was still broken after this. So I had to ask Mr. Dubick to buy me a new one.

Touch Sensor with ESP32-C3

During Input week, I did touch sensor with XIAO rp2040. In this week, I used the same touch sensor but switched to XIAO ESP32-C3.

Here’s a video of it working:

Screen with RP2040

Since my TFT was broken, I had to switch back to the OLED I used last week. However, this made this week so much faster since I already knew how to use an OLED screen. So I just use the same circuit as last week.

Communication between ESP32-C3 and RP2040

Then the hardest part of this week came: the communication between the two microcontrollers. I asked Claude for help. With the help of Claude, I used the simplest way - GPIO Communication - to make two microcontrollers communicate with each other. The only need to connect the two D1 on each microcontroller and connect the GND on each microcontroller. Here’s a wiring diagram of the additional part of the circuit.

I also got the code from Claude. The first time I tried it, the code worked but not completely.

The picture of Miffy did not full show up. I asked Claude to modify the code.

After several tries, the code was finally written correctly.

Correct Codes

Here’s the corrrect code for each microcontroller:

XIAO RP2040

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET   -1  // Reset pin not used
#define SWITCH_PIN 28    // Slide switch connected to GPIO28
#define SIGNAL_PIN D1     // Input pin for receiving signal from ESP32-C3


Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// Miffy bitmap data
const unsigned char miffyBitmap[] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x0e, 0x00, 0x07, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x80, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0x60, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xe0, 0xc0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x61, 0xc0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x61, 0x80, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x73, 0x80, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x73, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x73, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x73, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x77, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x77, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x77, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x3e, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x70, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x70, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x0e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x0e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x07, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x30, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x30, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xc7, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


// Variables
bool displayActive = false;
unsigned long displayStartTime = 0;
const unsigned long displayDuration = 5000;  // 5 seconds display time


void setup() {
  Serial.begin(115200);

  // Initialize pins
  pinMode(SWITCH_PIN, INPUT_PULLUP);  // Use internal pull-up resistor
  pinMode(SIGNAL_PIN, INPUT);


  // Initialize display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    while (true);  // Halt if display is not found
  }


  // Clear display on startup
  display.clearDisplay();
  display.display();

  Serial.println("XIAO RP2040 OLED Controller Ready");
}


void loop() {
  int switchState = digitalRead(SWITCH_PIN);
  int signalState = digitalRead(SIGNAL_PIN);

  if (switchState == LOW) {  // Switch ON (connected to GND)
    // Check for incoming signal from ESP32-C3
    if (signalState == HIGH && !displayActive) {
      Serial.println("Touch signal received, displaying Miffy!");
      displayActive = true;
      displayStartTime = millis();

      // Display Miffy bitmap
      display.ssd1306_command(SSD1306_DISPLAYON);  // Make sure display is ON
      display.clearDisplay();
      display.drawBitmap(0, 0, miffyBitmap, SCREEN_WIDTH, SCREEN_HEIGHT, WHITE);
      display.display();
    }

    // Check if display should turn off after timeout
    if (displayActive && (millis() - displayStartTime >= displayDuration)) {
      Serial.println("Display timeout - turning off image");
      display.clearDisplay();
      display.display();
      displayActive = false;
    }
  } else {  // Switch OFF
    if (displayActive) {  // Only need to check if the display is active
      // Turn off display if it was active
      display.clearDisplay();
      display.ssd1306_command(SSD1306_DISPLAYOFF);
      displayActive = false;
      Serial.println("System turned OFF - display deactivated");
    }
  }

  delay(50);  // Small delay to prevent excessive processing
}

XIAO esp32-c3

#include <Arduino.h>


// Pin definitions
const int touchPin = 6;      // Touch sensor input pin
const int outputPin = 3;     // Pin to send signal to RP2040
const int ledPin = 7;        // LED indicator


// Variables
int touchState = LOW;
int lastTouchState = LOW;


void setup() {
  pinMode(touchPin, INPUT);    // Touch Sensor
  pinMode(outputPin, OUTPUT);  // Output to RP2040
  pinMode(ledPin, OUTPUT);     // LED indicator

  // Initialize output pins to LOW
  digitalWrite(outputPin, LOW);
  digitalWrite(ledPin, LOW);

  Serial.begin(115200);
  Serial.println("XIAO ESP32-C3 Touch Sensor Ready!");
}


void loop() {
  // Read touch sensor state
  touchState = digitalRead(touchPin);


  // Print the current state
  if (touchState == HIGH) {
    Serial.println("TOUCH DETECTED!");
    digitalWrite(ledPin, HIGH); // Turn LED ON

    // Check if this is a new touch (rising edge)
    if (lastTouchState == LOW) {
      // Send signal to the RP2040
      digitalWrite(outputPin, HIGH);
      delay(100); // Short pulse
      digitalWrite(outputPin, LOW);
      Serial.println("Signal sent to OLED controller!");
    }
  } else {
    Serial.println("NO TOUCH DETECTED");
    digitalWrite(ledPin, LOW);  // Turn LED OFF
  }

  // Save the current touch state for next comparison
  lastTouchState = touchState;


  delay(100); // Short delay for stability
}

Here’s the video of it working:

Kicad and Milling

I designed the two boards in Kicad.

Here’s the schematic diagram:

Here’s the PCB diagram:

And the 3D view of the PCB:

Then I milled the boards out and got two delicated PCBs

Soldering

I soldered the pin headersand and other components onto the boards.

Then put the two microcontrollers onto the matching boards.

Then I got the two boards to work!

Reflection of the Week

This week was so dramatic. After experiencing my first hopefully last frying a component, I was upset for a while since the component was kinda expensive. However, after 15 minutes of panicking, I decided to use back to my tiny safe OLED screen (at leat if I frythis one, it won’t cost too much). I also learned a lot about communication. ChatGPT told me to use 12C communication (SPI and UART) while Claude gave me thesimpler way GPIO communication. Now I trust Claude more than ChatGPT on electronics (Claude you are my GOD but ChatGPT I still love you~~~). This week was really fun and I am kinda scared for machine week which is next week. Let’s see what I can make in two weeks!

AI Usage

I used ChatGPT to help me generate the code and fixing my wiring. You can found the whole conversation here.

I also used Claude to help me improve my code. You can find the whole conversation here.

File Download

You can download my file here.


Last update: June 2, 2025