This commit is contained in:
my 2026-06-08 11:38:58 +02:00
commit 822ce623ea
6 changed files with 202 additions and 0 deletions

Binary file not shown.

Binary file not shown.

BIN
3D model/Modified stamp.stl Normal file

Binary file not shown.

View file

@ -0,0 +1,166 @@
/*===================================================
* Clay PCB Workshop Mesh Node
*
* Change NODE_ID before flashing each board.
*
* D11 trigger input (button, sensor etc)
* A0A5 outputs 16
* D13 output 7
* D2 network bus (shared wire between all nodes)
* D5 - led pin for feedback
*
* When trigger fires -> sends NODE_ID to all nodes
* When message N arrives -> activates output[ N % 7 ]
*
* node 1 -> A5 | node 2 -> A4 | node 3 -> A3
* node 4 -> A2 | node 5 -> A1 | node 6 -> A0 | node 7 -> D13
* node 8 -> A5 (wraps around)...
*
* Bus wiring: one wire shared between all nodes on D9,
* one 4.7 pullup to 5V anywhere on bus.
* one shared ground wire.
*===================================================*/
#define NODE_ID 2 // <- change this for each board, starts at a humanfriendly #1
/*
| EXAMPLE: |
YOU ARE NODE 1
Your trigger: wire on D11
When YOU press A5 on
every board reacts
Your board reacts to:
A5 <- Node 1 (you)
A4 <- Node 2
A3 <- Node 3
A2 <- Node 4
A1 <- Node 5
A0 <- Node 6
D13 <- Node 7
*/
#define BUS_PIN 2
#define TRIGGER_PIN 11
const uint8_t OUTPUT_PINS[] = { A5, A4, A3, A2, A1, A6, 13 };
#define NUM_OUTPUTS 7
#define OUTPUT_MS 1000 // how long an output stays on (milliseconds)
#define BIT_US 1600 // bit period — long enough for 8MHz + oscillator drift
#define START_US 3200 // start pulse length
unsigned long outputOffAt[NUM_OUTPUTS];
#define LED_PIN 5 // slow blink pin to test if the sketch is running (its not broken out, but close to ground so you can hold a led to it)
static unsigned long ledChangeAt = 0; // timing for the led blink
static bool ledOn = false;
void setup() {
Serial.begin(9600);
Serial.print("Node ");
Serial.println(NODE_ID);
pinMode(TRIGGER_PIN, INPUT_PULLUP);
pinMode(BUS_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
for (int i = 0; i < NUM_OUTPUTS; i++) {
pinMode(OUTPUT_PINS[i], OUTPUT);
digitalWrite(OUTPUT_PINS[i], LOW);
outputOffAt[i] = 0;
}
// Blink own output pin and LED_PIN <NODE_ID> times on startup to confirm ID
int myOutput = OUTPUT_PINS[NODE_ID % NUM_OUTPUTS];
for (int i = 0; i < NODE_ID; i++) {
digitalWrite(myOutput, HIGH);
digitalWrite(LED_PIN, HIGH);
delay(100);
digitalWrite(myOutput, LOW);
digitalWrite(LED_PIN, LOW);
delay(400);
}
delay(1000); // wait a bit for clarity
}
void loop() {
// Turn off outputs whose timer has expired
unsigned long now = millis();
for (int i = 0; i < NUM_OUTPUTS; i++) {
if (outputOffAt[i] > 0 && now >= outputOffAt[i]) {
digitalWrite(OUTPUT_PINS[i], LOW);
outputOffAt[i] = 0;
}
}
// Send NODE_ID when trigger fires (INPUT_PULLUP -> active LOW)
if (digitalRead(TRIGGER_PIN) == LOW) {
sendByte(NODE_ID);
Serial.print("sent");
delay(250); // debounce
}
// Listen for incoming messages
int msg = readByte();
if (msg > 0) {
int idx = (msg - 1) % NUM_OUTPUTS;
digitalWrite(OUTPUT_PINS[idx], HIGH);
outputOffAt[idx] = millis() + OUTPUT_MS;
Serial.print("received ");
Serial.println(msg);
}
// slow blink a pin for testing
now = millis(); // even recycle variables ;)
if (now >= ledChangeAt) {
if (!ledOn) {
digitalWrite(LED_PIN, HIGH);
ledOn = true;
ledChangeAt = now + 20; // stay on 100 ms
} else {
digitalWrite(LED_PIN, LOW);
ledOn = false;
ledChangeAt = now + 5000; // stay off 1000 ms
}
}
}
void sendByte(byte b) {
pinMode(BUS_PIN, OUTPUT);
digitalWrite(BUS_PIN, LOW); // start pulse
delayMicroseconds(START_US);
for (int i = 0; i < 8; i++) { // 8 data bits
digitalWrite(BUS_PIN, (b >> i) & 1);
delayMicroseconds(BIT_US);
}
digitalWrite(BUS_PIN, HIGH); // stop
delayMicroseconds(BIT_US);
pinMode(BUS_PIN, INPUT_PULLUP);
}
int readByte() {
pinMode(BUS_PIN, INPUT_PULLUP);
if (digitalRead(BUS_PIN) == HIGH) return -1; // bus idle, nothing to read
delayMicroseconds(START_US + BIT_US / 2); // skip start pulse, land mid bit-0?
byte value = 0;
for (int i = 0; i < 8; i++) {
value |= (digitalRead(BUS_PIN) << i);
delayMicroseconds(BIT_US);
}
if (value == 0) return -1; // discard empty reads
return value;
}

36
README.md Normal file
View file

@ -0,0 +1,36 @@
# Clay PCB mesh
Code and other resources for the workshop Earthbound Hardware, as part of the Connecting Otherwise artistic research consortium.
Based on the original research and documentation of Patrícia J. Reis and Stefanie Wuschitz:
https://github.com/FeministHardware/Making-PCBs-from-natural-clay/tree/main
## "Mesh network"
The goal is to create a symbolic 'mesh' network using the clay pcbs.
Pressing a button on one node sends a signal across a shared two-wire bus, all other nodes blink a pin in response corresponding to the senders ID.
We tried to keep the parts count minimal as possible (just a resistor and conductive material).
RS232 did not fit because assumes a hierarchy, one device is always in charge, others respond. RS485 avoids that but needs an extra hardware, a transceiver chip on every node that were hard to source as used.
Instead we ended up on bitbanging, the nodes communicate by directly toggling a pin, a bit like morsecode. It keeps the circuit as bare as possible: two wires, a pull-up resistor, and whatever conductive material you find to connect the PCB's together.
## Code
Communication uses bitbanging over a half-duplex two-wire bus (signal pulled up with a 4.7kΩ resistor).
Each node:
- Has a unique NODE_ID (set in the sketch, values up to ~32)
- Sends its ID on the bus when the button is pressed
- Blinks its LED when it receives any message
Because everything runs in the main loop with delayMicroseconds, avoid using delay() elsewhere as it will break communication.
Before uploading, set a unique NODE_ID per node:
```cpp
#define NODE_ID 3 // change for each node
```
## Hardware modifications
The stamp used to press the PCB traces into clay has been modified:
- The trace between the motor driver circuit and pin 9 is removed.
- Two additional magnet/connection points have been added to allow nodes to connect to the shared bus.
One of the needs needs to pull up the bus wire with a 4.7ohm resistor!
To do this add a resistor between one of the 5V connection points (the 5V input makes sense) and the bus pin (D2).

BIN
presentation.odp Normal file

Binary file not shown.