Using the E40561 4 digit 7 segment common anode LED display

This page contains information that has been gathered together to aid in using the common anode version of the E40561 display. The information is grouped into two main sections:

  1. Pin-out: Information about the organisation of the display’s 36 pins.
  2. Circuit & Code: A circuit and associated C code that can be used to multiplex the display using a microcontroller.

The display I used to test this information was the E40561-G-UR3-0-W. The information should also apply to other common anode dislays in this series.

Pin-out

Information on the pinout of the E40561 is relatively hard to find, and a little inpenetrable when you do find it. This section summarises information that I have gleaned from several sources. It has been tested on two examples of the E40561-G-UR3-0-W display.

Identifying the parts of the display

The image below shows the 4 digits and the segments of each digit labelled A..G and dp (decimal point).

Labelling of LED segments

Using this information we can reference each segment of each digit as XY where X is the digit number and Y is the segment identifier. For example:

  • 1A is segment A of digit 1
  • 4G is segment G of digit 4
  • 3dp is the decimal point of digit 3

The display pinout

The display has 36 pins. We’ll treat the bottom of the display to be the side adjacent to the decimal point segments and the top to be the opposite side.

Pins 1 to 18 are arranged in ascending order along the bottom edge, from left to right, so that pin 1 is on the left and pin 18 is on the right. Pins 19 to 36 are arranged in ascending order, from right to left, along the top edge, with pin 19 on the right (above pin 18) and pin 36 on the left (above pin 1). The figure below should clarify:

Pinout illustration

On the displays I have, the part number is printed on the bottom side of the display.

Map of LED digits & segments to pins

This section describes which pins control each segment of each digit.

Since the display is common anode, there is only one anode pin per digit. These are as follows:

Digit 1 2 3 4
Pin # 32 31 23 22

There is a cathode pin for every LED segment. These are as follows:

Segment Digit
1 2 3 4
A 34 29 25 20
B 33 28 24 19
C 3 8 12 17
D 2 6 11 15
E 1 5 10 14
F 36 30 27 21
G 35 7 26 16
dp 4 9 13 18

Map of pins to LED digits & segments

The following table details the function of each pin:

Pin # Segment / Digit Anode or Cathode
(⊕ or ⊖)
1 1E
2 1D
3 1C
4 1dp
5 2E
6 2D
7 2G
8 2C
9 2dp
10 3E
11 3D
12 3C
13 3dp
14 4E
15 4D
16 4G
17 4C
18 4dp
19 4B
20 4A
21 4F
22 4
23 3
24 3B
25 3A
26 3G
27 3F
28 2B
29 2A
30 2F
31 2
32 1
33 1B
34 1A
35 1G
36 1F

Circuit & Code

With 36 pins it is unrealistic to expect to connect the display to a microcontroller directly. Some kind of multiplexing will be required.

In this section I present a sample circuit and associated source code that performs such multiplexing.

Circuit Design

So that we can multiplex each digit, we must common together the cathodes of the same segment of each digit. For example, segments 1A, 2A, 3A & 4A are commoned. Using the information in the tables above, the following pin connections need to be made:

E40561 Common segment wiring diagram

We multiplex the display by supplying 5V to each digit’s anode in sequence. For each digit we must connected the required segment cathodes to ground (0V).

The microcontroller will be used to perform the above sequencing. We will use 4 digital output pins to switch on and off the digits in sequence. The pins should’t be connected directly to the display because the current required may be more than microcontroller can provide. So, we connect each microcontroller pin to the base of a PNP transistor, via a resistor. The emitter of the transistor is connected to a suitably rated 5V supply and the collector is connected to the required pin on the display.

Note that, because we are using PNP transistors, we must set the microcontroller pin to LOW to turn on the transistor, and hence the digit. Conversely setting the pin HIGH turns off the digit.

Now, we could connect each commoned set of cathode pins to one of 8 digital input pins on the microcontroller and turn the segments on and off by setting the state of the pins as required. But we will save more pins by using a shift register and connecting the segment pins to its output.

The 8 commoned segments map nicely onto the 8 output pins of the commonly used 74HC595 shift register, so we will use that. The commoned segments will be connected to the 74HC595’s pins as follows:

Commoned segment pin 74HC595 pin
dp Q0
A Q1
B Q2
C Q3
D Q4
E Q5
F Q6
G Q7

Because we are dealing with LEDs, current limiting resistors need to be placed between each display pin and the shift register.

3 microcontroller output pins will be connected to the shift register’s DS, ST and SH pins.

Because we switch on segments by grounding them, zero bits in the byte sent to the shift register will switch on the related segments and one bits will switch related segments off. For example to switch on segment C (Q3) and the decimal point (Q0), we send 0b11110110 to the shift register.

The following circuit implements this design:

E40561 multiplex circuit

As can bee seen, the chosen microcontroller is an Arduino Nano. This is powered from the 5V power supply via its 5V pin.

If you choose to power the Nano via its USB port then disconnect its 5V pin from the main power supply, but ensure that the Nano’s ground remains connected to the power supply’s ground.

Code

The code is used to:

  1. Define a set of characters to be displayed.
  2. Keep track of the 4 digits currently being displayed.
  3. Perform the multiplexing.

Here’s the code:

// Pins used to control shift register
#define LATCH_PIN 8
#define CLOCK_PIN 12
#define DATA_PIN 11

// Number of digits
#define DIGIT_COUNT 4

// Pins used to switch each digit on or off
// Note that LOW values on these pins turns the digit ON and HIGH values turn the
// digit off this is because we're using PNP transistors which switch on when their
// base is grounded
const byte digitPins[DIGIT_COUNT] = {5, 4, 3, 2};

byte flag = false;
byte digit = 0;

// Define a mask for each segment: storing this pattern in the shift register will
// illuminate that segment alone.
// NOTE: Because this is a common anode display, we must connect the segment
//       cathodes to ground to illuminate them so we specify 1 (logic high) to
//       disconnect the segment from ground and 0 (low) to connect it to ground
#define SEGMENT_DP  0b11111110
#define SEGMENT_A   0b11111101
#define SEGMENT_B   0b11111011
#define SEGMENT_C   0b11110111
#define SEGMENT_D   0b11101111
#define SEGMENT_E   0b11011111
#define SEGMENT_F   0b10111111
#define SEGMENT_G   0b01111111
#define SEGMENT_OFF 0b11111111

// ledChars[] specifies the segments to illuminate for each digit.
// "0" is defined at index 0, "1" is defined at index 1 through to "9" being defined
// at index 9. Index 10 stores the value required to switch all segments off
// We AND the bitmasks of each required segment to create a "character" to display
const byte ledChars[] = {
    // Digit 0
    SEGMENT_A & SEGMENT_F & SEGMENT_B & SEGMENT_E & SEGMENT_C & SEGMENT_D,
    // Index 1 -> "1"
    SEGMENT_B & SEGMENT_C,
    // Index 2 -> "2"
    SEGMENT_A & SEGMENT_B & SEGMENT_G & SEGMENT_E & SEGMENT_D,
    // Index 3 -> "3"
    SEGMENT_A & SEGMENT_B & SEGMENT_G & SEGMENT_C & SEGMENT_D,
    // Index 4 -> "4"
    SEGMENT_F & SEGMENT_B & SEGMENT_G & SEGMENT_C,
    // Index 5 -> "5"
    SEGMENT_A & SEGMENT_F & SEGMENT_G & SEGMENT_C & SEGMENT_D,
    // Index 6 -> "6"
    SEGMENT_A & SEGMENT_F & SEGMENT_G & SEGMENT_E & SEGMENT_C & SEGMENT_D,
    // Index 7 -> "7"
    SEGMENT_A & SEGMENT_B & SEGMENT_C,
    // Index 8 -> "8"
    SEGMENT_A & SEGMENT_F & SEGMENT_B & SEGMENT_G & SEGMENT_E & SEGMENT_C & SEGMENT_D,
    // Index 9 -> "9"
    SEGMENT_A & SEGMENT_F & SEGMENT_B & SEGMENT_G & SEGMENT_C & SEGMENT_D,
    // Index 10 -> all segments off
    SEGMENT_OFF
};

#define LEDCHAR_SPACE 10   // index of space character (i.e. all sgements off)

// Add the decimal point to given bitmask v
#define addDp(v) ( (v) & SEGMENT_DP )
// Remove the decimal point from given bitmask v
#define removeDp(v) ( (v) | ~SEGMENT_DP)

// digits[] stores the four digits to be display:
// digits[n] stores digit n+1, e.g. digits[2] stores digit 3
// initialised so that all digits are off
byte digits[DIGIT_COUNT] = {SEGMENT_OFF, SEGMENT_OFF, SEGMENT_OFF, SEGMENT_OFF};

// Number of patterns of digits to be displayed
#define SEQUENCE_LENGTH 4

void setup() {
    // Set up output pins for shift register
    pinMode(LATCH_PIN, OUTPUT);
    pinMode(CLOCK_PIN, OUTPUT);
    pinMode(DATA_PIN, OUTPUT);
    // Set up output pins for digits & make sure they're all off
    for (int i = 0; i < DIGIT_COUNT; i++) {
        pinMode(digitPins[i], OUTPUT);
        digitalWrite(digitPins[i], HIGH);
    }
}

void loop() {
    // In the loop we set up and display a sequence of digits for time delta ms then
    // change to another digit sequence. After SEQUENCE_LENGTH different sequences have
    // been displayed we start again
    static long ticks;
    static long lastChange = 0;
    const long delta = 2000;
    static int index = 0;       // index of current pattern of digits

    ticks = millis();
    if (ticks - lastChange >= delta) {
        // Time's up: set required pattern
        switch (index) {
            case 0:
                // Display "0123",
                digits[0] = ledChars[0];
                digits[1] = ledChars[1];
                digits[2] = ledChars[2];
                digits[3] = ledChars[3];
                break;
            case 1:
                // Display "4567"
                digits[0] = ledChars[4];
                digits[1] = ledChars[5];
                digits[2] = ledChars[6];
                digits[3] = ledChars[7];
                break;
            case 2:
                // Display "89"
                digits[0] = ledChars[8];
                digits[1] = ledChars[9];
                digits[2] = ledChars[LEDCHAR_SPACE];
                digits[3] = ledChars[LEDCHAR_SPACE];
                break;
            case 3:
                // Display "3.142"
                digits[0] = addDp(ledChars[3]);
                digits[1] = removeDp(addDp(ledChars[1]));  // checking removeDp() macro works!
                digits[2] = ledChars[4];
                digits[3] = ledChars[2];
                break;
        }
        lastChange = ticks;
        index = (index + 1) % SEQUENCE_LENGTH;
    }
    updateDisplay();
}

void shiftOutByte(byte v) {
    // Writes bit mask v required to shift register
    digitalWrite(LATCH_PIN, LOW);
    shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, v);
    digitalWrite(LATCH_PIN, HIGH);
}

void updateDisplay() {
    // Performs multiplexing
    // Each time this function is called it switches on the next digit in turn
    static byte curDigit = 0;   // digit to be lit up - starts at 0
    // Turn off all digits
    for (byte d = 0; d < DIGIT_COUNT; d++) {
        digitalWrite(digitPins[d], true);
    }
    // Display segments of current digit
    shiftOutByte(digits[curDigit]);
    digitalWrite(digitPins[curDigit], false);
    // Record digit to be displayed on next call
    curDigit = (curDigit + 1) % DIGIT_COUNT;
    // Delay arrived at by experiment: compromise between brightness and flicker
    // Adjust as required
    delay(6);
}

Here’s an overview of what’s going on:

  • We start by defining which pins of the Arduino Nano to use for controlling the shift register and the display’s digits.
  • Next we define bitmasks for the display segments A..G & dp. These bitmasks relate to the output from the shift register, with the least significant bit controlling Q0 through to the most significant bit controlling Q7. The bitmasks are all ones except for a zero to switch on the required segment.
  • We now set up the ledChars array to store a bitmask for each of the characters we want to be able to display. ledChars[0] represents "0", ledChars[1] represents "1" etc. through to ledChars[9] representing "9". ledChars[10] has all segments off. These character bitmasks are created by ANDing together the relevant segment bitmasks we defined above.
  • There are a couple of macros, addDp() and removeDp(), that can be used to switch on or off the decimal point for a given digit. For example addDp(ledChars[3]) returns the bitmask need to display digit "3" with the decimal point illuminated.
  • We set up the digits array to store the bitmask of the characters to be displayed in each of the four digits. digits[0] stores digit 1 and so on. digits is intialised so that all digits are off.
  • SEQUENCE_LENGTH stores the number of different sets of digits to display in the main loop sequence (see below).
  • In setup() we simply set all the Nano’s pins we’re using as output pins and ensure all digits are off. Recall that digits are turned off by setting the associated pins HIGH.
  • In the main loop we display a sequence of four different sets of digits in turn, changing sets every 2 seconds. The digit sets are 0123, 4567, 89 (digits 3 & 4 off) and 3.142 (digit 1’s decimal point on). We call updateDisplay() every time loop() is called.
  • shiftOutByte() simply writes the given byte value to the shift register. This function is called to display the segments of the currently illuminated digit.
  • Finally, updateDisplay() performs the actual multiplexing. Each time it is called the function displays one of the four digits, in sequence, turning the others off. There is a brief delay before returning. This is to give the LEDs time to switch on before being turned off again, ensuring they are bright enough. There is a balance to struck between making this delay long enough to achieve the desired brightness and short enough to avoid flicker. Adjust as necessary.

Breadboard test rig

To make sure all this theory worked out in practise I built a breadboard test rig using the wiring diagram and code above. Here’s an annotated photo of the circuit:

E40561 breadboard circuit annotated photo

The following short video shows the circuit with the Nano running the display sequence:

Mulitplexing E40561 4 digit common anode LED display (simplified version)

This second, longer, video shows the same circuit running enhanced code (not included here) that defines additional characters and displays a longer sequence.

Mulitplexing E40561 4 digit common anode LED display (enhanced version)

Note: the circuit used in these videos is the same as that in the circuit diagram above except that 1kΩ current limiting resistors have been used with the LED segments instead of 470Ω resistors. This is a hang over from when I was testing the circuit and wanted to give the LED segments extra protection. I simply forgot to swap them for 470Ω resistors later!