7-SEGMENT COUNTER 0-99 with 74HC595

Hi
I am trying to make a counter(0-99) with 2 digit 7-segment display(common cathode) and the two pushbuttons, one for increment by 1 and one for decrement by 1.
I found this code on the internet but I didnt find a way to use it with my 7-seg display so I decided to use a single shift register driving the segments (anodes) and 2 digital i/o pins each driving a NPN transistor to switch in each cathode one at a time.

Now I have to modify the code to drive these transistors that will switch in each cathode at a certain time.
I am still learning programming and I am not so sure how to do this properly so any help is welcome :wink:

This is the code I have:

const byte  latchPin = 5;  // Pin connected to Pin 12 of 74HC595 (Latch)
const byte dataPin  = 6;   // Pin connected to Pin 14 of 74HC595 (Data)
const byte clockPin = 7;   // Pin connected to Pin 11 of 74HC595 (Clock)

const byte upPin = 2;     // pushbutton attached to pin 2
const byte downPin = 3;   // pushbutton attached to pin 3

int prevUpState = 0;
int prevDownState = 0;
int currUpState = 1;
int currDownState = 1;

int counter = 0;           // initialise counter as zero

byte numberOfDigits = 2;

const byte numbers[10] =   // Describe each digit in terms of display segments  0, 1, 2, 3, 4, 5, 6, 7, 8, 9
{
  B11111100, //0
  B01100000, //1
  B11011010, //2
  B11110010, //3
  B01100110, //4
  B10110110, //5
  B10111110, //6
  B11100000, //7
  B11111110, //8
  B11110110, //9
};

void setup()
{
  pinMode(latchPin, OUTPUT);   // set SR pins to output
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(upPin, INPUT);      // sets pin 12 as pushbutton INPUT
  pinMode(downPin, INPUT);    // sets pin 13 as pushbutton INPUT
}

void loop()
{
  //counter part
  currUpState = digitalRead(upPin);

  if (prevUpState != currUpState)           // has the state changed from HIGH to LOW or vice versa
  {                                         
    prevUpState = !prevUpState;    //invert

    if (currUpState == HIGH && counter < 99)   // If the button was pressed AND not reached 99

      counter++;                     // increment the counter by one

    if(counter == 99) counter = 0;    

  }
  
  currDownState = digitalRead(downPin);

  if (prevDownState != currDownState)   // has the state changed from HIGH to LOW or vice versa
  {                                                 
    prevDownState = currDownState;

    if (currDownState == HIGH && counter > 0)    // If the button was pressed AND not reached 0

       counter--;                         // decrement the counter by one


  }

  showNumber(counter); // display the current digit
}

void showNumber(int number)
{

  digitalWrite(latchPin, LOW);     // Set latchPin LOW while clocking bits in to the register

  for(byte i = 0; i < numberOfDigits; i++)
{
    shiftOut(dataPin, clockPin, LSBFIRST, numbers[number % 10]);
    number /= 10;
  }

  digitalWrite(latchPin, HIGH);    //set latchPin to high to lock and send data
}

You can see pictures down bellow with the datasheet of my 7-seg display as well as the schematic I made for this counter.

Try this

http://www.instructables.com/id/Arduino-powered-7-seg-LED-display-using-Shift-Regi/step2/Circuit/

use this as your schametic

and add your up and down buttons to pin 2 and 3

you need to find the pin out for the 7 segment display .

Yes but have you seen my pinout for display? It has 2 digits and each segment from A to G is connected together from each digit... So I cant use that schematic, because I will end up displaying two same digits, and for that reason I need to modify the code so I can light up certain digit at certain time trough transistors. You know what I mean?

Here is the picture of the pinout to make it clearer for you:

https://www.dropbox.com/s/nxdg5v0mqcxwmmu/2%20digit%207-seg%20display.jpg?dl=0

Right, the segments are all hooked together and they go to the shift register just like they were one digit. Then you choose which digit to light up at any given time by choosing the right cathode or anode depending on whether it is a common cathode or common anode display.

It is common cathode…
I didnt change the code for controling transistors yet, could you help me out with it?

That is a completely standard display construction. All the anodes (segments A-G + DP) are wired in parallel. The cathodes are separate. This means you have to multiplex the display, which simply means that you display digit one for a short period then display digit two for a short period, then repeat endlessly.

If tried to fix your function showNumber() so it should work with the 2 digit display. My modifications are not pretty, but have been designed for the minimum disturbance of the existing code.
Ideally, the function would be called by a timer say every 1 mS, and would directly access the global variable counter.
You’ll also have to set pinMode() for the transistor pins in setup().
I’ve not tested it.

void showNumber(int number)
{
  // digits are : (LH - pin 8) and  (RH - pin 9)

  for(byte i = 0; i < numberOfDigits; i++)
  { 
    digitalWrite(latchPin, LOW);     // Set latchPin LOW while clocking bits in to the register
    digitalWrite( 9 , LOW ) ; // switch off digit RH
    digitalWrite( 8 , LOW ) ; // switch off digit LH

    shiftOut(dataPin, clockPin, LSBFIRST, numbers[number % 10]);
    number /= 10;

    if ( i == 0 ) {
       digitalWrite( 9 , HIGH ) ; // switch on digit LH
    } else if ( i == 1 ) {
       digitalWrite( 8 , HIGH ) ; // switch on digit RH
    }
    digitalWrite(latchPin, HIGH);    //set latchPin to high to lock and send data
    delay( 500 ) ;   // for debugging so you see the multiplexing 
  }
}

Hi,
You need to attach your pictures rather than load them offsite, there are some platforms that make it difficult to view offsite pictures.
The Ops circuit.
7dig595.jpg

Tom… :slight_smile:

TomGeorge: Hi, You need to attach your pictures rather than load them offsite, there are some platforms that make it difficult to view offsite pictures. . . .

In general, of course you are right. In this specific case, however, where the OP has used Fritzing to create the image, the picture doesn't help much. This is because, as is usual with Fritzing, most of the essential detail (pin numbers etc.) is blurred or covered with other features leaving only a pretty looking picture, which has anyway to be loaded into an image viewer where you can magnify many times it to see this otherwise barely visible detail.

I put a dropbox link of the pictures and I attached them too so you can see them where ever you like.

Anyway, thank you @6v6gt for helping me with the code.

I have tried it and it works…but I am having some weird problem. My D segment doesnt ligt up on the right digit. Why is this happening?

Besides that, I found that all other segments(that shouldnt be turned on)are not completely turned off.
Here´s the picture(i dont know if you can see that segments ). It shows number 15, you can see segment D on the right digit doesnt light up.

7seg display15.jpg

6v6gt: In general, of course you are right. In this specific case, however, where the OP has used Fritzing to create the image, the picture doesn't help much. This is because, as is usual with Fritzing, most of the essential detail (pin numbers etc.) is blurred or covered with other features leaving only a pretty looking picture, which has anyway to be loaded into an image viewer where you can magnify many times it to see this otherwise barely visible detail.

I know its fritzy, but it has been logically drawn and its better then nothing. Tom... :)

My D segment doesnt ligt up on the right digit. Why is this happening?

But it works fine on the left side ? If you swap the connection to pins 8 and 9 on the Arduino, does the problem of the failed Segment D move to the other side ? If so, did you also have that problem when the delay was set to 500 mS ? If not, then it is almost certainly a display hardware failure which you could verify by applying 5 volts via a 220R resistor to the appropriate pins on the display.

It was a hardware display failure...I changed the display andit works now :). Now I just need to find a way to stop lighting up those segments which are not completely turned off(and should be) Any ideas?

Is there anything I can do to stop these unwanted segments being turned on.

On the right digit it is less noticeable but on the left I found out that it displays the number from right digit too but in much less brightness(and still visible).

Show the program that's doing it. Can't do anything without that. Maybe you're switching one before the other.

Sorry…here´s the code:

const byte  latchPin = 5;  // Pin connected to Pin 12 of 74HC595 (Latch)
const byte dataPin  = 6;   // Pin connected to Pin 14 of 74HC595 (Data)
const byte clockPin = 7;   // Pin connected to Pin 11 of 74HC595 (Clock)

const byte UpPin = 12;     // pushbutton connected to pin 12 for increment by 1
const byte DownPin = 13;   // pushbutton connected to pin 13 for decrement by 1
const byte reset = A0;
const byte Digit1 = 8;     // transistor for ones digit connected to pin 8
const byte Digit2 = 9;     // transistor for tens digit connected to pin 9


int prevUpState = 0;
int prevDownState = 0;
int currUpState = 1;
int currDownState = 1;

int res = 0;

int counter = 0;           // initialise counter as zero

byte numberOfDigits = 2;

const byte numbers[10] =   // Describe each digit in terms of display segments  0, 1, 2, 3, 4, 5, 6, 7, 8, 9
{
  B11111100, //0
  B01100000, //1
  B11011010, //2
  B11110010, //3
  B01100110, //4
  B10110110, //5
  B10111110, //6
  B11100000, //7
  B11111110, //8
  B11110110, //9
};

void setup()
{
  pinMode(latchPin, OUTPUT);   // set SR pins to output
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(UpPin, INPUT);      // sets pin 12 as pushbutton INPUT
  pinMode(DownPin, INPUT);    // sets pin 13 as pushbutton INPUT
  pinMode(reset, INPUT);
  pinMode(Digit1, OUTPUT);
  pinMode(Digit2, OUTPUT);
 
}

void loop()
{
  //counter part
  currUpState = digitalRead(UpPin);
  if (prevUpState != currUpState)           // has the state changed from HIGH to LOW or vice versa
  {                                         
    prevUpState = !prevUpState;    //invert
    if (currUpState == HIGH && counter <= 99)  // If the button was pressed AND not reached 99

        counter++;                                          // increment the counter by one

    if(counter > 99) counter = 0;        //if counter is greater than 99, set it to 0

  }

  currDownState = digitalRead(DownPin);
  if (prevDownState != currDownState)     // has the state changed from HIGH to LOW or vice versa
  {                                                 
    prevDownState = currDownState;
    if (currDownState == HIGH && counter >= 0)    // If the button was pressed AND not reached 0
        counter--;                         // decrement the counter by one  

    if(counter < 0) counter = 99;        // counting backward from 99 to 0

  }

  

  res = digitalRead(reset);
  if(res == HIGH) counter = 0;

  showNumber(counter); // display the current digit

}

void showNumber(int number)
{
  // digits are : (Digit1 - pin 8) and  (Digit2 - pin 9)

  for(byte i = 0; i < numberOfDigits; i++)
  { 
    digitalWrite(latchPin, LOW);     // Set latchPin LOW while clocking bits in to the register
    digitalWrite(Digit1, LOW ) ; // switch off Digit1(ones)
    digitalWrite(Digit2, LOW ) ; // switch off Digit2(tens)

    shiftOut(dataPin, clockPin, LSBFIRST, numbers[number % 10]);
    number /= 10;

    if ( i == 0 ) 
    {
      digitalWrite(Digit1, HIGH ) ; // switch on Digit1   
    }
    else if ( i == 1 )
    {
      digitalWrite(Digit2, HIGH ) ; // switch on Digit2
    }
    

    digitalWrite(latchPin, HIGH);    //set latchPin to high to lock and send data
     delay(5); 
  }
}

Does this effect appear to be ghosting from one side to the other ?
From an earlier picture of 15, the only truly dark segement (segment A) was not shared between either the 1 or the 5.
You could alternately disconnect pin 8 and then later pin 9 to see if effect is still there.
You could also try modifying showNumber() . . .

void showNumber(int number)
{
  // digits are : (Digit1 - pin 8) and  (Digit2 - pin 9)

  for(byte i = 0; i < numberOfDigits; i++)
  {
    
    digitalWrite(Digit1, LOW ) ; // switch off Digit1(ones)
    digitalWrite(Digit2, LOW ) ; // switch off Digit2(tens)

    digitalWrite(latchPin, LOW);     // Set latchPin LOW while clocking bits in to the register

    shiftOut(dataPin, clockPin, LSBFIRST, numbers[number % 10]);
    number /= 10;

     digitalWrite(latchPin, HIGH);    //set latchPin to high to lock and send data

     digitalWrite(Digit1, ( i == 0 ) ) ; // switch on/off Digit1   
  
     digitalWrite(Digit2, ( i == 1 ) ) ; // switch on/off Digit2

     delay(5);
  }
}

If that does not work, you can then experiment with the NOT OE (pin 13) on the shift register to suppress output until everything is stable.

What transistors are you using, incidentally ?

Wow. It works fantastic now. Thank you so much @6v6gt :)

Hi, One question: Is it possibe to connect one or two more 2 digit 7seg displays on the same shift register but to control them with other pushbuttons so they count from 0 to 99 too?

You should be able to do that: 1. Connect pins A through to G on the new display directly to the equivalent pins on the existing display (no additional resistors) 2. Connect the cathodes of the new display via transistors to two new arduino pins. 3. modify function showNumber to handle 4 digits.

You'll then create an additional button controlled counter 0-99. Simply add the existing counter to 100 times the new counter and call showNumber with this combined value.

6v6gt:
You’ll then create an additional button controlled counter 0-99.
Simply add the existing counter to 100 times the new counter and call showNumber with this combined value.

I didnt understand you very well about this.
Do I need to make a new counter?