The problem
A smart ring streams tri-axial acceleration from the finger — one of the noisiest, most freely-rotating places on the body to mount a motion sensor. The ring tumbles as the hand swings, so no single axis is a reliable step signal, and rhythmic non-walking motion (typing, eating, brushing teeth) can look a lot like gait. The job: turn that raw stream into an accurate step count, while rejecting everything that isn’t walking.
One recording, end to end
The clearest way to see the pipeline is to push a single real recording through every stage and plot the actual signal at each step.
- Example: a normal walk, hand-counted at 300 steps, 156 s, recorded as one gap-free segment.
- Result: the pipeline counts 301 steps (+0.3%).
Step 1 — Raw tri-axial accelerometer
The ring streams ACC_X/Y/Z at 25 Hz (each CSV row holds 25 samples/axis), in units of g. Below is a 12 s window of steady walking. The three axes are all oscillating at the step rate, but their individual shapes depend on how the ring happens to sit and rotate on the finger — so no single axis is a reliable step signal.

Step 2 — Magnitude |a| (orientation invariance)
We collapse the three axes into their magnitude |a| = √(x²+y²+z²). This is orientation-invariant — it doesn’t matter which way the ring points — which matters because the data analysis showed the ring rotates continuously during motion. Each footfall now shows up as a clear hump riding on the ~1 g gravity baseline.

Step 3 — Band-pass 0.7–5 Hz
A 4th-order Butterworth band-pass (0.7–5 Hz) removes the gravity offset and slow drift (below 0.7 Hz) and high-frequency noise (above 5 Hz), leaving a clean zero-centred gait oscillation. Everything downstream runs on this signal. (The recording is also split into gap-free segments first, on any break in the 1 s timestamps — this example is a single segment.)

Step 4 — Activity gate (is this actually walking?)
Sliding windows are scored on three features, shown below over the whole recording:
- window RMS — band-limited motion energy (must clear a floor),
- spectral prominence — how sharp/dominant the cadence peak is,
- dominant cadence — must fall in the locomotion band (green).
Windows that pass are stitched into bouts (with hysteresis). A second sustained-gait fallback rescues real walking that the spectral test is too strict on. The shaded region (top panel) is what the gate accepts as walking — here, everything except the brief low-energy settling at the very start. This is the stage that rejects typing/eating and most non-gait motion.

Step 5 — Step counting (adaptive peak detection)
Inside the accepted region, steps are counted by adaptive peak detection on the band-passed signal: a prominence threshold that scales with the local amplitude, plus a refractory period (≥0.28 s, ~3.5 steps/s ceiling) so each footfall is counted once. Every red marker is one detected step.

Step 6 — Result
Summing the detected steps across all accepted bouts gives the final count. The cumulative-step curve climbs steadily with the walk and lands right on the ground truth.

301 vs 300 steps (+0.3%).
And this single example isn’t cherry-picked. Across the full evaluation — 62 labelled recordings, ~14.7 h of walking, jogging, stairs and free-living — the pipeline averages 4.0% absolute step error, beating the ring’s on-board firmware counter on every locomotion scenario (for example, 5.0% vs 25.4% on free-living commute data), while counting zero steps for typing and eating.
The full pipeline in one line
load (gap-aware segments) → |a| → band-pass 0.7–5 Hz
→ activity gate (energy + cadence prominence + sustained-gait fallback)
→ adaptive peak detection within accepted bouts → sum
Design notes
A few choices, all driven by the data analysis rather than guessed at:
- Orientation-invariant by construction. Because the ring rotates freely on the finger, the whole pipeline runs on acceleration magnitude
|a|, never individual axes. - A two-path activity gate. A spectral-prominence test rejects rhythmic non-gait motion; a sustained-gait fallback recovers messy or intermittent real walking that the spectral test alone would miss.
- DSP, not ML. ~62 files from a single wearer is too little to train without overfitting, and a transparent pipeline — with every threshold living in one config file — is far easier to port to the ring’s MCU.