Mission
Build this
Build a privacy-preserving occupancy interval detector with an uncertain state, aggregate dwell time, and an end-of-visit stretch.
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 | HC-SR04 ultrasonic sensor | — |
| ● kit | 1 kΩ and 2 kΩ Echo-divider resistors | — |
| ● kit | RGB LED and 220 Ω resistors ×3 | — |
| ● kit | SG90 servo | — |
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
Watch the bench without watching the person
A useful public space can be understood without identifying anyone who uses it. Your device will ask only whether the bench seems occupied, how long that interval lasts, and when the space becomes available again.
The hard part is humility. A bag can look like a person. A wind-blown branch can enter the beam. Someone may sit at the edge. Instead of forcing every scene into yes or no, you can give the device a third answer: uncertain.
No image. No identity. No device address. Only aggregate states and completed durations.
The central idea
Occupancy is an interval, not a detection
One short near reading might be a hand, a bird, or a bad echo. A useful occupied interval has a beginning, a middle that persists, and an end.
Distance stays near the empty-bench baseline.
Several readings move into the occupied region.
Start the private, local timer. Stay physically still.
Publish duration once, then stretch.
Dwell time is the length of the completed occupied interval. Do not publish a growing timer every second. The garden needs the final aggregate duration when the bench becomes vacant.
Learn the empty bench first
The baseline is a cloud, not one perfect distance
Even an empty bench produces slightly different echoes as wind, rain, angle, and nearby leaves change. Record that spread before setting any threshold.
Clearly occupied
Distance remains well away from the empty range for long enough.
Uncertain
The reading sits near an edge, changes too quickly, or resembles known clutter.
Clearly empty
Distance returns to the measured baseline and remains there.
How does the ultrasonic sensor measure distance?
It sends a short ultrasound pulse and measures the echo’s round-trip time. Sound travels to the bench or object and back, so the one-way distance is half the journey.
The 5 V Echo output must pass through a 1 kΩ/2 kΩ divider before the 3.3 V ESP32 input. That divider protects the pin; it is not optional.
Wiring
Make the quiet watcher electrically quiet too
Stabilise the sensor and measure the empty bench before adding lights or movement. The servo should never shake the ultrasonic mount.
The power rule: The HC-SR04 uses 5 V and needs an Echo divider before GPIO 34. Each LED colour needs its resistor. The servo uses a separate 5 V supply. Join all grounds.
Bench referenceOpen the exact wiring map
| ESP32 pin | Part | Part marking | Carries |
|---|---|---|---|
5V / VIN | HC-SR04 | VCC | 5V power |
GPIO 5 | HC-SR04 | TRIG | Digital in/out — 3.3 V trigger pulse |
GPIO 34 | HC-SR04 | ECHO via divider | Digital in/out — 1 kΩ from ECHO to GPIO and 2 kΩ from GPIO to GND |
GND | HC-SR04 | GND | Ground |
GPIO 25 | RGB LED | R via 220 Ω | Digital in/out — common-cathode LED; invert logic for common-anode |
GPIO 26 | RGB LED | G via 220 Ω | Digital in/out |
GPIO 27 | RGB LED | B via 220 Ω | Digital in/out |
GND | RGB LED | common cathode | Ground |
GPIO 18 | SG90 servo | signal (orange) | PWM to actuator — stretches after an occupied interval ends |
external 5 V | SG90 servo | power (red) | 5V power — separate supply |
GND | SG90 servo | ground (brown) | Ground — join servo and ESP32 grounds |
Never connect Echo directly to an ESP32 pin. Keep outdoor electronics dry and mount the sensor where the servo cannot move it.
- 5V power
- Digital in/out
- Ground
- PWM to actuator
The map assumes a common-cathode RGB LED. If your LED is common-anode, connect the common pin to 3V3 and invert the colour logic.
Give uncertainty a colour
A third state is not indecision. It is honesty.
Clearly inside the empty baseline.
Wait. Do not start or end the interval yet.
Timer runs locally; the creature remains still.
Your team decides:
- How many readings confirm entry and vacancy?
- How wide is the uncertain region?
- How long can a missing echo last before the state becomes uncertain?
- What end-of-visit stretch feels visible without rating the visitor?
Your occupancy rehearsal
Invite clutter to the experiment
- Record the empty baseline.
Collect a long run in ordinary wind and light. Keep the minimum, maximum, and missing-echo rate.
- Stage labelled visits.
Use different sitting positions and short and long intervals.
- Stage convincing impostors.
Try a bag, coat, moving plant, person walking past, and someone standing nearby.
- Choose thresholds from the records.
Report misclassifications and uncertain cases instead of tuning them out of memory.
| Scene | Truth | Distance pattern | Device state | Duration error |
|---|---|---|---|---|
| centre seat | occupied | ___ | ___ | ___ s |
| bag left behind | team defines | ___ | ___ | ___ |
| windy empty bench | vacant | ___ | ___ | — |
When the bench tells a strange story
Presence and occupancy are not always the same
A bag starts an endless visit
The sensor detects obstruction, not a person. Decide and document whether unattended objects count as occupied or uncertain.
Someone at the edge remains invisible
The ultrasonic cone misses them or reflects away. Change placement and map the usable seating region.
Wind creates rapid state changes
A plant or loose cover is entering the beam. Re-aim the sensor and require persistence before changing state.
Missing echoes end visits too early
Treat isolated missing echoes as uncertain, not vacant. End only after the empty baseline returns.
The stretch creates a new occupancy
The servo is moving the sensor or reflector. Isolate the mount and ignore only the known gesture window.
Choose your public-space question
What kind of bench observer will you become?
The threshold designers
Make the three states the main work and show how error changes as uncertainty grows or shrinks.
The obstruction librarians
Build a catalogue of people, bags, coats, plants, and passers-by that challenge simple occupancy.
The time keepers
Focus on beginnings and endings. Measure how confirmation delays affect reported dwell time.
A calm way through the build
Collect four small wins
bw-01says hello.Join the garden before watching the bench.
- The empty baseline has a measured spread.
Protect Echo and stabilise the mount.
- One occupied interval begins and ends once.
Add state memory and local timing.
- The light and stretch respect the interval.
Stay still during occupancy; move once after vacancy.
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.
Occupancy state
garden/outdoor-1/bench-node/bw-01/occupancyUnit: enum
Completed dwell time
garden/outdoor-1/bench-node/bw-01/durationUnit: seconds
Listen beyond your own device.
garden/entrance/counter/gk-01/countEntrance activity gives broad context for busy periods. It must never be used to infer which visitor reached or used this bench.
Finish line
Ready to introduce to the garden
bw-01 stays online and publishes occupancy state and completed duration.
The reject feed stays clear after the final code starts.
The device reads the aggregate Gate Keeper count.
The light shows three states and the servo moves only after a completed interval.
The build log records the empty spread, labelled visits, obstruction trials, uncertain cases, misclassifications, and timing error.
The Echo divider is fitted, outdoor electronics are protected, movement is isolated, and the device label can be scanned.
The Bench Watch succeeds by knowing less about people, not more: enough to describe how a shared space is used, never enough to identify who used it.