IAN LANG ELECTRONICS

Go Back

On the last page, I gave you some code for a binary counter. Here's some more:

/////////////// Button Binary///////////////

//////////////    Ian Lang   //////////////

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

int latchPin = 4; //sets pin to control latch

int clockPin = 3;// sets pin to control clock

int dataPin = 2;//sets pin to say where data's coming from.

int buttonpress;// a variable to see if the button's been pressed

int inpin=8; //sets pin to control button press

int val; // another variable to do with the button

int bcount;// a variable to initialise the count

void setup() { // does this once, sets our initial conditions

pinMode(latchPin, OUTPUT);///////////////////////////////////////////////////////////

pinMode(clockPin, OUTPUT);///// Won't work without these three steps ////////////////

pinMode(dataPin, OUTPUT);////////////////////////////////////////////////////////////

pinMode(inpin,INPUT); //sets up a input pin

buttonpress=0;//initialises variable

bcount=0;//initialises variable

digitalWrite(latchPin, LOW);               ///////////////////////////////////////////////////

shiftOut(dataPin, clockPin, MSBFIRST, bcount); ///////these three set first count to zero////////

digitalWrite(latchPin, HIGH);                 ///////////////////////////////////////////////////

}

void loop() { ///goes on and on endlessly, like David Mellor.....

buttonstate (); //calls function

if (buttonpress==1) {// does the following five lines if condition satisfied

buttonpress=0; // resets the variable

bcount=bcount+1; //increments the count

digitalWrite(latchPin, LOW); // set latch to input data

shiftOut(dataPin, clockPin, MSBFIRST, bcount);  //input data

digitalWrite(latchPin, HIGH);// set latch to display//

}

}

void buttonstate ( ){//this function sees if button pressed

int (val = digitalRead (inpin));//inpin goes HIGH when button pressed

if (val == HIGH){// so if button is pressed, do the next 13 things

buttonpress=1;// so void loop () will do the last five lines

delay (500);} // makes it so further input is ignored for half a second

if (bcount > 150){// 150 is our maximum count-change it higher if you like up to 255

// if the count's at 151, do the next 12 things

for (int j=0;j<100;j=j+1){// do the next 10 lines 100 times

// the next ten lines cause a flash

bcount =255; // binary 11111111

digitalWrite(latchPin, LOW);// set latch to input data

shiftOut(dataPin, clockPin, MSBFIRST, bcount);//  switch em on

digitalWrite(latchPin, HIGH);//set latch to display

delay (50);//wait

bcount=0;//binary 00000000

digitalWrite(latchPin, LOW);// set latch to input data

shiftOut(dataPin, clockPin, MSBFIRST, bcount);//switch em off

digitalWrite(latchPin, HIGH);//set pin to display

delay (50);}// wait and go round again 100 times

bcount=0;// redundant, but there just in case

buttonpress=0;//resets variable

}

}

Now, to make this work you need to set up a button just like this:

When you switch it on, none of the LEDs should shine. Briefly press the button once, and the first one should come on. Do it again, and the second will. Do it again and the first two come on. On the fourth press, the first two go off and the third comes on. It's counting upwards in binary, just as described on the last page,  to your command. If you keep your finger on the button, it'll go through slowly until it reaches 150, then flash and reset. If you just keep pressing the button one jab at a time, it'll go up as slowly as you like.

If you want it to go higher than 150 then find this line

if (bcount > 150){// 150 is our maximum count-change it higher if you like up to 255

and change the > value but remember it can only count up to 255 (eight bits).

The REM statements in the code are fairly explanatory and so I don't intend to go through line by line, but there are three lines in here that pop up frequently and which need closer examination. They are:

digitalWrite(latchPin, LOW); // set latch to input data

shiftOut(dataPin, clockPin, MSBFIRST, bcount);  //input data

digitalWrite(latchPin, HIGH);// set latch to display//

These three lines are  working together as part of a process, and without all three the circuit won't work.

Remember when I described the 74HC595  I said:

" Similarly that from pin 4 of the Arduino goes to 12, RCK which is the latch. When this is low, and pins 10 & 13 are high and low respectively (which they always are because they're connected to 5V and GND) and a clock pulse comes in at 11, data is transferred and stored in the register. One clock pulse means one bit of data. Once the latch goes high, the data is shifted to the output pins."

Well, this is how it's done. digitalWrite(latchPin, LOW); sets the latch down low so we can start transferring the data over to the pin. This wakes the shift register up.

shiftOut(dataPin, clockPin, MSBFIRST, bcount);  //input data

shiftOut is a command to start transferring data to the shift register;

(datapin tells the ATmega on your board which pin to shift it from

clockPin tells the ATmega where to pulse the clock from

MSBFIRST means most significant bit first. This means it'll transfer 128 as either zero or one first, then 64, then 32, then 16,8,4,2,1  in order. You can do LSBFIRST as well, which reverses the order, but I can't think why you'd particularly want to.

bcount is the numeric variable you want to transfer, between 0 and 255. It doesn't have to be called bcount. Try changing the name to your favourite profanity. As long as you change every instance the program will still work.

digitalWrite(latchPin, HIGH);// set latch to display//

."Once the latch goes high, the data is shifted to the output pins." And that's how we do it. This last line tells the shift register that all the data's there so get on and process it.

Well, having some LEDs twinkling away counting in binary is all well and good but when your non-techie random relative or acquaintance comes up and says "yes, but what actual good is it?"  instead of going into hysterics and bashing them around the head with a heavy ashtray (policemen, relatives and more importantly judges take a dim view of  that sort of thing) you can say "because, you tossbadger, I can make it do this, which could be an important safety device for cyclists and/or joggers on dark December mornings if I build it into some sort of belt or hat and power it by battery. " Then upload the following code:

/////////////////////////////////////////////////////////////////////

///////////////////Shift register SIPO example coding////////////////

////////////////////////////////////////////////////////////////////

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

////////////////////////////////////////////////////////////////////

int (lightarray [] )={1,3,7,15,31,63,127,255}; // sets up an array to control the LEDS

int (chasearray [] )={1,2,4,8,16,32,64,128,255};//sets up an array to control the LEDS

int latchPin = 4;// defines the latch

int clockPin = 3;//defines the clock

int dataPin = 2;// defines where the data's coming from

void setup(){

pinMode(latchPin, OUTPUT);//////////////////////////////////////////////////////////

pinMode(clockPin, OUTPUT);///////// Won't work if you don't do these 3 steps///////

pinMode(dataPin, OUTPUT);//////////////////////////////////////////////////////////

digitalWrite(latchPin, LOW);// set pin low to begin data input

shiftOut(dataPin, clockPin, MSBFIRST, 0);  //output data

digitalWrite(latchPin, HIGH);//set latch high to display

}

void loop () {

allon ();/// calls function

chaseup ();// calls function

}

void lastoff () {//this function switches off the last LED

digitalWrite(latchPin, LOW); //set latch low to input data

shiftOut(dataPin, clockPin, MSBFIRST,0); //output data

digitalWrite(latchPin, HIGH);//set latch high to display

}

void allon (){// this turns em on and off in a row

/////////////// on ////////////////////

for (int j=0;j<8;j=j+1){// 8 Leds to light

digitalWrite(latchPin, LOW);//set latch low to input data

delay (50); //gives us a visible pause in the sequence

shiftOut(dataPin, clockPin, MSBFIRST, lightarray [j]);//output data

digitalWrite(latchPin, HIGH);} //set latch high to display

delay (1000);//gives us a visible pause in the sequence

//////////////off//////////////////

for (int j=7;j>-1;j=j-1){ //8 Leds to unlight

digitalWrite(latchPin, LOW);//set latch low to input data

delay (50); //gives us a visible pause in the sequence

shiftOut(dataPin, clockPin, MSBFIRST, lightarray [j]);//output data

digitalWrite(latchPin, HIGH);} //set latch high to display

lastoff ();//calls function

}

void chaseup (){

for (int j=0;j<8;j=j+1){  //8 LEDs to light

digitalWrite(latchPin, LOW);//set latch low to input data

shiftOut(dataPin, clockPin, MSBFIRST, chasearray [j]);//output data

delay (50);//gives us a visible pause in the sequence

digitalWrite(latchPin, HIGH);} //set latch high to display

delay (50);   //gives us a visible pause in the sequence

for (int j=7;j>-1;j=j-1){  //8 Leds to unlight

digitalWrite(latchPin, LOW);//set latch low to input data

shiftOut(dataPin, clockPin, MSBFIRST, chasearray [j]);//output data

delay (50);//gives us a visible pause in the sequence

digitalWrite(latchPin, HIGH);} //set latch high to display

delay (50); //gives us a visible pause in the sequence

lastoff ();// calls function

}

When they say "oh, that's a pretty good idea, actually" you can smile smugly as you've got all the satisfaction you would have from whacking them with the ashtray and no solicitors need be involved.

Asuming all went well there, what you should see is two light sequences The first should be the LEDs flickering on one by one and then going off again one by one in reverse order followed quickly by a moving light going up then down again.

It works exactly the same way as the button one did, but instead of the shiftOut being activated by your pressing a button it's activated by an array:

for (int j=0;j<8;j=j+1){  //8 LEDs to light

digitalWrite(latchPin, LOW);//set latch low to input data

shiftOut(dataPin, clockPin, MSBFIRST, chasearray [j]);//output data

delay (50);//gives us a visible pause in the sequence

digitalWrite(latchPin, HIGH);} //set latch high to display

is the whole thing and out of that the bit that tells us which LED to light or not is:

shiftOut(dataPin, clockPin, MSBFIRST, chasearray [ j ] );//output data

The two arrays are:

int (lightarray [ ] )={1,3,7,15,31,63,127,255}; // sets up an array to control the LEDS

int (chasearray [ ] )={1,2,4,8,16,32,64,128,255};//sets up an array to control the LEDS

If you look at the top one, you'll see that we're summing up the binary numbers all the time. this means the most significant bit is always a power of two plus the sum of the previous  powers of two : 1, is the first, and 2 the next. 1+2 is 3. ----3+4=7-----7+8=15-----15+16=31-------31+62=63-----63+64=127-----127+128=255

The practical upshot is that it makes the LEDs look as though they are coming on by one.

In the other array, we're just doing powers of two straightforwardly. If we light the LED attached to the appropriate pin and then switch it off again, it looks like a light is moving. This is due to a phenomena known as Persistance of Vision, or PoV, sometimes known as a trompe d' oeil.

Here endeth the lesson, and hopefully if you knew nothing about shift registers you know a great deal more now. If you did know about shift registers hopefully you learned something extra. At the very least you should have learned not to hit people with heavy ashtrays. Don't do it with paperweights either. A roll of Andrex might be okay, and a fresh Cornish pastie ( NOT a frozen one, learn from history people) but people will look at you as though you are mad if you do that.

Alllrigghhttty then. I'm stalling for time now before the next lesson, because I have to confess it's something I don't know a great deal about at all. Should be a steep learning curve for us all then.

5V

GND

pin 8 (of the Arduino Board)

10k

Persistence of Vision CIRC-06 Page 1