Charter 15 · react · available project

Chorus

Distributed Coordination

Make separate machines share a beat, lose one another, and find a principled way back into the performance.

Difficulty
★★★
Prefix
ch
Zone
visitor-centre
Type
chorus
Device
ch-01
Build time
10 hours

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.

One kit, one team repository.

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

SourcePartFallback
● kitSG90 servo—
● kitPassive buzzer and 100 Ω resistor—
● kitOLED—

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.

Programme note

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

same tempo

Two private metronomes

They begin together but slowly drift. No messages are required.

following

One shared beat

A conductor publishes numbered beats. The follower reacts only to new numbers.

negotiating

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

topic…/ch-01/beat
payload1042
meaning

This 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.

Do not use arrival time as proof of exact sending time.

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
WiringNumbered-beat display, restrained tone, and visible conducting arm
ESP323V3OLED (SSD1306)VCCGNDOLED (SSD1306)GNDGPIO 21OLED (SSD1306)SDAGPIO 22OLED (SSD1306)SCLGPIO 25Passive buzzer+ via 100 ΩGNDPassive buzzer−GPIO 18SG90 servosignal (orange)external 5 VSG90 servopower (red)GNDSG90 servoground (brown)
ESP32 pinPartPart markingCarries
3V3OLED (SSD1306)VCC3V3 power
GNDOLED (SSD1306)GNDGround
GPIO 21OLED (SSD1306)SDAI²C bus
GPIO 22OLED (SSD1306)SCLI²C bus
GPIO 25Passive buzzer+ via 100 ΩPWM to actuator — short tones only
GNDPassive buzzer−Ground
GPIO 18SG90 servosignal (orange)PWM to actuator — visible beat gesture
external 5 VSG90 servopower (red)5V power — separate supply
GNDSG90 servoground (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?”

A

The steady conductor

ch-01 publishes every fixed interval. Shy Bug status selects calm, cautious, or silent patterns.

B

The call and response

The partner answers each new beat with a gesture. The conductor leaves enough time to see the reply.

C

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

  1. Run a hundred-beat baseline.

    Log sent numbers at the conductor and received numbers plus arrival intervals at the partner.

  2. Introduce one documented interruption.

    Disable Wi-Fi or broker access for a fixed interval while both devices keep running.

  3. Observe without rescuing.

    Record the last good beat, local stale behaviour, reconnect time, first accepted beat, and any duplicate gesture.

  4. Repeat with the same script.

    After one rule change, rerun the baseline and interruption. Report what improved and what became slower.

PhaseSent beatsReceived beatsDuplicates acted onLargest gapRecovery
baseline100_________ 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

  1. ch-01 says hello.

    Publish a status before producing a beat.

  2. The OLED shows an increasing beat number.

    Schedule it without a blocking delay.

  3. A partner acts once on each new number.

    Reject duplicates and reveal skipped beats.

  4. 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.

Every 1–5 seconds

Monotonic beat number

garden/visitor-centre/chorus/ch-01/beat

Unit: count

When state changes

Ensemble state

garden/visitor-centre/chorus/ch-01/status

Unit: enum

Listen beyond your own device.

garden/visitor-centre/ladybug/sb-01/status

Shy 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.

Backbone now

Live status

Updates from the same public event stream

Checking ch-01…