by Floris Wouterlood – March 27, 2020
Introduction
Seven-segment led displays have conquered the world: my fridge has one, and so do my radio alarm clock, microwave oven, TV, stereo set, set top box, induction cooking plate, car, anything that seems to be fit to accommodate these useful and often superfluous devices. They are cheap and they provide high visual contrast. And sometimes they are frightening! As a child I was fascinated by James Bond movies featuring evil things like digital display-equipped bombs or missiles that, without intervention by James in person, would tick away the time separating the civilized world from Armageddon.
The common countdown counter is based on 7-segment technology that went viral in the 1970’s because 7-segment displays provided output in the at the time immensely popular cheap Japanese hand held calculators.
In a previous contribution* I have discussed how to connect a 4-digit 7-segment display to an Arduino. These 4-digit devices are usually controlled by a TM1637 chip. Counting down on 4-digit devices is limited to numbers between 9999 and 0, maybe sufficient for a flash scene in a James Bond movie but insufficient in many other applications. To accommodate larger numbers the market supplies breakout boards for the Arduino that consist of two 4-digit 7-segment displays ‘in series’ (figure 1). With such a breakout we can count down from 99,999,999 to zero, that is almost 100 million ticks. These displays are controlled by an old acquaintance: the MAX7219 chip. How to connect these devices to an Arduino is the subject of this paper.
Two sketches are provided: one demo sketch displaying the word ‘Arduino’ and one that counts down from 99999999 to zero in 100 msec decrements.
Figure 1: Front and side views of a breakout board with two four-digit 7-segment led displays. A MAX7219 is mounted on the back of the breakout board. Pins are available to connect the breakout board with a next one. This board is 3.3 – 5V compatible.
Short excursion into 7-segment led display technology
Figure 2: Basics of 7-segment display technology.
A 7-segment display is just a stencil showing eight segments, each with a led behind it. Segments are identified with letters: ‘a’ through ‘g’ and ‘DP’ for the dot. It is amazing that seven leds can be used to display any number between 0 and 9 and, in addition, several letters of the alphabet. That an eight led is available to generate a decimal point is even more attractive. The on-off state of eight leds can be controlled with one byte of information. That, and the robustness and low energy consumption of leds makes the 7-segment display interesting as application in an Arduino project. The numerical display can be tweaked to display characters, for instance the ‘A’ in ‘Arduino’ is generated by illuminating all segments except segment ‘d’. With some customization the word ‘Arduino’ can be generated on the display.
Wiring the eight-digit 7-segment display breakout board – power considerations
As can be seen in figure 3 the device needs on its VCC pin a 3.3V or 5V power supply, and it needs GND. The current that Arduinos can provide on their 5V pin is limited to 400 mA. Notice that an eight-digit device may have as much as 56 segments and eight dots. One display therefore contains 64 leds. If one segment would draw the same power as a conventional two-pin led (15 mA), total power consumption while displaying the number ‘8888 8888’ together with all the dots would be a staggering 960 mA. This would clearly overload a poor Arduino and cause the brave microprocessor to fail. As my 8-digit led display arrived without documentation of its power consumption, I tested current running through the 5V wire with an (uncalibrated) multimeter. Immediately after upload of the sketch ‘2x7_seg_MAX7219_countdown.ino’ to the Arduino the meter reported 69 mA. In full operation (continuous display of the number 8888 8888; no dots) current use was 27 mA. This remarkably low power consumption of the MAX9217 eight-digit 7-segment display compared with a row of conventional leds suggests extreme multiplexing by the controller chip. OLED displays and E-paper displays are said to be much less power hungry than 7-segment led displays.
Figure 3: Wiring diagram. Here pins D7, D8 and D9 of an Arduino Nano are connected with pins CS, DIN and CLK, respectively, of the display breakout board. VCC and GND complete the wiring. Pin selection is not critical, provided that pin numbers are declared in the ‘constructor’ section in the sketch.
Pin connectivity with an Arduino
Pins VCC and GND of the display are reserved for power. The other pins: DIN, CS and CLK subserve the logic.
In the wiring diagram of figure 3, pin DIN (data in) receives signal from Arduino pin 8, CS is connected with Arduino pin 7 and CLK with Arduino pin 9. Selection of these pins is not hardware determined: one can take any other digital pin provided that the LedControl ‘constructor’; in the sketch is adapted likewise.
For instance: in the configuration in figure 3 the constructor should list as follows:
LedControl seg71 = LedControl (8,9,7,1);
where seg71 is the designation of the display while the numbers in between the brackets correspond with DIN, CLK, CS and the number of displays connected. If a second breakout board is wired in series, the last number in the constructor should be ‘2’.
Demo sketch for testing the display: the word ‘Arduino’
A basic sketch that brings the 8 digit 7-segment display to life (and no more than that) by displaying the text ‘Arduino’ is discussed here: 2x7_seg_MAX7219_displays_Arduino.ino.
Once the pins of the display breakout board are connected with the proper pins of the Arduino and connectivity has been double checked, the Arduino is connected to a computer and the following sketch is compiled and uploaded.
// 2x7_seg_MAX7219_displays_Arduino.ino
//
// controls a 8 digit 7-segments led display unit with MAX7219 controller
// March 18, 2020
// original author of most stuff: Nicola Bernardelli – 2019-06-22
The sketch starts with reference to a library. This library is supplied with the Arduino IDE, so don’t worry about starting a search on the internet to download it.
// libraries
#include <LedControl.h>
Next we have to instruct the Arduino which of its interface pins are connected with the display and we have to define the display with the LedControl ‘constructor’.
#define DIN 8 // DIN to pin 8 of Nano
#define CLK 9 // CLK to pin 9 of Nano
#define CS 7 // CS to pin 7 of Nano
LedControl seg71 = LedControl (DIN,CLK,CS); // constructor for the 2×4 7-segment led display unit
Next comes the setup section of the sketch:
void setup () {
seg71.shutdown (0,false); // wakeup MAX7219
seg71.setIntensity (0,6); // between 0 and 15
seg71.clearDisplay (0);
writeArduino ();
}
This group of instructions tells the MAX2719 to wake up because the chip is in power saving mode (say: dark) at startup. The intensity of the leds can be controlled with the setIntensity instruction. The first number here indicates how many displays there are (the first display is number 0) while the second number is the intensity index. This number should be conveniently between 0 (lowest intensity) and 15 (highest intensity).
writeArduino (); refers to the subroutine that contains the instructions for every digit of the display to activate a particular set of its led segments.
The section ‘loop’ is empty because the word ‘Arduino’ will be displayed permanently. ‘setup’ contains all the instructions to achieve this.
void loop() {
}
After the ‘loop’ section a subroutine is placed that does the actual work: printing the word “Arduino” on the display. The configuration of a single 7-segment display unit allows only a few alphabetical characters to be displayed. These are A, b, c, C, d, E, F, g, H, h, I, i, J, L, n, O, o, P, p, r, S, t, U, u and Y. Of these characters, A,b,c,d, E,F, H, L, P are programmed in the ledControl library and can be called from the library. This would make the word “A.d….”. The unavailable characters must be ‘constructed’ by lighting up their corresponding segments of the display unit. This is done through calling their hexadecimal representation value: 0x00 to 0x0F. These hexadecimals code for the led segment configuration corresponding with the requested character. For instance, the numbers 0 through 9 are represented as follows:
The subroutine ‘writeArduino’ can be written in several ways: as a mix of library characters (‘setChar’) and hexadecimal calls to character-specific segment configurations (’setRow’), or as a series of ‘setRow’s. Here the mix is used:
void writeArduino () {
seg71.setChar (0, 6, ‘a’, false); // A – taken from library
seg71.setRow (0, 5, 0x05); // r
seg71.setChar (0, 4, ‘d’, false); // d – taken from library
seg71.setRow (0, 3, 0x1c); // u
seg71.setRow (0, 2, 0x10); // i
seg71.setRow (0, 1, 0x15); // n
seg71.setRow (0, 0, 0x1D); // o
}
In each instruction the first parameter within the brackets represents the display, the second the unit in the 8-digit display that must be activated (notice that the most right unit is labeled ‘0’, the neighbor to the left is ‘1’ and so forth), and the third parameter is either the library character (followed with ‘false’) or the hexadecimal custom character. Notice that the word “Arduino” is built up right to left, in fact “oniudrA”. If you want a period at the end, replace
seg71.setRow (0, 0, 0x1D); // o
with the instruction that displays the custom character together with the dot:
seg71.setRow (0, 0, 0x9D); // o.
Counting Down à la James Bond
The ‘James Bond’ type countdown counter sketch is quite simple. The number to start with is defined as well as the amount of milliseconds that each tick of the clock lasts. Countdown can thus be made faster or slower. After declaring the variables the display is initialized and starts counting in the ‘loop’ section. A subroutine is called that updates the timer. The declared variables are extended size variables of the ‘unsigned long’ class, that is, positive numbers from 0 to 4,294,967,295 (4 bytes memory allocation).
The variables ‘counter’ and ‘tickTime’ define the start number and the counting pace.
// 2x7_seg_MAX7219_countdown.ino
#include <LedControl.h>
unsigned long counter = 99999999; // initial value for countdown
unsigned long nextTick; // time to update counter
int tickTime = 100; // modify decrement time here – in milliseconds
LedControl lc = LedControl (8,9,7,1); // Arduino pins – DIN, CLK, CS, one devices
‘setup’ contains the necessary instructions to start the display and to provide the first tick of the counter
void setup(){
// Initialize the MAX7219 device
lc.shutdown (0, false); // wake up display
lc.setIntensity (0, 6); // set brightness level (0 to 15)
lc.clearDisplay (0); // clear display register
nextTick = millis(); // first tick will happen right away
}
‘loop’ does the ticking and sends the result to the subroutine ‘printNum’ that handles the display:
void loop(){
if( millis() >= nextTick) // if it’s time to update counter
{
if ( counter >= 0 ) // if there are any time units left
{
lc.clearDisplay (0); // clear display
printNum (counter); // write next number
counter–; // decrement counter
}
nextTick = millis() + tickTime; // tick time in millis
}
}
// ======= subroutine ===========================
void printNum (unsigned long num) { // handle the 8-number display
unsigned long dig = 1;
unsigned long digCnt = 0;
if( num > 0 ) // if number is greater than zero
{
while ( num >= dig ) // count # of digits
{
dig *= 10;
digCnt++;
}
for(int d=0, dig=10; d < digCnt; d++) // while more digits
{
lc.setDigit(0,d,byte(num%10),false); // write this digit
num /= 10; // writing from right to left
}
}
else
{
lc.setDigit(0,0,(byte)0,false); // just write a zero
}
}
Figure 4: The ‘James Bond’ countdown counter in action.
Discussion
In this paper we have connected a eight-digit, 7-segment led display to an Arduino, discussed the sketch necessary to bring the display to life. Then we created a ‘James Bond’ type countdown counter.
This kind of display is easy to implement in hardware because it requires only three pins of the Arduino which can be any of the available pins. Pins are assigned in software via the constructor together with the <LedControl.h> library. This is quite different from TM1637 controlled 4-digit led displays which run under the I2C protocol and the <TM3637.h> library.
The possibilities to combine this display with sensors are numerous: counter, speed, current, voltage, temperature, pressure, altitude, humidity, etcetera. Limitation is that these are numerical displays with very limited possibility to display characters. The older among may remember alphanumerical tricks that could be played on the old hand calculators.
Sketches
2x7_seg_MAX7219_displays_Arduino.ino
2x7_seg_MAX7219_countdown.ino
(these sketches are zip-ped)
Other contributions on 7-segment displays
*Floris Wouterlood: Four digit, 7-segment led display for Arduino based on the TM1637 driver