12. Networking and Communications.¶
Making things communicate. I’ll be playing around with I2C. The plan is to have three boards. One main and two nodes. The main is Seeed Xiao ESP32C2 and the nodes are one Seeed Xiao RP2040 and one Attiny412. The ESP provides power to the other two over 5V and the nodes have a button and an LED. I’m largely basing this off Andri’s Design (He’s re-doing his page, Adding link when ready). I’m choosing the ESP for the option to control it over Wi-Fi or Bluetooth if I have the time for it.
Group Assignment¶
Hero-Ish shot.¶
Research¶
I did some light reading. Particularly this fantastic Basic Guide to I2C from Texas Instruments and the I2C manual linked on this week’s class page.
We also got a new toy at the lab. An Xtool F1 Ultra I’ll be playing around with that for making these.
Board Design¶
I’ll go through each part separately. These are all done in KiCad 9. The idea is I want each one to be some variation of my hand. I’ll do the traces and a rough outline in KiCad but use Inkscape to fine-tune them.
Main Xiao¶
Starting off with the Schematic, I’m using an extra pair of headers as a semi-breakout to for breadboarding or getting measurements. Not sure how that’ll work with measurements since it can’t easily complete a circuit.
Moving on to the PCB, Fairly simple stuff. I’m using the Edge cuts to get a rough outline for the intended design which is a fist.
Here’s the fist image:
I trace the fist in Inkscape then import the traces as an SVG and use Inkscape’s greatest tools to combine the two. (the “Path” tools)
Here’s what the completed Inkscape file looks like:
I export the fist outline on the left as a .PNG at 1000DPI and the other as a separate SVG. I’ll use the Roland MDX-20 to cut the board outline and the Xtool to burn away everything but the traces.
Node Tiny412¶
Schematic:
PCB:
Inkscape:
(I only realized after making this one that I completely forgot the 1 uF capacitor. )
Node RP2040¶
Schematic:
PCB:
Inkscape:
I used Inkscape to stretch out the traces on each side into the fingers.
Node Whoopsie¶
After making the RP2040 I realized I also completely forgot the Resistors on SDA and SCL so I quickly made a very ironic thumbs down board to fix that.
Schematic:
PCB:
Inkscape:
Manufacture¶
Making these boards was a lot of fun. I start off cutting the board outline on the Roland MDX-20:
Then I move on to doing the traces using the Xtool. The process of using the xTool for traces is surprisingly easy. I had some trouble finding settings that worked properly for the FR1 we use here. I tried Neil’s settings from the Electronics Production Week page but I felt like they were too slow and aggressive. I ended up using a mix of Neil’s settings and the ones from this guide on Github. The settings I ended up using were:
Neil had his speed at 750 mm/s, The Github guide put it at 600 mm/s, I used 1400 mm/s. I’m also using 300 lines per cm. The most important part is making sure the Engraving mode is Bi-Directional and the angle set to Incremental.
Engraving mode set to Bi-Directional and the frequency upped to 32kHz. I noticed the surface didn’t look as rough when I upped the frequency slightly. This setting is significantly faster than both of the others.
Here’s a little video of the xTool engraving:
Here are the boards:
(TODO: Add image of the thumbs down resistor variant)
Code¶
Due to time constraints I had to use the code from Andri’s Networking and Communications Page I made some very* minor modifications. (Addresses and changing the print messages.)
ESP Code:¶
⌨️ show / hide code
#include <Wire.h>
//Modified code from Andri Sæmundsson. (https://fabacademy.org/2023/labs/akureyri/students/andri-semundsson/pages/week13.html)
int i = 0;
void setup() {
Serial.begin(115200);
//Begin Communication, no need for any address because this is the master
Wire.begin();
}
void loop(){
delay(200);
Wire.requestFrom(1,64);
while(Wire.available()){
int c = Wire.read();
if ( c > 0 ){
Serial.println("Node 1 Pressed! Tiny Attiny thumbs up!");
delay(200);
}
}
Wire.requestFrom(2,64);
while(Wire.available()){
int c = Wire.read();
if (c > 0 ){
Serial.println("Node 2 Pressed! Xiao fistbump!");
delay(200);
}
}
}
/*
void loop(){
//This is the part where the control requests data from a node
//Wire.requestFrom("address of node", "amount of bytes to request", true or false to not cut or cut communication)
Wire.requestFrom(1,64); //requesting 64 bytes from node1
while(Wire.available()){
int c = Wire.read();
if(c > 0 ){
Serial.println("Node 1 pressed! Tiny Attiny Thumbs up!");
}
}
Wire.requestFrom(2,64); //requesting 64 bytes from node2
while(Wire.available()){
int c = Wire.read();
if(c > 0){
Serial.println("Node 2 pressed! Not so tiny Xiao Fistbump!");
delay(200);
}
}
}
*/
ATtiny412 Node:¶
⌨️ show / hide code
#include <Wire.h>
#define LED_PIN 4
#define BUTT_PIN 5
int BUTT_STATE;
void setup() {
pinMode(LED_PIN, OUTPUT); // Set LED_PIN (Pin 4, PA3) as output
pinMode(BUTT_PIN, INPUT_PULLUP); // Set button as input with internal pull-up resistor
BUTT STATE = 0;
Serial.begin(115200); // Initialize serial communication
Wire.begin(1); // Begins I2C Wire as Node 1.
// Wire.onRequest waits for a request from the main board before running void(requestEvent)
Wire.onRequest(requestEvent);
}
void loop() {
if (digitalRead(BUTT_PIN) == LOW){
digitalWrite(LED_PIN, HIGH);
delay(200);
digitalWrite(LED_PIN, LOW);
BUTT_STATE = 5;
}
else{
BUTT_STATE = 0;
}
}
//send data from node to the control
void requestEvent(){
Wire.write(BUTT_STATE);
}
RP2040 Node:¶
⌨️ show / hide code
#include <Wire.h>
const int LED_PIN = D8; //#define LED_PIN 4
const int BUTT_PIN = D10; //#define BUTT_PIN 5
int BUTT_STATE;
void setup() {
pinMode(LED_PIN, OUTPUT); // Set LED_PIN (Pin 4, PA3) as output
pinMode(BUTT_PIN, INPUT_PULLUP); // Set button as input with internal pull-up resistor
Serial.begin(115200); // Initialize serial communication
Wire.begin(2); // Begins I2C Wire as Node 1.
// Wire.onRequest waits for a request from the main board before running void(requestEvent)
Wire.onRequest(requestEvent);
}
void loop() {
if (digitalRead(BUTT_PIN) == LOW){
digitalWrite(LED_PIN, HIGH);
delay(200);
digitalWrite(LED_PIN, LOW);
BUTT_STATE = 5;
}
else{
BUTT_STATE = 0;
}
}
//send data from node to the control
void requestEvent(){
Wire.write(BUTT_STATE);
}
Functionality?¶
After flashing everything and flashing what needed flashing I hooked everything up and went to test it. I was already out of time, I managed to get the ESP to communicate with the Attiny but the RP2040 didn’t respond at all. The issue was the ATtiny wouldn’t stop communicating. It was printing a button press event several thousand times per second and when it wasn’t doing that it threw NACK errors instead. (Non-Acknowledgement).
The AtTiny board works, somehow.
The top line (234) is the initial handshake failing. And then it throws plenty of NACK errors. If I get the time I definitely want to re-visit this and get it working properly. I know thanks to reading through the documentation that I can use an oscilloscope to check the ACK/NACK signals,
This is from the AN10216-01 I2C Manual.
If I read this correctly I should be able to check the pulse counts and use that to figure out what’s going on. My working theory is soldering issues or that the lack of capacitor on the Attiny is messing with the clock. I did start designing a new ATtiny board but ultimately ran out of time.
Design Files:¶
Master:
Filename | Type | Description | Link |
---|---|---|---|
Xiao_ESP_KiCad | .zip | Zipped up KiCad Project | Link |
Xiao_ESP_xTool_Traces | .svg | Traces for xTool | Link |
Xiao_ESP_Roland_Outline | .png | Outline for milling | Link |
RP2040 Node:
Filename | Type | Description | Link |
---|---|---|---|
RP2040_Node_KiCad | .zip | Zipped up KiCad Project | Link |
RP2040_Node_xTool_Traces | .svg | Traces for xTool | Link |
RP2040_Node_Roland_Outline | .png | Outline for milling | Link |
ATtiny412 Node:
Filename | Type | Description | Link |
---|---|---|---|
ATtiny_Node_KiCad | .zip | Zipped up KiCad Project | Link |
ATTiny_Node_xTool_Traces | .svg | Traces for xTool | Link |
ATTiny_Node_Roland_Outline | .png | Outline for milling | Link |