74HC595 digit/Using it/08. Count 0 to 9
Using it · 08 of 9

Count 0 to 9

Five wires and a sketch that counts from 0 to 9, a second each, with no library: shiftOut and a ten-byte table. The same sketch runs on an Uno, an ESP32 or an ESP32-S3, and there is a MicroPython version for the ESP32s and the Pico.

Five wires

Five wires
Your board
VCC to
5V
LATCH, CLOCK, DATA
D8, D12, D11
HIGH must reach
3.50 V
GND to GND, VCC to 5V, LATCH to D8, CLOCK to D12, DATA to D11, and nothing on NC. Any three digital pins would do; these are the ones the sketch names. At 5 V the chip wants 3.5 V for a HIGH, and an Uno's pins give about 5 V.

GND to GND. VCC to your board's logic supply: 5V on an Uno, 3V3 on the others. Then the three signals:

Your boardLATCHCLOCKDATA
Arduino UnoD8D12D11
ESP32GPIO 27GPIO 26GPIO 25
ESP32-S3GPIO 6GPIO 5GPIO 4
Raspberry Pi PicoGP2GP3GP4

NC gets no wire. Any three free outputs would do; these are the ones the sketches name, and they are free at boot on each board.

The sketch

show() does the three steps from Shift, then latch: LATCH low, shiftOut with MSBFIRST, LATCH high. DIGITS is the table from One byte, one digit. setup() sends 0 to blank the digit, since nothing else clears it at power-up, and loop() shows 0 to 9, a second each, then the dot alone.

What you should see

The digit counts 0, 1, 2 up to 9, then shows only its dot for a second, and starts again. At 115200 the serial monitor prints each digit and its byte:

0  0x3F
1  0x6
2  0x5B
The TK53 on a LEGO baseplate, wired to an Uno by a five-wire cable, counting.

If the shapes are wrong but steady, see Which bit goes first.

The code

No library to install: shiftOut is built into every Arduino core. show() is the whole conversation with the chip: LATCH low, eight bits, LATCH high. Change only the three pin numbers if your board is not an Uno.

hc595_segment_led.ino
/*
  74HC595 Segment LED - count 0 to 9                  TK53 / /p/tk53

  Wiring. Count from pin 1, printed GND-1 on the TinkerBlock board
  (this board has no square pad), digit up, header at the bottom:

    GND   -> GND
    VCC   -> your board's logic supply: 5V on an Uno, 3V3 on an
             ESP32, ESP32-S3 or Pico. At 5V the chip may not read
             a 3.3 V board's HIGH, so never 5V beside a 3.3 V board.
    NC    -> nothing   (unconnected on the board)
    LATCH -> D8 on an Uno, GPIO 27 on an ESP32, GPIO 6 on an
             ESP32-S3, GP2 on a Raspberry Pi Pico
    CLOCK -> D12 on an Uno, GPIO 26 on an ESP32, GPIO 5 on an
             ESP32-S3, GP3 on a Raspberry Pi Pico
    DATA  -> D11 on an Uno, GPIO 25 on an ESP32, GPIO 4 on an
             ESP32-S3, GP4 on a Raspberry Pi Pico

  Arduino IDE
    Tools > Board            your board, e.g. Arduino Uno
    Tools > Port             the one that appears when you plug in
    Tools > USB CDC On Boot  Enabled   (ESP32-S3 only)
    No library to install: shiftOut is built in.
    Serial Monitor at 115200.
*/

// The pins LATCH, CLOCK and DATA are wired to. These are the Uno's.
// ESP32: 27, 26, 25. ESP32-S3: 6, 5, 4. Pico: 2, 3, 4.
const int LATCH_PIN = 8;
const int CLOCK_PIN = 12;
const int DATA_PIN = 11;

// One byte per digit. Bit 0 is segment a (QA) and bit 7 the
// decimal point (QH). The digit is common cathode: a 1 lights.
const byte DIGITS[10] = {
  0b00111111,  // 0
  0b00000110,  // 1
  0b01011011,  // 2
  0b01001111,  // 3
  0b01100110,  // 4
  0b01101101,  // 5
  0b01111101,  // 6
  0b00000111,  // 7
  0b01111111,  // 8
  0b01101111,  // 9
};
const byte DOT = 0b10000000;   // the decimal point, QH

// Eight bits in, then one latch: the digit changes all at once.
void show(byte pattern) {
  digitalWrite(LATCH_PIN, LOW);
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, pattern);
  digitalWrite(LATCH_PIN, HIGH);         // the rising edge shows it
}

void setup() {
  Serial.begin(115200);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
  show(0);                               // blank
}

void loop() {
  for (int n = 0; n < 10; n++) {
    show(DIGITS[n]);
    Serial.print(n);
    Serial.print("  0x");
    Serial.println(DIGITS[n], HEX);
    delay(1000);
  }
  show(DOT);                             // a dot between rounds
  delay(1000);
}

The table is common cathode, a 1 lights, with segment a in bit 0 and the dot in bit 7, which is why shiftOut sends MSBFIRST. The Serial lines are only there so you can see which byte is on the digit.

View on GitHub · blocks/tk53-hc595-segment-led/arduino/hc595_segment_led/hc595_segment_led.ino @ v1.2

When it does not work

Nothing lights.

Check GND and VCC first, counting from GND-1 on the left. Then check LATCH goes to the pin the sketch names: until LATCH rises, the digit never changes. On an ESP32-S3, upload with the board's USB port selected.

It resets or never starts on my ESP32.

The sketch's pin numbers are the Uno's, and GPIO 11 and 12 on an ESP32 are not free: 11 runs the flash. Change the three numbers to 27, 26 and 25, as the comment above them says.

The serial monitor stays empty on my ESP32-S3.

Set Tools > USB CDC On Boot to Enabled and upload again. Without it the S3's USB port brings up no serial port at boot. The digit counts either way.

It counts, but the shapes are wrong.

Check the shiftOut line says MSBFIRST and the table is the one in the sketch. A table from another tutorial is often common anode or written in the other bit order.

Where this goes next

Dark, mirrored, inverted, random and dim: what each one means.

When the digit is wrong →

Edit this page — content/books/hc595-segment-led/count-zero-to-nine.mdx

Community

Questions about this product

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

Ask a question ↗

74HC595 Segment LED

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 →