Colin Calnan / Builds / Music hardware
Foot Stomper
A kick drum I wear on my foot. A small board strapped to my instep feels a tap or a stomp and plays a bass drum through the PA, so I can keep time at a gig without standing on one leg for two hours.
- Status
- Tuned on the foot through the gig PA, not played live yet
- Built
- August 2026. First port to a working kick in one evening
- Hardware
- M5StickS3: ESP32-S3, BMI270 accelerometer, 250 mAh battery
- Sends
- Bluetooth MIDI, note 35 on channel 10, to bs-16i on an iPad
- How
- Spec first, built with Claude Code, measured at every step


Why
A stomp pedal was wrecking my hip.
The kick drum in my solo set came from a Wazinator stomp box under my right foot. That means a whole gig standing on my left leg while the right one keeps time, and my left hip and back started paying for it. I wanted the beat without the stance.

The idea
It started on a massage table.
I was lying there talking it through with my massage therapist, trying to work out how to stop standing on one leg. Swap legs? Move the pedal? None of it fixed anything, so I went back to first principles. The real problem was that the pedal is fixed. It sits in one spot on the floor, and for two or three hours it's never quite where my foot is.
So what if the beat came from my foot instead of the floor? My first thought was tap shoes and a board to stand on. Then sensors, and electronic drums. I looked at electronic drumsticks, but they're expensive and hard to get in Canada. By then I was thinking about sensors anyway, so I opened Claude and typed this.
So here's a project idea. I play guitar and use a stomp pedal with my right leg. Recently I've been experiencing some hip and back issues on my left side, because I spend all the time standing on my left foot while playing and tapping with my right. I have a SH Stomping Bass pedal and a Wazinator Classic. I'm trying to figure out a way to remove or reduce the need to do this, and was wondering if there was something that could be attached to the sole of my shoe that could trigger a beat just like the pedal. Act as an inventor. Well, actually, first scour the web to try to find some sort of trigger tapper like that, or else try to find pieces of electronics that I could pull together to make something I could attach to my foot, so that I could trigger a beat while tapping either of my feet easily.
My first message, typos fixed
That conversation ran for days, and almost none of it was code. AI did the research, the thinking and the shopping before it wrote a line of firmware.
Research first
It searched before it invented. Nobody sells a shoe-mounted kick trigger. There's an insole controller stuck in beta for years, a US patent for a heel trigger that never became a product, and a scattering of DIY MIDI shoes. So the gap was real.
A cheaper answer before a clever one
Before building anything, it suggested a flat, low trigger pad, or two of them, one under each foot, so I could swap feet between songs. That's a fair answer. It just didn't fix the actual problem, which was the fixed spot on the floor.
Two ways to build it
A piezo disc in the heel, wired to a drum module, or a wireless board with an accelerometer that sends the kick over Bluetooth. I said I'd been wanting a good ESP32 project, so it was the wireless one.
No soldering
Its first parts list was a tiny ESP32 board and a separate accelerometer, wired together. I asked for the easiest build possible, with little or no soldering, and its reply was "scrap the parts list". That's how I got to the M5StickS3: the board, the motion sensor, a battery, a screen and a case, all in one thing the size of a matchbox.
Finding one in Canada
This took more back and forth than the code did. The prices weren't as low as it first said, some links were dead, one part was discontinued, and the StickS3 was out of stock nearly everywhere. I kept pushing it to find parts that would actually ship to BC, and in the end I found one on Mouser myself.
How it goes on the foot
I'd seen the Playermaker strap that soccer players wear, and asked whether that could be hacked. It dug in: the pods run locked firmware, so no, but silicone straps shaped like that are cheap and common.
From the original claude.ai conversation, August 2026. The ideas before it, the massage table, tap shoes and drumsticks, are my own account.
How it works
Feel the foot, send a kick.
Strap it to the top of the foot
An M5StickS3 sits on the instep, held firmly by a clip mount. It used to be the laces. It has an accelerometer, a 250 mAh battery and a small screen. Firm turns out to be the whole game, which is the next section.
Watch for a jump away from normal
The firmware reads acceleration about 188 times a second and keeps a slow-moving baseline of where the foot usually sits. When a reading jumps more than
1.65 gaway from that baseline it fires straight away, then ignores everything for 120 ms so the impact's ringing can't double-hit.Turn force into volume
The size of the peak sets the MIDI velocity, from 71 to 127, so a light tap plays quieter than a stomp.
Send it over Bluetooth
A BLE-MIDI note 35 (acoustic bass drum) on channel 10, written by hand on the chip's built-in Bluetooth stack after the usual libraries failed.
Play it through the PA
bs-16i on the iPad plays the kick from a soundfont, out a 3.5 mm cable into the Yamaha StagePas. The screen stays dark unless the side button wakes it, and the front button arms and disarms, flashing ARMED or OFF for two seconds, so walking around between songs never fires a beat.
float exc = mag - s->baseline; if (exc < 0.0f) exc = -exc; if (s->tracking) { if (exc > s->peak) s->peak = exc; if ((uint32_t)(us - s->track_start_us) >= c->peak_window_us) { s->tracking = false; s->refract_until_us = us + c->refractory_us; if (out_peak) *out_peak = s->peak; return true; } return false; // baseline deliberately frozen here } if ((int32_t)(us - s->refract_until_us) < 0) { return false; // still ringing from the last gesture } s->baseline += c->baseline_alpha * (mag - s->baseline); if (exc > c->threshold_g) { s->tracking = true; s->peak = exc; s->track_start_us = us; } return false;
From det_feed() in detector.h. The baseline freezes during a gesture, otherwise the gesture drags the baseline up behind it and shrinks its own peak. The peak window is now zero, so it fires on the crossing itself.
The proof
Measured, not felt.
Project status notes, early September 2026. Detection counts from the Phase 3 detector at its first 2.0 g threshold, replayed against the recorded captures.
The first mount was inside a sock, and no amount of tuning could make it work. This is why.
Peak movement per event, measured as excursion from 1 g, events at least 150 ms apart. All three recorded in one session at the end of August 2026, raw files in the project's captures folder.
On the instep every gesture lands to the right of the line and the shuffling sits well to the left of it. In the sock, the foot's own padding soaks up the light taps: 27 of the 31 sock events fall under the line, and 19 of them are no bigger than the biggest shuffle peak. No threshold separates those two groups. That's a mechanical limit, so the fix was the mount, not the code, and the rule I kept is to verify a mount by measuring it, never by how it feels.
Show the numbers
| Recording | Events | Smallest | Largest |
|---|---|---|---|
| Instep gestures | 40 | 2.02 g | 5.44 g |
| Sock gestures | 31 over 0.5 g | 0.55 g | 5.28 g |
| Sock shuffle | 24 peaks over 0.3 g | 0.31 g | 1.43 g |
How AI was used
Claude wrote the code. I wore the sensor.
Before any code, the same chat
Research, the design options, the parts and where to buy them all came out of one long claude.ai conversation, described above.
The first night, in a chat
When the board arrived on 27 August, versions 1.0 to 1.6 came out of that same conversation in one evening. Each version was downloaded straight from the chat, flashed to the board, and what the board did went back into the conversation for the next one. After a crash loop and two debugging builds, v1.4 worked.
Then a real project, spec first
After that it became a repository set up with my spec-driven development skill and run in Claude Code. A mission, a tech stack with rules the agent can't break, and a roadmap of phases. Each phase got an intent interview, then a dated folder with requirements, a plan, a validation file that says how done gets proven, and a status file. All 38 commits carry Claude as co-author.
Real data, so changes get tested on real feet
I recorded the accelerometer with the board on my foot: taps, stomps, shuffling and walking. A replay harness runs the detector over those recordings on the laptop, so a change can be checked against real movement without strapping it on every time. The chart above comes from those files.
What stayed mine
What it's for, what counts as a miss or a false trigger, wearing it, and recording every capture. An agent can write a detector. It can't stand on a stage in the thing.
AI when it runs
None. It's firmware on a small chip: a baseline, a threshold and a timer.
The hard parts
What fought back.
The Bluetooth libraries crash-looped
The usual BLE-MIDI and NimBLE libraries either wouldn't compile or sent the board into a crash loop. Version 1.2 dropped both and wrote BLE-MIDI by hand on the chip's built-in stack. Every version is pinned exactly now, because a core update is its own piece of work.
Speed costs battery
A kick has to land within about 10 ms, which needs a short Bluetooth connection interval, and the chip can't light-sleep with a live link. Slowing the sensor loop to save power dropped detection from 9 in 10 to 6 in 10, because a tap's peak only lasts one or two samples. Reverted.
The battery estimate was out by three times
I guessed 6 to 9 hours. Measured, it's 2 hours 15 minutes. That's the whole argument for measuring.
Heel-down didn't make the cut
Dropping a heel looks exactly like a step, so the gestures are tap and stomp only, and the button disarms it for walking.
Hardware I ruled out
An ESP32-C6 board (same power limit, no accelerometer), the M5 Capsule (same battery), and a battery base that weighs 90 g, which is a brick on a foot.
Tuned on the foot
Then I wore it properly.
With a clip mount on and the kick going through the Yamaha StagePas 1K I use at gigs, wearing it turned up four problems. My own note on the first one: "It's not sensitive enough, I really need to stamp my foot to get something out of it."
More sensitive, still silent when I shuffle
The threshold came down from 2.0 g to 1.5 g, which caught every light tap but fired the odd time on a shuffle. It settled at 1.65 g. Replayed against the recordings, that still keeps every soft tap in rhythm, the softest of which peaks at 1.67 g, and the shuffling recording still fires zero times.
Faster, and I chose the trade-off
The detector used to wait after crossing the line to catch the true peak. On the board that came to 13 to 15 ms, and through the PA the kick felt behind. It now fires on the crossing. The cost is that the crossing sets the volume, so about one hit in seven plays a little quieter than it should. I took that over a late kick.
A screen that stays dark
The screen kept lighting up on taps, which I didn't want on a shoe. It's now dark unless the side button wakes it, with a 60 second auto-off. A boot counter shows on screen too, so if a stomp ever resets the board, the number jumps and I'll know.
A battery figure I can believe
The library's battery percentage was a straight line between two voltages, which reads a lithium cell badly. I watched 17% disappear in five stomps. It now shows CHG while charging, a smoothed figure that only ever goes down, and it records a voltage curve every run. After one full run from charged to flat, it shows time left instead of a guess.
On in seconds, and a drier kick
No more lacing it on every time: the clip mount fits the StickS3, as M5Stack had confirmed. And the reverb is off the kick in bs-16i, which is what the sound needed.
From the project's September tuning spec and commit history, and the replay harness run against the August captures at 1.65 g.
Still open
What it can't do yet.
Last a full set
A three-hour gig needs about 25% less power draw. A small battery add-on is the likely fix. One full run, charged to flat, will calibrate the new gauge.
Both feet
The second board is bought. Setting it up for the other foot is next.
A real gig
It has been to one gig and stayed in the bag. The first full set with it is the next test.
Timeline
Seven versions in one evening.
| When | Version | What changed |
|---|---|---|
| Aug 2026 | First design | A different board and a separate accelerometer with a hardware tap interrupt. Never built. |
| 27 Aug, 17:40 | v1.0 | Ported to the M5StickS3 with the standard BLE-MIDI libraries. |
| 27 Aug, 18:45 | v1.1 | Flicker-free display. Crash loop. |
| 27 Aug, 18:53 | v1.2 | BLE-MIDI written by hand on the built-in stack. |
| 27 Aug, 19:23 | v1.4 | On-screen checkpoints. The first version that worked. |
| 27 Aug, 22:04 | v1.6 | Power management, and the note moved from 36 to 35. |
| Late Aug | Power | Radio, mic and screen trimmed. First real battery number: 2 h 15 m. |
| Early Sep | Detection | The baseline detector with velocity, a recorded test set, a replay harness, and the sock mount retired. |
| Late Sep | On the foot | Clip mount, 1.65 g threshold, fires on the crossing, dark screen, a battery gauge that learns. |
- ESP32-S3
- M5StickS3
- BMI270
- BLE-MIDI
- Arduino C++
- bs-16i
- Claude Code