Skip to content

Week 11 Group Assignments -

Group assignment:

Send a message between two projects

Document your work to the group work page and reflect on your individual page what you learned

Send a Message

We decided to use the I2C protocol to send messages between two projects. In this exploration we set up one development board to be a master to send messages and another as a slave that would receive and react to messages.

I2C with the Same Dev Boards

Setup

We started the setup by wiring 2 of Jeremy’s XIAO dev boards. We connected the grounds together and then ran jumpers from SCL to SCL and SDA to SDA. We did this so that the I2C connections would be able to talk to each other when we uploaded the code.

Setup using 2 of Jeremy's dev boards, the master with and SAMD XIAO and the other with ESP32C3 XIAO.

One of the boards was loaded with the XIAO SAMD21 and one was loaded with the XIAO ESP32C3. There was no particular reason for this other than the challenge of having two different boards communicating with each other.

For this exploration the SAMD was set as the master (the one sending the data) and the ESP32 was set as the slave (the one receiving and reacting to the data).

Code

There are two sets of code for this exploration, one for the master and one for the slave. The master code would loop through and send integers from 0 to 6 to the slave. The slave would listen on the line to the messages from the master and send the value to the serial output. It would also do a short blink of the onboard LED when the slave heard a “0” and a longer blink when the slave heard a “3” from the master.

Note to identify the board in the node, we chosed to give the slave ID number 9. So you will see that the master transmits to device 9, and the slave is setup to trigger when it sees data meant for device #9. Hypothetially, we could have another dev board hooked up as a slave with a different ID number that could react to a different set of messages in a different way.

The following set of code was used for the master and uploaded to the SAMD.

master_i2c.ino
// Include the required Wire library for I2C
#include <Wire.h>

int x = 0;
void setup() {
  // Start the I2C Bus as Master
  Wire.begin(); 
  Serial.begin(9600);
}
void loop() {
  Serial.print("Sent Value");
  Serial.println(x);
  Wire.beginTransmission(9); // transmit to device #9
  Wire.write(x);              // sends x 
  Wire.endTransmission();    // stop transmitting
  x++; // Increment x
  if (x > 5) x = 0; // `reset x once it gets 6
  delay(500);
}

Then the slave code was uploaded to the ESP32 PCB.

master_i2c.ino
// Include the required Wire library for I2C<br>
#include <Wire.h>
int LED = 20;
int x = 0;
void setup() {
  // Define the LED pin as Output
  pinMode (LED, OUTPUT);
  Serial.begin(9600);
  // Start the I2C Bus as Slave on address 9
  Wire.begin(9); 
  // Attach a function to trigger when something is received.
  Wire.onReceive(receiveEvent);
}
void receiveEvent(int bytes) {
  x = Wire.read();    // read one character from the I2C
}
void loop() {
  Serial.print("Recieved Value");
  Serial.println(x);

  //If value received is 0 blink LED for 200 ms
  if (x == 0) {
    digitalWrite(LED, HIGH);
    delay(200);
    digitalWrite(LED, LOW);
    delay(200);
  }
  //If value received is 3 blink LED for 400 ms
  if (x == 3) {
    digitalWrite(LED, HIGH);
    delay(400);
    digitalWrite(LED, LOW);
    delay(400);
  }
}

Testing

One the code was uploaded, we watched the data come through on the serial port. Indeed the slave was seeing the values come through from the I2C. We were also able to see the LED blinking as expected. Note the image at the top of the page shows the board in mid-blink with the same code.

Serial output from the I2C test.

I2C Test with Different Boards

Once this pathway was proven, we wanted to test to see if we could get David’s dev board to talk to Jeremy’s dev board.

Setup

For this exploration we setup David’s board as the master. David’s board used a soldered down XIAO ESP32C3.

We used the same electrical connections as in the first setup with 2 jumpers connecting GND, SDA, and SCL between the boards.

Setup using David's board (left) and Jeremy's board (right.)

Code

We used the same master code from above and flashed David’s device with it. We left the slave code on Jeremy’s board the same.

Testing

We observed after uploading the code that Jeremy’s board was recieving the same messages and the LED on his board was reacting to the “0” and “3” when they came across the line.

Demonstration of I2C sending data from David's board to Jeremy's board.

I2C Test with Different Boards and Neopixels

We did one final variation of the board communication exploration. We added some code to the slave sketch to drive the Neopixel on Jeremy’s board to show different colors when it saw the “0” or “3” from the master. We felt that this would help more positively identify when that bit of data came across the line.

Setup

Same setup as above with the same wiring.

Code

The updated code with the Neopixel library and code to show red when it hears a “0” and green when it hears a “3” is below.

master_i2c_neo.ino
// Include the required Wire library for I2C<br>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>

int LED = 20;
int LED_PIN= 10;
int x = 0;
int LED_COUNT= 1;

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

uint32_t colors[] = {
  strip.Color(255, 0, 0),      // Red
  strip.Color(255, 165, 0),    // Orange
  strip.Color(255, 255, 0),    // Yellow
  strip.Color(0, 255, 0),      // Green
  strip.Color(0, 255, 255),    // Cyan
  strip.Color(0, 0, 255),      // Blue
  strip.Color(255, 0, 255),    // Magenta
  strip.Color(128, 0, 128),    // Purple
  strip.Color(255, 255, 255),  // White
  strip.Color(0, 0, 0)         // Off
};

void setup() {
  // Define the LED pin as Output
  pinMode (LED, OUTPUT);
  Serial.begin(9600);
  // Start the I2C Bus as Slave on address 9
  Wire.begin(9); 
  // Attach a function to trigger when something is received.
  Wire.onReceive(receiveEvent);
}
void receiveEvent(int bytes) {
  x = Wire.read();    // read one character from the I2C
}
void loop() {
  Serial.print("Recieved Value");
  Serial.println(x);

  //If value received is 0 blink LED for 200 ms
  if (x == 0) {
    digitalWrite(LED, HIGH);
    strip.setPixelColor(0, colors[0]);
    strip.show();
    delay(200);
    digitalWrite(LED, LOW);
    delay(200);
  }
  //If value received is 3 blink LED for 400 ms
  if (x == 3) {
    digitalWrite(LED, HIGH);
    strip.setPixelColor(0, colors[3]);
    strip.show();
    delay(400);
    digitalWrite(LED, LOW);
    delay(400);
  }
}

Testing

We ran the test again and observed how the boards behaved. Now we were able to see that Jeremy’s board blinked the onboard blue LED and updated the color of the Neopixel correctly.

Demonstration of I2C sending data from David's board to Jeremy's board.