IAN LANG ELECTRONICS

Using your Arduino to Make an Electronic Dice

Go Back

Let's go through that code a chunk at a time then. We'll start off with the bit before void setup ( ):

 

//////// Electronic Dice ////////

///////// circuit ard01 /////////

//http://ianlangelectronic.webeden.co.uk/

int (picker);

int (buttonstate);

 

void setup( )

 

The first three lines right at the top all begin with the mark   //    and the first two go on to have many more forward slashes. Whenever the compiler that takes your code and translates it for your Arduino board sees the mark    //    it recognises these as a REM statement. A REM statement (REMark) is something a programmer can put in to tell him/her in plain English what the program is doing  in whole or at any point. I've used these to display my all-pervasive vanity but there we are. I'm quite ashamed of myself. Oh well.

The bottom two lines are declaring variables. if you did the lessons as supplied by Oomlout, or read through them on the prior pages you'll know exactly what a variable is and so can skip the next bit.

 

If not ;

 a variable is a storage space in memory that can have a value that comprises either a numerical value or an alphabetical string of characters. The variable can be accessed by the computer at run time and take on a new value as needed (hence variable).

 

The two variables here are named  "picker" and "buttonstate" although I could have named them Janet and John if I'd wanted. It's usually best to give your variables short names that reflect what they do, and in keeping with that idea picker is the variable that the random number is going to be assigned to. Why did I just not call it  "random"? Because the word is a command in the programming language, and so is reserved. For the same reason I can't call a variable "if" or "else" or any other word used as a command prompt. Similarly buttonstate is going to be the variable that holds a value that tells the microcontroller if the button has been pressed or not.

All variables need to be declared as a type, and the type these are declared as is "int". This means that they are numeric variables (i.e they will hold an absolute mathematical value and not a string of characters) and furthermore this value will be an integer (that is a whole number, no decimal points).

Picker will have the values 1-6, assigned to it in random fashion during run-time. Buttonstate will be a logic argument and so will only ever have the value 0 or 1.

The next part of the code is:

 

void setup( ) {

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

    digitalWrite (j,HIGH);

    delay(400);

    digitalWrite (j,LOW);} // these lines test LEDs

  digitalWrite (5,HIGH); // this line sets it to show a 1

 

}

 

void loop () {

 

void setup( ) is a mandatory function and is the first the microcontroller looks for. It runs only once, each time power is applied (i.e. when you switch the device on). The code is bracketed with curly brackets which look like seagulls, one flying left and one flying right:  {  } and everything in these brackets comprises the whole function, or the function parameters. In the above example, the left flying seagull { comes just after void setup ( ) and the right } is the last line before void loop ( ).

Notice how each command and its parameters end with a semicolon  ;   This is to tell the microcontroller that this command is finished and if it's not there your compiler will complain.(The compiler is in that bit where you upload the code to your board. It translates your program into a series of commands the microprocessor understands and if it finds something it doesn't like it kicks it back and moans at you).

The first line of this function starts a for next loop. This is the syntax:

 

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

 

for prompts the microcontroller to initiate a loop. The parameters of the loop are contained in the normal brackets ( ) and the first is the starting value. You have to assign a variable and for this it is j, whose type is int. In this case, j begins at 2, hence the first argument in the brackets  int j = 2. The second argument tells the loop when to stop. If j <9  means if j has a lesser numeric value than nine, and the loop will continue until this condition is satisfied. The variable j can only be an integer value, and so the highest number it can be lesser than nine is eight. Two whilst eight inclusive is in fact seven instances 2,3,4,5,6,7,8 and so this loop will repeat all the commands inside it seven times, or more technically make seven cycles. Why not simplify it and just make j=1 and say j<8? You will see why not shortly. The third thing inside the brackets is not an argument but a thing to do if the condition j<9 is true. It states j++ and what it means is increment the value of j by 1. This is an idiosyncracy of C and is designed to keep code tight. Sometimes, being used to other languages, I put j=j+1 instead. Either will work, but the second uses more memory space. Not important really unless it's a big block of code and space is getting scarce.

 

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

 

Look at this line again. You will notice that each command inside the curly brackets is terminated by a semi-colon except the last one, j++   and furthermore you will notice a new left-flying seagull {

All the parameters of the for/next loop have to be contained inside two curly brackets  { } and you will see the corresponding right-flying seagull in this line:  digitalWrite (j,LOW);} // these lines test LEDs

Did you spot it?  Here it is made clearer:  digitalWrite (j,LOW);     }           // these lines test LEDs

As curly brackets (or seagulls)  { } mark out the beginnings and ends of both the function and the for/next loop I sometimes shove the terminating bracket } in after the very end of the loop commands so I know where it is. You have to be careful with them as the compiler moans bitterly if it finds any missing.

The whole of the for/next loop spread out looks like this:

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

    digitalWrite (j,HIGH);

    delay(400);

    digitalWrite (j,LOW);

}

Here's how your Arduino board (or more specifically the big chip in it) thinks this through:

 

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

"So, at the beginning j=2, and that's lesser than nine, so do this loop and afterwards up j by 1.......

   digitalWrite (j,HIGH);

Okay, now he wants me set a pin high. Which? Oh j, well j is equal to two so set pin 2 high........

(the practical upshot of the pin being high is that the LED attached to it will light)

delay(400);

Right, do nothing for 400 milliseconds......

digitalWrite (j,LOW);

So that pin I've just set high, set it low again......

(the practical upshot is that the LED attached to it will go out)

}

Oh, that's the end of the loop. So, I'll just add 1on to j and go round again......

 

And so on until when it adds 1 on to j and gets 9 it stops doing the loop and goes to the next line immediately outside the loop:

 

  digitalWrite (5,HIGH); // this line sets it to show a 1

 

which makes the dice display 1 as the LED attached to pin 5 is the one in the middle. After this line it encounters the seagull }  and that tells it that void setup ( ) is finished. It will not run this code again unless you turn off the power, and so if the microcontroller were not on the breadboard but inside a device this would be when you turn it on, and every time you turn it on, but never again until you turn it off and turn it on again.

 

The microcontroller now moves on to void loop ( ) which it runs continually until the power is turned off. The The whole thing reads:

 

void loop () {

    if (digitalRead (11)==HIGH){

        buttonstate=1;

randomgen ();

tone (12,65,10);

       delay (70);

     digitalWrite (12,LOW);}

else{

  if ( buttonstate==0){}

  else{

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

  randomgen ();

  delay (t*t);}

  buttonstate =0;

}

}}

 

You'll notice that the function is bracketed in seagulls. The first one appears here:  void loop () {    but the second one appears as a double seagull at the end. This is laziness on my part I'm afraid. The first seagull } marks the end of the preceding else statement (we'll get to that later), and the last seagull } in any function is always the one that marks the end of that function.

Going through it in bite sized chunks, the first line is:

 

    if (digitalRead (11)==HIGH){

 

Pin 11 is the pin to which the button is attached. Since we set the button up to be default low, the pin can't be high until the button is pressed. (High means a voltage is present, low means a voltage is not present).

The commands to do in this if statement are once again bracketed in seagulls { } and the corresponding right-flying one to this is found here:

 

if (digitalRead (11)==HIGH){

        buttonstate=1;

randomgen ( );

tone (12,65,10);

       delay (70);

     digitalWrite (12,LOW);}

 

This means all the code inbetween these two seagulls { } won't be executed unless the button is pressed. Right then, let's press the button. Ooh, I got a three. Do it again. This time I got a two. Again. This time I got a six. Hurrah!  (I actually did, I was pressing the button as I wrote). This is because when the button is pressed it does the following.

 

  buttonstate=1;

 

This sets the variable buttonstate to a logic argument of 1. This variable can have a logic argument of either 0 or 1, if it's 0 the button hasn't been pressed, if 1 the button has been pressed. You'll see why this is important later. The following line is

 

randomgen ( );

 

Now what this does is call an external function. The two functions you've absolutely got to have to stop the compiler moaning are void setup ( ) and void loop ( ) but you can have as many others as you like. They won't run unless they are called to by either setup or loop, or a function currently running that has been called by either setup  or loop.  The way you call them is by the name you've given them and the normal brackets. Those of you who program in basic may remember the GOSUB  command. This is just the same, it temporarily leaves void loop ( ), does whatever is in the external function and then returns to the point in void loop wherever it left it.

 You still call your external functions void when you create them but you miss the word void off when you call them. Now this is where it can get confusing because we're going to leap about different parts of the program. Let's do it in baby-steps and start a new page.

Continuation >