This is Mr. Dice - a handheld dice rolling gadget powered by a Raspberry Pi Pico.
Mr. Dice allows you to quickly chose and roll up to five dice of varying values, displaying both the roll for each individual die and the total value.
To see Mr. Dice in action, check out this short video.
If you're more of a video watcher than a blog post reader, I have a full-length video about the creation of Mr. Dice as well.
Overall, this project was a big step forward for me in terms of hardware design and development. It was the first time I created a useful PCB for a project, the first time I used multi-color printing, and the first time I wrote a robust / stable application for the Raspberry Pi Pico.
How (and why) I Made It
Please note: This post contains affiliate links to many of the parts used in this build!
I've always had a bit of a fixation on dice - there is something so fascinating about these little objects which embody randomness and chance. The fact that these little cubes are central to thousands of games - representing billions of hours of good times - is just so freaking cool.
However I did not originally plan to make a dice rolling gadget, in fact this project started as an attempt to learn KiCad, the fantastic open-source EDA (read: PCB designing) tool. After experiencing the pain of the wiring mess inside my PokeDex I desperately wanted to swap all those wires for a beautiful, clean circuit board.
Sadly, KiCad - like any complex tool - has quite a learning curve and since I knew nothing about electrical engineering I knew I needed to start with the basics. I followed a lovely intro to KiCad course by DigiKey which talked me through the basic terminology - footprints, layers, traces, etc.
Luckily my goals for my first project were quite unambitious, so it was easy to turn the simple example in the DigiKey course into a practical PCB.
I decided, for simplicity sake, to design my device around a regular Raspberry Pi Pico. If you're not familiar, these devices are an outlier in the Raspberry Pi family. Compared to the full-size Raspberry Pi devices or the smaller Raspberry Pi Zero devices which are both larger boards capable of running full operating systems, the Pi Pico are microcontrollers (not microprocessors) which means they run simpler programs with direct access to hardware. They are also very cheap (less than $5 in some cases) and still very capable for many tasks.
Here's a Pi Pico - in case you've never seen one.
Each of those gold pads wire up (most of the time) directly to the device's RP2040 chip which is the real workhorse of the device. These pins are a mix of power inputs, power outputs, I/O, and debugging pins.
For simple uses you could grab a Pico, solder up some wires and immediately begin reading button presses or flashing LEDs. However an important element of the Pico's physical design is it's castellated mounting holes. Each gold pad has both a full circle hole (for a pin or wire to solder into) and a half circle right on the edge.
These clever holes allow the Pico to be soldered directly to a daughter board as long as that second board has the correct pads with the correct spacing which line up with the Pico's physical layout.
For example, here is the final PCB for Mr Dice. You can see the large Pico-like footprint which has all the pads and some additional silkscreening with labels.
Once you place your Pico on top you can solder each of those pins (in this photo, very poorly solder) to the daughter board and with minimal effort we've now created a custom PCB with a fully functioning brain to do our bidding.
But we're getting ahead of ourselves. Before you can think about the physical layout of a PCB we need to have a sense of the schematic (e.g. the logical layout of the device in comparison to the PCB which is the physical layout).
Here is Mr. Dice's schematic - errors and all.
If you tap on that schematic to enlarge it there is a decent chance you'll be able to follow most of the elements. In the center we have the symbol for the Pico (symbol is the logical element in the schematic, footprint is the physical element on the PCB). Then we wire out a handful of GPIO (input/output pins) to some buttons which pull to ground when clicked.
On the right, near the blue text, we have all the pins used for the OLED screen module.
I discuss it more in the Mr. Dice video at the 8:15 mark but I completely messed up this wiring. The blue text is my notes to myself about how to correct the wiring after the fact.
The last potentially confusing element of this design is the battery wiring in the top right. The design has the battery connecting directly to the VSYS input pin and has the voltage also going to two 220k resistors which fork off the battery voltage into a GPIO pin. This is a type of circuit called a voltage divider. Most normal lithium ion batteries used for projects like this have nominal voltage of around 3.5v which varies from around 3.3v to 3.7v in practice. The Pi Pico is a 3.3v logic board which means we should try our best to never shove more than 3.3v into a GPIO pin.
I wanted Mr Dice to have a low-battery warning, which would be accomplished by sampling (i.e. reading over time) the voltage coming from our battery. If it was 3.3v we'd know it was almost dead and if it was 3.7v we'd know it was almost full. Sadly, as mentioned, anything above 3.3v is potentially damaging to our microcontroller, so this voltage divider divides the voltage in half so instead of a maximum of 3.7v going into our pin, it's now a maximum of 1.85 which is well within spec. We do lose a little resolution by doing this - but it's totally fine for our use case.Â
Once the schematic was locked in I was able to move onto the PCB design.
Again, please click to enlarge the design.
PCB designs start as a tangled "rats nest" of floating footprints. Each footprint correlates to a component which will be eventually soldered to the board. In our case we have the Pico, six buttons, a power switch, and some pin holes for connecting the battery, screen, and programming/debugging the device.
To lay out your board you take each component one by one and move them to a location which fulfills your requirements. Some components have very precise requirements like spacing to other components or specific complex footprints but ours are all very basic so we can place them wherever we want for our design.
Then we draw traces (wires) on the copper layers of the board - for a basic board this is either the front (red wires) or back (blue wires). The small yellow/white circles on these lines are called vias and they connect a trace on the front copper to a trace on the back which is critical for routing around components or other traces.
The entire board is red because it has a "copper fill" which is a large blob of copper which fills all non-trace areas of the board. If you look closely you can see how there is a small gap between each red trace and the red copper fill. This is because they on the same layer of copper so unless we had that seperation, we'd be shorting the trace's copper to the fill's copper. This is totally okay if the trace and fill are on the same net (for example a grounded pin being connected to a grounded copper fill) but it's not desirable in most cases.
Once I had laid out the board I was able to use KiCad's 3D view to triple-check the layout.
Many common footprint / symbol libraries will also provide 3D models for the components. In my case the two buttons near the top are displayed wrong because these will be 90-degree bent buttons in the final design, but everything else is looking good!
After this I sent the board away to NextPCB (who provide free fabrication services to me in exchange for shoutouts like this) and went onto designing the case.
I designed the 3D printable case in TinkerCAD a really great, basic 3D modelling tool. I am told it is predominately used in grade schools which makes sense because it is very easy albeit quite limiting for some things.
From KiCad I exported the front copper layer of my PCB as an SVG and imported it into TinkerCAD to use as a reference.
This was a great way to visualize the layout and ensure mounting holes lined up.
The case is made of four layers. The battery compartment (pictured above), the spacers (pictured below left) which provides room for the OLED display, the front cover (below right) which I designed to look somewhat suit-like to allude to the Mr. Dice name, and...
... the back cover which really leans into the Mr. Dice vibe.
I printed these out on a BambuLab X1 Carbon and they came out brilliantly.
The front is also quite striking with the vivid, vibrant OLED display.
Â
The final electrical element to discuss before moving onto the software is the charging circuitry.
Inside the back cover we can see the battery plugs into a blue PCB. This is a micro-lipo charger from Adafruit.
It has all the logic needed to safely charge the battery and provide power to our unit. It has a USB-C plug which faces out for easy charging, however the disadvantage is that the plug is power-only so we need a different mechanism to program and debug our device.
If you take a look at the photo with the back cover open, there are 5 pins about half-way up the left side of the device - those are our debugging pins. It's not as simple as using the USB, but it's not a big deal to pop open the case to do development.
Finally with all the hardware sorted I was able to move onto software.
I first went into Asesprite, a pixel art drawing tool and made a canvas the resolution of my OLED display. Then I started mocking up the UI and pulling out individual assets to transfers into code.
Once I had a bunch of these images, I found a great blog post which discussed driving our OLED from C. So I adapted that code and we were off to the races.
The actual code I wrote is quite basic, mostly just code to draw the UI pixel-by-pixel.
Perhaps the biggest point of interest for the software is it's randomness. Many people have mentioned to me concern over the true randomness of the numbers generated with folks assuming that a piece of software can not generate truly random numbers. This is a bit of an odd point as dice in real life are also not truly random, their end state is the result of environmental factors. In theory a dice roll could be manipulated with a perfect throw or more realistic factors like loaded dice.
The Pico's random number generator is seeded by a combo of either it's ring oscillator (a hardware feature which has a floating "jittering" bit which can be used as a source of entropy) or more traditional sources like the wake time, board ID, or ram hash. These sources vary in randomness quality but I think it's safe to say these sources combine to make it functionally "boardgame level random" if not "cryptography level random."
I am not an expert in this space, but I would be curious to really know if the Pico's entropy sources produce a more / less linear distribution of randomness than a human throwing a die against a game board. I, however, will not be further investigating this.
Conclusion
And that's Mr. Dice! It was a fantastically fun beginner project which really helped me bridge the gaps in my skillset.
If you're interested in building your own version of Mr. Dice - fear not, I plan on open-sourcing all the materials at some point in the future. Make sure you're on the mailing list so you don't miss that.