{"slug": "sloth-clock-slow-and-steady-wins-the-morning-an-offline-ai-alarm-that-rewards-in", "title": "Sloth Clock: Slow and Steady Wins the Morning, an Offline AI Alarm That Rewards You for Sleeping In 🦥", "summary": "A developer built Sloth Clock, an offline bedside alarm clock on an Arduino UNO Q that uses a Seeed MR60BHA2 60 GHz mmWave radar to score the previous night's sleep and grants up to 30 extra minutes of rest when the night was rough, capped at four lie-ins per week by hard-coded rules. The device wakes the sleeper with a ten-minute, eight-step LED-matrix sunrise and a soft chime, and runs Gemma 3 1B locally to generate a one-sentence explanation of the decision roughly 45 minutes before wake time at about 4.4 tokens per second. A no-glow e-paper card displays the result, and a demo mode scores a short nap so the system can be tested without an overnight sleep; the project is MIT licensed and described as a work in progress.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady](https://dev.to/challenges/hacktoberfest-week3-2026-10-19)*\n\n**Sloth Clock: the alarm clock that rewards you for sleeping badly.** 🦥\n\nEvery alarm clock on Earth punishes laziness. It rings at the same minute whether you slept like a log or stared at the ceiling until 3 a.m. Then it gives you a snooze button, so you can chop the last half hour into nine-minute pieces of broken, useless sleep.\n\nSloth Clock flips that. It **watches how you actually slept**, and if the night was rough, it **lets you stay in bed longer**, up to 30 extra minutes, decided once and up front. Then it wakes you the way a sloth would want to be woken: *slowly*. A ten-minute sunrise creeps across the LED matrix, a soft chime follows, and **Gemma 3 1B, running on the clock itself**, greets you as a sleepy, kind sloth and tells you *why* you got the lie-in.\n\n06:45. Good morning, dear. Your sleep was a bit restless, so I've given you a longer rest.\n\nThat is a real message, written by the model on the board.\n\nIt is a small **physical AI agent**: it **senses** (radar), **decides** (night score + hard-coded health rules), and **acts** (light, sound, words), all on one board, offline.\n\nSleeping in is the easiest feature in the world to get wrong, so the sloth has rules it cannot break:\n\nThese limits are hard-coded in one small file, not settings. *Future-sleepy-me does not get a vote.*\n\nBecause of the \"not two days in a row\" rule, the most the sloth can give in a normal week is **4 lie-ins × 30 min = 2 hours** of extra sleep, calculated straight from the rules. It never gives you a late morning.\n\nThe theme isn't just the name. Every part of the clock is deliberately slow:\n\n| Part | How it is slow and steady | \n|---|---|\n| 🌅 Wake-up | A **10-minute sunrise** over 8 brightness steps instead of a blaring beep | \n| 🧠 The model | Gemma writes **one sentence a day** ,**45 minutes before you wake** , at a calm ~4.4 tokens/s. It has all the time in the world. | \n| 📟 The card | A **no-glow e-paper card** that refreshes only when something changes, and uses no power to keep showing it | \n| 🪜 Your to-do list | **One tiny step** on a job you keep postponing, sized by how well you slept. Bad night? The step gets smaller. | \n\n*Sloth Clock on the nightstand: UNO Q with the LED-matrix sunrise, the radar facing the bed, and the e-paper card.*\n\n*Live page served by the UNO Q: breathing, heart rate and movement graphs, plus the night score with every term shown.*\n\n*The last decision: the final alarm, the rules that fired, the full decision record and Gemma's message.*\n\nYou shouldn't have to sleep eight hours to see an alarm clock work (that would be a little *too* on-theme). **Demo mode** lets you lie down for a few minutes. When the nap ends, the clock scores it, makes its decision, and wakes you right away with a one-minute sunrise. Demo data goes into a separate database, so it never mixes with your real nights.\n\nA bedside sloth that wakes you gently and moves the jobs you keep putting off forward, one tiny step a day.\n\nEverything runs offline on an Arduino UNO Q.\n\nWork in progress. Measured results…\n\n| Path | What lives there | \n|---|---|\n| `app/sketch/sketch.ino` | STM32 real-time side: radar line parsing, 10 s rows, LED-matrix sunrise, chime, button | \n| `app/python/` | Linux side: SQLite, night score, alarm decision, Gemma wake message, validator, web API | \n| `app/assets/` | The web page (plain HTML, CSS and JS, hand-drawn canvas charts, no frameworks) | \n| `firmware/radar_forwarder/` | Tiny sketch on the radar kit's XIAO ESP32C6 | \n| `firmware/epaper_card/` | The e-paper card firmware | \n| `tests/` | Decision, validator and night-score tests, plus the on-board Gemma message test | \n\nMIT licensed.\n\n| Component | Role | \n|---|---|\n| **Arduino UNO Q (4 GB)** | The whole brain: STM32U585 MCU + Qualcomm QRB2210 Linux on one board | \n| **Seeed MR60BHA2 60 GHz mmWave kit** (XIAO ESP32C6 inside) | Breathing, heart rate, presence and movement, contact-free | \n| **XIAO ePaper Display Board EE04 + 7.5\" 800×480 mono panel** | The no-glow bedside card, with 3 buttons | \n| **INMP441 I2S microphone** | Rain detection from sound *features* only, never recorded audio | \n| **PAM8403 amplifier + small speaker** | The soft chime | \n| **Push button** | Dismiss the alarm | \n\n*Everything that goes into a Sloth Clock. All of it runs on USB power: low voltage, no mains, nothing that heats up or moves.*\n\n*KiCad schematic: radar UART into the UNO Q, the INMP441 on the STM32's SAI pins (SCK = PB10, WS = D10, SD = A4), the PAM8403 on a PWM pin, and the dismiss button.*\n\n`llama-server`` web_ui` brick.\nAn alarm clock is a strange mix of jobs. Part of it must be **hard real time** (the alarm *must* ring, the button *must* work). Part of it is **heavy and slow** (a language model). Most boards make you pick one. The UNO Q is **two computers on one board**, and Sloth Clock uses both for what each does best:\n\n|  | ⚡ STM32U585 (Zephyr, real time) | 🐧 Qualcomm QRB2210 (Debian Linux) | \n|---|---|---|\n| Sense | Read the radar stream, validate every line, summarise 10 s rows | Store the rows in SQLite | \n| Think |  | Compute the night score, decide the alarm with hard limits, run **Gemma 3 1B** locally | \n| Act | Drive the **built-in 13×8 LED matrix** sunrise, play the chime, read the button | Validate every message, serve the web page | \n\nThey talk over the **Arduino Bridge** (MessagePack RPC), and every message stays tiny: one summary row of **8 integers every 10 seconds**, well under the Bridge's 256-byte limit. Over an 8-hour night that is **2,880 rows**, which is small enough to keep months of nights on the board.\n\nThe split is what makes it a *trustworthy* alarm clock:\n\n```\nMR60BHA2 radar ──UART──▶ XIAO ESP32C6 ──CSV, 1/s──▶ STM32 (validate, 10 s rows)\n                                                        │ Bridge\n                                                        ▼\n            Linux: SQLite ▶ night score ▶ decision (hard limits) ▶ Gemma 3 1B ▶ validator\n                                                        │ Bridge\n                                                        ▼\n                                  STM32: LED-matrix sunrise ▶ chime ▶ button\n```\n\nEvery minute is checked for movement, presence and breathing regularity, then:\n\n```\nscore = 100 − (restless % + 0.5 × irregular-breathing % + 10 × long awakenings)\n```\n\nEach term is a share of the minutes observed, so a 15-minute demo nap and a full night use the same scale. The web page shows every term, so you can see exactly why you got (or didn't get) your lie-in.\n\nThis was the most interesting part. A 1B model is lovely at sounding warm and terrible at facts. An alarm clock that *lies about what time it is* is worse than no alarm clock. So:\n\n`6:45` is one time, not 6 and 45, and a range like `2:10–3:30` is never read as a minus sign)\nThe first version asked the model to include the time itself. It often didn't. And on two test nights where the alarm had **not moved at all**, it cheerfully announced \"I've given you a little extra time\". 😅 Each failure became a validator rule and a test.\n\nHere are the results on the board, across 10 different decision records (good night, restless, rain, shifted yesterday, not enough data, and so on):\n\n| Prompt version | ✅ Valid on first try | 🔁 Valid after retry | 📄 Fell back to template | \n|---|---|---|---|\n| Model writes the time itself | 4 / 10 | 1 / 10 | 5 / 10 | \n| **Code writes the time, model writes the reason** | **8 / 10** | **2 / 10** | **0 / 10** | \n\nThat took the share of messages written by the model from **50% to 100%**, with **zero** wrong numbers getting through.\n\nMore real messages from that run:\n\n07:00. Good morning, dear. The rain is a bit gloomy, so I've given you a longer rest.\n\n06:30. Good morning, dear. I've been waiting for you.\n\n| Measured on the UNO Q | Result | \n|---|---|\n| Generation speed (Gemma 3 1B, 3 threads) | **~4.4 tokens/s** | \n| Prompt processing | **6.5–7.4 tokens/s** | \n| First token, cold prompt | **2.4 s** | \n| Time per wake message | **20–38 s** | \n| Time budget before the alarm | **45 min** , so**over 70×** headroom over the slowest message | \n\nIt is not perfect, and I'd rather say so. In one retry the model turned \"you slept badly, but you already slept in yesterday\" into \"you've already had a restful sleep\". Every number was right, but the tone was wrong. A rule-based validator can check facts; it can't fully check feelings. That's next on my list.\n\n`lines=12, bad=1`, so the bad line was caught and counted, not crashed on` docs/measurements.md`\nI used **Claude Code** as my coding assistant to write the software. Everything else was mine: the idea, choosing and wiring the hardware, the health rules, flashing and testing on the board, and every measurement in this post.\n\nBecause this device lives **in your bedroom, watching you sleep.** 🛏️\n\nA closed model could write a slightly nicer sentence. It could not do it on a nightstand, offline, for free, without learning when you sleep.\n\n😴 **Up to 30 minutes more sleep** on exactly the mornings you need it, and **up to 2 hours a week**, with zero risk of being late. The hard limit always wins.\n\n🧠 **Zero decisions before coffee.** You never again bargain with a snooze button, half asleep, about whether you \"can afford\" five more minutes. The sloth already did the maths against your hard limit.\n\n⌚ **Zero effort to track sleep.** No wearable to charge, no app to open, no button to press at bedtime. You just go to bed. The laziest possible sleep tracker is one you don't have to touch.\n\n🪜 **Progress without willpower.** Tomorrow's card asks for one tiny step, never the whole job, and a smaller one after a bad night. Slow and steady.", "url": "https://wpnews.pro/news/sloth-clock-slow-and-steady-wins-the-morning-an-offline-ai-alarm-that-rewards-in", "canonical_source": "https://dev.to/abhinavkrishna3211/sloth-clock-slow-and-steady-wins-the-morning-an-offline-ai-alarm-that-rewards-you-for-sleeping-in-5bl7", "published_at": "2026-10-26 06:38:29+00:00", "updated_at": "2026-10-26 06:43:12.402284+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "ai-tools", "large-language-models", "ai-products"], "entities": ["Arduino UNO Q", "Gemma 3 1B", "Seeed MR60BHA2", "XIAO ESP32C6", "Qualcomm QRB2210", "STM32U585", "Hacktoberfest"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/sloth-clock-slow-and-steady-wins-the-morning-an-offline-ai-alarm-that-rewards-in", "markdown": "https://wpnews.pro/news/sloth-clock-slow-and-steady-wins-the-morning-an-offline-ai-alarm-that-rewards-in.md", "text": "https://wpnews.pro/news/sloth-clock-slow-and-steady-wins-the-morning-an-offline-ai-alarm-that-rewards-in.txt", "jsonld": "https://wpnews.pro/news/sloth-clock-slow-and-steady-wins-the-morning-an-offline-ai-alarm-that-rewards-in.jsonld"}}