2

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 -> 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.

3

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&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:

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

with t1 >> 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.

  • Excellent, detailed answer; thank you! I will try that when I get home to see if it fixes it. – Daniel Bickler Sep 17 '14 at 17:59
1

I found the data sheet here:

https://www.sparkfun.com/datasheets/Components/LED/7-Segment/YSD-439AK2B-35.pdf.

It's a horrible bit of writing. Not at all clear.

It looks like it's multiplexed. You use pins 14, 16, 13, 3, 5, 11, 15, and 7 as the cathodes for the segments on a digit (ground the pins for the segments you want to light.) Pin 7 appears to be the decimal place for a given digit.

One of the pins 1, 2, 6, or 8 should be fed a +5V to light a particular digit.

The other pins control the colons and other dots on the display. Let's ignore those.

To light the display here's what I THINK you would do (I'm tired, and didn't study the data sheet that closely, so I may may be wrong here)

For pins 14, 16, 13, 3, 5, 11, 15, and 7: These are the cathodes for the segments in the current digit you are driving. Set the pins you want to light as digital outputs, LOW. Set the others as inputs, which will make them essentially open circuits. The selected pins will be grounded, and the ones set as inputs will not be connected to anything.

Pull pin 1 HIGH to light the selected segments in digit 1. Put it back low, set the segment pins, then pull pin 2 HIGH to light that digit. Repeat, pulling pins 6 and 8 high to light the selected segments in digits 3 and 4.

You'd have to cycle rapidly through the digits, lighting 1 at a time, in order to make them appear all lit at once.

Get that working first without using shift registers. (It will take 11 I/O lines to drive all 4 digits and their decimal places - 1 less if you don't care about the decimal place.)

I think that if your drive all the pins using a shift register then some of the unlit segments will be fed reverse voltage. (When set as an output, sending a LOW connects the output pin to ground, and setting it high drives it to 5V. With all the control pins driven from outputs of a shift register, the off segments will have 5 volts on them, and the off digit select pins will have ground on them.)

  • That datasheet does not match the OP descriprion, it has a : in the middle. – jfpoilpret Sep 17 '14 at 4:38
  • Yup. I assumed it was a variation on the same item. – Duncan C Sep 17 '14 at 11:15
  • It is much more than a simple variation: the one used by OP is common cathode, while yours is common anode! – jfpoilpret Sep 18 '14 at 21:02
  • @jfpoilpret, it sounds like you found the correct data sheet. Why not post either the correct data sheet or an assessment similar to mine based on the specs for the correct display. – Duncan C Sep 19 '14 at 0:07
  • Well I guess the OP already understood how to use his display, so it was not necessary IMO to detail further the specs. As I said in my answer the main problem is in the code not the wiring. – jfpoilpret Sep 19 '14 at 4:34
1

I don't have enough reputation to add a comment, but the datasheet link in @jfpoilpret is dead. This link has the datasheet from the same website.

Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.