Building a Digital Dosette
Building a Digital Dosette
I’ve been wanting to do more embedded work with Rust on ESP32s and I had some 8x8 WS2812B LED panels collecting dust. I knew I wanted to build something, so I just had to create a problem to solve with Rust, ESP32s and RGB LEDs.
The Concept
Regular dosettes, the plastic containers with separate compartments for each day, work great for preparing a week of medication in advance.
With everyone talking about the Enshittification, I’m getting FOMO because I haven’t got to enshittify anything. So, I decided to reinvent the dosette!
Reinventing the Wheel (with RGB)
![]()
My idea was to build a small device that shows the last day you took your medication. When you wake up, you check the display. If it says you last took it yesterday, you take your medication and press a button to update the dosette.
I wanted to make this somewhat practical, so I decided to make it battery powered with a small LiPo and use an ESP32C3 Xiao. The integrated BMS, low power draw and tiny form factor make it a no-brainer for most of my small projects.
I decided to try and make it feel like a product, so I went with 2 buttons on the front for the interface. The left button advances to the next day, or goes back to the previous day if you hold it. The right button puts the device to sleep, turning off the display and entering the ESP32C3 into a light-sleep.
For the switches, I decided to use MX Browns. They’re big, but feel nice and it’s amusing the digital dosette will have better switches than many gaming keyboards.
Using Rust
![]()
The Rust HAL isn’t as ergonomic as the C HAL, but that’s the cost of using a language with a safety model.
My choices for the HAL were using Espressif’s first-party esp-hal, or Embassy (which also has ESP32C3 support, built on esp-hal). As overkill as everything else was in this project, I decided against using Embassy’s async runtime, as the extra complexity simply isn’t necessary.
The only thing I would’ve done differently, if I was using the C HAL, would be to put the ESP32C3 into a deep-sleep.
Using deep-sleep would’ve dropped the ESP32C3’s power consumption down to ~5uA. Using light-sleep only gets the ESP32C3 down to ~130uA.
The Rust HAL for managing deep-sleep and NVRAM is more verbose and less documented than the C HAL, and this device doesn’t need to last for months or years on a single charge, so I opted out of the extra complexity.
Making it More Than a Hobby Project
![]()
I used crimped connectors so the screen, button module and battery attach easily. This keeps everything modular, which was very useful as I was revising the 3D printed parts. I used JST XH connectors, which made the electronics bigger than they needed to be. However, I didn’t care to optimise the size of the device at this stage.
For the case, I used a simple bottom housing with a white top panel. I’ve been wanting to use white filaments to diffuse LEDs, so it’s nice to do that testing as part of this project. It significantly softened the light, and made it look like a truly RGB LED, rather than the 3 LEDs in a trenchcoat. I didn’t have much room inside the case to make the white walls thicker to better diffuse the light, but I like that it keeps the dot-matrix aesthetic of the display.
An Easter Egg
![]()
Whenever I have a project with a screen, I always like making it play Pong, whether it’s a 2-metre long chunk of a digital billboard, or an 8x8 matrix.
If you hold both the left and right buttons, you get into a game of Pong. Use the left button to move left, the right button to move right, and play against a bad computer!
Rather than just make the computer follow the ball, I gave the bot a bit of a reaction time. It makes its move based on where the ball was, and if the speed is slow enough, where the ball will be, which makes it feel more human.
Future Tweaks
I’ve been thinking about integrating it into a single PCB. At the moment, the 8x8 matrix is one module, and I have protoboard with my voltage divider to get the battery reading and pullups for my buttons. If I swapped from Cherry MX switches to simple tactile switches, and made a larger PCB to hold the buttons, LED panel and ESP32C3 module, I’d be able to shrink the size significantly.
Swapping switches and going to a single PCB would probably take 10-20mm off of the case thickness. However, I’d need to add my own BMS module, and the cost of the unit would probably go up - 8x8 WS2812B panels are made in massive quantities, so I’d end up spending more just to replicate one of them.
For a single unit, the cheapest and highest quality option would be a generic WS2812B 8x8 module and a custom PCB for everything else.
I also considered using NTP to have the digital dosette track the date itself, so it can tell you when it’s overdue. However, it’d need a way to either enter WiFi credentials with only 2 buttons, or you’d need to use a companion app, which is a bit too enshittified for me!
Overall, this was a fun project. I got to use the tools I wanted to, and solved a problem no-one has.
Now, I just need to reinvent a way to remind people to use the digital dosette…