Dual Dice With Attiny85 Development Board (Digispark Clone)

Question: If you roll a dice six times, what is the probability of rolling a number six?
Answer: There is a 66.5% chance of it landing on a 6 at least once.

Let's try... :)

The ATtiny85 development board is essentially the same as the Digispark module, it is even compatible pin to pin with it and it is very cheap. I bought several modules on Aliexpress for experimenting. One of the results of this experiment is this project.

I have to tell you that I know this my project is not particularly original. On the one hand, it is an adaptation of the great tutorial about Controlling Two LEDs per uC pin where one controller digital output is used to drive two LEDs. I tried the Attiny13 green double led dice and Electronic Dice projects but the Digispark clone does not work very well, the ghosting phenomenon is particularly upsetting. On the other hand, I have borrowed some ideas from 3 Minute Game Timer, a Deep Sleeping ATtiny85 Digispark about timing and deep sleeping of ATtiny85. Anyway, I think that the effective realization of the project, it went out pretty well. With only four digital outputs and a simple multiplexing, the LEDs required to display the numbers that are controlled, and the other two remaining outputs can be used for other purposes (two if PB5 is enabled for output - see step 3).

I will explain the schematic a little bit, I will explain as clearly as possible the adaptation of the sketch that will be uploaded to the digispark clone (ATtiny85 adapter module) I will use. I will also describe the realization of a cheap yet attractive presentation of the concept.

This article is an entry in the Pocket-Sized Contest, I hope you will like it, and I hope you will vote it.

Step 1: Schematics, Electronics, Functioning...


The electronic schematic is the one in the image above with the following characteristics:

- the supply voltage, with two AA rechargeable batteries, will be about 3V (with two batteries even 3.5v);

- current limiting resistors for LEDs will have 220 ohms;

- I have not connected the vibration sensor module, I removed and soldered only the sensor itself to a separate digital input of the microcontroller (P3);

- if possible (P5 output on the digispark clone is available), using a piezo speaker to create small sound effects.

As I have already said, the point dots are displayed by multiplexing four digital outputs of the module. The LEDs are so connected that depending on the combination of digital outputs, some LEDs will light up, at a certain moment, only a certain group of LEDs are lit. Depending on how many groups must be lit, the microcontroller quickly passes through all the groups of LEDs that must be visible so the groups will look like they are displayed together. So if the LEDs are arranged as in the second picture, P0 will lit two groups of LEDs: 1 and 2a-2b, P1 will drive also two groups: 3a-3b and 4a-4b and so on (more at step 3 - The Sketch).

The LEDs that I use in this project are red ones, with a high brightness, you can see the specifications here.

The 220 ohm resistors cut the current through the LEDs to about 7mA statically, but using multiplexing, the average current, and implicitly the brightness drop slightly but the LEDs are bright enough. In 'Roll Mode' (when the numbers are displayed randomly), the total consumption is approx. 17 mA, when dice 6-6 are displayed, the consumption is about 14 mA, and in the deep sleep mode is about 7 mA. In daily use (3 hours of effective use + deep sleep + rest with the switch in OFF position) I think the 2000 mAh rechargeable batteries should last about 3 weeks, more or less...

Perhaps it would be worth, in order to reduce consumption, to make use of the points outlined in RonM9 article 3 Minute Game Timer, a Deep Sleeping ATtiny85 Digispark I will probably do that in the future and I will update the results.

Step 2: Enabling PB5 for Output

The Digispark clone has 6 I/O pins, but on most clones the P5 output is not enabled but instead is a RESET pin. This pin is used. for example to upgrade the Micronucleus bootloader. However, I wanted to use this pin also, for some beautiful sound effects :) To achieve this goal I have followed this tutorial.

- I made the connections

  • Arduino UNO --> Digispark clone
  • GND --> GND
  • 5v --> 5v
  • 10 --> P5
  • 11 --> P0
  • 12 --> P1
  • 13 --> P2

- used a 10uF capacitor from RESET to GND on the Arduino UNO board;

- found in the Arduino IDE the com port at which the UNO connects (com3 in my case);

- opened Arduino ISP sketch from examples in the Arduino IDE;

- opened command prompt and navigated to avrdude directory;

- issued info command

C:\Program Files (x86)\Arduino\hardware\tools\avr\bin>avrdude -P com3 -b 19200 -c avrisp -p attiny85 -n -C ..\etc\avrdude.conf

- issued fuse write command

C:\Program Files (x86)\Arduino\hardware\tools\avr\bin>avrdude -P com3 -b 19200 -c avrisp -p attiny85 -C ..\etc\avrdude.conf -U hfuse:w:0x5F:m

Now P5 is useable!

However, I noticed after three such enabling operations on three different modules, that the Digispark clones device IDs has become invalid, I tried to rewrite the modules (with a high voltage programmer) but I had no success. Anyway P5 is useable...

Step 3: The Sketch

The main part of the Dual Dice program is the function which lit the LEDs. This is the ShowDice function below.

void ShowDice(int group) {
	switch(group) {
	case 0:
		if (dice1 == 1 || dice1 == 3 || dice1 == 5) {
			pinMode(0, OUTPUT);
			digitalWrite(0, HIGH); // D1 Lit
	case 1:
		if (dice1 == 2 || dice1 == 3 || dice1 == 4 || dice1 == 5 || dice1 == 6) {
			pinMode(0, OUTPUT);
			digitalWrite(0, LOW); // D2a-D2b group lit
	case 2:   
		if (dice1 == 4 || dice1 == 5 || dice1 == 6) {
			pinMode(1, OUTPUT);
			digitalWrite(1, HIGH); // D3a-D3b group lit
	case 3:
		if (dice1 == 6) {
			pinMode(1, OUTPUT);
			digitalWrite(1, LOW); // D4a-D4b group lit
	case 4:
		if (dice2 == 1 || dice2 == 3 || dice2 == 5) {
			pinMode(2, OUTPUT);
			digitalWrite(2, HIGH); // D5 lit
	case 5:
		if (dice2 == 2 || dice2 == 3 || dice2 == 4 || dice2 == 5 || dice2 == 6) {
			pinMode(2, OUTPUT);
			digitalWrite(2, LOW); // D6a-D6b group lit
	case 6:   
		if (dice2 == 4 || dice2 == 5 || dice2 == 6) {
			pinMode(4, OUTPUT);
			digitalWrite(4, HIGH); // D7a-D7b group lit
	case 7:
		if (dice2 == 6) {
			pinMode(4, OUTPUT);
			digitalWrite(4, LOW); // D8a-D8b group lit

This function is called eight times per dice throw and at every call only one group of LEDs is lit. But before every call another short but important function is called: all_Input

void all_Input () {
  pinMode(0, INPUT);
  pinMode(1, INPUT);
  pinMode(2, INPUT);
  pinMode(4, INPUT);

This function sets these four pins to be in INPUT mode, in this mode all the LEDs are dimmed (if we do not dim the LEDs the numbers will not be displayed correctly).

For every dice throw we call the ShowDice in this way

for (int i=0; i<=7; i++) {<br>      all_Input();

For example, if the throw is 3-6 then:

  • all_Input - LEDs OFF
  • 1 - case 0 - D1 ON
  • all_Input - LEDs OFF
  • 2 - case 1 - D2a-D2b ON
  • all_Input - LEDs OFF
  • 3 - case 2 D3a-D3b OFF (no change)
  • all_Input - LEDs OFF
  • 4 - case 3 D4a-D4b OFF (no change)
  • all_Input - LEDs OFF
  • 5 - case 4 D5 OFF (no change)
  • all_Input - LEDs OFF
  • 6 - case 5 D6a-D6b ON
  • all_Input - LEDs OFF
  • 7 - case 6 D7a-D7b ON
  • all_Input - LEDs OFF
  • 8 - case 7 D8a-D8b ON
  • all_Input - LEDs OFF

Another function is go_to_sleep which is essentially a wrapper for the main sleep function. go_to_sleep is called when 'dice roll' part is displayed 10 seconds (of course, this timing can be modified) when first we dim all the LEDs and call the sleep function. When a change happens at P3 input the controller will awake and the code continues with some initializations.

In the main part (the loop function) first there is a check if there is vibration on P3, then a verifying of the timing for sleep. It continues with a part when numbers are rapidly is displayed (I called the 'Dice Roll' mode) and if there is a vibration (HIGH on P3) seven dice throws wil be displayed (with the decreasing display speed and tone frequency), and finally the last throw will be displayed for approximately 5 seconds.

The sketch can be downloaded from github.

Uploading the sketch is made as usual for a Digispark device. I must note however that when the controller is in place, soldered, for uploading you must put the power switch to OFF and remove the power connector from the microcontroller module.

Step 4: The Case

I designed for this project a case that should be printed on a 3D printer. There are three main components of the case: the base, the cover and the LED support. Another part is a piece of 3mm thick smoked plexiglass that sticks into the cover and a piece of tracing paper that is also needed to be cut to the same shape as the plexiglas sheet. There are two LED support variants, I think both are working all right. You can download the sources for the case and the plexiglas shape for cutting from tinkercad.

Step 5: It's Alive !!!

For the assembly I firstly put the LEDs in place in the support. In the image all the LEDs have their cathodes on the right. I have made the soldering and I took the second picture when all was done (sorry I don't have intermediary pictures). You can see the result in the video. I would like to remark that at the end of the record you can notice that the device does not wake up but instead it resets himself, this is happens from time to time and I don't know why.

In the future, I think to make two PCB-s for the LEDs (the wiring will be much easier) and to use a bare ATtiny85 (the USB interface components will not interfere with the program logic and the power consumption will be lower). I hope to come back soon with an article on this topic.



    • Fandom Contest

      Fandom Contest
    • IoT Challenge

      IoT Challenge
    • Classroom Science Contest

      Classroom Science Contest