IAN LANG ELECTRONICS

Using the same circuit we built on the previous page we can now build a dice which allows for a digital display. We need to add one button for the roll, and it is laid out like so:

 

Those of you who have been paying attention

will recognise this as a button setting the pin

to low. It does this by providing a path from the

pin to ground (GND) and as such the pin can

never have a positive potential- but if we press the

button, we give the pin the benefit of the 5V supply

and so it goes high.

 

Here's some code to slap your board with:

Go Back

7 Segment LED Display Dice

5V

GND

Pin 11

int uparray []={0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,1,1,1,0,0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,1,0,1,1,1,1,1,1,};

//                          *             *             *              *

int buttonstate;

int rdm;

int arstart;

int checkflag=0;

void setup () {

 

  for (int t=2;t<9;t=t+1){

  pinMode (t,OUTPUT);}

  pinMode (11,INPUT);

  arstart=0;

for (int t=0;t<6;t++){

  for (int j=2;j<9;j++){

    digitalWrite(j,uparray[arstart]);

    arstart=arstart+1;}

    delay(500);}

}

 

 

void loop (){

 

  buttonstate=(digitalRead(11));

  if (buttonstate ==LOW){

  if (checkflag==1){

    checkflag=0;

    for (int t=1;t<10;t++){

      for (int j=2;j<9;j++){

     digitalWrite (j,1);

    delay (t*t);

    digitalWrite (j,0);}}

    for (int t=2;t<9;t++){

      digitalWrite(t,uparray[arstart]);

      arstart=arstart+1;}

  }}

 

  else {

   

    roll();}

 

}

 

void roll (){

  checkflag=1;

 

     for (int t=2;t<9;t++){

                        rdm = random (0,6);

       arstart = rdm*7;

       delayMicroseconds(t+rdm);

       digitalWrite (t,1);

    delay (10);

    digitalWrite (t,0);}

}

 

 

If you've built the circuit and uploaded the code here's what should happen;

 

First, the display will cycle through the numbers 1-6 to test the operation. The display will now stay at 6.

If you now push the button, the display will go through a small animation and eventually roll out a number. This number is random, and can't be predicted. Press the button several more times and other numbers will appear. In twelve rolls I get:

 

4,3,4,2,6,1,3,3,2,3,4,4

 

and

 

4,1,2,3,5,6,4,2,5,1,6,6

 

Going through the code:

 

int uparray []={0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,1,1,1,0,0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,1,0,1,1,1,1,1,1,};

 

comprises an array of 42 digits. Each set of seven digits contains the data to say whether segment a through to g should be lit or unlit. As there are six numbers, each requiring seven digits, 6x7=42.

 

int buttonstate;

int rdm;

int arstart;

int checkflag=0;

 

These lines declare four variables we shall need.

 

  for (int t=2;t<9;t=t+1){

  pinMode (t,OUTPUT);}

  pinMode (11,INPUT);

 

These lines use a simple for/next loop to set pins 2-8 as output pins. They are necessary, as if we leave the pins at default setting they will not produce enough current to light any segment of the display.

 

 arstart=0;

for (int t=0;t<6;t++){

  for (int j=2;j<9;j++){

    digitalWrite(j,uparray[arstart]);

    arstart=arstart+1;}

    delay(500);}

 

These lines carry out the count upwards at the start of the run. the outer loop starting at for (int t=0;t<6;t++){  ensures the code inside the loop is done six times. The first line inside the loop is  

 for (int j=2;j<9;j++){ and this will go from 2-8, which is the range on the Arduino board to which we have attached the anodes of the segments of the display. There follows;

 digitalWrite(j,uparray[arstart]); which returns a value of either zero or one (depending on the postion in the array uparray indicated by the operator arstart. For example, if  j =3 and arstart =1, then pin 3 would be in the condition of the second (because the first position of the array is zero) digit of uparray; which is 1, and as 1 is high the segment attached to pin 3 (segment b) lights. We need to look at the next character in the array for the next segment, and so:

 

   arstart=arstart+1;}

 

which increments the tracker by 1 and }  terminates the inner loop when it gets to 6. To see the change in numbers there needs to be a visible delay:

 

    delay(500);}

 

and } terminates the outer loop when it gets to 5.

 

 

void loop (){

 

  buttonstate=(digitalRead(11));

 

This line checks to see if the button has been pressed. If the button has not been pressed, the condition will be low. If it has, the condition will be high. This is because the button we made was constructed to set the pin it is attached to (pin 11) by default low.

 

  if (buttonstate ==LOW){

  if (checkflag==1){

 

Two conditionals are given here; the first what to do when the button state is low, and the second to do it only if checkflag is equal to 1. The variable checkflag can only be equal to 1 if the button has been pressed and so the code following is ignored until the button has been pressed, and the dice does nothing but shows the last digit rolled. If this is at switch-on this will be a six as this was the last digit in the count up. Once the button has been pressed, the condition becomes high and the else statement is executed:

 else {

   

    roll( );}

 

 

and the function void roll ( ) is called. This  function starts:

 

checkflag=1;

 

and before void setup( ) we declared this a global variable and so it will carry back to void loop ( ). Next in the function comes:

 

 

for (int t=2;t<9;t++){

                        rdm = random (0,6);

       arstart = rdm*7;

       delayMicroseconds(t+rdm);

       digitalWrite (t,1);

    delay (10);

    digitalWrite (t,0);}

}

 

This chooses a random number six times, sets arstart ( which tracks the position in the variable uparray)to the first position in uparray that corresponds to the segment lighting sequence of the chosen number, introduces in each time a delay of t+rdm microseconds (to arbitrarily interrupt what is a pseudo-random sequence and turn it into a genuinely random one) and the last three lines rapidly turn on and off all the segments of the display giving the effect of the flickering 8 when the button is pressed. This will carry on for as long as the button is pressed, and releasing the button sets the condition of buttonstate back to zero, and so when it returns to the loop it meets the following lines:

 

  buttonstate=(digitalRead(11));

  if (buttonstate ==LOW){

  if (checkflag==1){

 

buttonstate is low is true, and so the else statement will be ignored,  and checkflag was set to 1 by the function roll ( ) and so that is true too. the following code can now be executed:

 

checkflag=0;

    for (int t=1;t<10;t++){

      for (int j=2;j<9;j++){

     digitalWrite (j,1);

    delay (t*t);

    digitalWrite (j,0);}}

 

checkflag gets set back to zero, which means this code locks itself out until the button gets pressed again, and the nested loops rapidly switch on and off the segments off the display one by one, giving the animation. The next lines are:

 

 for (int t=2;t<9;t++){

      digitalWrite(t,uparray[arstart]);

      arstart=arstart+1;}

 

These lines decide which segments should be lit and which unlit by reading the data at upparray in accordance with the value of arstart, which is incremented by 1 each of the seven times the loop cycles and so gives the data in uparray for the condition of the next segment, lit or unlit.

 

All of which is fine if you only want to run one display. If you want more, you will find that your Arduino Uno does not have enough pins. Never fear- we can use a shift register to increase your outputs dramatically. Over the page we learn how.

Display Circuit Using a Shift Register> <Previous page