4″ 7-segment/Three wires, eight outputs/07. The byte behind a digit
Three wires, eight outputs · 07 of 15

The byte behind a digit

Ten bytes are the whole font. Which bit reaches which bar, what the ULN2803A does with a 1, and what one wrong word in shiftOut does to every digit.

Ten bytes and you are done

The sketch's font is one line:

const uint8_t d[] = {
  0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F
};

Index 0 is the byte for a zero, index 9 for a nine. Bit 0 is segment A, bit 1 is B, and so on up to bit 6 for G. Bit 7 is the decimal point, so d[3] | 0x80 is a 3 with a point after it.

From a number to a byte to eight bars
MSBFIRST
Digit3
Bit order in shiftOut()
Byte in the table
0x4F
Byte on the segments
0x4F
Segments lit
A B C D G
0x4F is 01001111, and each 1 is one bar. A 1 on a shift register output turns on the ULN2803A channel behind it, which sinks that segment’s current to ground; because the segments share a common anode on the 12 V side, a sink is what lights the bar. Hexadecimal is only shorthand: 0x3F and 0b00111111 are the same number.

Slide through the digits. A 1 in the byte lights that bar, and the path it takes is short: the shift register output for that bit goes to one input of U2, a ULN2803A.

What U2 does with a 1

The ULN2803A is eight transistor stages, one per segment, and each one is inverting: when its input is high it sinks current from its output pin to GND. Its output goes through a resistor (75 ohm for A to G, 510 ohm for the point) to that segment's pin on the display, and the display's other end is the common anode, on the 12 V side.

So a 1 does not push current into a segment. It completes a path: 12 V through the dimmer to the anode, through the segment, through its resistor, through U2 to GND. A 0 leaves that path open.

How much current flows in a lit segment is not in any file we have, and we did not measure it. The shape of the sum is the 12 V, minus about 1 V across U2 (the datasheet gives 1.0 V typical at 200 mA), minus the segment's own forward voltage, divided by 75 ohm. U2 is rated for 500 mA per channel, and a 3.3 V logic high is enough to switch it: its input needs at most 2.4 V at 200 mA.

The one word that ruins it

shiftOut() takes a bit order, and both spellings are valid:

shiftOut(SER, CLK, MSBFIRST, d[n]);   // bit 7 goes out first
shiftOut(SER, CLK, LSBFIRST, d[n]);   // bit 0 goes out first

This board wants MSBFIRST: the bit sent first travels furthest, to QH, which is the decimal point, and the bit sent last stays in QA, which is segment A. Send the byte the other way and every bit lands on its mirror segment.

Switch the figure to LSBFIRST. The result is not a blank display or a broken one but a different, valid pattern, sometimes another digit. That is why the mistake survives: nothing looks wrong enough to suspect one word in one call.

When it does not work

The segments light but the shapes are nonsense

Swap MSBFIRST for LSBFIRST, or the other way round. Both spellings compile, and the wrong one mirrors every byte: 0x3F becomes 0xFC, a real pattern that lights real segments and looks like a broken display rather than a bit order.

Where does 0x3F come from?

It is the six segments that draw a zero, A to F, which are bits 0 to 5. In binary that is 0b00111111, the same number. Hexadecimal is shorter to type and nothing more.

How do I add a decimal point to a digit?

Set bit 7 on top of the digit's byte: d[3] | 0x80 is a 3 with the point. 0x80 on its own is the point with no digit, and 0x00 is a blank.

Can I show a minus sign, or a letter?

A minus is segment G alone, 0x40. Work a letter out on the drawing: E is A, D, E, F and G, which are bits 0, 3, 4, 5 and 6, which is 0x79. Put 0x40 in the leftmost module of a chain and digits in the rest to write a negative number.

Why does a 1 light a segment, not a 0?

Because of U2. Its stages invert: an input that goes high makes the output sink current, and the display's other end is the common anode on the 12 V side. A table written for a different display can be the other way round. Use the table in this book as it stands.

Where this goes next

A new module with nothing on its PWM pin stays dark. Why, and the three ways to use the pin.

The PWM pad →

Edit this page — content/books/seg4/the-byte-behind-a-digit.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

4″ 7-Segment LED Display with 74HC595

Loading discussions…

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum →