Unexpected Seven Segment Output

I wish to display the numbers "1,2,3, and 4" on 2 - 2 digit Seven Segment Displays (SSDs) (CL3621AH Common Cathode). "1" on SSD_1, "2" on SSD_2, etc.

When I run my code, the output is "1" on SSD_1, "2" on SSD_2, "1" on SSD_3, and "4" on SSD_4. If I change the first line in the void Loop function to "byte bits1 = GetBits(7) ;", the outputs become 7,2,7,4.

What I find particularly strange is if I remove the jumper wire from Arduino pin 11 (connects to the second SSD's #10 pin) and touch it to the jumper that is connected to Arduino 9 (connected to pin 5 of the first SSD), I get the expected output of "1,2,3,4".

My sketch is part of a larger project so you may find some variables that don't seem to belong. Sorry if I missed removing them.

Here is my code:

/*  Using CL3621AH Common Cathode 2 digit Seven Segment Displays
 *  Shift register SN74hc595    1 to digital display 9 (SevSeg B)
                               2                    8 (SevSeg C)
                               3                    6 (SevSeg D)
                               4                    7 (SevSeg E)
                               5                    4 (SevSeg F)
                               6                    1 (SevSeg G)
                               7                    not used
                               8                    grnd
                               9                    not used
                               10 to +5V
                               11 to arduino 4 CLOCK
                               12 to arduino 3  LATCH
                               13 to grnd
                               14 to arduino 5 DATA
                               15 to digital display 3 (SevSeg A)
                               16 to +5V
                               On 2nd SN74HC595, Pin 11 from first goes to 11 on second
                                                 Pin 12            goes to 12
                                                 Pin 9 from first goes to 14 on second
*/

#include <stdio.h>
#include <DS1302.h>
#include "SevSeg.h"

const int dataPin = 5;  //  to 74HC595 pin 14
const int latchPin = 3; //  to 74HC595 pin 12
const int clockPin = 4; //  to 74HC595 pin 11
const int Digit_1 = 11;  //  Digital Pin 11 on Arduino controls the Mins Tens Digit (Sev Seg 10)
const int Digit_2 = 12; //  Digital Pin 12 on Arduino controls the Hrs Tens Digit (Sev Seg 10)
const int Digit_3 = 9;  //  Digital Pin 9 on Arduino controls the Hrs Ones Digit (Sev Seg 5)
const int Digit_4 = 10; //  Digital Pin 10 on Arduino controls the Mins Ones Digit (Sev Seg 5)

bool decPt = true;  // decimal point display flag

void setup() {
  // initialize I/O pins
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(Digit_1, OUTPUT); // Mins Tens
  pinMode(Digit_2, OUTPUT); // Hrs Tens
  pinMode(Digit_3, OUTPUT); // Hrs Ones
  pinMode(Digit_4, OUTPUT); // Min Ones

  Serial.begin(9600);
}


void loop() {
  byte bits1 = GetBits(1) ; 
  byte bits2 = GetBits(2) ; 
  byte bits3 = GetBits(3);
  byte bits4 = GetBits(4);
  
  for (int t = 0; t < 20; t++) { // Change max value of t to speed up or slow down the amount of time between number progression
    digitalWrite(Digit_1, LOW); // Turn on the Tens
    digitalWrite(Digit_2, HIGH);
    myH1UpdateDisplay(bits1);    // display alphanumeric digit for bits1
    delay(4);
    digitalWrite(Digit_1, HIGH);
    digitalWrite(Digit_2, LOW);
    myH1UpdateDisplay(bits2);    // display alphanumeric digit for bits2
    delay(4);
    digitalWrite(Digit_2, HIGH);
    digitalWrite(Digit_3, LOW); // Turn on the Tens
    digitalWrite(Digit_4, HIGH);
    myH1UpdateDisplay(bits3);    // display alphanumeric digit for bits1
    delay(4);
    digitalWrite(Digit_3, HIGH);
    digitalWrite(Digit_4, LOW);
    myH1UpdateDisplay(bits4);    // display alphanumeric digit for bits2
    delay(4);
    digitalWrite(Digit_4, HIGH);
  }
}

void myH1UpdateDisplay(byte eightBits) {

  digitalWrite(latchPin, LOW);  // prepare shift register for data
  shiftOut(dataPin, clockPin, LSBFIRST, eightBits); // send data
  digitalWrite(latchPin, HIGH); // update display
}


byte GetBits(int someNumber) { // Maps which segments to light up for each number sent as "i" and returns the eightBits
  // which is then picked up by the function myH1UpdateDisplay which sents eightBits via the shiftOut call.
  switch (someNumber) {
    case 0:
      return B11111100;
      break;
    case 1:
      return B01100000;
      break;
    case 2:
      return B11011010;
      break;
    case 3:
      return B11110010;
      break;
    case 4:
      return B01100110;
      break;
    case 5:
      return B10110110;
      break;
    case 6:
      return B10111110;
      break;
    case 7:
      return B11100000;
      break;
    case 8:
      return B11111110;
      break;
    case 9:
      return B11110110;
      break;
  }
}

I don't understand the 'for' loop and display function. My way of thinking about this is to shift out the left digit of each display (16 bits altogether), then latch both 595s, then turn on those digits in the displays, wait, turn them off again. Then do the same for the right digits of both displays. And of course you can shift out while you're waiting. But it's not clear to me what your for loop is doing.

Also, you #include SevSeg.h, but don't use it at all.

Sounds like you've either got a wiring problem or a problem with the pins on the Arduino board. Can you try different IO pins for digits 1 and 3?

Thank you, ShermanP.

I copied this from something I found on the web. I'm having a difficult time understanding how to use shift registers so when I found something that seemed to work, I used it without fully following the logic.

Would it be taking advantage of your expertise to ask that you write the code that would accomplish what you are suggesting to me?? If this is unreasonable, I certainly understand. Perhaps I could compensate you for your time?

Regards,

Michael

Well before we get to that point, let's try to figure out what the digits are. Assuming your displays are oriented as HHMM, then these definitions:

const int Digit_1 = 11;  //  Digital Pin 11 on Arduino controls the Mins Tens Digit (Sev Seg 10)
const int Digit_2 = 12; //  Digital Pin 12 on Arduino controls the Hrs Tens Digit (Sev Seg 10)
const int Digit_3 = 9;  //  Digital Pin 9 on Arduino controls the Hrs Ones Digit (Sev Seg 5)
const int Digit_4 = 10; //  Digital Pin 10 on Arduino controls the Mins Ones Digit (Sev Seg 5)

would produce "2314" if the code works correctly. So lets first try to see why you are getting "1214". Are the digits actually wired according to the above definitions?

I double checked the connections. They are correct, but my readout is "2312".

And just to make sure I'm understanding correctly, Digit_1 connects to pin10 of SSD1, Digit_2 connects to pin 5 of SSD1, Digit_3 connects to pin 10 of SSD2 and Digit_4 connects to pin 5 of SSD2.

To avoid 'ghosting' where segments are lit when they should not be, you have to set the segments, turn on the digit, pause a bit, and turn off the digit, in that order.

for (int t = 0; t < 20; t++) { // Change max value of t to speed up or slow down the amount of time between number progression

    myH1UpdateDisplay(bits1);
    digitalWrite(Digit_1, LOW);
    delay(4);
    digitalWrite(Digit_1, HIGH);

    myH1UpdateDisplay(bits2);
    digitalWrite(Digit_2, LOW);
    delay(4);
    digitalWrite(Digit_2, HIGH);

    myH1UpdateDisplay(bits3);
    digitalWrite(Digit_3, LOW);
    delay(4);
    digitalWrite(Digit_3, HIGH);

    myH1UpdateDisplay(bits4);
    digitalWrite(Digit_4, LOW);
    delay(4);
    digitalWrite(Digit_4, HIGH);
  }

[/quote]

Thank you, johnwasser. I've corrected that, but, of course, I still do not get the output I am expecting.

ShermanP, I don't know why I'm not getting your replies. I wanted to let you know that I screwed up in my response to you because the code had changed and while my connections were correct, they were not in the code. I've corrected them and my output is "4134".

When I went to create this reply, I saw:

with no further explanation so I'm not certain what you are wanting me to try.

I won't throw any code in but I'll make these observations:

You have two LED modules. Each LED module can display two seven segment digits. Each module has its own SN74HC595. The shift registers are daisy chained. Is that all correct ?

Your numbering of the digits (Digit_1 etc.) seems odd because of way Hours and Minutes are mixed.

  pinMode(Digit_1, OUTPUT); // Mins Tens
  pinMode(Digit_2, OUTPUT); // Hrs Tens
  pinMode(Digit_3, OUTPUT); // Hrs Ones
  pinMode(Digit_4, OUTPUT); // Min Ones

It is difficult to imagine how these two displays are actually viewed. Is one above the other ?

As @ShermanP pointed out, your multiplexing is odd (if indeed you do have two shift registers).
Normally, and to maximise brightness, you'd simultaneously display 1 digit on each display. This means pushing out two digits at a time to the shift register chain.
You also save 2 arduino pins because you can join the cathodes of corresponding digits (assuming the load (mA) isn't too much, that is)

As it is, you appear to be displaying only one digit at any one time. Further, the effect you are noticing of mixed up digits is probably because, at the time you are switching on a particular digit, the matching data is not shift register belonging to that digit.

1 Like

Well, now I don't know what the code or wiring is now but I agree with the above wiring if SSD1 is hours (left display) and SSD2 is minutes (right display). But I don't know how you're getting 2312 if it's wired that way.

You might give this a try.

  for (int t = 0; t < 20; t++) { // Change max value of t to speed up or slow down the amount of time between number progression

    shiftOut(dataPin, clockPin, LSBFIRST, bits1); // send data
    shiftOut(dataPin, clockPin, LSBFIRST, bits3); // send data

    digitalWrite(Digit_2, HIGH);  // Turn off 2 and 4
    digitalWrite(Digit_4, HIGH);

    digitalWrite(latchPin, LOW);  // latch serial data to parallel out
    digitalWrite(latchPin, HIGH); // rising edge triggered

    digitalWrite(Digit_1, LOW); // Turn on 1 and 3
    digitalWrite(Digit_3, LOW); //
    delay(4);


    shiftOut(dataPin, clockPin, LSBFIRST, bits2); // send data
    shiftOut(dataPin, clockPin, LSBFIRST, bits4); // send data

    digitalWrite(Digit_1, HIGH);  // Turn off 1 and 3
    digitalWrite(Digit_3, HIGH);

    digitalWrite(latchPin, LOW);  // latch serial data to parallel out
    digitalWrite(latchPin, HIGH); // rising edge triggered

    digitalWrite(Digit_2, LOW); // Turn on 2 and 4
    digitalWrite(Digit_4, LOW); //
    delay(4);
  }

I couldn't get the code thing to work right. It got most of it, but missed the beginning and ending. Can someone explain how to make this work?

Edit: formatting fixed. Thanks 6v6gt

1 Like

Put 3 back ticks at the top of the code section. Put 3 at the bottom. Delete any groups of 3 back ticks in the middle. If your keyboard doesn’t have these, cut and paste these from elsewhere.

The </> control in the edit window should also work.

ShermanP, THANK YOU! THANK YOU! THANK YOU! That did the trick!

I obviously did not understand the output sequence of the shift registers.

6v6gt, thank you for your explanation. It makes a lot of sense to me. Yes, the hours digits are going to be mounted above the minutes digits.

Thanks again to everyone!