Week 11: Networking and Communications
Overview
This week I will be testing how to connect a keyboard to a PCB. My final project will have a handheld console that will require the use of a keyboard. I'm going to connect a wired Keyboard to my RP2040 console from weeks 4, 8, 9, and 10. I'm kind of nervous because the board is aready FULL and I did not leave myself ANY room to add components. So I am preparing myself for a battle.
The keyboard has its own ESP32-C61HF4 microcontroller and a fixed I2C bus address, which makes this a genuine two-node network rather than a simple peripheral wired to a GPIO pin.
This week I proved out the keyboard integration and communication layer on my existing test bench before committing to milling the final console PCB.
Group Assignment
- The group assignment this week was to send a message between two projects and document it on the group page.
Individual Assignment
- Design, build and connect wired or wireless node(s) with network or bus addresses and a local input and/or output device(s).
My keyboard is an Inter Integrated Circuit
An inter integrated circuit is a two wire serial communication protocol that allows multiple devices to share the same bus. One device acts as the controller and everything else is a peripheral (they listen and only respond when adressed by the controller directly.
The two wires are Serial Data and Serial Clock
- Serial Data: carries the actual data.
- Serial Clock: a clock signal generated by the controller that keeps everything in sync
Everytime my RP2040 calls a wire request it is specifically asking the keyboard (and only the keyboard) to send one byte. If a key has been pressed, that byte is the ASCII characer code. If nothing was pressed, it returns zeros and the sketch ignores it.
Why inter integrated circuits for this week?
My keyboard has a favtory default mode that is set for an inter integrated circuit so there does not need to be any firmware changes or mode switching. This was important to me because I value simplicity. It also only requires two data lines and if you've already seen my week 10 you know I'm STRESSED when it comes to available PCB real estate. My only alternative would have been a point to point system and doesn't have addressing or ESP now wich would have required going wireless. Again, simplicity was my biggest concern this week so going with the I2C allowed me to demostrate a real network with addresses.
What is Communicating:
| Mode | Role | MCU | Bus Address | Local input and output |
| Keyboard | Inter Integrated Circuit Peripheral | ESP32-C61HF4 | 0X5F | 42 Key keyboard input, RGB status LED |
| My custom PCB ft a RP2040 | Inter Integrated Circuit Controller | Seeed XIAO RP2040 | Controller (no addy) | My touchscreen, UV sensor, textile button, haptic feedback device |
A note about addressing: If a non-zero byte comes backm a key was pressed. This is how the controller selects which node to communicate with. I hope this piece satisfys this week's addressing requirement.
Wiring
Bill of Mateirals - This week's addition
| Component | Part | Interface |
| Keyboard | ESP32-C61HF4 | Via grove connector |
| My custom PCB ft a RP2040 | Custom milled (weeks 4 and 8 of my documentation) | Plugging via D4 and D5 |
Connections
| Keyboard Grove Pin | Signal | Pin on RP2040 | Note |
| GND | GND | GND | Common Ground |
| 5V | Power | 3V3 | DO NOT use the 5V on the RP2040 |
| G26 | SDA | D4 | In week 10 I kept this pen for the keyboard |
| G25 | SCL | D5 | In week 10 I kept this pen for the keyboard |
Bring Up Method
I relied on my tape method again mentioned in previous weeks to make sure I can reuse my main components witout accidently damaging them. Once all four wires were positioned I ran a continuity check with my multimeter: each wire rang through to its intended pad, and I confirmed no adjacent wires were bridged to each other. Only after that check passed did I solder. I also verified that the keyboard's wires were fully isolated on the keyboard side before connecting
Programming
Toolchain
Same toolchain as weeks 8–10: Arduino IDE with the RP2040 core, board set to Seeed XIAO RP2040, COM6, serial at 115200. No new libraries were needed this week.
How the code works
In setup() I initialise the I2C bus by calling Wire.begin(D4, D5), which assigns SDA to pin D4 (GP6) and SCL to pin D5 (GP7). Everything else (the button, UV sensor, display, and haptic feedback) are unchanged from week 10.
In loop() I added a keyboard poll. Each cycle I call Wire.requestFrom(0x5F, 1) to ask the CardKB2 for one byte, then read it with Wire.read().
The UV footer, the textile button prompt advance, and motor timeout from weeks 9 and 10 all continue running in the same loop unchanged.
// ───────────────────────────────────────────────────────────── // Fab Academy Week 11 — Networking & Communications // Heaven Whitby — handheld journaling console (test bench) // Board: Seeed Studio XIAO RP2040 (custom milled PCB, Week 8) // // NETWORK: I2C bus // Node 1 (peripheral): M5Stack CardKB2 at address 0x5F // Node 2 (controller): This RP2040 — polls 0x5F each loop for keystrokes // // OUTPUT devices (preserved from Week 10): // - 2.8" ILI9341 SPI TFT (240x320) — displays prompt + typed response // - DC vibration motor via MOSFET on D2 (reminder buzz) // Inputs preserved from Week 9: // - Velostat fabric button on A0/D0 (press = clear response + next prompt) // - GUVA-S12SD analog UV sensor on A3 (shown in footer) // // NEW this week: // - Wire.h I2C init on D4 (SDA) / D5 (SCL) // - CardKB2 polled at 0x5F each loop — keystrokes appended to userInput string // - Backspace (0x08) removes last character // - userInput rendered live in the response area below the prompt // // Libraries: Adafruit GFX, Adafruit ILI9341, Wire (built into RP2040 core) // Toolchain: Arduino IDE + Earle Philhower RP2040 core, board = XIAO RP2040 // ───────────────────────────────────────────────────────────── #includeProblems
Display blank and motor buzzing continuously on first power-up.
Lesson Learned:
When I first powered up the board with the CardKB2 connected, the display came on but showed nothing and the motor buzzed continuously.
I powered it off and started combing through the physical board. I didn't notice anything and tried plugging it back in. Unfortunately the buzzing continued with a blank screen.
Based on the buzzing continuing, I knew that it had to be something I'd done during soldering. I decided to pull out a magnifying glass to see if maybe there was something going on that I couldn't easily see. I then saw that there were some soldering issues related to my original fear of my board not being initally designed for a FILLED PCB.
Solder bridge between CS and motor resistor.
Lesson Learned:
I was really happy to find out why the motor was continuously buzzing was as "simple" as the resistor being interrupted. Then I was worried because the trace is SO tiny there and I had huge globs of flux all over that area. I had no idea what to do to get that area clear. All attempts to reheat and remove the flux was unsuccessful.
I don't have any solder wick so I used the flick method. The flick method worked good enough but I also grabbed my dull Xacto knife to try to "cut" the cold flux to separate it and destroy the bridge.
Ground Wire
Lesson Learned:
Even after clearing the bridge the display was still blank. I grabbed the magnifying glass again and noticed that the GRD from my touchscreen had come loose as well. Without a common ground the touchscreen didn't have a reference and everything was floating. It took a while but I was able to get it reconnected.
RST Wrie
Lesson Learned:
After fixing the gnd joint the serial monitor confirmed the sketch was running and I could see pressure and UV index values printing correctly but the display remained blank. I glanced over to my setup and noticed that in my rush to reconnect the gnd wire I somehow knocked the reset wire loose. A floating RST pin leaves the display in an undefined state on startup and prevents initialiation. I resolderd RST back to D7 and the display came back immmediatley.
Gallery
Videos
From Vimeo
Sound Waves from George Gally (Radarboy) on Vimeo.
From Youtube