Count from 00 to 99
Two modules, six signal wires, a 12 V supply and one short sketch. What each part of it does, the pad that has to be dealt with before anything shows, and the one number worth changing while you test the wiring.
What you need
Two modules joined at the seam, a 12 V supply on the two-pin header, and these wires from an Uno to the first module's IN edge. The holes are on the back, the face with the white printing; if any of it is unfamiliar, the wiring is in the article on the two edges.
| Uno | Module, IN edge |
|---|---|
| 5V | 3V3/5V |
| GND | GND (and the 12 V supply's negative lead to the same wire) |
| D8 | DATAIN (SER) |
| D11 | LATCH (RCLK) |
| D12 | CLOCK (SRCLK) |
| D9 | PWM, or nothing if the PWM pad is soldered shut |

The pad, before anything else
The shift register can be loaded perfectly and the digit will still be dark if
nothing powers the display, and on this board that is the PWM pad's job. It ships
open. Either wire D9 to PWM and leave PWM_PIN at 9, so setup() drives it
high, or solder the pad shut and set PWM_PIN to -1. Do one, not both: with the
pad shorted, PWM is tied to the logic rail and a pin driving it would be
fighting that.
The control at the foot of the figure is that pad. With it open the register holds the count and the sweep takes the same time, and you see nothing.
The one number worth changing
STEP_MS is the delay between numbers, and it is the only thing in this sketch
that decides how long anything takes. The bits themselves go out in
microseconds.
At 400 ms a two-module chain needs forty seconds to get all the way round, and for most of that it looks like a display showing a number rather than a display counting. Turn it down to 100 while you are checking the wiring, and back up when you want to read it.
How it works, in four pieces
The table. Ten bytes, one per digit, exactly as in the byte behind a digit.
updateDisplay. Latch low, one shiftOut per module, latch high. Every
digit changes at the same instant, and it is the same three lines whether the
chain is one module or six.
The limit. limit is worked out from NUM_DIGITS rather than typed in, so
changing the module count changes what the sketch counts to and nothing else
needs touching.
The peel. t % 10 takes the rightmost digit off the number and t /= 10
throws it away, filling b[] from the right. That is the
next article.
Blanking at start-up
setup() writes 0x00 to every module before anything else. A shift register
can come up holding anything, so without that line the display may show a
random pattern until the first count arrives, which looks, for a moment, exactly
like a fault.
The code
Set NUM_DIGITS to the number of modules you have joined together. One counts 0 to 9, two count 00 to 99, three count 000 to 999.
// Count 00 to 99 on chained 4" seven-segment modules with a 74HC595.
//
// Wiring, at the module's IN edge (reading the back, IN is on the left):
// 12 V supply + -> 12V two-pin header
// 12 V supply - -> GND two-pin header
// Uno 5V -> 3V3/5V six-pin header
// Uno GND -> GND six-pin header
// Uno D8 -> DATAIN (SER)
// Uno D11 -> LATCH (RCLK)
// Uno D12 -> CLOCK (SRCLK)
// Uno D9 -> PWM or leave PWM empty and solder the
// PWM pad shut (then PWM_PIN is -1)
//
// The board ships with the PWM pad OPEN. With nothing on PWM the digit
// has no supply and stays dark, whatever this sketch sends.
//
// The 12 V supply's ground and the Uno's ground must be the same wire.
// For a second module, join all eight pins of the first module's OUT edge
// to the second module's IN edge (its DATAOUT goes to DATAIN).
//
// Arduino IDE: Tools > Board > Arduino AVR Boards > Arduino Uno, then
// Tools > Port and pick the port the board appears on. No libraries.
#define NUM_DIGITS 2 // how many modules are joined together
#define SER 8 // DATAIN (SER)
#define LAT 11 // LATCH (RCLK)
#define CLK 12 // CLOCK (SRCLK)
#define PWM_PIN 9 // PWM; use -1 if you shorted the PWM pad instead
#define STEP_MS 400 // how long each number stays on screen
// One byte per digit. Bit 0 is segment A, bit 6 is G, bit 7 is the point.
const uint8_t d[] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F
};
// buf[0] is the leftmost digit. It goes out first, so it travels furthest
// down the chain and ends up in the module at the far end.
void updateDisplay(const uint8_t *buf) {
digitalWrite(LAT, LOW);
for (int i = 0; i < NUM_DIGITS; i++)
shiftOut(SER, CLK, MSBFIRST, buf[i]);
digitalWrite(LAT, HIGH);
}
void setup() {
pinMode(SER, OUTPUT);
pinMode(LAT, OUTPUT);
pinMode(CLK, OUTPUT);
if (PWM_PIN >= 0) {
pinMode(PWM_PIN, OUTPUT);
digitalWrite(PWM_PIN, HIGH); // high = the digit is supplied
}
uint8_t blank[NUM_DIGITS];
for (int i = 0; i < NUM_DIGITS; i++) blank[i] = 0x00;
updateDisplay(blank); // a register powers up holding anything
}
void loop() {
uint8_t b[NUM_DIGITS];
unsigned long limit = 1;
for (int i = 0; i < NUM_DIGITS; i++) limit *= 10;
limit -= 1; // 9, 99, 999 …
for (unsigned long n = 0; n <= limit; n++) {
unsigned long t = n;
for (int i = NUM_DIGITS - 1; i >= 0; i--) {
b[i] = d[t % 10]; // the rightmost digit of what is left
t /= 10; // drop it
}
updateDisplay(b);
delay(STEP_MS);
}
}Nothing here needs a library. shiftOut() is part of the Arduino core, and the four pins are ordinary digital outputs, so change them to suit your board. If you shorted the PWM pad, set PWM_PIN to -1 so the sketch does not drive a wire that is already held high.
When it does not work
Check the PWM pad first. The board ships with it open, so with nothing on PWM the digit has no supply whatever the sketch sends. Wire PWM to D9 with PWM_PIN 9, or solder the pad shut and set PWM_PIN to -1. Only then measure 12 V at the module's 12V pin with the black probe on the Uno's GND.
The inner loop has been rewritten to count upwards. It has to count down: the ones digit goes into the last slot of b[] because the last byte sent stays in the module nearest the Uno.
Either NUM_DIGITS is still 1, or the join between the two boards is not made. The sketch sends exactly NUM_DIGITS bytes, so a chain longer than that number never receives anything for its far end. Check DATAOUT to DATAIN with a continuity test, power off.
Change STEP_MS. At the 400 milliseconds it ships with, a two-module chain takes forty seconds to get from 00 back to 00, and most of that is spent looking at a display that appears not to be doing anything.
A PWM pad is soldered shut, on this module or on another in the chain. It ties the whole chain's PWM net to the logic rail, so the digits are full on and a pin wired to PWM is fighting a wire that is held high. Desolder the bridge before you drive PWM from a pin.
Pulling a number apart with two operators, and what happens when it has more digits than you have modules.
Show any number →Edit this page — content/books/seg4/count-from-00-to-99.mdx
Questions about this product
See what other owners have asked, and read their solutions.
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.