Tero's Arduino Blog

Using Arduino with Ada

Controlling 4-digit 7-segment display


A seven-segment display is nice for showing a single number. And 4-digit display is 4 times as nice since it can show four numbers.

However, using 4-digit version is also somewhat more complicated. The 4-digit 7-segment display (which I use) is done so that each digit will have same set of leds turned on at the same time when the digits are turned on. This means that if we want to show a different number in a different digit, we need to turn other digits off. Fortunately for us, other leds won't turn off immediately, so if you do turning on and off quick enough, you can set the display so that each digit shows a different number.


Required parts:

  • 4-digit 7-segment display from Sparkfun
  • Arduino Mega 2560 (Arduino UNO is also ok, but these instructions are tested with Mega 2560)
  • Lots of jumper wires
  • Four 330 or 220 ohm resistors

The circuit for the display is otherwise simple, but you need to be careful with the wires (since there are so many of them). If you cannot decipher the picture, there are many instructions around to follow.

The wiring table of my setup is following:

Pin numbers
Arduino Pin AVR Port Display pin LED segment
Digital 52 B1 pin 11 F
Digital 51 B2 pin 13 C
Digital 50 B3 pin 16 B
Digital 13 B7 pin 5 E
Digital 12 B6 pin 3 D
Digital 11 B5 pin 14 A
Digital 10 B4 pin 15 G
Analog 5 F5 pin 8 DIG 4
Analog 6 F6 pin 6 DIG 3
Analog 7 F7 pin 2 DIG 2
Analog 8 K0 pin 1 DIG 1

You should put the resistors between the analog pins and the display.


Once the circuit is done, we are ready to put the code on the device.

The code is following:

type Digit_Led is (D1, D2, D3, D4);

procedure Enable_Led (L : Digit_Led) is
   case L is
      when D1 =>
         MCU.PORTF_Bits (5) := False;
         MCU.PORTF_Bits (6) := False;
         MCU.PORTF_Bits (7) := False;
         MCU.PORTK_Bits (0) := True;
      when D2 =>
         MCU.PORTF_Bits (5) := False;
         MCU.PORTF_Bits (6) := False;
         MCU.PORTF_Bits (7) := True;
         MCU.PORTK_Bits (0) := False;
      when D3 =>
         MCU.PORTF_Bits (5) := False;
         MCU.PORTF_Bits (6) := True;
         MCU.PORTF_Bits (7) := False;
         MCU.PORTK_Bits (0) := False;
      when D4 =>
         MCU.PORTF_Bits (5) := True;
         MCU.PORTF_Bits (6) := False;
         MCU.PORTF_Bits (7) := False;
         MCU.PORTK_Bits (0) := False;
   end case;
end Enable_Led;

type Digit_Type is new Unsigned_8 range 0 .. 9;
type Digit_Array is array (Digit_Type) of Unsigned_8;

Segment_Digits : Digit_Array :=
        -- EDAGBCFx
   (0 => 2#00010000#,
    1 => 2#11110010#,
    2 => 2#00000110#,
    3 => 2#10000010#,
    4 => 2#11100000#,
    5 => 2#10001000#,
    6 => 2#00001000#,
    7 => 2#11010010#,
    8 => 2#00000000#,
    9 => 2#11000000#);

procedure Show_Digit (D : Digit_Type) is
   MCU.PORTB := Segment_Digits (D);
end Show_Digit;


   Enable_Led (D4);
   Show_Digit (1);
   MCU.PORTB := 0;

   Enable_Led (D3);
   Show_Digit (2);
   MCU.PORTB := 0;
end loop;

The rest of the code is available from arduino-mega2560-4d-7segment repository.

And now the explanation of the code:

Enable_Led procedure turns on the specified set of leds (either for digit 1, 2, 3 or 4) and turns off other sets. Array Segment_Digits is a mapping of numbers 0..9 to the digit segments A..G so that correct leds are disabled or enable for the numbers. Procedure Show_Digit then uses this array to turn on or off the leds. Notice also how all the segment wires go to port B to make this mapping possible.

Finally, in the loop we continuously turn on and off the leds to make them look like they were always on.

The example code uses only same static set of digits. Doing a counter or timer with digits changing all the time is left as an exercise for the reader.

Copyright © 2012, 2013 Tero Koskinen - Theme Skeleton; Blogging engine Pelican; Powered by Python