Een workout-coach op een scherm van zakformaat
Een trainer op een ESP32 met een AMOLED-scherm van 1,8 inch, met een editor en gereedschap om het apparaat op afstand te bedienen.

- Product
- Onderwerp
- Jaar
Een klein bordje met een scherm dat je door een workout leidt: kies een oefening met een veeg, stel het aantal in, tel af en ga. Om het te bouwen maakten we eerst gereedschap waarmee je het apparaat over wifi screenshot, aantikt en uitleest.
- ESP32-S3
- ESP-IDF
- LVGL
- C
- TypeScript en Vite
- Python-tooling
- Vitest
In het kort
- 113
- 339
- 20
- 3
- 141
Wat er lag
Een sporthorloge doet alles en daardoor niets echt goed. De vraag: hoe klein kan een trainer zijn die één ding doet, je door een setje oefeningen leiden? En hoe ontwerp je een interface voor een scherm van 368 bij 448 pixels, als je er niet elke keer met je neus boven wilt hangen om te zien wat er gebeurt?
Drie details die het verschil maken



Hoe het is gemaakt
Wat we bouwden
SportBillie draait op een bordje van Waveshare met een ESP32-S3 en een AMOLED-scherm van 368 bij 448 pixels. Het menu heeft twee assen: veeg omhoog of omlaag voor de spiergroep, opzij voor de oefening. Tik, kies met een veeg 5 tot 25 herhalingen of 15 tot 90 seconden, tel drie seconden af, en ga. Tijdens de set staat er alleen hoe ver je bent, en daarna wat je deed. Het werkt met aanraking, twee knoppen en wakker schudden, in ongeveer twintig milliseconden van vinger tot scherm.
Elke spiergroep heeft een eigen kleur: geel voor core, groen voor benen, blauw voor borst, oranje voor rug, lila voor armen en roze voor rekken. Daarop staat de oefening als zwarte lijntekening, 113 in totaal. De tekeningen zijn van Workout Guide door Bryl Lim, gebaseerd op Everkinetic, onder CC BY-SA 4.0; wij snijden ze bij en schalen ze naar het scherm. Herhalingen telt het bordje nog niet zelf: die sturen we nu met een commando, tot de bewegingssensor dat kan.
Alles uit één raster
Zo zag het er niet vanaf het begin uit. De eerste schets stond op een raster van 25 bij 30 stippen, 750 in totaal. Daarop tekenden we twaalf tekens: een gezicht om uit te rusten, een tempo voor hardlopen, een snelheid voor fietsen, herhalingen voor kracht, aftellen voor intervallen, een timer voor de plank, en verder een route, een week, een maand, hartslagzones, trots als je klaar bent en een gezicht dat slaapt.
De regel was dat er geen rangorde is tussen soorten inhoud, alleen tussen helderheden. Een getal, een gezicht en een kalender zijn allemaal stippen, en wat belangrijk is licht feller op. Het raster kende zeven helderheden, en de donkerste stond nooit helemaal uit, zodat je het raster altijd zag.

Fijner raster, zelfde rekenwerk
Op 25 augustus ging het raster in twee stappen van 23 bij 28 naar 46 bij 56 en daarna naar 92 bij 112 stippen, met vier pixels tussen elke stip. De afstand moest precies in 368 en 448 passen, anders blijft er een rand over, en dat kan alleen met 1, 2, 4, 8 of 16. Vier is het fijnste waarbij een stip nog als stip leest. Het kostte bijna niets: een beeld schrijft altijd hetzelfde aantal pixels, hoe fijn het raster ook is. Gemeten op het bordje: 17,0 milliseconden per beeld, 59 beelden per seconde.
Voor de letters kwamen er drie soorten: groot voor cijfers, een letter van vijf bij zeven voor woorden, en een kleine voor de editor. Woorden in de kleinste letter lukten niet, want met drie stippen breed lijken een U en een V op elkaar en stond er PVSH op het scherm. Een label paste in zes tekens, en daarom praat het scherm Engels: HERHALINGEN past niet, REPS wel.

Van stippen naar tekening
Daarna probeerden we de oefeningen als gerasterde figuren in stippen en helderheden te zetten. Een lijntekening laat zich daar slecht in vangen, en op de avond van 25 augustus ging het raster er helemaal uit, samen met alles wat er alleen voor bestond: de drie letters, de stippenschermen en het rasteren. Wat bleef is een pagina: een effen kleur per spiergroep, de tekening in zwart erop, en Inter voor de woorden.
De tekening is de brontekening zelf, alleen geschaald. Twee metingen op het scherm zelf bepaalden het formaat. Met alle grijstinten pasten de tekeningen niet in het geheugen, 4,9 MB tegen 4,4 MB vrij, dus is het één bit per pixel: 339 tekeningen in 949 kB, drie per oefening. En bij een drempel van 80 is de lijn op het scherm niet van het origineel te onderscheiden.

Het gereedschap eronder
Om een scherm van een paar centimeter te ontwerpen, moet je kunnen zien wat erop staat zonder te kijken. Daarom kreeg het bordje een klein agentje in de firmware. Met één commando maak je een screenshot van wat er echt naar het scherm ging, tik of veeg je op een plek of op een knop bij naam, en lees je de hele boom van interface-elementen uit. Over wifi gaat een screenshot ongeveer drie keer sneller dan over de kabel: zo'n 155 milliseconden tegen 500.
Naast het apparaat staat een editor in de browser met dezelfde logica, zodat ontwerpen snel blijft. De toestandsmachine is met de hand naar C overgezet en daar gelijk gehouden, en de oefeningen, kleuren en tekeningen komen uit één script dat de bestanden voor allebei schrijft. Die scheiding bleek zijn geld waard: toen het raster eruit ging, veranderde er in de toestandsmachine geen regel. De editor laat het raster nog wel zien; zijn tekenlaag is het volgende dat eruit gaat.

Wat we eruit hebben geleerd
- 01
Test door de laag die je wilt bewijzen. Een tik die we rechtstreeks in de logica stopten werkte altijd, terwijl een echte vinger niets deed: het achtergrondvlak ving elke aanraking af. Pas een nagebootste tik door het echte invoerpad liet dat zien.
- 02
Als het raster verandert, lopen de schermen niet vanzelf mee. Twee keer bleven er getallen staan die voor het oude raster waren afgemeten, en in de code zagen ze er bedoeld uit. De test die kijkt of alles op het scherm past, zag ze niet, want een gezicht op halve maat in de bovenhoek valt nergens af. Na elke verschuiving zoeken we nu de schermen af op losse getallen.
- 03
Houd de logica los van de tekening. Toen het hele raster eruit ging, veranderde er geen regel in de toestandsmachine, en ook niets aan het menu, de gebaren of het gereedschap. Dat was de eerste keer dat die scheiding echt op de proef werd gesteld.
- 04
Beoordeel een scherm op het scherm. Of de lijn met één bit per pixel nog goed genoeg was, beslisten we op het paneel zelf en niet op een monitor. Daar was hij bij een drempel van 80 niet van het origineel te onderscheiden.
Letters en kleuren
- Woorden
- Inter Medium
- Het getal
- Inter Bold
- #FFC72Cbuik en romp
- #2EB66Abenen
- #6CA6F0borst
- #FF7A3Crug
- #B08CFFarmen
- #FF7A94rekken
- #E8E4DCinstellingen
- #F4F2EChet gezicht als hij wacht
- #121212de tekening en de tekst
- De tekening heeft geen eigen kleur: het is alleen een vorm, en het scherm verft hem zwart over het vlak van de groep.
- Tot 25 augustus droeg het raster drie eigen stippenletters (5 bij 11 voor cijfers, 5 bij 7 voor woorden en 3 bij 5 voor de editor) en zeven helderheden. Die staan nog in de editor.
- Uitgelezen uit de code op 30 september 2026.
Waar het van gemaakt is
- Bordje
- ESP32-S3
- AMOLED 368 × 448
- 8 MB PSRAM
- Aanraking
- Firmware
- ESP-IDF 5.5
- LVGL 9.5
- C
- Tekeningen
- Python-script
- Eén bit per pixel
- 339 tekeningen
- Het agentje
- USB
- Wifi
- Schermafdruk
- Tikken op naam
- Editor
- TypeScript
- Vite
- Vitest
- Beweging
- Bewegingssensor
- 100 metingen per seconde
- Opnames
Voor wie verder wil lezen
Onder de motorkap
Het agentje kopieert elk stuk dat naar het paneel gaat naar een buffer.
Het agentje kopieert elk stuk dat naar het paneel gaat naar een buffer. Een schermafdruk laat dus zien wat er echt stond, en niet wat de code dacht te tekenen. Voor een afdruk tekent het eerst alles opnieuw, en dat is het grootste deel van die 155 milliseconden. Een tik van buiten gaat door een tweede invoer naast het echte aanraakscherm, zodat een vinger en een nagebootste tik door dezelfde laag lopen. Tikken op een knop bij naam gebeurt aan de kant van de computer: die leest de boom uit, zoekt de tekst en tikt in het midden.
Op het bordje worden de schermen één keer gebouwd en daarna alleen getoond, verborgen en van nieuwe tekst voorzien. Het hele scherm steeds opnieuw laten tekenen hongerde de timer van het aanraakscherm uit. Niets op het scherm is een knop: het hele paneel is één vlak voor gebaren, en elke tik valt door naar het scherm zelf.
Waar het nu staat
Af en getest op het bordje: het menu met de zes spiergroepen, het aantal kiezen, aftellen, de set en de samenvatting, slapen en wakker worden als schermstand, echte gebaren, beide knoppen, en de recorder voor de bewegingssensor.
Af en getest op het bordje: het menu met de zes spiergroepen, het aantal kiezen, aftellen, de set en de samenvatting, slapen en wakker worden als schermstand, echte gebaren, beide knoppen, en de recorder voor de bewegingssensor. Alles draait nog aan het bureau, aan de kabel.
Nog niet af: herhalingen tellen met de bewegingssensor, geluid via de audiochip, de begeleide sessie van zeven minuten naar het bordje, en een eigen routine of de vraag hoeveel tijd je hebt. Stroomverbruik meten, diep slapen en wakker worden door beweging wachten op een accu. Het agentje willen we los uitbrengen als gereedschap voor iedereen die met LVGL op een ESP32 werkt; het plan ligt er, gebouwd is het nog niet.
Telt SportBillie zelf je herhalingen?
Nog niet. Er is een recorder voor de bewegingssensor om dat af te stellen; tot die tijd sturen we een herhaling met een commando naar het bordje.
Op wat voor apparaat draait het?
Op een bordje van Waveshare met een ESP32-S3 en een AMOLED-scherm van 1,8 inch, 368 bij 448 pixels.
Van wie zijn de tekeningen?
Van Workout Guide door Bryl Lim, gebaseerd op Everkinetic, onder CC BY-SA 4.0. Wij snijden ze bij en schalen ze naar het scherm.
Waarom staan de stippen er niet meer in?
Een lijntekening laat zich slecht vangen in stippen. Op 25 augustus ging het raster eruit; nu is het een effen kleur per spiergroep met de tekening in zwart erop, en Inter voor de woorden.
Kan ik hem gebruiken?
Nog niet. SportBillie draait aan het bureau, aan de kabel, en wacht op een accu.

