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.

Created by Clém Clém

Tier 4

7 views

0 followers

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