Path: Home =>
AVR overview =>
Applications => Dice ATmega16
Tumbling dice with an ATmega16
Rolling dice twice: an application of an ATmega16 with two seven-segment-displays.
Dices real random numbers on key strokes. Two jumpers allow to a) reduce it to
single display mode (if you need only one dice) and/or b) to disable tumbling (if
it makes you nervous to see all those quickly changing numbers). The display goes
to power-saving mode 16 seconds after the last key stroke to allow for a longer
period of battery operation. And, for the researchers among you, it counts the
numbers diced in each round and the total number of key strokes (up to 65535)
so you can verify by yourself that the numbers diced are really random. Those
counters are located in the EEPROM of the device, so you can clear them or read
their current status via the ISP interface that is also provided on-board. And,
of course, they remain valid over different sessions when you turn battery power
This is the necessary hardware. The ATmega16 has many extra port pins that are
not used here. Ports A and C are used to drive the two seven-segment-displays,
including the dots. The INT0 input is connected to the key to initiate dicing.
This input and the two jumper inputs on port B are, by software, pulled up with
internal resistors to the operating voltage. The operating voltage either comes
from three batteries with 4.5 V or from four rechargeable batteries with
4.8 V. Batteries can be of AA or AAA size. If you prefer a supply with an
external source it should deliver between 3 and 5 V DC, the current is up
to 100 mA.
- Fuse settings
The LED currents are designed to be around 7 mA per segment, controlled by
the 390 Ω resistors. If you plan to supply smaller operating voltages,
such as 3 V, or if you need brighter displays, the use of smaller resistors,
such as 270 or 220 Ω is possible. Higher currents reduce the battery's
lifetime. Note that the dots need smaller currents to arrive at the same intensity.
An ISP6 interface is recommendable. Not only can one change the software of the
ATmega16 via this interface but also read out the EEPROM's content (seven 16 bit
The hardware can be plugged together on a breadboard, can be wired on an
experimental dot matrix board or on a PCB.
This is such a single-sided PCB layout and the related components placement plan.
With that, the complete set looks like this.
First, switch on the power supply. During init, all segments and all dot points of
the two displays are on. If you want to skip this phase, remove the respective
source code from the assembler source code file, either with the Studio's editor
or with any other editor that saves plain text only, re-compile (either with the
Studio's assembler or with
gavrasm or with
any other assembler that is capable to accept and process ".if" directives.
Then burn the program hex code to the flash memory of the ATmega16 and burn the EEPROM
segment as well. Set the respective fuses (see the respective fuses
of the ATmega16 as well).
After that you can dice with the key attached. Note that the tumbling includes five
random stages, by default over equal times. If you prefer slower tumbling or a change
from fast to slower, change the respective constants in the source code, re-compile
and burn it in.
Those are the two jumpers. They can be attached and removed at any time, the changes
come immediately into effect.
If you need only one single dice, close jumper 1 located on the left. If you do not want
tumbling, close jumper 2 located to the right.
If you do not close the key for longer than 16 seconds, the display is cleared and only
the dot point of the second display is on. You can immediately wake-up the controller
with the key and a new dice is immediately performed.
The commented assembler source code file is here, it can
be handled with any editor, such as Notepad under Windows or KWrite under Linux.
The random number generator is the TC0 timer. With a frequency of 1 Mcs/s it counts
from 0 to 251 and then restarts again (CTC mode). 252 was chosen to achieve an equal
distribution of all six combinations and to get a random number of tumble displacements.
Whenever the key is pressed, the current count is read and the modulo of 36 is calculated.
The resulting number is translated to 1-1 (zero) to 6-6 (35), the two combined dices, and
displayed. The divider (between 0 and 6) is translated to a displacement number between
0 and 35 (by a fixed table). The resulting number is used to displace the dice number in
case of tumbling.
The whole software is driven exclusively by interrupts. Each cycle starts with an INT0
interrupt from the key input. The compare match port A of TC1, that provides the tumbling
interrupts, is set to the initial value (as listed in a table). The dot point of the first
display is switched on, and remains so until the end of the cycle has been reached. As
long as this is the case, no further INT0 interrupt cycles are started (excluding key
bounces). Then TC1 is started in normal mode with a prescaler of 256 and overflow
as well as compare match A interrupts enabled.
Compare match A of TC1 downcounts a register that holds the number of tumbling events
to be processed (tumbling off: 1, on: 5). If not yet zero, the next compare match value
is read from a table and loaded to TC1. If tumbling is enabled, the last dice value is
displaced with the displacement number and displayed. If the register reaches zero,
the content of the EEPROM counters "total", "Na" and
"Nb", where a and b are the two dice numbers, are read, and increased by one.
The LSB of the first counter, "total", is written to the EEPROM and the
EEPRDY interrupt is enabled.
This interrupt writes the MSB of "total", then LSB and MSB "Na"
and finally LSB and MSB of "Nb" to the EEPROM. If all has been sent, the
cycle has reached the end: the dot point of display one is switched off, enabling INT0
Finally, if no key event starts a new cycle, the TC1 flows over (after 65536 * 256 =
16,777,216 µs = 16.8 seconds). This switches off both displays, and the
dot point of display 2 on.
In order to evaluate the equal distribution of the six dice numbers, a pascal program
has been written (source code is here, compiles with
Free Pascal). Download the EEPROM's content to a file named
"dice_m16_v1_read.hex" in the same directory and start the compiled exe.
This is the result. The distribution of dices 1 to 6 is rather equal, differences are
in the range of a few percent, already after 500 total cycles.
These are the result of 1,000 dicing cycles.
The following fuses must be modified:
- The JTAG fuse has to be disabled. Otherwise certain segments of display 2 remain
- If you want to program new code to the flash memory, normally the EEPROM content
is cleared, too. If you set the EESAVE flag, this can be prevented and the EEPROM
content remains intact.
- Make sure that the internal RC clock generator is running at 1 Mcs/s.
©2017 by http://www.avr-asm-tutorial.net