Mission
Build this
Build a conductor that publishes numbered beats, changes its pattern from Shy Bug’s status, and coordinates with a partner team’s existing device.
Borrowed parts are labelled below and have a fallback. The registered device ID is fixed; sensing and behaviour decisions remain yours.
Bill of materials
Parts
| Source | Part | Fallback |
|---|---|---|
| ● kit | SG90 servo | — |
| ● kit | Passive buzzer and 100 Ω resistor | — |
| ● kit | OLED | — |
Disconnect USB before rewiring. Motors, the relay, and the servo need appropriate power and a shared ground. Never drive an actuator from the ESP32 3V3 pin.
Your invitation
Make separate machines behave like they are listening
Place two devices apart. Give them no shared wires and no secret timing loop. One publishes a beat through the garden; another receives it and responds. When the exchange works, distance seems to disappear.
Then interrupt Wi-Fi. Restart one device. Deliver a duplicate beat. The real project begins when the performance can recover without a human quietly resetting both actors.
Coordination is not never failing. It is knowing what to do when shared timing becomes incomplete.
The central idea
Looking simultaneous and being coordinated are different
Two private metronomes
They begin together but slowly drift. No messages are required.
One shared beat
A conductor publishes numbered beats. The follower reacts only to new numbers.
Leadership can move
Devices use an explicit rule for whose turn matters. This route needs the strongest recovery story.
Your minimum build is a conductor that publishes an increasing beat number and changes its pattern when Shy Bug’s status changes. Coordinate with the partner team so one existing device also reads the beat and performs a visible response.
Give each beat a passport
A number lets the listener recognise old news
…/ch-01/beatThis is beat 1042, not “move sometime.”
The follower stores the largest beat it has handled. The same number arriving twice must not create two gestures. A jump from 1042 to 1045 reveals missed beats. A smaller number may mean a delayed message or a restarted conductor, so recovery must be explicit.
Without aligned clocks, you can measure gaps, jitter, missed sequence numbers, and recovery. Claim one-way latency only if you document how the clocks were aligned.
Wiring
Make one reliable performer before recruiting the chorus
Display the beat number first. Add a short tone, then a servo gesture. No performance step may block incoming messages or delay the next scheduled beat.
The power rule: The OLED uses 3V3. The small passive buzzer is current-limited by 100 Ω. The servo uses a separate 5 V supply. Join all grounds.
Bench referenceOpen the exact wiring map
| ESP32 pin | Part | Part marking | Carries |
|---|---|---|---|
3V3 | OLED (SSD1306) | VCC | 3V3 power |
GND | OLED (SSD1306) | GND | Ground |
GPIO 21 | OLED (SSD1306) | SDA | I²C bus |
GPIO 22 | OLED (SSD1306) | SCL | I²C bus |
GPIO 25 | Passive buzzer | + via 100 Ω | PWM to actuator — short tones only |
GND | Passive buzzer | − | Ground |
GPIO 18 | SG90 servo | signal (orange) | PWM to actuator — visible beat gesture |
external 5 V | SG90 servo | power (red) | 5V power — separate supply |
GND | SG90 servo | ground (brown) | Ground — join servo and ESP32 grounds |
Never power the servo from ESP32 3V3. Confirm the buzzer type and current; use a driver module if the part is not a small passive piezo. Keep tones brief in the shared visitor centre.
- 3V3 power
- Ground
- I²C bus
- PWM to actuator
- 5V power
GPIO 25 produces the passive-buzzer tone. If your kit has a three-pin buzzer module, follow its printed VCC, GND, and signal markings instead.
Choose who carries time
Every ensemble needs an answer to “whose beat?”
The steady conductor
ch-01 publishes every fixed interval. Shy Bug status selects calm, cautious, or silent patterns.
The call and response
The partner answers each new beat with a gesture. The conductor leaves enough time to see the reply.
The passing baton
Leadership changes by a written rule. Include a timeout so two silent devices can begin again.
Your team and partner decide:
- Who is allowed to start a phrase?
- What does a duplicate, skipped, or smaller beat number mean?
- How long without a message makes the partner stale?
- After reconnecting, does the device catch up, join the newest beat, or wait for a new phrase?
Your interruption rehearsal
Pull the network out from under the performance
- Run a hundred-beat baseline.
Log sent numbers at the conductor and received numbers plus arrival intervals at the partner.
- Introduce one documented interruption.
Disable Wi-Fi or broker access for a fixed interval while both devices keep running.
- Observe without rescuing.
Record the last good beat, local stale behaviour, reconnect time, first accepted beat, and any duplicate gesture.
- Repeat with the same script.
After one rule change, rerun the baseline and interruption. Report what improved and what became slower.
| Phase | Sent beats | Received beats | Duplicates acted on | Largest gap | Recovery |
|---|---|---|---|---|---|
| baseline | 100 | ___ | ___ | ___ ms | — |
| interruption 1 | ___ | ___ | ___ | ___ ms | ___ s |
| interruption 2 | ___ | ___ | ___ | ___ ms | ___ s |
When the ensemble loses the room
The awkward beat is usually the informative one
One beat causes two gestures
The message was repeated or the callback handled the same sequence twice. Store the last accepted number and make the physical response idempotent: repeated news changes nothing.
The follower races through missed gestures after reconnecting
It is treating backlog as live rhythm. Join the newest beat or begin at the next phrase boundary; document the choice.
The devices drift even though messages arrive
Long blocking gestures or tones delay message handling. Schedule outputs from elapsed time and keep the garden loop running.
A conductor restart looks like very old news
The beat counter returned to zero. Publish a warning status while the follower waits for a documented restart rule or new phrase marker.
Shy Bug goes silent
Keep the last status only for a limited age. After that, use a neutral pattern and show that the partner input is stale.
Choose your ensemble problem
What kind of coordination team will you become?
The rhythm engineers
Measure interval variation and make a clear performance from imperfect message arrival without hiding the jitter.
The recovery directors
Make disconnects, restarts, stale partners, and rejoining the centre of a performance that repairs itself.
The baton designers
Attempt shared leadership with explicit turns and timeouts. Demonstrate how the system avoids two leaders or no leader.
A calm way through the build
Collect four small wins
ch-01says hello.Publish a status before producing a beat.
- The OLED shows an increasing beat number.
Schedule it without a blocking delay.
- A partner acts once on each new number.
Reject duplicates and reveal skipped beats.
- The pair survives an interruption unaided.
Add stale behaviour and one explicit rejoining rule.
The garden handshake
Share what you found
These names are the rigid part of the project. They let another team find your work without knowing what you called the variables in your code.
Monotonic beat number
garden/visitor-centre/chorus/ch-01/beatUnit: count
Ensemble state
garden/visitor-centre/chorus/ch-01/statusUnit: enum
Listen beyond your own device.
garden/visitor-centre/ladybug/sb-01/statusShy Bug’s registered status can select the pattern: calm while it peeks, cautious while active, and sparse while hiding. Treat an old status as stale rather than permanent.
Finish line
Ready to introduce to the garden
ch-01 stays online and publishes an increasing beat plus a registered ensemble status.
The reject feed stays clear after the final code starts.
The conductor reads Shy Bug status, checks its age, and a partner device responds to Chorus beats.
Display, tone, and servo perform without blocking messages; duplicate beats never create duplicate gestures.
The build log contains a hundred-beat baseline, sequence gaps, interval variation, a fixed interruption, stale behaviour, recovery time, and the result of a repeated test.
The servo is safely powered, the buzzer is current-safe and restrained, and both participating device labels can be scanned.
The memorable moment is not two machines moving together. It is the moment they lose one another, notice, and find a principled way back into the same performance.