Monday 28 November 2011

I designed a display PCB in Eagle

I am sorry for not posting more recently....Life sometimes is busy!

I have designed and laid out a printed circuit board for the chess clocks display section.  I used Eagle CAD although any decent PCB layout package would do.  I have to make an admission here.....I am not very good at PCB layout.  I do my best but it isn't something I'm good at.  Professionally I cheat and pay someone else to do it for me!!  Cheating I know...but easier and quicker in the long run!  I accept that I'm not going to improve unless I practice....Why do you think I'm doing this!!

I wasn't intending to discuss the different nuances in PCB layout or how to use Eagle CAD.  There are plenty of tutorials and information available online for this purpose and they will do a better job than I can at the moment.  I will try if people request it!

Here are some links to some Tutorials that I have read and think are reasonable:

http://www.eeweb.com/blog/paul_clarke/the-route-to-pcb - Paul Clarke's blog entry on EE Web

http://www.alternatezone.com/electronics/pcbdesign.htm - Dave Jones's from the EEVblog Tutorial

So here is the layout.  I used the schematic from the previous post and just connected all the wires together as best as I could.  I tried to make the PCB single sided but that didn't work so I have a few...jumper wires or I could make the board double sided.  It all depends on whether I can afford to have the board made professionally or whether I etch the board at home.  If I go for the home method I normally make my PCBS single layer....It's easier for me.

Here is the bottom layer:


And here is the top layer:


I have performed all the usual checks and I believe this design will work as required for my purposes.  Its at this point I should mention the design would be better with a 4 digit Seven Segment Display...that way all of the segments are in line and directly next to each other....As I don't have any of these I will use this layout.  For the mark II version I may well get some 4 digit displays!!

If someone were looking to get some 4 Digit Seven Segment Displays they could do worse than looking at these helpful and useful Vendors:

http://proto-pic.co.uk/4-digit-7-segment-display-kelly-green/ - Proto-PIC

http://www.sparkfun.com/products/9482 - Sparkfun

http://www.coolcomponents.co.uk/catalog/product_info.php?cPath=45_70&products_id=697 - Cool Components!

Thats it for now...Have fun and happy tinkering!

Monday 21 November 2011

More on the Chess Clocks

Right....here is where we are!!!

We have got some Seven Segment LED Displays (They are cool, green and common Cathode!)  We have connected them to four 74HC595 latching shift registers and driven these shift registers with three Control lines and the ground connection from an arduino.  With this circuit we made a 1 hour up counter.

Here is the updated Schematic Diagram.  I intend to route this to a PCB soon so that I can make a more permanent version of the circuit and get rid of the horrible mess of wires on the breadboard.  We will be making two of them for each clock.  But each clock will be driven from one arduino.


I have removed the arduino as we are going to lay out a PCB and I will use wires to connect the PCB to the arduino.  I have also added some current limiting resistors to the outputs of the shift registers.  I don't want any issues with over current to the displays.  I should really have added these to the breadboard but I was short on space.  If you are driving the circuit from a current limited supply there would not be an issue.  It is better to be safe than sorry though and that is why I have added the resistors.

I am working on getting this laid out on a single or double sided PCB which I will probably etch and drill myself at a later date.

I also wrote a new arduino sketch to make the displays count down.  The program does exactly the same thing as the previous sketch except that it counts down for an hour instead of up!.


/*
 Langster's Code for driving 4x seven segment displays via 4x Shift Registers
 This sketch will make a One Hour Down Counter!  After an hour has passed the count 
 will reset


 Repeat these steps four times for the different shift registers

 Connect Pin 3 and pin 10 on the seven segment display to 0V
 Connect all the other pins to the Shift Register digital ouputs 
 as listed below:

 pin 1 of 74HC595 to Seven Segment LED pin 6  
 pin 2 of 74HC595 to Seven Segment LED pin 4
 pin 3 of 74HC595 to Seven Segment LED pin 2
 pin 4 of 74HC595 to Seven Segment LED pin 1
 pin 5 of 74HC595 to Seven Segment LED pin 9
 pin 6 of 74HC595 to Seven Segment LED pin 8
 pin 7 of 74HC595 to Seven Segment LED pin 5
 pin 8 of 74HC595 to 0V

 pin 9 of 74HC595 is of shift register One is connected to pin 14 of 
 shift register Two...etc

 pin 10 of 74HC595 to +5V
 pin 11 of 74HC595 to Arduino pin 12  
 pin 12 of 74HC595 to Arduino pin 13
 pin 13 of 74HC595 is connected to 0V - 0V is better!
 pin 14 of 74HC595 to Arduino pin 11 for first shift register
 pin 15 of 74HC595 to Seven Segment LED pin 7
 pin 16 of 74HC595 to +5V


*/


int minutesTens = 5; // count the minutes tens


int minutesUnits = 9; // count the minutes units 


int secondsTens = 5; // count the seconds tens


int secondsUnits = 9; // count the seconds units


// Pin connected to ST_CP (pin 12) of 74HC595
int latchPin = 13;


// Pin connected to SH_CP (pin 11 of 74HC595
int clockPin = 12;


// Pin connected to DS (pin 14) of 74HC595
int dataPin = 11;


// Initialise a two Dimensional integer array with 
// the values for 0 - 9 on the Seven Segment LED Display
// and 0-9 with the decimal point!


int seven_seg_digits[2][10]= {
                             { 189,132,47,143,150,155,187,140,191,158   },
                             { 253,196,111,207,214,219,251,204,255,222  }
                             };


/*
   
  without decimal point 
  { 1,0,1,1,1,1,0,1 },  // = 189 in decimal
  { 1,0,0,0,0,1,0,0 },  // = 132 in decimal
  { 0,0,1,0,1,1,1,1 },  // = 47 in decimal 
  { 1,0,0,0,1,1,1,1 },  // = 143 in decimal
  { 1,0,0,1,0,1,1,0 },  // = 150 in decimal
  { 1,0,0,1,1,0,1,1 },  // = 155 in decimal
  { 1,0,1,1,1,0,1,1 },  // = 187 in decimal
  { 1,0,0,0,1,1,0,0 },  // = 140 in decimal
  { 1,0,1,1,1,1,1,1 },  // = 191 in decimal
  { 1,0,0,1,1,1,1,0 },  // = 158 in decimal
  
  with decimal point
  { 1,1,1,1,1,1,0,1 },  // = 253 in decimal
  { 1,1,0,0,0,1,0,0 },  // = 196 in decimal
  { 0,1,1,0,1,1,1,1 },  // = 111 in decimal 
  { 1,1,0,0,1,1,1,1 },  // = 207 in decimal
  { 1,1,0,1,0,1,1,0 },  // = 214 in decimal
  { 1,1,0,1,1,0,1,1 },  // = 219 in decimal
  { 1,1,1,1,1,0,1,1 },  // = 251 in decimal
  { 1,1,0,0,1,1,0,0 },  // = 204 in decimal
  { 1,1,1,1,1,1,1,1 },  // = 255 in decimal
  { 1,1,0,1,1,1,1,0 },  // = 158 in decimal




//  Just for further reference here are the 
//  separate segment connections


  pin 2 = C
  pin 3 = DOT
  pin 4 = E
  pin 5 = F
  pin 6 = A
  pin 7 = B
  pin 8 = G
  pin 9 = D


*/


void setup() {
  // set the arduino pins to output so you 
  // can control the shift register(s)
  
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  
  //Turn on the serial Monitor - useful for debugging!
  Serial.begin(9600);
  
  //take the latch pin of the shift register(s) low
  digitalWrite(latchPin, LOW);
  
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 4th or secondUnits display
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 3rd or secondTens display
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 2nd or minutesUnits display
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 1st or minutesTens display
  
  //take the latch pin of the shift register(s) high
  digitalWrite(latchPin, HIGH);
}


void timerCountDown(){
  
        for (secondsUnits = 9; secondsUnits >= 0; secondsUnits--){
            
            // take the latch pin of the shift register low
            digitalWrite(latchPin, LOW);   
            
            // Update the displays with the respective values 
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[0][secondsUnits]);    
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[0][secondsTens]); 
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[1][minutesUnits]); 
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[0][minutesTens]); 
            
            // take the latch pin high so the LEDs will light up:      
            digitalWrite(latchPin, HIGH);
            
            // pause for a second before next value:
            delay(100);
                      
            // for debugging send the count to the serial monitor
            
            Serial.print("Timer Count = ");
            Serial.print(minutesTens);
            Serial.print(minutesUnits);
            Serial.print(":");
            Serial.print(secondsTens);
            Serial.println(secondsUnits);       
            
            // check if the Seconds count is at 10 
            // if it is decrement the Seconds Tens count 
            // and reset the Minutes unit count to zero
  
            if (minutesTens == 6 && minutesUnits == 0 && secondsTens == 0 && secondsUnits == 0){
                Serial.println("you are here!");
                minutesTens = 5;
                minutesUnits = 9;
                secondsTens = 6;
                secondsUnits = 0;
                }    
            
            if (minutesTens == 0 && minutesUnits == 0 && secondsTens == 0 && secondsUnits == 0){
                minutesTens = 5;
                minutesUnits = 9;
                secondsTens = 6;
                secondsUnits = 9;
                }    
        
            if (minutesUnits == 0 && secondsTens == 0 && secondsUnits == 0){
                minutesTens--;
                minutesUnits = 9;
                }
                                  
            if (secondsTens == 0 && secondsUnits == 0){
               minutesUnits--;
               secondsTens = 6;
               }                
              
            if (secondsUnits == 0){
               secondsTens--;
               secondsUnits = 0;
               }                              
       }
}
   


void loop() {   
  
  // call the function timerCountDown!
  timerCountDown();


}  


I will post a video of the circuit working some other time.  Enjoy people!  




Sunday 20 November 2011

Multiple Shift Registers and Lots of Seven Segment LEDS!!

So, after the success of the last part where We managed to get a shift register to control a seven segment LED display I decided to connect up four shift registers and four Seven Segment LED displays.  The jumble of wires is horrible but it does prove that all the displays and shift registers are working.  It is definitely time to consider designing a PCB or putting this design on strip board so that I can concentrate on something other than wiring issues!

The circuit I am using is exactly the same as in the previous post.  I have connected each shift register in turn and the data, latch and clock pins are connected together.  This makes all the displays count up in the same way at the same time!

If anyone else is doing this Kudos!!  Check out the video:


What we need to do now is get this circuit controlled in such a way so that we can use it as a clock or timer.  As I mentioned in the video we could turn this into an Alarm clock or a stopwatch.  The scope for timing in the real world is vast.  Everyone is concerned with time!

In order to do this we need to make some changes to the circuit.  I have connected the data, clock and latch inputs from the arduino to each shift register.  We need to disconnect the data lines from each shift register and then reconnected them as below:

pin 14 of  the 1st 74HC595 goes to pin 11 of the arduino

pin 9 of the 1st 74HC595 goes to pin 14 of the 2nd 74HC595

pin 9 of the 2nd 74HC595 goes to pin 14 of the 3rd 74HC595

pin 9 of the 3rd 74HC595 goes to pin 14 of the 4th 74HC595

Once we have made these connections we then need to update our sketch so that the unit counts up or down.  Lets do count up from zero first.  This sketch needs to control the shift registers and seven segment displays carefully.  We want to be able to distinguish between minutes and seconds and we want the clock to be able to count up to a some maximum value and then reset.  Lets set our clock to be a One hour timer.

Here is the Sketch:



/*
 Langster's Code for driving 4x seven segment displays via 4x Shift Registers
 This sketch will make a One Hour Counter!  After an hour has passed the count 
 will reset


 Repeat these steps four times for the different shift registers

 Connect Pin 3 and pin 10 on the seven segment display to 0V
 Connect all the other pins to the Shift Register digital ouputs 
 as listed below:

 pin 1 of 74HC595 to Seven Segment LED pin 6  
 pin 2 of 74HC595 to Seven Segment LED pin 4
 pin 3 of 74HC595 to Seven Segment LED pin 2
 pin 4 of 74HC595 to Seven Segment LED pin 1
 pin 5 of 74HC595 to Seven Segment LED pin 9
 pin 6 of 74HC595 to Seven Segment LED pin 8
 pin 7 of 74HC595 to Seven Segment LED pin 5
 pin 8 of 74HC595 to 0V

 pin 9 of 74HC595 is of shift register One is connected to pin 14 of 
 shift register Two...etc

 pin 10 of 74HC595 to +5V
 pin 11 of 74HC595 to Arduino pin 12  
 pin 12 of 74HC595 to Arduino pin 13
 pin 13 of 74HC595 is connected to 0V - 0V is better!
 pin 14 of 74HC595 to Arduino pin 11 for first shift register
 pin 15 of 74HC595 to Seven Segment LED pin 7
 pin 16 of 74HC595 to +5V


*/


int secondsUnits = 0; // count the seconds units


int secondsTens = 0; // count the seconds tens


int minutesUnits = 0; // count the minutes units 


int minutesTens = 0; // count the minutes tens
  
int unitCount=0; // count the units


// Pin connected to ST_CP (pin 12) of 74HC595
int latchPin = 13;


// Pin connected to SH_CP (pin 11 of 74HC595
int clockPin = 12;


// Pin connected to DS (pin 14) of 74HC595
int dataPin = 11;


// Initialise a two Dimensional integer array with 
// the values for 0 - 9 on the Seven Segment LED Display
// and 0-9 with the decimal point!


int seven_seg_digits[2][10]= {
                             { 189,132,47,143,150,155,187,140,191,158   },
                             { 253,196,111,207,214,219,251,204,255,222  }
                             };


/*
   
  without decimal point 
  { 1,0,1,1,1,1,0,1 },  // = 189 in decimal
  { 1,0,0,0,0,1,0,0 },  // = 132 in decimal
  { 0,0,1,0,1,1,1,1 },  // = 47 in decimal 
  { 1,0,0,0,1,1,1,1 },  // = 143 in decimal
  { 1,0,0,1,0,1,1,0 },  // = 150 in decimal
  { 1,0,0,1,1,0,1,1 },  // = 155 in decimal
  { 1,0,1,1,1,0,1,1 },  // = 187 in decimal
  { 1,0,0,0,1,1,0,0 },  // = 140 in decimal
  { 1,0,1,1,1,1,1,1 },  // = 191 in decimal
  { 1,0,0,1,1,1,1,0 },  // = 158 in decimal
  
  with decimal point
  { 1,1,1,1,1,1,0,1 },  // = 253 in decimal
  { 1,1,0,0,0,1,0,0 },  // = 196 in decimal
  { 0,1,1,0,1,1,1,1 },  // = 111 in decimal 
  { 1,1,0,0,1,1,1,1 },  // = 207 in decimal
  { 1,1,0,1,0,1,1,0 },  // = 214 in decimal
  { 1,1,0,1,1,0,1,1 },  // = 219 in decimal
  { 1,1,1,1,1,0,1,1 },  // = 251 in decimal
  { 1,1,0,0,1,1,0,0 },  // = 204 in decimal
  { 1,1,1,1,1,1,1,1 },  // = 255 in decimal
  { 1,1,0,1,1,1,1,0 },  // = 158 in decimal




//  Just for further reference here are the 
//  separate segment connections


  pin 2 = C
  pin 3 = DOT
  pin 4 = E
  pin 5 = F
  pin 6 = A
  pin 7 = B
  pin 8 = G
  pin 9 = D


*/


void setup() {
  // set the arduino pins to output so you 
  // can control the shift register(s)
  
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  
  //Turn on the serial Monitor - useful for debugging!
  Serial.begin(9600);
  
  //take the latch pin of the shift register(s) low
  digitalWrite(latchPin, LOW);
  
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 4th or secondUnits display
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 3rd or secondTens display
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 2nd or minutesUnits display
  shiftOut(dataPin, clockPin, LSBFIRST, 0); // clears the 1st or minutesTens display
  
  //take the latch pin of the shift register(s) high
  digitalWrite(latchPin, HIGH);
}


void timerCountUp(){
  
        for (secondsUnits=0; secondsUnits <=9; secondsUnits++){
            
            // take the latch pin of the shift register low
            digitalWrite(latchPin, LOW);   
            
            // Update the displays with the respective values 
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[0][secondsUnits]);    
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[0][secondsTens]); 
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[1][minutesUnits]); 
            shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[0][minutesTens]); 
            
            // take the latch pin high so the LEDs will light up:      
            digitalWrite(latchPin, HIGH);
            
            // pause for a second before next value:
            delay(1000);
            
            // count the number of units that have paased
            unitCount++;
            
            // for debugging send the count to the serial monitor
            
            Serial.print("Timer Count = ");
            Serial.print(minutesTens);
            Serial.print(minutesUnits);
            Serial.print(":");
            Serial.print(secondsTens);
            Serial.println(secondsUnits);       
            
            // check if the Seconds count has reached ten
            // if it has increment the Seconds Tens count 
            // and reset the Minutes unit count to zero
            
              if (unitCount == 10){
                secondsTens++;
                unitCount = 0;
                }
                
            // check if the Second Tens count has reached six        
            // if it has reset it to zero
                   
              if (secondsTens > 5){
                minutesUnits++;
                secondsTens = 0;
                }
              
              // check if the Minutes unit count is ten
              // if it is increment the Minutes tens count
              // and reset the Minutes unit count to zero
              
              if (minutesUnits == 10){
                minutesTens++;
                minutesUnits = 0;
                }
                
            // check if the Minute Tens count has reached six        
            // if it has reset it to zero
                              
              if (minutesTens > 5){
                minutesTens = 0;  
                }
                 
       }
}
   


void loop() {   
  
  // call the function timerCountUp!
  timerCountUp();





This actually took me a while to work out how to do and there is more than one method of achieving the functionality that was required.  This is my implementation there may be other more efficient ways of getting the same result.  Have a play with the code and see if you can do any better!

Here is the video of the circuit working.  I have speeded up the timing delay because it was soooo boring to watch!!


For the next post we will modify the program to make the counter count down instead of up and then add some buttons so that the user can set the start time....For now happy circuit hacking and take care people!


Tuesday 15 November 2011

The Joy of Shift Registers!

The joy of Latching Shift Registers!

So...I figured tonight would be a good time to continue my new found habit of writing about technical stuff!  Carrying on from the last post where I wrote about how to connect and use a Seven Segment LED display.  The overall goal is to make a set of Chess clocks.

I have visions of my display having eight LED segments....This is so that each player has a different timer and can view how much time they have left at any point whilst playing the game.  Most Chess players I know set the game length to 20 minutes.  Therefore in order to meet those requirements we will need to have 8x LED displays, 4x for each player allowing a maximum time setting of 99:99 each.  That should be long enough!!  I also would like the user to be able to set the time for each game via a rotary encoder....next post might be on just that subject!



Players will then be able to independently set the game times and then set the clocks to run mode. The time for each turn will start and stop when a player presses the requisite button (something huge and mushroom shaped!)  I may add some pointless but amusing sound effects when the time starts approaching zero.....frivolous and unnecessary and the perfect excuse to buy an arduino wave shield!!!



For now though we need to talk about my shameless misuse of microcontroller outputs.  In my previous post I used no less than eight digital outputs to control one Seven Segment LED display.  I can already hear my boss berating me for a lack of electronic design skills!!  He moans too much but he is correct....It is shameful to waste the output pins of microcontrollers when there is a better way of going about things.  The Arduino has 18 potential output pins....For eight LED displays we will need 64 output pins!!!  The arduino just doesn't have enough digital output pins.  By the way check out the datasheet for the Atmel AVR 328P (it's the microcontroller used in the arduino)....it is useful for two purposes.  It provides all the information you need to know about the brains of an arduino and can cause narcosis in seconds!  In all seriousness though datasheets can be extremely useful and when designing electronic circuits they are a must.  Knowing what all the pins on a device does is half the battle in mastering control of the circuit....and possibly the universe*

*may or may not be true

Atmel 328P Datasheet

So we need 64 output pins just to control the LED displays....but we don't have enough pins on a single arduino...What does one do now??  Well....it is possible to daisy chain multiple arduinos together...this can be considered to be even more wasteful and getting all the arduino devices to talk to each other and stay in time with each other would be very difficult.  I'm not saying it can't be done I'm just saying that there are better easier and cheaper ways of doing things....I am a great believer in keeping things simple!

We could use a different microcontroller with more output pins.  This is a viable option but I haven't got one to hand and it is a little overkill.  An ATMEGA 2560 still doesn't have enough pins and is more way more expensive, Don't worry though I have a cunning plan!

Lets use some old fashioned digital electronics and use Shift Registers!  These are nifty logic circuits which can be used to perform several functions.  They were very popular in previous decades and are essentially a temporary data store.  Information in BITS are input or 'shifted' into the device and stored in the device memory or 'register' until required.  They are actually several J-K flip flops cascaded together in Data mode.  If requested, I can explain all about J-K flip flops in another post. (Note to self, blogging subject matter growing considerably quickly...possibly exponentially??!!)

So these shift registers can temporarily store information.....how does that help us?  Well....they can also convert serial data into parallel data....still not with me??  Ok...how about that we can use then to make three digital output pins from a microcontroller into eight. At the same time we lower the number microcontroller outputs we are using.  The device I have got hold of is the ancient but extremely useful and cheap 74LS595 from Texas Instruments.  This is an 8 bit shift register with latching functionality....The latching stuff is very cool and useful!  Check out the Datasheet!

74LS595 Shift Register Datasheet

The device can be obtained from all good electronic component vendors....Ebay is your friend!  I can't remember where I got mine from but Proto-PIC sell them online for 74 pence a go!  Proto-pic are one of many online component distributors that I favour....they give good service and reasonable value for money, worth a look!

8-bit-74HC595 Shift Registers for sale on Proto-PIC

By the way 74HC595 is the same device as the 74LS595 but it uses CMOS technology instead of TTL....Another subject for another post....the list is growing.....*sigh* always growing!

So what we are now going to do is use this device to control the Seven Segment LED display from three arduino digital output pins freeing up the other output pins for more useful purposes.  We will still need to control each of the Seven Segment LED Displays but hey....its better than a massive expensive over specified and difficult to program microcontrolller that we haven't got!!  I would like to mention at this point that there are always pros and cons in electronic design.  This is one of those moments.....the amount of physical space that this design will take up is another...(more on this subject later!!)

Lets implement the shift register into our circuit and free up some digital output pins!  I'm going to use the shift register as a serial to parallel converter and latching data store.  See the circuit below....I'm not going to talk about how to connect it all up, I am assuming if you have read this far and are still interested then you know how, By the way thanks for reading!!  I do intend getting and using Fritzing to draw diagrams but for now EagleCAD schematics will have to suffice....



The sharper eyed among you may have noticed that the Seven Segment LED Display in the schematic diagram above has different pins labelled from the one that I used in my previous post. That is because the seven segment footprint I used in EagleCAD has different pins.  I will be swapping pin 8 and 10 in my circuit because of this.  I will also need to create a new footprint in EagleCAD later.....*Sigh* More stuff to write up!!

Now then, what we need to do is write a control sketch in the arduino ide and upload it.  We can build upon the code we used in the last sketch although we now need to change things.  We are now going to output the data in a serial string and the shift register will convert it to parallel for us, we also need to create two clock signals for the shift register, one for the Shift Register Clock (SCK) and one for the Storage Register Clock (RCK).  Three output pins to control eight outputs....awesome!

Ok....So here is where we have to do some coding to ensure that we get the arduino to correctly control the Seven Segment LED Display.  You may remember the code from the previous post contained a 2 dimensional array.  This array was a convenient method of telling the microcontroller which pins to put high and low to display the required digit.  That section of code looked like this:

byte seven_seg_digits[10][8] = { 

  { 1,0,1,1,1,1,0,1 },  // = 0 
  { 1,0,0,0,0,1,0,0 },  // = 1 
  { 0,0,1,0,1,1,1,1 },  // = 2  
  { 1,0,0,0,1,1,1,1 },  // = 3 
  { 1,0,0,1,0,1,1,0 },  // = 4 
  { 1,0,0,1,1,0,1,1 },  // = 5 
  { 1,0,1,1,1,0,1,1 },  // = 6 
  { 1,0,0,0,1,1,0,0 },  // = 7 
  { 1,0,1,1,1,1,1,1 },  // = 8 
  { 1,0,0,1,1,1,1,0 },  // = 9 

};

If we look carefully we can see that the lines of 1's and zero's in the array are binary numbers.  Binary numbers are just like ordinary numbers but are written differently as they have a different 'base'.  I will go through the binary number system in another post but for now lets just re-write the above values and then convert them into decimal which is the numbering system that people with ten digits (fingers!) use.


   10111101 in binary = 189 in decimal
   10000100 in binary = 132 in decimal
   00101111 in binary = 47 in decimal
   10001111 in binary = 143 in decimal
   10010110 in binary = 150 in decimal
   10011011 in binary = 155 in decimal
   10111011 in binary = 187 in decimal
   10001100 in binary = 140 in decimal
   10111111 in binary = 191 in decimal
   10011110 in binary = 158 in decimal

Once the numbers have been converted we can then re-write the code with a 1 dimensional array which stores the values for each number in the array cells.  We can then call the array in order from right to left (least significant bit first) and send the values serially to the shift register and it will output the digits on the Seven Segment LED Display. 

Here is the arduino Sketch:


/*

 Langster's Code for driving a seven segment display via a Shift Register
 Connect Pin 3 and pin 10 on the seven segment display to 0V
 Connect all the other pins to the Shift Register digital ouputs as listed below:

 pin 1 of 74HC595 to Seven Segment LED pin 6  
 pin 2 of 74HC595 to Seven Segment LED pin 4
 pin 3 of 74HC595 to Seven Segment LED pin 2
 pin 4 of 74HC595 to Seven Segment LED pin 1
 pin 5 of 74HC595 to Seven Segment LED pin 9
 pin 6 of 74HC595 to Seven Segment LED pin 8
 pin 7 of 74HC595 to Seven Segment LED pin 5
 pin 8 of 74HC595 to 0V
 pin 9 of 74HC595 is unconnected
 pin 10 of 74HC595 to +5V
 pin 11 of 74HC595 to Arduino pin 12  
 pin 12 of 74HC595 to Arduino pin 11
 pin 13 of 74HC595 is unconnected or connected to 0V
 pin 14 of 74HC595 to Arduino pin 13
 pin 15 of 74HC595 to Seven Segment LED pin 7
 pin 16 of 74HC595 to +5V

*/

//Pin connected to ST_CP of 74HC595
int latchPin = 13;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
//Pin connected to DS of 74HC595
int dataPin = 11;


//initialise a One Dimensional integer array with the values for //0 - 9 on the Seven Segment LED Display

int seven_seg_digits[10]= {189,132,47,143,150,155,187,140,191,158};

/*
  { 1,0,1,1,1,1,0,1 },  // = 189 in decimal
  { 1,0,0,0,0,1,0,0 },  // = 132 in decimal
  { 0,0,1,0,1,1,1,1 },  // = 47 in decimal 
  { 1,0,0,0,1,1,1,1 },  // = 143 in decimal
  { 1,0,0,1,0,1,1,0 },  // = 150 in decimal
  { 1,0,0,1,1,0,1,1 },  // = 155 in decimal
  { 1,0,1,1,1,0,1,1 },  // = 187 in decimal
  { 1,0,0,0,1,1,0,0 },  // = 140 in decimal
  { 1,0,1,1,1,1,1,1 },  // = 191 in decimal
  { 1,0,0,1,1,1,1,0 },  // = 158 in decimal

//  Just for further reference here are the separate segment connections

  pin 2 = C
  pin 3 = DOT
  pin 4 = E
  pin 5 = F
  pin 6 = A
  pin 7 = B
  pin 8 = G
  pin 9 = D

*/

void setup() {
  //set the arduino pins to output so you can control the shift      // register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
    // Start a loop from 0 to 9 and output the count to the //Seven Segment Display 
    for (int i=0; i <= 9; i++){
     //take the latch pin of the shift register low
      digitalWrite(latchPin, LOW);
      //write the binary number as a serial pulse train 
      shiftOut(dataPin, clockPin, LSBFIRST, seven_seg_digits[i]);  
      //take the latch pin high so the LEDs will light up:
      digitalWrite(latchPin, HIGH);
      // pause for a second before next value:
      delay(1000);
    }    
}



As promised here is a video of the circuit up and working!

Sunday 13 November 2011

Driving a Seven Segment!

I recently had an idea....I have lots of those sometimes!

I have decided to make a set of Chess timing clocks for a friend of mine.  We play fairly often but don't have any timers....He can sometimes take forever on his moves, particularly when he is under pressure ;)  We have been using an Android app but it isn't quite the same.  As Christmas is coming I thought it would be nice to make him a set of chess clocks.

To that end I bought ten common cathode seven segment displays off Ebay.  They came from dannell.4you and cost a very reasonable £5.52.  They were delivered pretty quickly and they all work!  




It has been a long time since I played with seven segment displays....Not since my college days and that was with 74 series logic!  Anyway I decided to drive them with my arduino, although any microprocessor will work as long as it has eight pins that can be set to outputs and they can source enough current to drive LEDS.  There are a fair few arduino tutorials on-line available but I thought I would add my own efforts to the mix.

Some things to understand about seven segment displays:
Seven segments are essentially a set of LEDS arranged in a simple way so that when driven correctly they display a character, either 0 to 9 or A to F.  They were more popular in years gone by as they were cheaper and more readily available than liquid crystal displays.  The other reason for using them is that they can easily be seen from a distance unlike an LCD.
Unfortunately my seven segments didn't arrive with any information at all....No problems I say, we can work this out!  Suffice to say it took me a little longer than I though it would but here is how I found out the internal connections.  I knew the device was common cathode.  Seven Segment LED displays come in two flavours, common cathode and common anode.  Cathode being the negative connection on a diode and anode being the positive.  I will go into diodes in another post if needed.  That's enough for now....expect more later!

So I have a common cathode seven segment LED display, I just didn't know which pins were which.  I turned the device over and counted the number of pins available.  Ten pins all present and correct!  As there  are seven segments and a dot I can guess that there are eight LEDS inside the display.  All I have to do now is find out which pins connect to what.  Two of the connections will be to the cathode and should be directly connected together.  Grabbing my multimeter, I switched it to its ohm meter (resistance) measurement setting on the lowest division.  I then using the red and black probe leads went through every pin until I found which ones were connected.  Helpfully my meter on lowest ohm measurement setting bleeps when the leads are connected together (have continuity).  It is so useful, some meters don't have this feature on ohms and or it only bleeps on the diode setting.  If this is the case with yours use low ohms measurement anyway as the diode tester will pick up the LEDS and not the common connections.  You will just have to keep an eye on the display until it registers that the wires are connected together (0.05R or similar).

I found that pins 3 and 10 are common (connected together).  All the other pins must be the diodes.  I then set the multimeter to diode tester and put the black lead of my multimeter on pin 3 or pin 10 and the red probe lead on all of the other pins in turn.  Each of the separate segments will light up if it is working.  The meter will also measure the voltage drop for each segment.  On the Seven segment display I had the forward voltage drop was 1.8 volts.  Useful to know for when we want to design a circuit.

    
So now that we know how all the pins are connected we can set up a simple driving circuit using the arduino.  I have my arduino set up with a couple of breadboards to make it a bit easier for me to do development and stuff.  I recommend everyone gets a breadboard for doing electronics hobbyist stuff.  You can quickly build up and check circuits and then take them apart once you are finished.  I also use the wingshield addon that is available from loads of good online vendors.  Google is your friend!  

Put the seven segment into the breadboard make sure it is oriented so that none of the pins are connected 
together.  There is a separating channel down the middle of the breadboard for this.  Next connect pins 3 and 10 on the Seven Segment Display to 0V.  Next connect the following pins on the arduino to the Seven Segment Display:

Arduino Pin 2 to Seven Segment Display pin 7 (A)
Arduino Pin 3 to Seven Segment Display pin 6 (B)
Arduino Pin 4 to Seven Segment Display pin 4 (C)
Arduino Pin 5 to Seven Segment Display pin 2 (D)
Arduino Pin 6 to Seven Segment Display pin 1 (E)
Arduino Pin 7 to Seven Segment Display pin 9 (F)
Arduino Pin 8 to Seven Segment Display pin 8 (G)
Arduino Pin 9 to Seven Segment Display pin 5 (dot)

It really helps to have breadboard wires for doing this!  Anyway, once you have made all of the connections load up the arduino ide and paste the code below into the sketch space.  What the code does is define a 2 dimensional byte array which has eighty cells in an eight by ten matrix.  We then set the cells in the array to store the values required to display the numbers from zero to nine.

We then tell the compiler to set pins 2 to 9 as outputs on the arduino and then we tell the program to count from 9 down to 0 in one second intervals waiting at zero for four seconds before repeating the process.  At each point in the count we set the output pins on the arduino with the values stored in each of the array cells.  This sets the output pins high (+5V) or low (0V) depending on what is required.  The Seven Segment Display will output a number as the correct internal LED segments are turned on.        





// Langster's Code for driving a seven segment display
// I bought them off ebay from dannell.4you - great ebay shop for low volume 
// electronic components!
// Connect Pin 3 and pin 10 on the seven segment display to 0V
// Connect all the other pins to the arduino digital ouputs as listed below:

// Arduino pin 2 goes to pin 7 on the seven segment
// Arduino pin 3 goes to pin 6 on the seven segment
// Arduino pin 4 goes to pin 4 on the seven segment
// Arduino pin 5 goes to pin 2 on the seven segment
// Arduino pin 6 goes to pin 1 on the seven segment
// Arduino pin 7 goes to pin 9 on the seven segment
// Arduino pin 8 goes to pin 8 on the seven segment
// Arduino pin 9 goes to pin 5 on the seven segment

// Define the LED digit patters, from 0 - 9 in an integer array
// Note that these patterns are for common cathode displays
// For common anode displays, change the 1's to 0's and 0's to 1's
// 1 = LED on, 0 = LED off, in this order:
// Arduino pin: 2,3,4,5,6,7,8,9

byte seven_seg_digits[10][8] = {

  { 1,0,1,1,1,1,0,1 },  // = 0
  { 1,0,0,0,0,1,0,0 },  // = 1
  { 0,0,1,0,1,1,1,1 },  // = 2
  { 1,0,0,0,1,1,1,1 },  // = 3
  { 1,0,0,1,0,1,1,0 },  // = 4
  { 1,0,0,1,1,0,1,1 },  // = 5
  { 1,0,1,1,1,0,1,1 },  // = 6
  { 1,0,0,0,1,1,0,0 },  // = 7
  { 1,0,1,1,1,1,1,1 },  // = 8
  { 1,0,0,1,1,1,1,0 },  // = 9

/* Just for reference

  pin 2 = C
  pin 3 = DOT
  pin 4 = E
  pin 5 = F
  pin 6 = A
  pin 7 = B
  pin 8 = G
  pin 9 = D

*/

};

void setup() {              
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}


void sevenSegWrite(byte digit) {
  byte pin = 2;
  for (byte segCount = 0; segCount < 8; ++segCount) {
    digitalWrite(pin, seven_seg_digits[digit][segCount]);
    ++pin;
  }
}

void loop() {
  for (byte count = 10; count > 0; --count) {
   delay(1000);
   sevenSegWrite(count - 1);
  }
  delay(4000);
}