7 segment display help

Hi,

Can anyone recommend a tutorial on how to make a 2 digit 7 segment display with 2 shift registers, toggle on a and off so it blinks the current number displayed with a button press. i have searched but can find anything.

Thanks.

Search the forum for "7 segment".

Hi,

I did that but i cant find anything that,s relevant. Even tried to use some code for one led to blink when on a press of a button and i have got that working, but cant adapt it for the 7 segment display.

You have to decode the 4 bit nibbles of your number into 8 bit 7 segment data, then send both bytes out to the shift registers.

How many pins does your 7 segment display bring out ? About 17 or about 10 ? Do you know if it is common anode or common cathode ? Post a link to it if you are not sure.

Yes, is it like the top display here, or the bottom one?
And common cathode (as pictured) or common anode?

If the top one, you can connect the 2 shift registers to the 2 sets of segment pins, with a current limit resistor per pin, and connect the common cathode to Gnd, or the common anode to +5, and just your data into the shift registers:

#include <SPI.h> // at the top of your sketch
byte ssPin = 10;

// put this in setup()
pinMode (sspin, OUTPUT);
SPI.begin();

// then in loop() send our you data
digitalWrite (ssPin, LOW); // connect to both chip's SRCK
SPI.transfer (byte0); // connect D13 to both chip's SRCLK, D11 to 1st Data in, data out to 2nd chip's data in
SPI.transfer (byte1); // connect MSCLR of both chips to +5, OE/ on both to Gnd
digitalWrite (ssPin, HIGH); // outputs update on this rising edge

If the bottom one, and you still want to use 2 shift registers, I would connect the outputs in parallel, thru a set of current limit resistors, to the segment pins.
Then shift in data as above.

However, you then need to time multiplex and one turn on one shift register at a time. You can do that by controlling the OE/ pin of the two shift registers. Turn on one for 3-5 ms, turn on the other for 3-5 ms, and keep repeating. The Blink without delay example code shows a good way to do that.
Basically:

void loop(){
currentMillis = millis(); // all time related variables declared as type unsigned long
elapsedMillis = currentMillis - previousMillis; // how much time passed?
if (elapsedMillis >= four_ms){  // declare four_ms as unsigned long four_ms = 4;
previousMillis = previousMillis + four_ms; // set up for next time check
toggle = 1 - toggle; // declare before setup as byte toggle; results in 1-0-1-0
digitalWrite (shiftRegister1OE, toggle); // if high, make low. if low, make high
digitalWrite (shift Register2oe, (1-toggle); // if low, make high, if high, make low.
}
// now do whatever to update the data to go out,
read switches, receive serial data, whatever, and update byte0, byte1 as needed
//and send it out when it changes
digitalWrite (ssPin, LOW); // connect to both chip's SRCK
SPI.transfer (byte0); // connect D13 to both chip's SRCLK, D11 to 1st Data in, data out to 2nd chip's data in
SPI.transfer (byte1); // connect MSCLR of both chips to +5, OE/ on both to Gnd
digitalWrite (ssPin, HIGH); // outputs update on this rising edge
}

Wiring examples


Forgot, common segment needs common cathode control as well.

Typically tho, for the common segment parts, most folks just use 1 shift register and the common cathode control, and shift out the data for 1, then the other, displaying either for 3-5ms.

I guess this is a school exercise, but for a normal solution, my preference would have been for using an atmega328p (or similar) with 2 transistors for the common parts (anodes or cathodes depending on the chosen display) and, if necessary, connecting the corresponding segments together so multiplexing would be required. The penalty is a less bright display.

I'm not sure about the design with 2 shift registers for the common segment version. I'd have to assure myself that there was no risk of 1 output pin being high and conflicting with a low output pin from the other shift register on the same segment. With high power shift registers ( e.g. TPIC6B595 which are purely low side) that is not, however, a problem.

"I'd have to assure myself that there was no risk of 1 output pin being high and conflicting with a low output pin from the other shift register on the same segment."

That's a coding issue. Could also use just 1 pin to one transistor and invert the signal going to the other - use one of the transistors for that even. Use the low from common cathode 1's collector to drive common cathode 2's base. Probably need a pullup resistor then to have some current available.

Thanks for the replys

Here is what i have so far a uno connected to 2 74HC595 then 14 220R resistors to a common cathode.

The button turns on the blinking and any of the other 4 buttons turn the blinking off.

with the following 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)


#define BOUNCEDELAY 25

int counter = 0;          // initialise counter as zero
 const byte button1=13;
bool blinking = false;  //defines when blinking should occur

unsigned long blinkInterval = 500;  // number of milliseconds for blink
unsigned long currentMillis; // variables to track millis()
unsigned long previousMillis;

#define SWITCH1 2
#define SWITCH2 3
#define SWITCH3 4
#define SWITCH4 12
int switches[4] = { SWITCH1, SWITCH2, SWITCH3, SWITCH4,};
int switchState[4] = { HIGH, HIGH, HIGH, HIGH,};

int currentSwitch = 0;
int currentProgram = 0;   // current program - sent to the output


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,
  B01100000,
  B11011010,
  B11110010,
  B01100110,
  B10110110,
  B10111110,
  B11100000,
  B11111110,
  B11100110,
};

void setup()
{
  pinMode(latchPin, OUTPUT);   // set SR pins to output
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(button1,INPUT);
  digitalWrite(button1, HIGH);
 
  for( currentSwitch = 0; currentSwitch < 4; currentSwitch++ ) {
		pinMode( switches[currentSwitch], INPUT );          // Set pin for switch
		digitalWrite( switches[currentSwitch], HIGH );      // Turn on internal pullup
		
		
	}
}

void loop()
{
   for( currentSwitch = 0; currentSwitch < 4; currentSwitch++ ) {
		if((digitalRead(switches[currentSwitch]) != switchState[currentSwitch] )&&(switchState[currentSwitch] == HIGH)){
			
                                showNumber(currentSwitch + counter);
                                blinking=false;
                          
			
			delay( BOUNCEDELAY );
		}
		
		
		
		
		switchState[currentSwitch] = digitalRead( switches[currentSwitch] );
		
		
	}
  //Blinking part
 // 
  if (blinking) {    
    currentMillis = millis();  // better to store in variable, for less jitter
    if ((unsigned long)(currentMillis - previousMillis) >= blinkInterval) {  // enough time passed yet?
     (showNumber(counter),showNothing());  // shortcut to toggle the LED
      previousMillis = currentMillis;  // sets the time we wait "from"
    }
    } else{
      
      showNumber(counter);
    
    }
  
     
  
  
 
  int presson = digitalRead(button1);
  delay(50); // crude de-bouncing
 
  if (presson==LOW){ // buttons with pull-up are pressed when LOW
   blinking=true; // start blinking
   counter = counter+4; // when button is pressed the current number is added by 4
   delay(5);
  }
 
}

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
}


void showNothing()
{
  digitalWrite(latchPin, LOW);                  // Set latchPin LOW while clocking bits in to the register
 
  for(byte i = 0; i < numberOfDigits; i++){
    shiftOut(dataPin, clockPin, LSBFIRST, 0);
  }
 
  digitalWrite(latchPin, HIGH);                //set latchPin to high to lock and send data
}

in the blinking section i have tried to take a blinking led sketch on a button press and adapt it for the 7 segment display.
but to no avail.

Is it possible that second statement in this pair of statements:

(showNumber(counter),showNothing());  // shortcut to toggle the LED

is immediately blanking the display so the effect of the first is not visible.

Incidentally, I had to look up the C comma operator to see what this expression is doing. http://stackoverflow.com/questions/2087026/effect-of-using-a-comma-instead-of-a-semi-colon-in-c-and-c

Thanks for that, :)

I See what you mean,

how do i toggle between the showNumber and the showNothing function ?.

I guess you could try something like this assuming that either showNumber(counter) or showNothing() must be executed on each loop cycle.

  //Blinking part
  //
  static bool toggle ;
  if (blinking) {
    currentMillis = millis();  // better to store in variable, for less jitter
    if ( currentMillis - previousMillis  >= blinkInterval ) {  // enough time passed yet?
      toggle = !toggle ;
      previousMillis = currentMillis;  // sets the time we wait "from"
    }
    if (toggle) {
      showNumber(counter);  // shortcut to toggle the LED
    } else {
      showNothing() ;
    }
  } else {
    showNumber(counter);
  }

:slight_smile: Thanks!! That works great now to blink the 7 segment, the only think is i am doing something wrong, when i press any of the 4 switches it does stop the blinking but doesn’t display the number of the pressed switch.
However when the presson switch is pressed it blinks and increments the number by +4 which is perfect.
When i comment out the blinking section it also works fine.(without the blinking)
Any help would be great.

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)


#define BOUNCEDELAY 25

int counter = 0;          // initialise counter as zero
int bankup = 0;
 const byte button1=13;
bool blinking = false;  //defines when blinking should occur

unsigned long blinkInterval = 500;  // number of milliseconds for blink
unsigned long currentMillis; // variables to track millis()
unsigned long previousMillis;

#define SWITCH1 2
#define SWITCH2 3
#define SWITCH3 4
#define SWITCH4 12
int switches[4] = { SWITCH1, SWITCH2, SWITCH3, SWITCH4,};
int switchState[4] = { HIGH, HIGH, HIGH, HIGH,};

int currentSwitch = 0;
int currentProgram = 0;   // current program - sent to the output


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,
  B01100000,
  B11011010,
  B11110010,
  B01100110,
  B10110110,
  B10111110,
  B11100000,
  B11111110,
  B11100110,
};

void setup()
{
  pinMode(latchPin, OUTPUT);   // set SR pins to output
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(button1,INPUT);
  digitalWrite(button1, HIGH);
 
  for( currentSwitch = 0; currentSwitch < 4; currentSwitch++ ) {
		pinMode( switches[currentSwitch], INPUT );          // Set pin for switch
		digitalWrite( switches[currentSwitch], HIGH );      // Turn on internal pullup
		
		
	}
}

void loop()
{
   for( currentSwitch = 0; currentSwitch < 4; currentSwitch++ ) {
		if((digitalRead(switches[currentSwitch]) != switchState[currentSwitch] )&&(switchState[currentSwitch] == HIGH)){
			
                                showNumber(currentSwitch + bankup);
                               blinking=false;
                          
			
			delay( BOUNCEDELAY );
		}
		
		
		
		
		switchState[currentSwitch] = digitalRead( switches[currentSwitch] );
		
		
	}
  //Blinking part
 // 
 static bool toggle ;
 if (blinking) {    
    currentMillis = millis();  // better to store in variable, for less jitter
    if ((unsigned long)(currentMillis - previousMillis) >= blinkInterval) {  // enough time passed yet?
     toggle = !toggle ;  // shortcut to toggle the LED
      previousMillis = currentMillis;  // sets the time we wait "from"
    }
     if (toggle) {
      showNumber(bankup);  // shortcut to toggle the LED
    } else {
      showNothing() ;
    }
  } else {
    showNumber(bankup);
    }
  
     
  
  
 
  int presson = digitalRead(button1);
  delay(50); // crude de-bouncing
 
  if (presson==LOW){ // buttons with pull-up are pressed when LOW
  blinking=true; // start blinking
   bankup = counter;
   counter+=4; // when button is pressed the current number is added by 4
// showNumber(bankup);
  }

}

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
}


void showNothing()
{
  digitalWrite(latchPin, LOW);                  // Set latchPin LOW while clocking bits in to the register
 
  for(byte i = 0; i < numberOfDigits; i++){
    shiftOut(dataPin, clockPin, LSBFIRST, 0);
  }
 
  digitalWrite(latchPin, HIGH);                //set latchPin to high to lock and send data
}

OK. Can you post the whole code you are now using (formatting it nicely with Tools -> Auto Format in the IDE).

Thanks

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)


#define BOUNCEDELAY 25

int counter = 0;          // initialise counter as zero
int bankup = 0;
const byte button1 = 13;
bool blinking = false;  //defines when blinking should occur

unsigned long blinkInterval = 500;  // number of milliseconds for blink
unsigned long currentMillis; // variables to track millis()
unsigned long previousMillis;

#define SWITCH1 2
#define SWITCH2 3
#define SWITCH3 4
#define SWITCH4 12
int switches[4] = { SWITCH1, SWITCH2, SWITCH3, SWITCH4,};
int switchState[4] = { HIGH, HIGH, HIGH, HIGH,};

int currentSwitch = 0;
int currentProgram = 0;   // current program - sent to the output


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,
  B01100000,
  B11011010,
  B11110010,
  B01100110,
  B10110110,
  B10111110,
  B11100000,
  B11111110,
  B11100110,
};

void setup()
{
  pinMode(latchPin, OUTPUT);   // set SR pins to output
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(button1, INPUT);
  digitalWrite(button1, HIGH);

  for ( currentSwitch = 0; currentSwitch < 4; currentSwitch++ ) {
    pinMode( switches[currentSwitch], INPUT );          // Set pin for switch
    digitalWrite( switches[currentSwitch], HIGH );      // Turn on internal pullup


  }
}

void loop()
{
  for ( currentSwitch = 0; currentSwitch < 4; currentSwitch++ ) {
    if ((digitalRead(switches[currentSwitch]) != switchState[currentSwitch] ) && (switchState[currentSwitch] == HIGH)) {

      showNumber(currentSwitch + bankup);
      blinking = false;


      delay( BOUNCEDELAY );
    }




    switchState[currentSwitch] = digitalRead( switches[currentSwitch] );


  }
  //Blinking part
  //
  static bool toggle ;
  if (blinking) {
    currentMillis = millis();  // better to store in variable, for less jitter
    if ((unsigned long)(currentMillis - previousMillis) >= blinkInterval) {  // enough time passed yet?
      toggle = !toggle ;  // shortcut to toggle the LED
      previousMillis = currentMillis;  // sets the time we wait "from"
    }
    if (toggle) {
      showNumber(bankup);  // shortcut to toggle the LED
    } else {
      showNothing() ;
    }
  } else {
    showNumber(bankup);
  }





  int presson = digitalRead(button1);
  delay(50); // crude de-bouncing

  if (presson == LOW) { // buttons with pull-up are pressed when LOW
    blinking = true; // start blinking
    bankup = counter;
    counter += 4; // when button is pressed the current number is added by 4
    // showNumber(bankup);
  }

}

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
}


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

  for (byte i = 0; i < numberOfDigits; i++) {
    shiftOut(dataPin, clockPin, LSBFIRST, 0);
  }

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

I guess you mean here:

when i press any of the 4 switches it does stop the blinking but doesn't display the number of the pressed switch.

that the number of the pressed switch is not displayed long enough for you to see it.

You do this if a switch is pressed:

showNumber(currentSwitch + bankup);

but immediately do this afterwards in the blinking part (where blinking is false)

showNumber(bankup);

Which overwrites your display of the pressed switch.

Maybe have a global variable theNumberToDisplayNow instead of supplying a parameter to showNumber(). showNumber() always displays theNumberToDisplayNow. When you detect a switch press, simply change the value of theNumberToDisplayNow. After some time or event, revert theNumberToDisplayNow to the value of the counter.

Thanks for your help i will experiment with that.