Two builds and a check · 10 of 11

Show any number

Two operators pull a number apart into digits, and the loop runs backwards for a reason. What to do when the number has more digits than you have modules, because the sketch will not tell you.

Taking a number apart

A chain does not accept a number. It accepts one byte per module, so the number has to be split up first, and the two operators that do it are % and /.

Peeling digits off the right
73 across 2
Modules in the chain
The number to show73
Highest this chain holds
99
Peels done
0 of 2
Display shows
t % 10 is the rightmost digit and t / 10 throws it away. Whole-number division on an unsigned long keeps no fraction, so 73 / 10 is 7, not 7.3. Two lines and the number has been taken apart from the right.

t % 10 is the remainder after dividing by ten, which is the rightmost digit. t /= 10 divides and keeps no fraction — on an unsigned long, 73 / 10 is 7, not 7.3 — which throws that digit away. Repeat, and the number comes apart from the right.

The loop counts down through the array because the digit that comes off first is the ones digit, and the ones digit has to be the last byte sent. That is the rule from the previous article showing up in code.

The number that is too big

Set the slider above past 99 on a two-module chain. Nothing errors. The loop runs twice, takes two digits, and the rest are simply never looked at — so 1234 shows as 34 and your sketch carries on believing it displayed 1234.

That is why showNumber() in the sample returns a bool. One comparison against chainLimit() turns a silent wrong answer into something you can handle:

if (!showNumber(reading)) {
  // too wide for this chain — show an error, or scale it
}

Blank is a digit too

0x00 lights nothing, which reads as a gap rather than a nought. That gives you leading-zero suppression for free — walk the array from the left blanking zeros until you hit something else — and it gives you somewhere to put a minus sign, which is segment G on its own, 0x40.

Both cost a digit position. A two-module chain that can show a sign covers −9 to 99, and there is no arrangement of seven bars that avoids that.

The code

Show_A_Number.ino

The same wiring as the counting sketch, with one function you can call with any value. showNumber() refuses a number too wide for the chain instead of quietly truncating it.

// Show any number on chained 4" seven-segment modules with a 74HC595.
//
// Wiring, at the module's IN edge (printing towards you, IN is top left):
//   12 V supply +   -> 12V            two-pin header
//   12 V supply -   -> GND            two-pin header
//   Uno 5V          -> 3V3/5V         five-pin header
//   Uno GND         -> GND            five-pin header
//   Uno D8          -> DATAIN (SER)
//   Uno D11         -> LATCH (RCLK)
//   Uno D12         -> CLOCK (SRCLK)
//
// The 12 V supply's ground and the Uno's ground must be the same wire.
//
// 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

#define SER  8         // DATAIN (SER)
#define LAT 11         // LATCH  (RCLK)
#define CLK 12         // CLOCK  (SRCLK)

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

const uint8_t BLANK = 0x00;   // no segments
const uint8_t MINUS = 0x40;   // segment G on its own
const uint8_t POINT = 0x80;   // the decimal point

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);
}

// Highest number this chain can hold: 9, 99, 999 …
unsigned long chainLimit() {
  unsigned long limit = 1;
  for (int i = 0; i < NUM_DIGITS; i++) limit *= 10;
  return limit - 1;
}

// true if it was shown, false if the number needs more modules than you
// have. Without this check the top digits vanish and nothing says so.
bool showNumber(unsigned long value, bool leadingZeros = true) {
  if (value > chainLimit()) return false;

  uint8_t b[NUM_DIGITS];
  unsigned long t = value;
  for (int i = NUM_DIGITS - 1; i >= 0; i--) {
    b[i] = d[t % 10];       // rightmost digit of what is left
    t /= 10;                // drop it
  }

  if (!leadingZeros) {      // blank the noughts in front of the number
    for (int i = 0; i < NUM_DIGITS - 1 && b[i] == d[0]; i++) b[i] = BLANK;
  }

  updateDisplay(b);
  return true;
}

void blank() {
  uint8_t b[NUM_DIGITS];
  for (int i = 0; i < NUM_DIGITS; i++) b[i] = BLANK;
  updateDisplay(b);
}

void setup() {
  pinMode(SER, OUTPUT);
  pinMode(LAT, OUTPUT);
  pinMode(CLK, OUTPUT);
  blank();

  if (!showNumber(42, false)) blank();   // 42 on a two-module chain
}

void loop() {
  // nothing: the display holds what it was last given
}

blank() and showNumber() are the two you will keep. Everything else is the same table and the same three-line update.

When it does not work

A big number shows its last digits only

That is the failure this sketch's return value exists to catch. The peeling loop runs once per module and stops, so 1234 on a two-module chain shows 34 and nothing reports a problem. Check the value against chainLimit() before you send it.

Leading zeros look wrong on a clock

Pass false for leadingZeros and the noughts in front of the number become blanks instead. For a clock you usually want the opposite — 09:05 reads better than 9:5 — so leave it true for the minutes and decide for the hours.

How do I show a negative number?

Put MINUS in the leftmost slot and the digits in the rest, which costs you one module's worth of range: a two-module chain shows -9 to 99. There is no other way round it, because a minus sign needs a digit position to live in.

The display keeps the old number when the sketch resets

It would. The output register holds its contents until something latches new ones into it, and a board reset does not touch the module. Call blank() at the top of setup() so a restart always clears what was there.

Where this goes next

Five symptoms, and the one measurement that settles each of them before you rewire anything.

When nothing lights

Edit this page — content/books/4-inch-7-segment/show-any-number.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