Networking and Communications

Task:-

Group assignment: Send a message between two projects.

Individual assignments: design, build and connect wired or wireless node(s) with network or bus addresses and a local input and/or output device(s).


Overview

For this assignment, I designed a simple communication system between two XIAO RP2040 boards using the I2C protocol.

Master Board:
The sitar PCB (input board), which includes a XIAO RP2040, capacitive touch pads, a NeoPixel, a switch, and a JST connector for I2C communication. This board is used to detect touch inputs and send data.

The Peripheral Board:
The output PCB (audio board), which includes a XIAO RP2040, a DFPlayer Mini MP3 module, and a speaker. This board is responsible for receiving data and playing audio.

The main issue is that the output PCB does not have a JST connector or proper I2C connection points, as it has a pin header made for servo motor - used this to connect a breakout board.

To solve this, I will design a small breakout board that connects to the servo header using sockets and provides a JST connector with SDA, SCL, VCC, and GND for I2C communication.

The communication flow is as follows:

when a touch pad on the sitar PCB is activated, the signal is sent via I2C to the output PCB. The output PCB receives this data and triggers the DFPlayer to play the corresponding swara. The switch is used to change between different swara sets, and the NeoPixel gives visual feedback.

I2C Communication

1

Breakout Board Design

Schematics

PCB routing

Milling and soldering

2

I2C Communication master and peripheral connection drawing

Using the draw.io sketch the communication connection diagram. Draw.io can be used to create diagrams, flowchart for visualization.

This process helps to understand the connections error i made, and understand I2C communication wiring.

From my experience, i recommend to always sketch the connection diagram of nodes before pcb production, to avoid silly mistakes and for better visualization of the communication flow.

Learning from the Mistake

I added a voltage regulator assuming the sitar PCB I2C operates at 3.3V, while the output PCB provides 5V, so instructor suggested add regulation, it the volatges are not matched. However, later realized that the sitar PCB I2C is already operating at 5V, so the regulator was unnecessary.

Learnings :
First verify the actual operating voltage of all connected boards before adding a voltage regulator and also understood that in I2C communication, both devices must share the same logic voltage level(for SDA and SCL).

How do i fix it

Desoldered the voltage regulator and its capacitor. After removing them, I shorted the input and output power pads of the voltage regulator footprint on the PCB.
The power path may break, and it is sometimes necessary to short (bridge: means solder both in and out pwr traces) the input and output pads to restore the connection.

Learning from the Mistake

In Master Pcb:
In the XIAO RP2040, the KiCad schematic and footprint use physical pin numbering (starting from 1), while the actual usable pins are labeled as D0, D1, D2… in the pinout.

Pin Mapping Issue

So the math doesn't process well with me, and connection i made mismatched this mapping. For example:

  • Physical pin 4 ≠ D4
  • It's actually D3 pin
I connected:
  • Pin 4 as SDA
  • Pin 5 as SCL

But in reality, those were D3 and D4, So my I2C connection was wired incorrectly.

The correct default I2C pins are:

SDA: D3, SCL: D4

How do i fix it

Master Code

            
             // Wire Master Writer
            // by Nicholas Zambetti [http://www.zambetti.com](http://www.zambetti.com)

            // Demonstrates use of the Wire library
            // Writes data to an I2C/TWI Peripheral device
            // Refer to the "Wire Peripheral Receiver" example for use with this

            // Created 29 March 2006

            // This example code is in the public domain.


            #include ⁢Wire.h>
            #define SDA_PIN D4
            #define SCL_PIN D5

            void setup() {
              Serial.begin(115200);   // better speed for RP2040
              delay(1000);

              Wire.setSDA(SDA_PIN);   // set SDA pin
              Wire.setSCL(SCL_PIN);   // set SCL pin
              Wire.begin(); // join i2c bus (address optional for master)
            }

            byte x = 0;

            void loop()
            {
              Wire.beginTransmission(4); // transmit to device #4
              Wire.write("x is ");        // sends five bytes
              Wire.write(x);              // sends one byte
              Wire.endTransmission();    // stop transmitting

              x++;
              delay(500);
            }
             
            

Peripheral Code

            
             // Wire Peripheral Receiver
            // by Nicholas Zambetti [http://www.zambetti.com](http://www.zambetti.com)

            // Demonstrates use of the Wire library
            // Receives data as an I2C/TWI Peripheral device
            // Refer to the "Wire Master Writer" example for use with this

            // Created 29 March 2006

            // This example code is in the public domain.

            #include ⁢Wire.h>
            #define SDA_PIN D4
            #define SCL_PIN D5

            void setup() {
              Serial.begin(115200);   // better speed for RP2040
              delay(1000);

              Wire.setSDA(SDA_PIN);   // set SDA pin
              Wire.setSCL(SCL_PIN);   // set SCL pin
              Wire.begin(4);                // join i2c bus with address #4
              Wire.onReceive(receiveEvent); // register event
              Serial.begin(9600);           // start serial for output
            }

            void loop()
            {
              delay(100);
            }

            // function that executes whenever data is received from master
            // this function is registered as an event, see setup()
            void receiveEvent(int howMany)
            {
              while(1 ⁢ Wire.available()) // loop through all but the last
              {
                char c = Wire.read(); // receive byte as a character
                Serial.print(c);         // print the character
              }
              int x = Wire.read();    // receive byte as an integer
              Serial.println(x);         // print the integer
            }
             
            

Chatgpt AI
Prompt Used:

I designed an output PCB(student) using the Seeed Studio XIAO RP2040, which includes an LED connected to pin D0 through a 499ohm resistor and a 10uF capacitor, DFPlayer Mini module - with the speaker connected to SPK1 and SPK2, and the BUSY pin connected to D8, Module's TX to xiao's RX, Modules RX to xiao's TX.

To enable communication between boards, I designed a breakout board using a vertical 2x3 pin socket and 2 JST S4B-PH connectors. This breakout board connects the output PCB and the sitar PCB. The I2C lines include 10kohm pull-up resistors to ensure stable communication.

On the sitar PCB (master), the JST connector intended for I2C communication is wired to default configuration of the XIAO RP2040 (SDA >> D4, SCL >> D5). The sitar PCB includes capacitive touch pads: PAD1 connected to D6, PAD2 to D8, and PAD3 to D7, each with 1Mohm resistors. A push button is connected to D9 with a 10kohm resistor, and a NeoPixel LED is connected to D5.

Give program to play music while the button is pressed; button is on sitar pcb, mp3 module in output pcb - in SD card, folder is made in name: 01 and play 0001.mp3 inside that folder.

Master Code

            
            #include 

            #define STUDENT_ADDR 0x10
            #define BUTTON D9

            void setup() {
              Wire.begin();
              pinMode(BUTTON, INPUT);
              Serial.begin(115200);
            }

            void loop() {
              int state = digitalRead(BUTTON);

              Wire.beginTransmission(SLAVE_ADDR);
              Wire.write(state);   // 1 = pressed, 0 = released
              Wire.endTransmission();

              Serial.print("Button: ");
              Serial.println(state);

              delay(100);
            }
             
            

Peripheral Code

            
            #include ⁢Wire.h>
            #include ⁢DFRobotDFPlayerMini.h>

            #define STUDENT_ADDR 0x10

            DFRobotDFPlayerMini player;

            bool isPlaying = false;

            void receiveEvent(int howMany) {
              while (Wire.available()) {
                int val = Wire.read();

                if (val == 1 && !isPlaying) {
                  Serial.println("Play");
                  player.playFolder(1, 1);  // plays 0001.mp3 in folder 01
                  isPlaying = true;
                }

                if (val == 0 && isPlaying) {
                  Serial.println("Stop");
                  player.stop();
                  isPlaying = false;
                }
              }
            }

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

              // DFPlayer Serial
              Serial1.begin(9600);

              if (!player.begin(Serial1)) {
                Serial.println("DFPlayer NOT detected");
                while (1);
              }

              player.volume(0); // 0-30

              Wire.begin(STUDENT_ADDR);
              Wire.onReceive(receiveEvent);

              Serial.println("Ready");
            }

            void loop() {}
             
            

Downloads