Blueprint

Pocket Dice - A tiny electronic LED dice

It's a dice, barely bigger than a coin cell (CR2016), based upon the ATtiny1616, with 7 orange 0603 LEDs. With the press duration being recorded, it should display a truly random generated number, unlike pseudo random number generator algorithms. I did my best to build a really good looking dice with a sleek pocket sized design: Curved exposed PCB traces on a Black PCB, transparent Resin SLA case, with a top acrylic cover.

Created by Clém Clém

Tier 4

20 views

0 followers

CAN CAN ⚡🚀 submitted Pocket Dice - A tiny electronic LED dice for ship review ago

Clém Clém submitted Pocket Dice - A tiny electronic LED dice for ship review ago

Shadow Shadow requested changes for Pocket Dice - A tiny electronic LED dice ago

user req - needs to add links and images

Tier: 4

Jay Jay ⚡🚀 submitted Pocket Dice - A tiny electronic LED dice for ship review ago

Clém Clém submitted Pocket Dice - A tiny electronic LED dice for ship review ago

Clém Clém added to the journal ago

Finished the build

Build  BP (3)

I finally received the 100 acrylic plates, and they look insane! I even received a few extra pieces! They come with protective sheets on both side, and I'm amazed to see that the cuts are really clean. The parts look just as beautiful as if they were commercially produced (... Actually, they are, but IDK, it still seemed half DIY...) I'm really happy with those, and since I now have a few in my possession, I'll certainly use them in future projects too...

Acrylic plates

I didn't waited before finishing the assembly of the last dice: I desoldered the programming wires, choosed the material for the case, and decided to take the transparent resin one. I really love being able to see the inside, and I really want to see how durable they are (I already know that I don't have to worry for the durability of the Nylon PA12 ones, but I'm not sure how the oil sprayed transparent resin parts will hold...).

So I added a CR2016 coin cell, placed the PCB in its case, removed the protective film on one acrylic rounded square plate, then attached it securely with a few drops of Cyanoacrylate on the side of the top plate (only on the top edge, and on the upper half on each side, so that the plate is still able to flex nicely on the lower side, where the button sits)

And... Here is the result:

Build  (1) BP

Build  (8)

Build  (6)

Build  (7)

Build  (5) BP

I'm really happy of how this project turned out, especially for me whose very first electronic project was also an electronic dice, but as I was just beginning with electronics a few years ago, the dice was a shield for the Arduino UNO board... so let's say that with a 9V battery and a 3D printed enclosure, the overall build was... bulky, to say the least... I'm really happy to see how far I've come!

Now, the last thing to do, is to ensure I get the expected battery life (I'm looking at 18 000 rolls on one CR2016, I hope I'll get at least 10 000), and to see if it's a fair dice... And for that, I'll just have to make as many rolls as possible, and I think that 30 rolls a day, which only takes like 5 minutes, should get me there pretty quickly... I mean in more or less a year 😅... I'll just won't forget to gather the data, keeping the outcomes on a .csv file, so I can later analyse the distribution to see how fair my dice really is.

Sasukeop159 Sasukeop159 gave kudos to Pocket Dice - A tiny electronic LED dice ago

Nice project

Clém Clém added to the journal ago

Corrected the software

As I said earlier, I had to make a few changes in the software for the Pocket Dice to work neatly and reliably.

For the false positives (all the time the dice stopped rolling because it thought I had released the button, because every slight pressure drop, before the 'bump', the 'click', can release the button. So I added a check process, to ensure the button really has been released: Once the interrupt is triggered for the released button, instead of directly going through the 'rolling outcome' part, it ensures the button is still HIGH (button released) for the next 500ms before acknowledging the button has been pressed.
This way a slight finger pressure drop wasn't long enough to trigger the dice. Nice!

I also rewrote the snippet for differentiating long from short presses, and now it works reliably.

Another quick update: I tried reducing the rolling time, to get a faster rolling animation, while the button is pressed. Initially at 250ms, I tried a few smaller durations, and I think that 120ms is the sweet spot: not too fast, but fast enough for our brain to think it's truly random, and that the moment we decide to release the button won't change the outcome...

I also noticed a slight flicker in the LEDs, especially when the room is dark (the evening), so I increased the refresh rate from 50ms to 10ms. theoretically, it should update the display 5 times faster, so the flicker is no longer visible.

Another think I thought would be cool, is to find a way to differentiate the 'Display previous dice' to the 'real random roll' (short press/long press). I changed the code, so that now, when the previous dice is displayed, the leds blink. we can still clearly see the number, but everyone knows it was the previous roll, not a newly generated one... Can be useful to prevent cheating...

The last thing I did in this Pocket_Dice_code_V2 was to add an animation just before displaying the real dice outcome. Previously, while the button is pressed, the dice 'roll', displaying random numbers one by one, just to give an impression of movement. The dice is rolling. Once the button is released, the dice would immediately display the outcome, giving an impression of sudden loss of movement, which wasn't really pleasant. In this updated version, the dice now 'slows down', by displaying 2 intermediate dummy rolls for respectively 260 and 400ms. (I had to play around a bit with the durations to get the best and smoothest result). I'm really happy with the result, because it makes the dice experience way smoother, and it also helps us understanding that we can't choose the dice outcome, since once the button is realeased, the dice keeps rolling a bit, before settling down to the True random generated number.

I think the code is now way better than before, and I'm really happy with the user experience. I think the software part is done. The V2 is available on github, and I also kept the older version for archive.

Quick review on how the false positive release determination works:

I think this part is the only not-straightforward-update-that-needs-explanations, so there it is:

If an interrupt gets fired (button state changed), the variable intAttribute is set to 1 (button pressed) but for a button release, it's a counter that starts (counterIntTime)

in the loop(), the dice keeps randomly rolling the dice while the button is pressed (intAttribute == 1). If at some point the counter counterIntTime becames valid (no longer disabled, meaning not equal to 0), it means that the interrupt has been flagged, but we don't know whether it's a real button release or a false positive, and for that the MCU has to wait 500more milliseconds, and if the button was still released during that time, meaning it's likely to be a real button release, it then enters the 'outcome' phase, with intAttribute = 0;. otherwise, if the button turned out noisy and one check fails, the counter is disabled.

Code V2 snippet

*No AI has been used to code the firmware

Clém Clém added to the journal ago

The 3D printed case:

In the meantime, I received the cases for the dice: I wanted to try JLC3DP 3D printing services, and I have to admit, the quality is way better than with a FDM 3D printer (obviously...) and for the price! When it comes to small parts, it's definitely worth it. I wanted to try multiple materials, so I ordered a few cases, from 31 cents to $1.5 per case, I got 12 cases for $11!

I tried SLA resins, like 9600 white resin, LEDO 6060 white resin, grey resin, JLC black resin, and 8001 resin, both transparent and translucent. I also tried PA12S-HP nylon, and all the parts turned out perfectly fine (I had to change a bit the CAD, to get all the walls thick enough, 0.8 to 1.2mm minimum depending on the material)

I think the Nylon 12 and transparent resin give the better results, and even though it's a bit more expensive, the premium feel is definitely worth it, so I think I'll order with Nylon 12 for other projects (as long as it stays relatively cheap, so if the parts aren't too big, otherwise FDM is just a better choice)

For the top cover, I tried to laser cut a 1mm clear acrylic sheet, but it didn't worked as planned... I mean, it's not a 3W violet laser diode that'll cleanly cut through clear acrylic... even after many slow passes, the laser couldn't go all the way through, while burning and darkening the sides, so I tried snapping the parts, which gave uneven sides, and broke the rounded corners... So I tried a different approach: Cutting the acrylic sheet into a square with a cutter, as we usually do, but I then had to round the corners, which ~half worked, breaking the corners before sanding it down, but as we can see on the picture below, it was 1. really hard to get evenly sized rounded on the 4 corners and 2. messy, and sometimes the corner just broked completely...

As I don't have any CNC machine, doing this sort of custom shape acrylic work isn't really easy and reliable, so I ordered (a few) 100 pcs (it's WAY cheaper in bulk) perfectly cut rounded squares on snijlab. For around $55, I get 100 cleanly cut top cover. I'll be using a few if I plan to make a bunch of these Pocket dice, but I'll also be able to use these acrylic squares in many more projects, now that I'll have plenty of those, I'll may orient the design choices to include these clear panels...

For the moment, I have to wait til March 10, as I chose the 'economical' shipping...

Gallery:

Case (1)

Case (4)

Case (5)

The slightly textured Nylon PA12

Case (2)

Case (3)

Case (6)

Case (7) (2)

Clém Clém added to the journal ago

PCB Assembly and debugging

I received the PCBs in a panel and after separating one board and sanding the mouse bites, I populated it, carefully adding small blobs of solder paste on each pads before using tweezers to add the components. I then reflow soldered the board with my hot plate: it's actually a bit sketchy, just a 450W heating element connected to the 230V... at least it's heating really fast, but maybe I should design a variator to control the heating curve profile... For the moment, it works, so...

IMG_20260208_200503932

IMG_20260207_193137806

For the bottom side, there were only the 0805 cap, Programming pads, and the cell holder: I added a big blob of solder paste on the negative CR2016 pad, before blasting hot air on it so it forms a thin tin dome, and did the same thing after placing the metal cell holder to solder it to the plus pads. For the 0805 cap, I hand soldered it because my hot air gun isn't meant to solder electronic stuff, so it blasts air a bit too violently, and I experienced multiple times flying components 😅...

I soldered wires to the programming pads, and crimped Duponts connectors.

IMG_20260207_200633275

IMG_20260208_191702580

I programmed the Attiny1616 with an arduino UNO as a jtag2UPDI programmer. I was amazingly astonished to see that it worked the first time. However, after hooking up a 3V power supply with my multimeter in serie, I noticed that the sleep current definitely wasn't what I was expecting: 40µA... Even though it seems really small, as the Pocket dice don't have any on/off switch, it could drain the battery in a few months while being unused... I was originally aiming for 100nA to 1µA, and it's definitely achievable according to attiny1616's datasheet...

Well, well, well...

So I went through a long phase of debugging, trying to change the code in order to completely shut down the MCU... After many research (by research, I mean: looking online, like on SpenceKonde's MegaTinyCore documentation, and also begging for help from ChatGPT, which ultimately gave me multiple things to try...), I went from changing one line of code to testing the current consumption, went back in devlopment... and after many attempts, including setting all floating pins to a defined state (I tried INPUT, INPUT_PULLUP, OUTPUT LOW, OUTPUT HIGH), changing registers, explicitely disabling ADC, etc..., I started being scared because the more things I changed, the worst it became: the current consumption went up to 400µA, for like, no reason at all... However, I noticed that when I held the board in my hands, the current consumption varied a lot, going down to .1µA when I covered it with my hand... At first, I wondered what black magic was happening here, but after thinking about it (and asking my new Electronic-related-AI-companion), I'm pretty sure it was the floating GPIOs randomly changing state due to ambiant electrical noise around it (my hand cover was acting like a shield, pulling them to a define voltage, I guess?) So after playing around for a while with registers, to completely disable pin interrups on floating pins Pxy: PORTx.PINyCTRL = PORT_ISC_INTDISABLE_gc;, - while keeping all the LED Pins to LOW -, it ended up shutting down correctly the MCU, thus achieving the .5µA continuous current consumption while idle. Finally!

Ok. So I've measured the current multiple times, and it seems to stay around .5µA while the dice is turned off, but I don't know for sure if the MCU is turning itself off correctly each time, so I guess the only way to see whether the 'mathematically accurate' battery life calculation who gives me 5-10 years idle is applicable to the real world, is to roll the dice multiple times, verifying the current consumption each time, but it's time consuming, so I'm thinking on a way to automatize this, by running a few thousands wake/sleep cycle every 10 seconds or so, while another MCU turns on and off its 3V supply once the Pocket dice is sleeping, so it rely on the charge stored in the onboard 10µ capacitor, which the voltage accros it is monitored, so that I know at which pace the capacitor discharges, thus I know the current consumtion. That could be a really fun thing to do to know if it really has a .5µA power consumption while idle, but I think I'll do that later, maybe as another project...

And when active...

The LEDs are, indeed, dimmed, but I'm happy to see that it's still visible indoor (the black/orange constrast makes it particularly efficient). Sometimes 15mA continuous for an LED isn't necessary...
As I expected, the current consumption doesn't go higher than 2mA, (maybe with peaks as my multimeter average a bit the readings), so I'm really happy to see that I achieved my low current consumption goal. if the time to roll a dice is 3 sec hold + 4 second display, I can expect more than 20 000 rolls on one CR2016! pretty impressive! Ok. Maybe the maths aren't representative enough for a real use case, but if it can achieve 10 000 rolls on a single cell, I'll be happy, trust me 😁

Ok, maybe the code wasn't perfect at the first time...

I still have to change a few things (I'll do it later this holiday):
The way it randomly rolls dice while the user hold the button is a bit too slow... I think I'll go from 250ms per frame to 100. I'll see if it's better. Another more important thing, is that the 'short press' and 'long press' determination isn't working really well... I think I'll have to troubleshoot this... Another thing is that sometimes the dice think the user released the button, while I was still holding: to really keep it running until I decide to, I have to press it relatively hard. I think it's because only 1 small fluctuation (the button bouncing just once), that make it loose contact even for a blink of an eye, is still interpreted as a falling edge so the interrupt is triggered. I thought the hardware debounce was enough, but maybe the RC values aren't properly chosen (I wanted to keep a High 200K for the pull up), or maybe I'll just enable some sofware check that ensure it's not a ghost release (maybe checking another time after a few milliseconds? I still need to figure that out.

Obviously, I'll still have to check if the dice is biaised or not, if the TRNG algorithm does it thing correctly, but for that, the only possible thing to do is to run a few hundred if not thousands rolls and see the outcome distribution... I thinks I'll do a few 20 rolls once in a while maybe each day or week, and I should be able to gather enough information. I could also see how much rolls I can really get on one cell: two birds one stone!

Ok, so... Here it is, a -half working dice- but I'll quickly fix the few problems mentioned above, and it'll be the best dice I've made so far (yeah, it's not the first time I'm making an electronic dice...).

While I'm working on it, here is how the dice looks for the moment:

.trashed-1773167020-IMG_20260208_192024949_HDR

IMG_20260208_192318478

IMG_20260208_192108823

Clém Clém added to the journal ago

Arduino code: Part 3 - added logic, TRNG algo ...

Here we are, with our 237 lines of code... (actually, I was expecting more than that, but anyway)
I finished the Arduino code (V1.0). It was definitely pretty hard to get to this point, because I had to make multiple iterations to manage this dice, but I think it should be pretty good. I let chatGPT check my work, and after multiple corrections, it should be working.

I implemented the logic behind the dice behavior (wake up, mesuring the press duration, displaying the dice outcome, etc...) and the TRNG algorithm: I used here xoshiro128plus library, so with the seed changing every time (millis(), button press duration and analog noise of a floating pin used as entropy for the dice), I should get results really close to True Random Number Generators.

I'm not commenting the code in detail, I've a life too 😅, but briefly, here is how it works:
when the button is pressed, the interrupt (falling edge on PB2) wakes up the MCU, it records a timestamp (timeIntCapture), wait for the button to be released (wait for another interrupt, this time rising edge on PB2), mesure the press duration (duration = millis() - timeIntCapture).
If the press duration is smaller than 600ms (short press), then the dice displays the previous dice outcome (if the user didn't had time to see the result in the previous roll)
Otherwise, the press duration serves as a seed for the TRNG, and the randomly generated dice outcome is displayed. After 4 secondes, the MCU turns off the LEDs, and go to sleep, waiting for the next button press in background.

To add a bit of fun, while the user press the button, the dice displays random values (changing every 250ms), like if the dice was rolling (this time using the random() function, as it's not critical, it's just for the animation)

This code is a bit sketchy, or at least it's how it feels, but if it works (we'll find out soon...), it's the only thing I need...

Arduino Code

Clém Clém added to the journal ago

Arduino code: Part 2 - added the sleep management

It took me quite a while to figure out how to manage the sleep POWER Down mode while still waking up when the button is pressed, but looking on the web, and with the help of ChatGPT, I've got a code that hopefully should work:

sleep arduino code

That was kind of the hardest part, because I've never done bare metal coding before, manipulating registers, so I had to use AI a bit, but from now on, I'll type everything myself since the remaining code is only logic, handling pins...

Clém Clém added to the journal ago

Started the Arduino code: Part 1

I started the arduino code by managing the 7-LEDs display.

As done in my other project (custom segmented display), which worked well, I managed the LEDs with 2 arrays, one for pinpointing the hardware pin, another for having the state of the LED:

Setup:

init Arduino code 01 corrected

Updating the LED array:

I created a function that update the state array, so we can either display the dice outcome (from 1 to 6) or turning off the LEDs (displayDice (0))

displayDice function code 01

Turning ON and OFF the LEDs:

Ok. Here comes the hardest part. I don't simply want to turn on the LEDs that are set to 1 in the array, and turning off the LEDs set to 0, because it would mean that all the LEDs are either on or off. So an outcome of 6 would result in 6 LEDs lit at the same time! so each LED drawing around 1 - 2 mA, it would mean ∽6 - 12 mA, so on a CR2016, it's (way) too much! Instead, I will only lit 2 LEDs at a time, going in cycles. something like :

  1. L1 on, L2 on
  2. L1 off, L3 on
  3. L2off, L4 on ...
  4. L5 off, L6 on
  5. L6 off
  6. And circle back to 1

All these steps repeating multiple times.

This way, each LED gets turned on and off one after another (only 2 LEDs lit at the same time), a bit like a custom PWM, and I should get more reliable results. I just hope it will be bright enough, but I guess we'll see once it's built... Anyway, I had to come up with a pretty difficult function, refreshDisplay(int duration), but with the help of chatGPT for correcting my work, it should be working pretty well. By the way, thanks to RAM sticks in AI datacenters for coming up with the % 7 idea, which is actually really smart because it warps the loop flawlessly:

refresh function arduino code 01

With this function, I can generate the 'custom PWM' for driving the LEDs according to the array stateLED[], for duration ms. In the loop, I'll have multiple events (like reading the button state, ...) with in between calls of the function refreshDisplay (200) or refreshDisplay (500), depending on the precision required ( refreshDisplay ()is a blocking function).

Clém Clém added to the journal ago

Designed the Case

I designed the case in Fusion 360, doing my best to have a sleek and stylish enclosure for the 4mm thin dice. The PCB will be placed in the 3d printed part consisting of the bottom plate and 4 walls all around, and I'll add on top a 1mmm acrylic sheet (laser cut if I somehow manage to cut through the transparent acrylic sheet, or with the help of a cutter and sand paper otherwise...). The acrylic sheet would be glued to the 3d printed enclosure only on it's sides, and the button underneath will be pressed by the small flex of the thin 1mm acrylic. I'm pretty convinced it'll work, but I'll only really know once the Pocket Dice will be assembled.

The Pocket Dice is approximately 30mm by 30mm by 7mm high.

Renders:

As always, I made a few Renders :

RENDER 2

RENDER 1

RENDER 3

RENDER 4

RENDER 5

RENDER 6

Clém Clém added to the journal ago

Panelized and ordered the board

I changed my mind, and instead of having multiple circuit onto the PCB, I'll just have multiple dice. So I wanted to panelize the PCB, a 3 by 3 grid would fit, but when doing the automatic panelization on EasyEDA, I couldn't tweak each pcb separatly. What I wanted to do was to change a bit the silkscreen for each board, so that 3 per panel are the original one (with the text like 'Pocket Dice' and 'Dieu de l'élec'), another 3 with simply the 'Pocket Dice' mention, and the 3 remaining completely blank.

So to do that, I add to manually panelize the PCB, drawing the board outline and adding the mouse bites, based on what Easyeda Automatic panelization looked like, which was a quite tedious task. I then made the few modification I wanted, and the panel was ready for production. I hope JLC PCB don't reject it, if they thinks it's 9 different designs...

Let's see if the panel get produced.

PCB PANEL

PCB PANEL 2D n

PCB PANEL 2D back n

And...

I just order the PCBs. Fingers crossed! 🤞
JLCPCB

EDIT: Yeah, so, I had to pay an extra $7 for paneling, but I think for 45 PCBs it's still worth it.

Clém Clém added to the journal ago

Oops: I forgot an imporant part...

Just remembered to add the Pads for programming (UPDI (D), GND and VCC)...
I added them in a corner on the back side of the PCB

Here is a zoom of the updated PCB:

EDIT

Clém Clém added to the journal ago

Prepared the CAD...

I added the CAD of the PCB in a new Fusion 360 project, but before starting designing the case, I had to do a few things...
Some components didn't loaded well when exporting from EasyEDA, so I had to manually add them to Fusion 360, downloading them from GrabCad (0603 Caps, QFN20) and I also added the CR2016 Coin cell, and I had to modify the coin cell holder (the orinigal 3d model was for a CR2032, so too thick, so I shrank it a bit following the thickness given in the datasheet). I also changed the PCB thickness to .8mm instead of the basic 1.6mm.

As always, I then added a few appearances, and made a few renders of the PCB:

PCB 3d render 1

PCB 3d render 2

PCB 3d render 3

Clém Clém added to the journal ago

Made the PCB

I designed the PCB, a 26 by 26mm square, and placed the components. All the components thin enough are on the top side, and the bigger ones (CR2016 cell holder and 0805 caps) are on the other side. This way, the button protrudes and it can be pressed without being affected by the height of the other components around. I then routed the few traces, like this:

PCB 1

I thought it would look way better with curved traces so I ''melted them'' by hand (EasyEDA don't have a cool plug-in that do the job):

PCB 2

And as it is more of an artwork than a basic PCB (still functionnal though), I thought it would look awesome with all the curved traces exposed. So It's what I did: drawing lines on top of each trace in the soldermask layer, and I'm really happy with the result. As always, I removed all the unnecessary silkscreen around the components, and added custom text.

Here is the result:

PCB 3 3d

PCB 3 back 3d

PCB 3

PCB 3 back

Clém Clém added to the journal ago

Drew the schematic

As said, we've got the ATtiny1616, a metal coin cell holder (CR2016), a few decoupling caps, 7 LEDs connected to the MCU in source mode, and a button with it's pull-up and debouncing cap. Pretty straightforward.

Don't bother with the ''.A'' on each net... it's not important. (well, it's just that I'll put many small designs onto one PCB to save on cost, so to avoid having a lot of blue ratlines in between the pcbs, I make separate GNDs and VCCs for the separate designs...)

Schematic Dice

Clém Clém added to the journal ago

Research,Brainstorming on the goals & electronic integration

The main goal of this project is to keep the dice running for an extended period of time. When displaying the dice outcome, it will obviously draw a few milliamps, which will still drain the CR2016 in a few hours, and lowering the current drawn by the LEDs is the only thing we can do about that (thus lowering the dice brightness, but as long as it can be seen indoor, it's fine) But when unused, the goal is to have the smallest continuous current, and yes, It won't have a switch to turn off the device, only a single button that wakes up the MCU, rolls the dice, and then the MCU goes back into sleep mode after a few seconds.

So to achieve that, I initally though about using a load switch IC (like the SY6280AAC) that would have a really small shut down current (1µA), and that would be controlled by the button, and then the MCU latching the EN pin, so that it can display the dice while the user has already released the button. In order for the MCU to still be able to determine wether the button was held or not, I had simulated a set of resistor voltage dividers to join the latching function and MCU monitoring, and it seemed pretty convincing.

However, I thought it was a bit overcomplicated, and that the limited space won't accept too much external components, so after doing more research, I decided that I'll use the ATtiny1616 Power down mode:

This QFN20 IC was the perfect chip for this project:
- It's Arduino compatible, so easy to work with
- It can run with VDD being as low as 1.8V, so perfect for a CR2016 3V coin cell, even a bit discharged
- It has awesome current consumption : with a low Clock speed, I should be able to lower the current consumption when running down to ∽600µA, and when sleeping in Power down Mode, It should go down to 5 - 10µA.
- Last but not least, it's cheap. Not absurdly cheap, but still 90 cents...

So along with 0603 orange LEDs and 1k serie resistor with each LED, the overall current consumtion should stay low enough for the CR2016. Just hope it's going to be bright enough for indoor use...

Here is roughly how the dice will look like (5min sketch on Fusion 360, just to lay down my ideas) :

rough shape

I think I'm good to go, so let's jump into the schematic!

Clém Clém started Pocket Dice - A tiny electronic LED dice ago

1/21/2026 - Research,Brainstorming on the goals & electronic integration

The main goal of this project is to keep the dice running for an extended period of time. When displaying the dice outcome, it will obviously draw a few milliamps, which will still drain the CR2016 in a few hours, and lowering the current drawn by the LEDs is the only thing we can do about that (thus lowering the dice brightness, but as long as it can be seen indoor, it's fine) But when unused, the goal is to have the smallest continuous current, and yes, It won't have a switch to turn off the device, only a single button that wakes up the MCU, rolls the dice, and then the MCU goes back into sleep mode after a few seconds.

So to achieve that, I initally though about using a load switch IC (like the SY6280AAC) that would have a really small shut down current (1µA), and that would be controlled by the button, and then the MCU latching the EN pin, so that it can display the dice while the user has already released the button. In order for the MCU to still be able to determine wether the button was held or not, I had simulated a set of resistor voltage dividers to join the latching function and MCU monitoring, and it seemed pretty convincing.

However, I thought it was a bit overcomplicated, and that the limited space won't accept too much external components, so after doing more research, I decided that I'll use the ATtiny1616 Power down mode:

This QFN20 IC was the perfect chip for this project:
- It's Arduino compatible, so easy to work with
- It can run with VDD being as low as 1.8V, so perfect for a CR2016 3V coin cell, even a bit discharged
- It has awesome current consumption : with a low Clock speed, I should be able to lower the current consumption when running down to ∽600µA, and when sleeping in Power down Mode, It should go down to 5 - 10µA.
- Last but not least, it's cheap. Not absurdly cheap, but still 90 cents...

So along with 0603 orange LEDs and 1k serie resistor with each LED, the overall current consumtion should stay low enough for the CR2016. Just hope it's going to be bright enough for indoor use...

Here is roughly how the dice will look like (5min sketch on Fusion 360, just to lay down my ideas) :

rough shape

I think I'm good to go, so let's jump into the schematic!

1/22/2026 12 AM - Drew the schematic

As said, we've got the ATtiny1616, a metal coin cell holder (CR2016), a few decoupling caps, 7 LEDs connected to the MCU in source mode, and a button with it's pull-up and debouncing cap. Pretty straightforward.

Don't bother with the ''.A'' on each net... it's not important. (well, it's just that I'll put many small designs onto one PCB to save on cost, so to avoid having a lot of blue ratlines in between the pcbs, I make separate GNDs and VCCs for the separate designs...)

Schematic Dice

1/22/2026 6 PM - Made the PCB

I designed the PCB, a 26 by 26mm square, and placed the components. All the components thin enough are on the top side, and the bigger ones (CR2016 cell holder and 0805 caps) are on the other side. This way, the button protrudes and it can be pressed without being affected by the height of the other components around. I then routed the few traces, like this:

PCB 1

I thought it would look way better with curved traces so I ''melted them'' by hand (EasyEDA don't have a cool plug-in that do the job):

PCB 2

And as it is more of an artwork than a basic PCB (still functionnal though), I thought it would look awesome with all the curved traces exposed. So It's what I did: drawing lines on top of each trace in the soldermask layer, and I'm really happy with the result. As always, I removed all the unnecessary silkscreen around the components, and added custom text.

Here is the result:

PCB 3 3d

PCB 3 back 3d

PCB 3

PCB 3 back

1/22/2026 8:30 PM - Prepared the CAD...

I added the CAD of the PCB in a new Fusion 360 project, but before starting designing the case, I had to do a few things...
Some components didn't loaded well when exporting from EasyEDA, so I had to manually add them to Fusion 360, downloading them from GrabCad (0603 Caps, QFN20) and I also added the CR2016 Coin cell, and I had to modify the coin cell holder (the orinigal 3d model was for a CR2032, so too thick, so I shrank it a bit following the thickness given in the datasheet). I also changed the PCB thickness to .8mm instead of the basic 1.6mm.

As always, I then added a few appearances, and made a few renders of the PCB:

PCB 3d render 1

PCB 3d render 2

PCB 3d render 3

1/22/2026 8:57 PM - Oops: I forgot an imporant part...

Just remembered to add the Pads for programming (UPDI (D), GND and VCC)...
I added them in a corner on the back side of the PCB

Here is a zoom of the updated PCB:

EDIT

1/23/2026 - Panelized and ordered the board

I changed my mind, and instead of having multiple circuit onto the PCB, I'll just have multiple dice. So I wanted to panelize the PCB, a 3 by 3 grid would fit, but when doing the automatic panelization on EasyEDA, I couldn't tweak each pcb separatly. What I wanted to do was to change a bit the silkscreen for each board, so that 3 per panel are the original one (with the text like 'Pocket Dice' and 'Dieu de l'élec'), another 3 with simply the 'Pocket Dice' mention, and the 3 remaining completely blank.

So to do that, I add to manually panelize the PCB, drawing the board outline and adding the mouse bites, based on what Easyeda Automatic panelization looked like, which was a quite tedious task. I then made the few modification I wanted, and the panel was ready for production. I hope JLC PCB don't reject it, if they thinks it's 9 different designs...

Let's see if the panel get produced.

PCB PANEL

PCB PANEL 2D n

PCB PANEL 2D back n

And...

I just order the PCBs. Fingers crossed! 🤞
JLCPCB

EDIT: Yeah, so, I had to pay an extra $7 for paneling, but I think for 45 PCBs it's still worth it.

1/24/2026 - Designed the Case

I designed the case in Fusion 360, doing my best to have a sleek and stylish enclosure for the 4mm thin dice. The PCB will be placed in the 3d printed part consisting of the bottom plate and 4 walls all around, and I'll add on top a 1mmm acrylic sheet (laser cut if I somehow manage to cut through the transparent acrylic sheet, or with the help of a cutter and sand paper otherwise...). The acrylic sheet would be glued to the 3d printed enclosure only on it's sides, and the button underneath will be pressed by the small flex of the thin 1mm acrylic. I'm pretty convinced it'll work, but I'll only really know once the Pocket Dice will be assembled.

The Pocket Dice is approximately 30mm by 30mm by 7mm high.

Renders:

As always, I made a few Renders :

RENDER 2

RENDER 1

RENDER 3

RENDER 4

RENDER 5

RENDER 6

1/28/2026 - Started the Arduino code: Part 1

I started the arduino code by managing the 7-LEDs display.

As done in my other project (custom segmented display), which worked well, I managed the LEDs with 2 arrays, one for pinpointing the hardware pin, another for having the state of the LED:

Setup:

init Arduino code 01 corrected

Updating the LED array:

I created a function that update the state array, so we can either display the dice outcome (from 1 to 6) or turning off the LEDs (displayDice (0))

displayDice function code 01

Turning ON and OFF the LEDs:

Ok. Here comes the hardest part. I don't simply want to turn on the LEDs that are set to 1 in the array, and turning off the LEDs set to 0, because it would mean that all the LEDs are either on or off. So an outcome of 6 would result in 6 LEDs lit at the same time! so each LED drawing around 1 - 2 mA, it would mean ∽6 - 12 mA, so on a CR2016, it's (way) too much! Instead, I will only lit 2 LEDs at a time, going in cycles. something like :

  1. L1 on, L2 on
  2. L1 off, L3 on
  3. L2off, L4 on ...
  4. L5 off, L6 on
  5. L6 off
  6. And circle back to 1

All these steps repeating multiple times.

This way, each LED gets turned on and off one after another (only 2 LEDs lit at the same time), a bit like a custom PWM, and I should get more reliable results. I just hope it will be bright enough, but I guess we'll see once it's built... Anyway, I had to come up with a pretty difficult function, refreshDisplay(int duration), but with the help of chatGPT for correcting my work, it should be working pretty well. By the way, thanks to RAM sticks in AI datacenters for coming up with the % 7 idea, which is actually really smart because it warps the loop flawlessly:

refresh function arduino code 01

With this function, I can generate the 'custom PWM' for driving the LEDs according to the array stateLED[], for duration ms. In the loop, I'll have multiple events (like reading the button state, ...) with in between calls of the function refreshDisplay (200) or refreshDisplay (500), depending on the precision required ( refreshDisplay ()is a blocking function).

1/29/2026 1 PM - Arduino code: Part 2 - added the sleep management

It took me quite a while to figure out how to manage the sleep POWER Down mode while still waking up when the button is pressed, but looking on the web, and with the help of ChatGPT, I've got a code that hopefully should work:

sleep arduino code

That was kind of the hardest part, because I've never done bare metal coding before, manipulating registers, so I had to use AI a bit, but from now on, I'll type everything myself since the remaining code is only logic, handling pins...

1/29/2026 9 PM - Arduino code: Part 3 - added logic, TRNG algo ...

Here we are, with our 237 lines of code... (actually, I was expecting more than that, but anyway)
I finished the Arduino code (V1.0). It was definitely pretty hard to get to this point, because I had to make multiple iterations to manage this dice, but I think it should be pretty good. I let chatGPT check my work, and after multiple corrections, it should be working.

I implemented the logic behind the dice behavior (wake up, mesuring the press duration, displaying the dice outcome, etc...) and the TRNG algorithm: I used here xoshiro128plus library, so with the seed changing every time (millis(), button press duration and analog noise of a floating pin used as entropy for the dice), I should get results really close to True Random Number Generators.

I'm not commenting the code in detail, I've a life too 😅, but briefly, here is how it works:
when the button is pressed, the interrupt (falling edge on PB2) wakes up the MCU, it records a timestamp (timeIntCapture), wait for the button to be released (wait for another interrupt, this time rising edge on PB2), mesure the press duration (duration = millis() - timeIntCapture).
If the press duration is smaller than 600ms (short press), then the dice displays the previous dice outcome (if the user didn't had time to see the result in the previous roll)
Otherwise, the press duration serves as a seed for the TRNG, and the randomly generated dice outcome is displayed. After 4 secondes, the MCU turns off the LEDs, and go to sleep, waiting for the next button press in background.

To add a bit of fun, while the user press the button, the dice displays random values (changing every 250ms), like if the dice was rolling (this time using the random() function, as it's not critical, it's just for the animation)

This code is a bit sketchy, or at least it's how it feels, but if it works (we'll find out soon...), it's the only thing I need...

Arduino Code

2/8/2026 - PCB Assembly and debugging

I received the PCBs in a panel and after separating one board and sanding the mouse bites, I populated it, carefully adding small blobs of solder paste on each pads before using tweezers to add the components. I then reflow soldered the board with my hot plate: it's actually a bit sketchy, just a 450W heating element connected to the 230V... at least it's heating really fast, but maybe I should design a variator to control the heating curve profile... For the moment, it works, so...

IMG_20260208_200503932

IMG_20260207_193137806

For the bottom side, there were only the 0805 cap, Programming pads, and the cell holder: I added a big blob of solder paste on the negative CR2016 pad, before blasting hot air on it so it forms a thin tin dome, and did the same thing after placing the metal cell holder to solder it to the plus pads. For the 0805 cap, I hand soldered it because my hot air gun isn't meant to solder electronic stuff, so it blasts air a bit too violently, and I experienced multiple times flying components 😅...

I soldered wires to the programming pads, and crimped Duponts connectors.

IMG_20260207_200633275

IMG_20260208_191702580

I programmed the Attiny1616 with an arduino UNO as a jtag2UPDI programmer. I was amazingly astonished to see that it worked the first time. However, after hooking up a 3V power supply with my multimeter in serie, I noticed that the sleep current definitely wasn't what I was expecting: 40µA... Even though it seems really small, as the Pocket dice don't have any on/off switch, it could drain the battery in a few months while being unused... I was originally aiming for 100nA to 1µA, and it's definitely achievable according to attiny1616's datasheet...

Well, well, well...

So I went through a long phase of debugging, trying to change the code in order to completely shut down the MCU... After many research (by research, I mean: looking online, like on SpenceKonde's MegaTinyCore documentation, and also begging for help from ChatGPT, which ultimately gave me multiple things to try...), I went from changing one line of code to testing the current consumption, went back in devlopment... and after many attempts, including setting all floating pins to a defined state (I tried INPUT, INPUT_PULLUP, OUTPUT LOW, OUTPUT HIGH), changing registers, explicitely disabling ADC, etc..., I started being scared because the more things I changed, the worst it became: the current consumption went up to 400µA, for like, no reason at all... However, I noticed that when I held the board in my hands, the current consumption varied a lot, going down to .1µA when I covered it with my hand... At first, I wondered what black magic was happening here, but after thinking about it (and asking my new Electronic-related-AI-companion), I'm pretty sure it was the floating GPIOs randomly changing state due to ambiant electrical noise around it (my hand cover was acting like a shield, pulling them to a define voltage, I guess?) So after playing around for a while with registers, to completely disable pin interrups on floating pins Pxy: PORTx.PINyCTRL = PORT_ISC_INTDISABLE_gc;, - while keeping all the LED Pins to LOW -, it ended up shutting down correctly the MCU, thus achieving the .5µA continuous current consumption while idle. Finally!

Ok. So I've measured the current multiple times, and it seems to stay around .5µA while the dice is turned off, but I don't know for sure if the MCU is turning itself off correctly each time, so I guess the only way to see whether the 'mathematically accurate' battery life calculation who gives me 5-10 years idle is applicable to the real world, is to roll the dice multiple times, verifying the current consumption each time, but it's time consuming, so I'm thinking on a way to automatize this, by running a few thousands wake/sleep cycle every 10 seconds or so, while another MCU turns on and off its 3V supply once the Pocket dice is sleeping, so it rely on the charge stored in the onboard 10µ capacitor, which the voltage accros it is monitored, so that I know at which pace the capacitor discharges, thus I know the current consumtion. That could be a really fun thing to do to know if it really has a .5µA power consumption while idle, but I think I'll do that later, maybe as another project...

And when active...

The LEDs are, indeed, dimmed, but I'm happy to see that it's still visible indoor (the black/orange constrast makes it particularly efficient). Sometimes 15mA continuous for an LED isn't necessary...
As I expected, the current consumption doesn't go higher than 2mA, (maybe with peaks as my multimeter average a bit the readings), so I'm really happy to see that I achieved my low current consumption goal. if the time to roll a dice is 3 sec hold + 4 second display, I can expect more than 20 000 rolls on one CR2016! pretty impressive! Ok. Maybe the maths aren't representative enough for a real use case, but if it can achieve 10 000 rolls on a single cell, I'll be happy, trust me 😁

Ok, maybe the code wasn't perfect at the first time...

I still have to change a few things (I'll do it later this holiday):
The way it randomly rolls dice while the user hold the button is a bit too slow... I think I'll go from 250ms per frame to 100. I'll see if it's better. Another more important thing, is that the 'short press' and 'long press' determination isn't working really well... I think I'll have to troubleshoot this... Another thing is that sometimes the dice think the user released the button, while I was still holding: to really keep it running until I decide to, I have to press it relatively hard. I think it's because only 1 small fluctuation (the button bouncing just once), that make it loose contact even for a blink of an eye, is still interpreted as a falling edge so the interrupt is triggered. I thought the hardware debounce was enough, but maybe the RC values aren't properly chosen (I wanted to keep a High 200K for the pull up), or maybe I'll just enable some sofware check that ensure it's not a ghost release (maybe checking another time after a few milliseconds? I still need to figure that out.

Obviously, I'll still have to check if the dice is biaised or not, if the TRNG algorithm does it thing correctly, but for that, the only possible thing to do is to run a few hundred if not thousands rolls and see the outcome distribution... I thinks I'll do a few 20 rolls once in a while maybe each day or week, and I should be able to gather enough information. I could also see how much rolls I can really get on one cell: two birds one stone!

Ok, so... Here it is, a -half working dice- but I'll quickly fix the few problems mentioned above, and it'll be the best dice I've made so far (yeah, it's not the first time I'm making an electronic dice...).

While I'm working on it, here is how the dice looks for the moment:

.trashed-1773167020-IMG_20260208_192024949_HDR

IMG_20260208_192318478

IMG_20260208_192108823

2/18/2026 - The 3D printed case:

In the meantime, I received the cases for the dice: I wanted to try JLC3DP 3D printing services, and I have to admit, the quality is way better than with a FDM 3D printer (obviously...) and for the price! When it comes to small parts, it's definitely worth it. I wanted to try multiple materials, so I ordered a few cases, from 31 cents to $1.5 per case, I got 12 cases for $11!

I tried SLA resins, like 9600 white resin, LEDO 6060 white resin, grey resin, JLC black resin, and 8001 resin, both transparent and translucent. I also tried PA12S-HP nylon, and all the parts turned out perfectly fine (I had to change a bit the CAD, to get all the walls thick enough, 0.8 to 1.2mm minimum depending on the material)

I think the Nylon 12 and transparent resin give the better results, and even though it's a bit more expensive, the premium feel is definitely worth it, so I think I'll order with Nylon 12 for other projects (as long as it stays relatively cheap, so if the parts aren't too big, otherwise FDM is just a better choice)

For the top cover, I tried to laser cut a 1mm clear acrylic sheet, but it didn't worked as planned... I mean, it's not a 3W violet laser diode that'll cleanly cut through clear acrylic... even after many slow passes, the laser couldn't go all the way through, while burning and darkening the sides, so I tried snapping the parts, which gave uneven sides, and broke the rounded corners... So I tried a different approach: Cutting the acrylic sheet into a square with a cutter, as we usually do, but I then had to round the corners, which ~half worked, breaking the corners before sanding it down, but as we can see on the picture below, it was 1. really hard to get evenly sized rounded on the 4 corners and 2. messy, and sometimes the corner just broked completely...

As I don't have any CNC machine, doing this sort of custom shape acrylic work isn't really easy and reliable, so I ordered (a few) 100 pcs (it's WAY cheaper in bulk) perfectly cut rounded squares on snijlab. For around $55, I get 100 cleanly cut top cover. I'll be using a few if I plan to make a bunch of these Pocket dice, but I'll also be able to use these acrylic squares in many more projects, now that I'll have plenty of those, I'll may orient the design choices to include these clear panels...

For the moment, I have to wait til March 10, as I chose the 'economical' shipping...

Gallery:

Case (1)

Case (4)

Case (5)

The slightly textured Nylon PA12

Case (2)

Case (3)

Case (6)

Case (7) (2)

3/3/2026 - Corrected the software

As I said earlier, I had to make a few changes in the software for the Pocket Dice to work neatly and reliably.

For the false positives (all the time the dice stopped rolling because it thought I had released the button, because every slight pressure drop, before the 'bump', the 'click', can release the button. So I added a check process, to ensure the button really has been released: Once the interrupt is triggered for the released button, instead of directly going through the 'rolling outcome' part, it ensures the button is still HIGH (button released) for the next 500ms before acknowledging the button has been pressed.
This way a slight finger pressure drop wasn't long enough to trigger the dice. Nice!

I also rewrote the snippet for differentiating long from short presses, and now it works reliably.

Another quick update: I tried reducing the rolling time, to get a faster rolling animation, while the button is pressed. Initially at 250ms, I tried a few smaller durations, and I think that 120ms is the sweet spot: not too fast, but fast enough for our brain to think it's truly random, and that the moment we decide to release the button won't change the outcome...

I also noticed a slight flicker in the LEDs, especially when the room is dark (the evening), so I increased the refresh rate from 50ms to 10ms. theoretically, it should update the display 5 times faster, so the flicker is no longer visible.

Another think I thought would be cool, is to find a way to differentiate the 'Display previous dice' to the 'real random roll' (short press/long press). I changed the code, so that now, when the previous dice is displayed, the leds blink. we can still clearly see the number, but everyone knows it was the previous roll, not a newly generated one... Can be useful to prevent cheating...

The last thing I did in this Pocket_Dice_code_V2 was to add an animation just before displaying the real dice outcome. Previously, while the button is pressed, the dice 'roll', displaying random numbers one by one, just to give an impression of movement. The dice is rolling. Once the button is released, the dice would immediately display the outcome, giving an impression of sudden loss of movement, which wasn't really pleasant. In this updated version, the dice now 'slows down', by displaying 2 intermediate dummy rolls for respectively 260 and 400ms. (I had to play around a bit with the durations to get the best and smoothest result). I'm really happy with the result, because it makes the dice experience way smoother, and it also helps us understanding that we can't choose the dice outcome, since once the button is realeased, the dice keeps rolling a bit, before settling down to the True random generated number.

I think the code is now way better than before, and I'm really happy with the user experience. I think the software part is done. The V2 is available on github, and I also kept the older version for archive.

Quick review on how the false positive release determination works:

I think this part is the only not-straightforward-update-that-needs-explanations, so there it is:

If an interrupt gets fired (button state changed), the variable intAttribute is set to 1 (button pressed) but for a button release, it's a counter that starts (counterIntTime)

in the loop(), the dice keeps randomly rolling the dice while the button is pressed (intAttribute == 1). If at some point the counter counterIntTime becames valid (no longer disabled, meaning not equal to 0), it means that the interrupt has been flagged, but we don't know whether it's a real button release or a false positive, and for that the MCU has to wait 500more milliseconds, and if the button was still released during that time, meaning it's likely to be a real button release, it then enters the 'outcome' phase, with intAttribute = 0;. otherwise, if the button turned out noisy and one check fails, the counter is disabled.

Code V2 snippet

*No AI has been used to code the firmware

3/16/2026 - Finished the build

Build  BP (3)

I finally received the 100 acrylic plates, and they look insane! I even received a few extra pieces! They come with protective sheets on both side, and I'm amazed to see that the cuts are really clean. The parts look just as beautiful as if they were commercially produced (... Actually, they are, but IDK, it still seemed half DIY...) I'm really happy with those, and since I now have a few in my possession, I'll certainly use them in future projects too...

Acrylic plates

I didn't waited before finishing the assembly of the last dice: I desoldered the programming wires, choosed the material for the case, and decided to take the transparent resin one. I really love being able to see the inside, and I really want to see how durable they are (I already know that I don't have to worry for the durability of the Nylon PA12 ones, but I'm not sure how the oil sprayed transparent resin parts will hold...).

So I added a CR2016 coin cell, placed the PCB in its case, removed the protective film on one acrylic rounded square plate, then attached it securely with a few drops of Cyanoacrylate on the side of the top plate (only on the top edge, and on the upper half on each side, so that the plate is still able to flex nicely on the lower side, where the button sits)

And... Here is the result:

Build  (1) BP

Build  (8)

Build  (6)

Build  (7)

Build  (5) BP

I'm really happy of how this project turned out, especially for me whose very first electronic project was also an electronic dice, but as I was just beginning with electronics a few years ago, the dice was a shield for the Arduino UNO board... so let's say that with a 9V battery and a 3D printed enclosure, the overall build was... bulky, to say the least... I'm really happy to see how far I've come!

Now, the last thing to do, is to ensure I get the expected battery life (I'm looking at 18 000 rolls on one CR2016, I hope I'll get at least 10 000), and to see if it's a fair dice... And for that, I'll just have to make as many rolls as possible, and I think that 30 rolls a day, which only takes like 5 minutes, should get me there pretty quickly... I mean in more or less a year 😅... I'll just won't forget to gather the data, keeping the outcomes on a .csv file, so I can later analyse the distribution to see how fair my dice really is.