intial
This commit is contained in:
commit
822ce623ea
BIN
3D model/Modified stamp 110prc.3mf
Normal file
BIN
3D model/Modified stamp 110prc.3mf
Normal file
Binary file not shown.
BIN
3D model/Modified stamp.blend
Normal file
BIN
3D model/Modified stamp.blend
Normal file
Binary file not shown.
BIN
3D model/Modified stamp.stl
Normal file
BIN
3D model/Modified stamp.stl
Normal file
Binary file not shown.
166
Code/clay_mesh_workshop/clay_mesh_workshop.ino
Normal file
166
Code/clay_mesh_workshop/clay_mesh_workshop.ino
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*===================================================
|
||||
* Clay PCB Workshop — Mesh Node
|
||||
*
|
||||
* Change NODE_ID before flashing each board.
|
||||
*
|
||||
* D11 — trigger input (button, sensor etc)
|
||||
* A0–A5 — outputs 1–6
|
||||
* 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.7kΩ 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
36
README.md
Normal 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
BIN
presentation.odp
Normal file
Binary file not shown.
Loading…
Reference in a new issue