Tuesday, 27 December 2011

Its the holiday Season!! More on Clocks....

Hello there blog readers!  Merry Christmas!

I apologise again for not posting more recently.  I have been suffering from a really virulent chest infection which has held me back a bit!

I was in the middle of constructing one of the display sections of the Chess clock on matrix board.  It is nearly complete but I have had terrible trouble making it.  Matrix board is ok providing you have a simple layout.  The circuit that we are trying to construct with separate seven segment displays and four separate shift registers is not a simple layout.  Upon reflection I should have had PCBS professionally made and my problems would have been solved.  I didn't and I have a three quarters complete mess of wires and chip holders on some matrix board!  I will complete and get it working but I don't think I'll be making another in that fashion.  It was a nightmare!!

So what do we do now?  The faint hearted quit and go and do something else...hopefully something more profitable!  The stubborn and courageous (thats me!!) find another solution.....Browsing the various websites available and looking at some of the other technical blogs online; various other people have done things slightly differently.  Most people have used a combined 4x Seven Segment display which gets rid of a lot of the circuit layout issues.

Check out the following sites for inspiration:

http://proto-pic.co.uk/categories/LCD-and-LED-Displays/ - Where displays can be obtained for a very reasonable price....

http://tronixstuff.wordpress.com/2010/07/07/getting-started-with-arduino-chapter-twelve/ - Jon Boxall's blog which is excellent by the way...better than mine at the moment!

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265669651 - The arduino forum on common anode seven segment LED displays

So I bought two of these 4x Seven Segment displays and began working out how they tick.  They come from China as do most electronic components these days and there is a datasheet available.  As these parts are stocked by Sparkfun I will link to their page from here:




Helpfully sparkfun already also have an eagle footprint created so we can draw a schematic and once the circuit is complete and working layout another PCB!  This time things should be much more simple to achieve....less wires equals less of a layout and construction headache...(I say this now...later I may change my mind!!)

So it was while I was looking at the device on sparkfun's website and reading some of the tutorial pages available when I noticed an issue....well not really an issue but a difference from the other displays we have been using.  For starters these are common anode displays, meaning that the positive input to the diodes are connected together; our previous displays were common cathode.  The other issue is that these displays have to have each segment driven separately.  For those who are interested these displays are quite easy to get up and running....here is an excellent tutorial which I used at first myself just to ensure the displays were working:

http://allaboutee.com/2011/07/09/arduino-4-digit-7-segment-display-tutorial/

The article goes through all of the important bits of information....and gets the general ideas and concepts across in order to get this display up and running.  The issue is that in order to drive this display fully 14 control pins will be needed from our microcontroller of choice.  I'm using an arduino development system but any micro will need 14 pins....This is a lot of pins to sacrifice just to drive one display and as I need two of these for my chess clocks this isn't an option.  Ok...as in previous posts....I'll just use shift registers.  I got the parts needed and set up the circuit as shown on Jon Boxall's blog.

Parts needed:

1x Microcontroller and development area - An arduino and breadboard
1x Serial cable for programming and powering the arduino
2x 74HC595 shift registers
4x BC548 transistors
4x 1k resistors
9x 220R resistors
Lots of connector wires
Lots of patience and a sense of humour!

Here is the applicable chapter from Jon's blog

http://tronixstuff.wordpress.com/2010/07/07/getting-started-with-arduino-chapter-twelve/

As can be seen things are a little different.  This is because in we are going to have to multiplex the display in order to get all four displays on at the same time.  This uses a persistence of vision technique that I didn't use in the previous circuits.  The seven segments are turned on as before by the appropriate binary code number being sent serially to the first shift register.  The second shift register controls which segment is on and we will write the control software to multiplex the segments (flash the segments at a high refresh rate to make it look like they are all on at the same time.....in reality they aren't but this isn't visible to the naked eye so it isn't an issue.

Here is the circuit diagram.  I am using a common anode display so my transistors are controlling the anodes of the display with the emitter pins unlike Jon's circuit where he had a common cathode display and was controlling the collectors.  My transistors are controlling when the pins go HIGH and Jon's were controlling when the pins go LOW....



So....I connected up the circuit and commenced with the writing of the control software....I had already looked at Jon's code...assumed I understood it and figured it wouldn't be too difficult to make a fork of it to control mine.  For some reason life is never simple and it took me ages to get this working....I must be losing my edge!!  I found it very difficult to get each display on correctly and update properly.  My biggest mistake was that I was trying to turn the display completely on and off when I updated the display with a new character.  I now know and understand that it isn't possible to do this when using a persistence of vision multiplexed display!

Here is the code....As it is quite a big program I'm giving a link.


By the way Git hub - great idea but a massive pain to use for the neophyte.

I accept this code is horrible to look at for someone else....so I will break the program down into what it does in each section and that should make it easier to understand.  Please feel free to comment or email me if there is something that is not clear.

I decided just for fun to make the circuit into a clock getting the current time from my computer via the serial programming cable.  

The first section tells the compiler to include two libraries and set up some variables ready to store information.  The comments provided give most of the detail of what is going on.  Like in the previous posts I am using a couple of arrays to store the information which turns on the required LEDS to create the characters and I also am using a small array to store the information for which cell is currently active.  The other variables are for counting and to tell the compiler which microprocessor pins are being used in this circuit.

//External libraries for getting the current PC Time
//over the serial connection

#include <Wire.h>
#include "RTClib.h"

//Function for getting the current system time
RTC_Millis RTC;

//Count variables
int i=0;
int j=0;

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

// 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 four element array which turns the transistors on
   to control which segment is active */
   
int segmentSelect[4]= { 1,2,4,8 };  

/* Initialise a One Dimensional integer array with 
   the values for 0 - 9 on the Seven Segment LED Display */
   
int seven_seg_digits[10]={ 192,249,164,176,153,146,130,248,128,152 }; 
                             
/*
   
  without decimal point(s) 
  { dp,g,f,e,d,c,b,a },  
  { 1,1,0,0,0,0,0,0 },  // = 192 in decimal - common anode  

  { 1,1,1,1,1,0,0,1 },  // = 249 in decimal - common anode

  { 1,1,0,0,0,0,0,1 },  // = 164 in decimal - common anode
  
  { 1,0,1,1,0,0,0,0 },  // = 176 in decimal - common anode
  
  { 1,0,0,1,1,0,0,1 },  // = 153 in decimal - common anode
  
  { 1,0,0,1,0,0,1,0 },  // = 146 in decimal - common anode
  
  { 1,0,0,0,0,0,1,0 },  // = 130 in decimal - common anode
  
  { 1,1,1,1,1,0,0,0 },  // = 248 in decimal - common anode
  
  { 1,0,0,0,0,0,0,0 },  // = 128 in decimal - common anode
  
  { 0,1,1,0,0,0,0,1 },  // = 152 in decimal - common anode
  
//  Just for further reference here are the 
//  separate segment connections

  segment a = 14
  segment b = 16
  segment c = 13
  segment d = 3
  segment e = 5
  segment f = 11
  segment g = 15
  d.p. = 7 
  
*/

// constants won't change. Used here to 
// set pin numbers:

// Arduino Pin 9 is connected to the colon LED pin on the Seven Segment
const int colonPin =  9;      

// Variables will change:
int colonLedState = LOW;  // colonLedState used to set the LED
long previousMillis = 0;  // will store last time the Colon LED was updated

/*
The following variables is a long because the time, measured in miliseconds,
will quickly become a bigger number than can be stored in an int.
*/

long interval = 1000;     

//Integer variables to store the value(s) of the character that we wish to display on the Seven Segment

int firstDigit=0;
int secondDigit=0;
int thirdDigit=0;
int fourthDigit=0;

****************************************************************

The next section of code is a small function which clears the display completely by turning off the transistors which are controlling the cell anodes.  It does this by loading the binary number 0000 0000 0000 into the shift registers which causes the anode pins to be low and therefore not powered.

void clearDisplay() {
        
        /*   
        Take the latch pin of the shift register(s) low. shift         zero serially into the shift register(s) which turns the transistors off
        and then take the latch pin of the shift register high to re-latch with the new 'zero' data
        */
        
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin, MSBFIRST, 0);
        shiftOut(dataPin, clockPin, MSBFIRST, 0);
        digitalWrite(latchPin, HIGH);   
}       

***************************************************************

The next section is the setup function.  This part of the program tells the compiler which pins are being used as outputs and to start the serial listener.  It also grabs the current PC system time over the serial link.  We will use this as the display data for the seven segment so that we have something meaningful to display.  I'm going to change this for the chess clocks as we want a count down timer in that situation...not a real time clock!  The setup function is only called once, so whatever needs setting up in order for our device to correctly function needs to be done here...  

void setup() {
  
  // set the arduino pins to output so you 
  // can control the shift register(s)
  // and the colon LED segment
  
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(colonPin, OUTPUT);  
  
  //Clear all the Display
  clearDisplay;
  
  //Turn on the serial Monitor - useful for debugging!
  Serial.begin(57600);
  Serial.println("Ready");  
  
  //Get the current system time via the serial port
  RTC.begin(DateTime(__DATE__, __TIME__));

****************************************************************

The next section is the main loop function.  This is the part of the program that is constantly run.  It calls the other functions which get the circuit to function as we designed...In this case it calls the next function which is the display function:

void loop() {
  
  // Call the display function
  displayNumber();        
        
}       

****************************************************************


The code below is the main heart of the program and hopefully is explained by the text following it!

/*
Using an interrupt constantly display characters on the display which are taken from the system clock
Display these characters by rapidly sweeping from right to left to make it seem as though the characters are constantly on....Persistence of vision technique
*/

void displayNumber() {
#define DISPLAY_BRIGHTNESS  1500

  long beginTime = millis();

  for(int digit = 4 ; digit > 0 ; digit--) {

    //Turn on a digit for a short amount of time
    switch(digit) {
    case 1:
      displayDigitOne();
      break;
    case 2:
      displayDigitTwo();
      break;
    case 3:
      displayDigitThree();
      break;
    case 4:
      displayDigitFour();
      break;
    }
    
    //Display this digit for a fraction of a second (between 1us and 5ms)
    delayMicroseconds(DISPLAY_BRIGHTNESS); 

    //Turn on all segments
    updateDisplay(); 

  }
    
    //Wait for 20ms to pass before we paint the display again
    while( (millis() - beginTime) < 10) ; 

   unsigned long currentMillis = millis();
  
    if(currentMillis - previousMillis > interval) {
    
    // save the last time you blinked the Colon LED 
    previousMillis = currentMillis;   
    
    if (colonLedState == LOW)
      colonLedState = HIGH;
    else
      colonLedState = LOW;

    // set the colon LED with the State of the variable:
    digitalWrite(colonPin, colonLedState);
    
    }
}

****************************************************************
This is the section of code that I found the hardest to write and after looking at other people's code and explanations at first I still didn't get it!  So what is going on here:

the first line of code is a statement of definition - where the compiler sees DISPLAY_BRIGHTNESS written it will use the value 1500....what the program does here is set the refresh rate for the 4x Seven Segment Display.  Just like your computer monitor or television's refresh rate our display will flicker on between each segment every 1500 micro-seconds.

The next line is a variable declaration that stores the amount of time the program has been running.  We will use this information as a starting point to get the microcontroller to perform certain functions such as updating each display in turn....

After that we have a For to loop combined with a switch statement.  What this section of code does is turn on each segment in turn from right to left from four to one calling a separate function which contains the information we wish to display.  This information is written to the display for 20ms before it is then updated with a new a possibly different character to display.  

The final section is a fork of the blink without delay example from the arduino forum.  We are using it in this case to flash the colon on the display every second so that it looks like a clock!  Again we are marking the point at which this section of code has been run and then after a second has passed we toggle the state of the colon led which is connected to pin 9 of the arduino.

The above code section is an example of using an interrupt.  The code above constantly runs no matter what else is going on in the program.  The reason we need to do this is because if we interrupt the display it will look flickery and dull...and as I found all the time while I was trying to get this working the last segment is wonderfully bright and all the others are barely on.....

*********************************************************************************

The next function is quite a simple one...all it does is grab the current system time from the serial connection and then by using some simple maths tricks send the required number to each of the displays in turn.  The time stamp is obtained in sections.  The hour will be a two digit number from zero to 23.  If we divide this number by ten we get a number and a remainder.  If we drop the remainder (3) we have the first number we wish to display on the first segment.  For segment two we display the remainder 3.  The minute functions are obtained in the same way

Get the current time from the serial connection - DateTime now = RTC.now();

divide the hours value - for example 16 by ten and we have 1 remainder 6 
store the value 1 for the first segment - firstDigit=now.hour()/10;
store the remainder value 6 to the second segment -  secondDigit=now.hour()%10;


divide the minutes value for example 35 by ten and we have 3 remainder 5
store the value 3 for the third segment - thirdDigit=now.minute()/10;
store the remainder value 5 to the fourth segment - fourthDigit=(now.minute()%10);

/*
Using the current PC time as a data source, set the segments to    display the time by passing the current time as variables to the segments
*/

void updateDisplay() {
      
      DateTime now = RTC.now();
      firstDigit=now.hour()/10;
      secondDigit=now.hour()%10;
      thirdDigit=now.minute()/10;
      fourthDigit=(now.minute()%10);     
     
}


****************************************************************

This next section of code deals with sending the required character to the required segment via the shift register serially.  The latch pin of the shift register is taken low.  The required character is shifted into the register serially from the position highlighted in the character array.  The required segment is then selected and finally the data is then latched into the shift register by taking the latch pin high.  Each of the segments are treated in the same way but they all have their own function.


void displayDigitOne() {  
          
//take the latch pin of the shift register(s) low and shift in 
//the data for the required character, then turn the correct //transistor 
//for the first segment on which turns the segment on
//then latch the shift register by taking the latch pin HIGH
        
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin, MSBFIRST,                    seven_seg_digits[firstDigit]);
        shiftOut(dataPin, clockPin, MSBFIRST, segmentSelect[0]);
        digitalWrite(latchPin, HIGH);   
  
}


********************************************************************************

And now finally for the ubiquitous video showing that this all works and it isn't some great pretence!  Enjoy people and happy holidays.  Next up will be setting the time using a rotary enoder and then finally we will turn the clocks into fischer count down chess clocks.  Then hopefully I will get all of it permanently constructed and into some sensible and reasonable looking housings and give them away!  I might make two  just in case....i'm growing quite attached to the idea!








Friday, 9 December 2011

Updates on the Project

My sincerest apologies to those that follow my blog....

I haven't had the time to do any posts or updates in some time.  I have been thinking about the project and I have done some work on it.....

I am in the process of making up what I call the seven segment display modules which will be the 4x Seven Segment LEDS and the associated shift registers.  I was intending to etch and make a PCB but as I currently don't have access to etching facilities I haven't gone down this route.  I bought some matrix board off an excellent small electronic components distributor via their online shop:

www.bitsbox.co.uk

They don't have as large a selection of components as RS or Farnell but they have most of what I need and they don't mind small orders.  Their service is excellent!  I order before 12am on a weekday and more often than not my stuff is delivered the next day....that kind of service seems hard to find for electronic components in the UK and this is at very reasonable prices.  I wholeheartedly recommend them.

Here is the matrix PCB:




What I will have to do is solder in the components and then either use wire links to make the connections or make solder tracks.  There are pitfalls in using matrix board and this will become apparent as I post more photographs of the construction.

A few tips when using matrix PCB:

  1. Plan your layout carefully.  Place the components on the PCB in a rough semblance of where you want them to go.
  2. Ensure you have display components centred and placed in a logical fashion.  Try and ensure you have enough room to wire the components together.  It can be difficult to go back once you have started.
  3. Once you are certain of where you want to place components begin soldering.  I recomment soldering the corner pins first off.  Then once you are comfortable with the component placement solder the rest of the pins.  There is no rush when doing this....I would also avoid hangovers and coffee!
  4. Use a sensible heat setting on your soldering iron.  Soldering at too high a temperature can and DOES melt the glue that holds the pads onto the FR4 material.  Wire up the circuit slowly testing each section as you go.  Desoldering and moving components can be difficult.  I write with experience in things not going according to plan!


For those that don't know most electronic circuits use a special material as the base surface called FR4.  It is glass reinforced plastic which is an excellent insulator.  Copper material is glued to the FR4 to allow conductance of electricity.  The copper is then removed to create tracks or in my case a matrix. 

As I write I am half way through completing the construction and test of the first display board.  I hope it all comes together.  Check out the mess of wires on the underside!!



I made a classic mistake in not considering how thick wire can cause issues when making connections and this will cost me dearly.  I also didn't use a sensible wiring practice when making the connections and will have to work out which wires connect which resistors to the LED segments.  I should have wired the shift registers first.  Hindsight is a wonderful thing!  I can still get this working but I think I will construct the other PCB with the same component placement but wire the shift registers first off.  

Well that is about it for now.  After I have both display boards constructed and testing and working I will be showing how we can use Rotary Encoders to set the count down time.  I'm still hopeful to get this finished for Christmas!!  

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!