All projects
Hardware2026

Smart Alarm

A bedside alarm clock that tracks your sleep with a motion sensor on the mattress and wakes you during light sleep instead of at a fixed time. I built all of it: the code, the sleep model, and the circuit board it runs on.

Everything runs on the clock itself. No phone, no cloud, no app.

Part 1 · Firmware and interface
Ten screens, one knob, one button: the alarm, the smart alarm, your sleep data, the weather and the settings.
  • →Sets its own time from the internet and pulls a five-day forecast
  • →Redraws only the digits that changed, so the screen never flickers
  • →Alarm and snooze settings survive being unplugged, so the clock wakes up exactly as you left it
ESP32ArduinoTFT_eSPISPII2CEEPROM
Finished Smart Alarm PCB showing time, date, weather and alarm status
The finished board. Home screen: the time, the date, live weather and the alarm status, all flicker-free.
Paging the menus, opening Sleep Data, and dropping into sleep mode, all on one encoder and one button.
Part 2 · Sleep tracking and on-device ML
A motion sensor sits on the mattress next to the pillow and records how much you move, twice a second, onto a memory card.
  • →Every 30 seconds: half a minute of movement boiled down to 21 numbers, scored as light or deep sleep
  • →The verdict is saved as it goes, so the chart survives overnight even if the power drops
  • →Trained on eight nights I labelled by hand, roughly 420,000 readings
  • →Converted to run on the clock itself, no phone, no server
Pythonscikit-learnmicromlgenMPU-6050SD / CSV
Overall accuracyright call across every window65%
Light sleep caughtof the windows that were actually light76%
Deep sleep caughtof the windows that were actually deep19%
Baselineaccuracy from just always guessing light81%

Below the baseline, and worth saying plainly: mattress movement alone barely separates light sleep from deep.

Sleep Data screen showing a night charted as light and deep sleep, with totals underneath
The Sleep Data screen: how long you slept, the night charted out, and the light and deep totals, read back off the memory card.
Part 3 · Schematic and PCB
The first version lived on two breadboards with the display taped to the front. Once I stopped moving wires around, I redrew the whole thing as a real circuit board and had it manufactured.
  • →Every part breaks out to a labelled socket, so any one of them can still be swapped
  • →Same code, considerably less wire
Altium DesignerSchematic CapturePCB Layout
The original two-breadboard prototype running the same firmware
Where it started. Same firmware, same home screen, considerably more wire.
Schematic split into passive components, active components, and the processor
The schematic, organised into passive parts, active parts, and the processor itself.
Circuit board layout with each part broken out to a labelled socket
The layout. Every part breaks out to a labelled socket, so any one of them can still be swapped.
3D render of the assembled PCB
The 3D render of the assembled board, before it went out for fabrication.
Highlights
→Rings early at the first stretch of light sleep, at one of three sensitivity levels, and falls back to the exact alarm time if that moment never comes
→The model I trained ended up below a plain always-guess-light baseline, so I did not ship it as the displayed stage: see the numbers above
→Shipped the standard sleep-cycle model instead: 20 to 27% deep sleep, matching published norms, with my model’s guess still logged every window for comparison
→Roughly 1,100 lines of code plus a 1.4 MB model outgrew the chip’s default program space, which meant redrawing how its memory is divided up
→A button that double-registered and a pin needing a resistor the chip doesn’t supply, both caught on the breadboard and fixed in the board design
→The memory card file opens once per sleep session, not on every write. An earlier version corrupted the card doing that, so the rule is now built into the code
Austin Zhai