DYCE — a Premium Round Die
by merlin-rce in Circuits > Electronics
27 Views, 0 Favorites, 0 Comments
DYCE — a Premium Round Die
Why roll the same old dice?
Hi, I'm Merlin a 17yo, electronics Student in Switzerland, and DYCE is my first real hardware project — built completely in the open as a learning log. It started from a small annoyance: every electronic die I'd seen was a square box with seven blinking LEDs. They work, but they feel like a classroom exercise. I wanted the opposite — something that feels like an actual product.
So I built DYCE: a round electronic die. The circular screen sits inside a ring you spin with your thumb — and here's the trick, the screen stays perfectly still while the ring turns around it. Spin it, a ring of light charges up, and it rolls and lands on a number with the odds shown right there. Inside there's a weight that gives it real heft, so it sits on a desk like a small object you actually want to pick up.
It's my first custom PCB ever (hand-soldered, and it powered up first try — still can't believe that). It's 100% offline: the rolls come from the ESP32's hardware random generator with rejection sampling, so every face is exactly equally likely — it's a genuinely fair die, not a fake animation.
And because this is the Battery-Powered Contest: DYCE runs entirely on a small internal LiPo, charges over USB-C, and a charge gives you a few hours of cordless rolling. No wall outlet, no cable — pick it up and spin.
Everything is open source (PCB, firmware, 3D files, CAD).
You can even try it in your browser with no hardware: merlin-rce.tech/Dyce
This guide walks the whole build, start to finish, so you can make your own. Let's go.
Supplies
Electronics
- ESP32-S3-WROOM-1 (N16R8) — 16 MB flash + 8 MB PSRAM. The PSRAM is what makes the full-screen animation smooth.
- GC9A01 1.28″ round TFT — 240×240, SPI. (I used the bare panel; a small breakout is easier for a first build.)
- Ring rotary encoder (hollow center) — the part that makes the whole concept work.
- IP5306 — single chip that charges the LiPo over USB-C and boosts it to 5 V (the IC inside most power banks).
- MC33269ST-3.3 LDO — drops 5 V to a clean 3.3 V for everything.
- USB-C connector
- 3.7 V LiPo battery — small one fits inside; a bigger one fits too if you want more runtime.
- General power switch + a few passives — full BOM and schematic in the repo.
Mechanical
- Custom round PCB (2-layer) — order files are in the repo (Step 2).
- Weight for the base — a brass disc, OR literally anything heavy you have (more on this in Step 8).
- PLA (matte looks great) or PETG for the 3D-printed shell.
Tools
- Soldering iron, flux, thin solder, tweezers
- 3D printer (I used a Bambu Lab A1)
- Multimeter — genuinely your best friend for the power section
- A computer with PlatformIO (VS Code)
No reflow oven needed — I hand-soldered the whole board.
How DYCE Works (and How You Use It)
The hard part of a round e-die isn't the code — it's the mechanics. If you put a normal screen on a normal rotary encoder, the screen turns with it. Useless. The fix is a ring-shaped encoder with a hollow center: the screen sits still in the middle, only the outer ring rotates. Finding that part is the moment the whole project clicked.
Using it is all in your thumb:
- Spin right (clockwise) → a ring of light charges up, then it rolls and reveals a number with its odds underneath, like 1 in 99.
- Spin left (counter-clockwise) → change the die: 1 in 2 / 5 / 10 / 50 / 99. Keep going past the last one and you hit a Contact screen with a QR code to the project.
- Leave it alone and it drifts into an attract mode that cycles little tips on screen — "Spin to roll", "Turn left to change Dice", "Bored? Spin the Dice".
- Easter egg: while a roll is charging, ease off so the ring settles around two-thirds full… and you'll land on a hidden easter egg ;)
Every roll uses the ESP32 hardware RNG with rejection sampling, so the odds are honest — no weighting, no fake reveal.
Order the PCB
This was my first PCB ever and ordering it was far less scary than I'd imagined. The whole thing is "zip a folder, upload, click order."
- Grab the Zip files on the google drive https://drive.google.com/file/d/1SQFWnhKhs6L--LeQpznVvhV_TLuFKIH2/view?usp=drive_link
- Go to a board house — JLCPCB or PCBWay (both cheap and fine for a first board) — and upload the zip.
- The site reads everything automatically. Defaults are perfect: 2 layers, 1.6 mm thickness, HASL or ENIG finish. The round outline is already in the Gerbers, so there's nothing special to set.
- (Optional) order a stencil if you want to paste-and-reflow. I only got a stencil for one side and hand-soldered the other — for a board this size, no stencil at all is totally fine.
- Order, wait about a week, and your boards turn up in the post. Holding my own PCB for the first time was one of the best moments of the build.
Solder the Board
I hand-soldered everything with a normal iron and a lot of flux. A rough order that worked for me: ESP32-S3 module first, then the power ICs (IP5306, MC33269), then USB-C, the encoder pads, and finally the passives.
Things I'd tell past-me:
- Flux is your friend. It makes the small parts easy and the joints come out shiny.
- The ESP32-S3 has lots of pads but they're along the edges — drag-soldering with flux works great.
- Mind the belly pad under the IP5306. It has a big thermal/ground pad underneath that must connect. I missed it the first time and 5 V wouldn't come up; reflowed it properly and it was fine. If a power IC seems dead, check the pad underneath first.
- Check for shorts before powering anything. Multimeter in continuity across the power rails — two minutes now saves real pain later.
- Take your time on the USB-C connector and the encoder pads; the rest is forgiving.
Downloads
The Power System (USB-C, Charging & Battery)
This is the heart of a battery build, and it's simpler than it looks:
USB-C → IP5306 → MC33269 LDO → 3.3 V → ESP32-S3 + screen + encoder
The IP5306 does two jobs at once: charges the LiPo when USB-C is plugged in, and boosts the battery to a stable 5 V when you're running cordless. One chip, the whole power-bank job.
The MC33269 LDO turns that 5 V into a clean 3.3 V for the ESP32-S3, the display and the encoder.
A side power button turns the device on/off, and the IP5306 drives a small status LED — it blinks while charging and goes solid when full. A general switch sits inline on the battery as a true cut-off.
Runtime: I ran an autonomy test on a small 3.7 V LiPo and got a little over 3 hours of active use per charge, recharging fully over USB-C. There's still empty room inside the shell, so if you want all-day runtime you can drop in a bigger cell — the power chain doesn't change at all. That headroom mattered to me: it's a desk object that should just always be ready.
⚠️ LiPo safety: never short the cell, check polarity (+/–) before powering on, and don't charge it unattended on something flammable.
First Boot & Test the Bare Board
Before assembling anything, test the bare board. I added test points on the PCB exactly for this — worth doing on your own design.
- Connect the battery, power it on with the side button. The status LED should light — the power chain is alive.
- Plug in USB-C and confirm the LED blinks (charging). With the multimeter, check 5 V at the boost output and 3.3 V after the LDO.
- Flash a tiny test sketch (I literally ran a basic blink/serial print) just to confirm the ESP32-S3 boots and is talking over USB.
When that all checks out, the scary part is behind you. Mine worked on the first real power-up and I was way too happy about it.
Flash the Firmware
The firmware is C++ on PlatformIO, targeting the ESP32-S3-WROOM-1, with TFT_eSPI driving the round display. To keep the animation flicker-free, the whole screen is drawn into a full-screen sprite in PSRAM and pushed at once — that's why the N16R8 (with PSRAM) matters.
To build and flash:
git clone https://github.com/merlin-rce/Dyce.git
cd Dyce/Firmware
pio run -t upload # build & flash
pio device monitor # serial @ 115200If upload won't start, hold the BOOT button while it connects, then release.
The code is split so it's easy to follow and to hack on:
- src/main.cpp — setup/loop, wires the encoder to the game
- src/dice.cpp — the game state machine (intro · attract · charge · reveal)
- src/ui.cpp — all the round-screen rendering (the sprite buffer)
- src/rng.cpp — fair rolls (hardware RNG + rejection sampling)
- lib/Encoder_lib/ — my own non-blocking ring-encoder driver
- include/config.h — every tunable in one place: the odds list, colors, animation timings, even the secret. Change the odds or the feel and reflash.
Pins are set at compile time in platformio.ini (display: SCLK 14, MOSI 13, DC 12, CS 11, RST 10) and config.h (encoder A 6, B 5 — flip ENC_DIR if it reads backwards). You don't have to write any of this; it's all in the repo and it's MIT-licensed.
3D Print the Enclosure
The shell is five printed parts (all in 3D Files/, exported from the parametric CAD on Onshape):
PartWhat it is
Printing is genuinely no-drama. I printed the whole set in matte PLA on a Bambu Lab A1, straight from Bambu Studio's standard 0.20 mm preset with no custom tuning, and it came out clean. PLA (matte looks great) or PETG both work. Use supports only where overhangs actually need them.
I won't pretend the design was one-shot — that pile of prototypes in the photo is real, the proportions took a bunch of iterations. But the final STLs print first time.
Want to change a part? The full parametric model is on Onshape — ask me for access via a GitHub issue, make your own copy, and edit freely.
Add the Weight (the "Premium" Trick)
This is the single cheapest upgrade to how DYCE feels, and it's the one part where you can do whatever you want. The base has a pocket for added mass, and honestly it doesn't care what you fill it with.
I used a brass disc (~200 g) because it looks clean and packs weight into a small space. But the pocket will happily take basically anything heavy you've got lying around:
- a brass or steel disc / slug (cleanest)
- steel washers, nuts, or coins stacked in
- sand or small stones / gravel
- even a bit of cast resin or concrete poured to shape
More mass = more "expensive object" feel in the hand. Aim for as much as comfortably fits — it completely changes how the thing reads. A light plastic gadget becomes something you keep picking up.
Tip: if you use loose fill (sand/gravel), seal it in first so nothing rattles or escapes into the electronics.
Final Assembly
Bring it together, from the bottom up:
- Put the weight into the Bottom base.
- Seat the PCB in, ESP32-S3 side down, and connect the battery; line the USB-C port and side button up with their openings.
- Drop the PCB-cover over the board.
- Set the Screen-holder in the center and fit the GC9A01, connecting its FPC to the board.
- Place the Encoder-ring so it spins freely around the still screen.
- Push the Button-cap onto the side button.
Check: the ring spins smoothly, the screen sits flush and dead-center, USB-C lines up.
If the ring fights you on the first fit, a tiny bit of plastic trimming where it meets the shell sorts it — completely normal.
It's Alive!
That's it — power it on, spin the ring, watch it roll.
For something that started as "what if a die had a screen and felt premium," I'm genuinely proud of how it came out: round, weighted, USB-C rechargeable, cordless for hours, fully open, and weirdly addictive to fidget with. It also taught me more than any class — first PCB, first enclosure, first time chasing a feeling and not just a function.
Everything is open source — PCB, firmware, 3D files and the full CAD:
And if you don't want to build one yet, you can try the whole thing in your browser:
If you make your own (or a variation — fork it, change the animation, redesign the shell), I'd genuinely love to see it.
Thanks for reading — and happy rolling. 🎲