Fab Academy Logo
EN | PT
EN | PT

Week 11: Embedded Networking and Communications

Group Assignment

Embedded Networking and Communications

Group assignment:

  • Send a message between two projects
  • Document your work on the group work page and reflect on your individual page what you learned

The Challenge

For this week, due to travelling and the lab being closed for Easter vacations, we needed to demonstrate communication with the least amount of hardware. We used a Pico W dev board and a Xiao RP2040 with soldered pins and a couple of wires.

For input we're just "sensing" touch on one of the analog pins and reading the value. Since it's an open pin, the value will fluctuate naturally due to noise, but when touched with the finger, the changes are quite noticeable due to capacitive coupling.


Reading the Touch Input

We ran this code to detect touch:

#define SAMPLES 50

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
}

void loop() {
  float averageValue = 0;

  for (int i = 0; i < SAMPLES; i++) {
    int rawADC = analogRead(29); // P29 / A3 / D3

    averageValue += rawADC / SAMPLES;
    delay(1);
  }

  Serial.println(averageValue);

  delay(30);
}

We then plotted the output with Arduino IDE's tool "Serial Plotter" to establish what a good threshold would be, and settled for 500 as threshold:


Master Board: Xiao RP2040 with NeoPixel

Once we established the threshold, we added communication through serial pins and controlled the onboard NeoPixel for a nicer display, since the onboard LEDs on the RP2040 are a bit dim.

Thus the protocol is quite simple: send 1 for turning on the LED, and 0 for turning it off.

Here's the code for the Xiao RP2040 which acts as the master:

#include <Adafruit_NeoPixel.h>

#define SAMPLES 50
#define NUMPIXELS    1    // Just the one LED

// Initialize the NeoPixel object
Adafruit_NeoPixel pixels(NUMPIXELS, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(115200);
  Serial1.begin(9600); // Pins D6 (TX) and D7 (RX)
  analogReadResolution(12);

  // Requirement for the RGB on the XIAO RP2040 versions
  pinMode(12, OUTPUT); // power pin needs to be on also
  digitalWrite(12, HIGH);
  pinMode(11, OUTPUT);  // PIN_NEOPIXEL
  digitalWrite(11, HIGH);

  pixels.begin();           // Start the NeoPixel
  pixels.setBrightness(30); // 0-255 range (30 is plenty for a desk)
  pixels.show();            // Initialize all pixels to 'off'
}

void loop() {
  float averageValue = 0;

  // Smoothing loop
  for (int i = 0; i < SAMPLES; i++) {
    averageValue += (float) analogRead(29) / SAMPLES;
    delay(1);
  }

  // Threshold logic
  if (averageValue < 500) {
    Serial.println("ON");
    // Set color to GREEN (Red=0, Green=255, Blue=0)
    pixels.setPixelColor(0, pixels.Color(0, 255, 0));
    Serial1.print('1');
  }
  else {
    Serial.println("OFF");
    // Set color to RED (Red=255, Green=0, Blue=0)
    pixels.setPixelColor(0, pixels.Color(255, 0, 0));
    Serial1.print('0');
  }

  pixels.show(); // Push the color to the hardware
  delay(30);
}

Notice that Serial is the serial communication with the computer through USB, whereas Serial1 corresponds to the pins on the Xiao that we use to communicate with the other board. The baud rate needs to be the same on both boards.


Slave Board: Pico W with Built-in LED

For the Pico W, that we used as slave, the code is quite simple:

void setup() {
  Serial.begin(115200);
  Serial1.begin(9600); // Pins GP0 (TX) and GP1 (RX)

  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if (Serial1.available() > 0) {
    char c = Serial1.read();

    if (c == '1') {
      digitalWrite(LED_BUILTIN, HIGH);
    } else if (c == '0') {
      digitalWrite(LED_BUILTIN, LOW);
    }
  }
}

Final Result

Here's the final result showing the communication in action:

We can see that when the pin is touched, the Xiao sends a 1 to the Pico through the serial connection and turns on the LED. Likewise, when the pin is no longer touched, it sends a 0 and it turns off the LED on the Pico.