4-digit 7 Segment LED displaying numbers in the wrong order I am a novice Arduino programmer and am currently having trouble with a SH5461AS 4-digit/7-segment LED when using it with an Arduino Uno. I have struggled to find an accurate datasheet/tutorial of any kind for this particular model (It is the LED without the colons in between digits 2 and 3) but I believe I have it figured out.

I currently have it going through a HC595 shift register but when I removed the register and connected the LED directly to the board the problem remained. My code below is with the shift register; I am displaying it this way because it is simpler to view and I thought it would make it easier to debug.

I can display a single digit at a time correctly. However, when I try to display 2+ digits at one time, they are in the incorrect order.
For example, I can count 1-9 on the first digit, then 1-9 on the 2nd digit, and so on and everything displays correctly (other digits are off). But as soon as I try to display multiple digits they are in the wrong order. So if I try to display 12__ with the last 2 digits off, 21__ is displayed with the last two digits off. If I try to display 23, 32 is displayed. If I try to display 1234, 4123 is displayed.

I am at a loss because the code seems like it should be simple.

const int DATA = 0;
const int LATCH = 1;
const int CLOCK = 2;

const int DIGIT_ONE = 3;
const int DIGIT_TWO = 4;
const int DIGIT_THREE = 5;
const int DIGIT_FOUR = 6;

//digits[0-9] corresponds to the patterns for numbers 0 -&gt; 9.
//Add 1 to the digits[X] to turn on the dot.
byte digits[] = {B11111100, B00011000, B01101110, B00111110, B10011010, B10110110, B11110010, B00011100, B11111110, B10111110};

void setup() {
  pinMode(DATA, OUTPUT);
  pinMode(CLOCK, OUTPUT);
  pinMode(LATCH, OUTPUT);

  pinMode(DIGIT_ONE, OUTPUT);
  pinMode(DIGIT_TWO, OUTPUT);
  pinMode(DIGIT_THREE, OUTPUT);
  pinMode(DIGIT_FOUR, OUTPUT);

  digitalWrite(DIGIT_ONE, HIGH);
  digitalWrite(DIGIT_TWO, HIGH);
  digitalWrite(DIGIT_THREE, HIGH);
  digitalWrite(DIGIT_FOUR, HIGH);
}

void loop() {
  writeDigit(DIGIT_TWO, 2);
  writeDigit(DIGIT_THREE, 3);
}

/*
 * Write a digit to the 4-digit 7-segment LED
 * - digitPin corresponding to the pin on the LED to light up the correct digit.
 * - number 0-9 to display on the LED
 */
void writeDigit(int digitPin, int number) {
  digitalWrite(digitPin, LOW);

  digitalWrite(LATCH, LOW);
  shiftOut(DATA, CLOCK, LSBFIRST, digits[number]);
  digitalWrite(LATCH, HIGH);

  digitalWrite(digitPin, HIGH);
}


So in this instance, I am expecting 23 but 32 is displaying instead.

I am also having trouble with some bleeding (I don't know what the correct term is) where some segments are very faintly glowing even though I am not doing it intentionally. This is a much smaller issue, however, than digits randomly in the wrong order.

If it would help, I can try to post the circuit diagram as well.
Here is a datasheet I found that seems a better macth for your display model (that's the datasheet for a display that I use):

http://www.play-zone.ch/en/fileuploader/download/download/?d=1&amp;file=custom%2Fupload%2FFile-1356269320.pdf

This is the datasheet I directly got from my local supplier.

According to what you say, the problem does not seem to be a wiring problem.

It looks more like a timing issue:

void writeDigit(int digitPin, int number) {
  digitalWrite(digitPin, LOW);

  digitalWrite(LATCH, LOW);
  shiftOut(DATA, CLOCK, LSBFIRST, digits[number]);
  digitalWrite(LATCH, HIGH);

  digitalWrite(digitPin, HIGH);
}


The first issue when you call writeDigit() is that it forces the cathod low BEFORE having set the shift register, so the digit will first show the current register value, i.e. the one from the previous call to writeDigit().

Then it pushes the new value for the segments on the shift register, that will be fast but not as fast as two consecutive calls to loop().

If we try to roll and expand the loop() call in your example that will be:

// First call: writeDigit(DIGIT_TWO, 2)
  digitalWrite(DIGIT_TWO, LOW);
  digitalWrite(LATCH, LOW);
  shiftOut(DATA, CLOCK, LSBFIRST, digits[2]);
  digitalWrite(LATCH, HIGH);
  digitalWrite(DIGIT_TWO, HIGH);

// Second call: writeDigit(DIGIT_THREE, 3)
  digitalWrite(DIGIT_THREE, LOW);
  digitalWrite(LATCH, LOW);
  shiftOut(DATA, CLOCK, LSBFIRST, digits[3]);
  digitalWrite(LATCH, HIGH);
  digitalWrite(DIGIT_THREE, HIGH);


The calls to loop() and writeDigit() are negligible in terms of timing here.

In the sequence above, most of the time is spent in:

  shiftOut(DATA, CLOCK, LSBFIRST, digits[2]);
  shiftOut(DATA, CLOCK, LSBFIRST, digits[3]);


So that means your function will:


show the previous value on the new digit for t1 us
show the new value of the new digit for t2 us


with t1 &gt;&gt; t2, hence your eyes will see the opposite of your intent!

To fix that issue you definitely need to introduce some delay to reverse what your eyes will see:

void writeDigit(int digitPin, int number) {
  digitalWrite(LATCH, LOW);
  shiftOut(DATA, CLOCK, LSBFIRST, digits[number]);
  digitalWrite(LATCH, HIGH);
  digitalWrite(digitPin, LOW);
  delayMicroseconds(100);    
  digitalWrite(digitPin, HIGH);
}


In the code above:


no digit shows while the shift register is set
the requested digit shows immediately after the shift registry has been written and lacthed, and for a duration of 100us, which will be much longer than the rest of the time.


That code should also get rid of the "bleeding" you observed.