Structure through rhythm.
Small, distinct tactile patterns.
Research ↗Haptic communication / Wearable computing
A quiet cue.
A human reply.
Gesture recognition, tactile feedback
and a deliberate connection.

On the wrist
A wrist movement sends a cue. A vibration asks for attention. A button leaves the reply to its wearer.
把“设备收到了”和“人回应了”分开设计。
paired wearables
intentional messages
motion channels
01 Background → design decisions
Common Ground’s interest in nonverbal musical coordination carries forward into a direct exchange between two people.
Small, distinct tactile patterns.
Research ↗Deliberate requests and responses.
Research ↗Evaluate electronics on the wrist.
Process ↗Design hypotheses to test. Earlier audience observation and room-scale lighting remain part of Common Ground, outside this wearable’s scope.
02 Interaction score
A packet ACK confirms delivery.
A person’s reply confirms intention.
Interactive illustration. It does not connect to a wearable.
Ready to send
A shared vocabulary
Choose a cue to beginListening
Send a cue, then decide when Player B replies.
Wrist-turn gesture or attention button.
Downward-motion gesture.
A deliberate button reply, distinct from the BLE acknowledgement.
Receiver vocabulary. Pulse marks are schematic; feedback requires enabled output and a calibrated driver.
03 Electronics & signal paths
Sensing, communication and feedback share one small object.
The real constraint is their interaction: power, timing, antenna space and motor vibration.
Functional wiring, v328. Six LEDs run at brightness 12/255 on 3V3; long-term supply margin remains unverified.
LSM6DS3TR-C
104 Hz configuration
XIAO Sense
On-device inference + BLE
I²C 0x5A
1040 LRA actuator
D1 light
D9 Attention / D10 Received
| Part | Role / interface | Design or verification note |
|---|---|---|
| XIAO nRF52840 Sense | IMU + Bluetooth + control | Motion sensing on the body; firmware shares the sensing and feedback schedule. |
| DRV2605L + 1040 LRA | I²C / tactile output | Current hardware differs from the earlier DRI0056 proposal. Startup calibration and feedback masking matter. |
| Two buttons | D9 / D10, active-low input | Direct attention and human acknowledgement remain available alongside gestures. |
| Six addressable LEDs | D1 / 3V3 / GND | Brightness 12/255 in the source configuration; prototype setting, not a validated supply specification. |
| Battery + slide switch | Battery-path switching | Battery voltage in the UI is a reading, not a calibrated charge percentage. |
| Carrier + printed enclosure | Mechanical integration | Reserve openings, wires, antenna space and accessible controls before judging the fit. |
04 Electronic assembly
The carrier locates the controller and controls. The complete wearable also needs its haptic driver, light strip, actuator, battery and interconnects.
Two levels of evidence. The original carrier comes from the collaborator’s CAD. Added modules follow photographs; battery and LRA dimensions were supplied by the author. Driver dimensions and LED spacing remain approximate. Leads are schematic.
Model provenance ↗The light has a place to sit
The original bridge transfers the strip’s load to two ledges in the shell. A separate diffuser sits beneath the light window.
Nominal mounting heights follow the archived CAD. The component envelopes still need a physical fit check.
Component volume, cable access and repeatable closure belong to the same design.
Earlier driver & pin map
Revise firmware & openings
Wiring, restraint & fit checks
CAD studies document their own revisions. The final presentation records a snap-latch choice; later clearance variants are CAD/slicer checked, without retained physical assembly verification.
05 Embedded machine learning
Before classifying a gesture, the system must decide which part of the stream belongs to it.
6 channels
104 Hz configured
Motion onset + quiet tail
Quality rejection
128 resampled frames
58 features
96 decision trees
3 class scores
Score ≥ 0.65
Consume + cooldown
The 58-value description
42 / Six channels × seven statisticsMean, variation, extrema, absolute magnitude, crossings and differences.
7 / Window & stroke structureDuration, stroke counts and relative angles.
9 / Motion & stillnessAxis energy, magnitude and quiet-time features.
Random forest / structural illustration
Score bars illustrate the architecture, not a recorded prediction. A v326 / B v328 share the v322 model.
unsigned until = tree + 32 < RfModel::TREES
? tree + 32 : RfModel::TREES;
for (; tree < until; tree++)
RfModel::tree(tree, features, probability);
if (tree < RfModel::TREES) return;Share the processor. Evaluate up to 32 trees per tick, giving sensing and BLE time to continue.
grid = np.linspace(tt[0], tt[-1], FRAMES)
resampled = np.stack([
np.interp(grid, tt, vv[:,d]) for d in range(6)])
centered = resampled - resampled.mean(
1, keepdims=True)
centered[:3] /= 400.
duration = (tt[-1] - tt[0]) / 1e6
basic = features(
centered[None], np.asarray([duration]))[0]Match the representation. Resample to 128 time positions, center each channel and retain a fixed physical scale.
Offline training loop / explicit deployment
Training negatives misclassified as gestures receive extra weight in one fixed pass. Validation/test examples do not supply this pass. New recordings never retrain the bands automatically.
Physical feedback → recognition guard
Continue saving raw samples. Exclude vibration-affected samples from recognition.
Independent event guard: consume the accepted movement + 800 ms cooldown.
06 Read the recording
A recorded stream connects the movement, the annotation and the device’s decision. It also exposes pauses, feedback and incomplete attempts.
Group onset and cycle-end markers stay separate from detections.
Device time, host receipt time and browser input time are retained separately.
Follow the event to the remote driver, then check what the wearer felt.
07 Recording & analysis system
A local Python service and browser panel connect live streams, action labels, transport events and reproducible session files.
Two angular-velocity plots use the same vertical range and a 12-second view. Device state sits beside the signal.
Original UI pixels / A v326 + B v328 / historical capture
Select the recording band and gesture. Human markers remain separate from the model’s detections.
Capture protocol from the source. The selected group below retains two Space marks and no explicit onset mark.
Session, sequence and code link a request to its ACK. Output and human response require their own evidence.
REQUESTCreatedTX_ATTEMPTAttempt 1ACK_DEVICE_DELIVERYPeer acceptedRendered ledger from the selected A USB record / A’s device clock. B playback and a human reply are absent from this file.
Select an event to connect the motion, the operator’s mark and the device’s own record.
The operator marks a completed cycle. This records an observation; it does not trigger recognition or feedback.
cycle_end / cycle 1 latest sample: 745347656 μs source: Space key
One selected successful group from session 20261019_142008_test_cc691f. Times use A’s device clock and an excerpt origin of 743 s. Marker positions include human delay; they do not measure recognition latency.
The partner link works without the computer. B routes notifications by subscription handle; connection order is not a reliable identity. Debug disconnection was checked without resetting the pair.
Capture protocol / one annotated two-cycle group
Markers never trigger the motor or fake a detection. Human reaction and buffering delay remain in the record; annotations require review.
Capture files / availability varies by session version
imu.csvRaw stream + device eventssample_timing.jsonlDevice ticks ↔ host receiptgroup_onsets.jsonlStart of intended groupmarkers.jsonlCycle ends + undo historypair_events.jsonlPaired debug events / when availablesession.jsonRole, units, pose, quality countssha256.jsonSaved-file integritynow = time.monotonic()
raw.write(line + "\n")
timing.write(device_us, now)
if clock_reset or large_gap:
save_and_stop("clock discontinuity")
# Label the action, not the model output.
marker = {"type": "cycle_end",
"host_mono": now,
"last_sample": latest_sample}Stop on device-clock reset or a gap above one second. Preserve timestamps instead of pretending the clocks are synchronized.
Two thresholds, two jobs. A gap above 30 ms invalidates a recognition window. A gap above 1 s or device-clock reset stops and saves the recording.
Separate provenance. A sessions and B sessions have separate directories; B recordings are not automatically added to the default training set.
Preserve missing evidence. Old firmware without output events leaves feedback unconfirmed. Cached battery values are marked as old readings.
Measure before claiming latency. Human marker delay and USB/BLE buffering are not corrected; these logs do not establish millisecond end-to-end latency.
08 Three engineering investigations
Each investigation connects a symptom to retained evidence, an implementation decision and a bounded result.
A classifier that worked on clean clips missed every target group in continuous replay.
One archived diagnostic group. A changed boundary produces a changed feature vector.
0/8 groups matched. Three other twists produced no valid candidate window.
Use the same causal window generator and 58-feature representation for training and runtime replay.
7/8 matched, with three unassigned outputs. Window labels and model fitting changed together.
Historical development replay, not a blind test or proof that the classifier alone caused the improvement.
A motor and an IMU share one small enclosure. Playback must not masquerade as intentional motion.
// Exact predicate, line-wrapped / Hardware.h
bool masked(uint32_t now) const {
return busy_ || !Fermata::elapsed(now, ended_, 200);
}Later misses occurred after masking ended. Removing the flags produced an identical replay log.
Keep every raw sample and its mask flag. Exclude playback and 200 ms recovery from recognition.
The guard remained inspectable. This check did not show an accuracy gain or explain the later misses.
The controlled replay comparison is from the historical v316 DTW-era system. Current v322 logic retains the raw-recording/masking separation.
Earlier Attention requests were acknowledged even when the receiver was not ready to vibrate.
Delivery, motor playback and a felt cue require different checks.
Retain calibration gates; correlate output logs by session / sequence / code. Keep the reply button separate from ACK.
Across seven button tests, the author confirmed vibration and green light in both directions.
Different dates and firmware. These button checks do not prove every gesture cue was felt and are not a user study. Evidence and exact source excerpts ↗
Clear stale RX / TX / CCCD handles. A 60.25 s follow-up had no drops; power and placement also changed.
Seeed’s OUTPUT_H0H1 drive mode restored identification and approximately 104.33 Hz sampling in a short check.
Failed nut seating and a reversed button made fit, travel and reopening separate assembly checks.
09 Results & limits
The v325 candidate improved the development replay, while validation matches fell. It was not the model deployed on the photographed pair.
Logged bidirectional button messages; author confirmed vibration and green light.
Python / C++ candidate replay consistency. This does not measure real-device latency.
Later worn tests still include misses and disconnection. Fit remains part of the sensing problem.
Planned demonstration / filming storyboard
Follow the four shots planned for the live demonstration. This is an interaction storyboard; footage has not yet been recorded.
Keep A’s wrist and the shared activity in view. Film one deliberate two-cycle wrist-turn gesture.
Schematic framing / planned sequence

Physical prototype
Author photograph
The live take will keep the complete exchange in one continuous master shot. A filmed light or packet ACK alone will not stand in for the wearer’s tactile confirmation.
The study, kept open
Precedents inform design and documentation choices. Their results are not presented as Fermata’s findings. Project evidence and asset provenance are indexed in the source notes.