I connected a 4-digit 7-segment display to the GPIO-port. It uses 8 ports for the LEDs and 4 ports for multiplexing via PNP-transistors. It is running so far with a loop written in C program:

while(1) {
  for(j = 0; j < 4; j++) { // Loop through 4 digits
    writeSegments(j+1, values[j]);
    delayMicroseconds(500); // approximately 2 kHz total refresh frequency

In general this works fine but maybe once or two times a second there is some irregular flickering. There is no XSession running and only MPD plays music. I run the program with a very high priority:

nice -n -19 /home/pi/mpd/C/main &

What else can I do?

I already did some research and found out the following options:

Both ways seem to be very complicated for just using such a simple display.

What do you suggest?

  • This doesn't directly answer your question but, have you thought about changing your hardware -- you can get a 4 digit 7-segment display with an I2C interface and let it manage the multiplexing. As an added bonus it should only need 2 pins. – Craig Nov 21 '12 at 21:15
  • You are right. Changing the hardware is a solution. For example using another small Atmel dedicated for the display might do the job as well. I would like to stick to the original hardware. – Lukas Nov 21 '12 at 23:15
  • What happens when you shorten that delay you are using. Based on your 500 Hz for 32 segments is only 15 Hz per segment. For a steady display you need at least 20Hz (or better 25Hz) per segment. If it still flickers at that rate, you can start to blame the scheduler. An other solution might be to use a D-latch and use those 4 GPIO's to control the state of the D-latch, this way you don't need any high frequency to update. Just write when needed, so no scheduler or flickering problems at all. – ikku Nov 22 '12 at 2:37
  • Only the digits are multiplexed. 500m microseconds already result in 50 Hz update rate for each digit. The segments are enabled parallel. The display flickers only once up on a time (maybe two times a second) but in general it is updated fast enough. A D-latch would mean, I have to change the hardware as well. Any other suggestions? – Lukas Nov 22 '12 at 17:47
  • @Craig How to use a 4 digit 7-segment display with I2C interface with the Raspberry Pi? Is there a high level Python library? Like segmentdisplay.print(23) (outputs 0023) ? – Basj Mar 25 '15 at 7:20

If I understand correctly what you are trying to do then there is a simple software solution.

The following Python code should update multiplexed 7-segment LCDs in a flicker free way.

For testing purposes each LCD is updated for 100000 µs in turn. In a practical application a value like 1000 µs should be used. The period is set by the REFRESH constant.

The code assumes that a segment is switched on by setting a gpio high. Similarly a LCD is enabled by setting a gpio high. You'd need to invert the logic if your segments/LCD are wired differently.

#!/usr/bin/env python

# _7_segment.py
# 2015-08-07
# Public Domain

import time
import pigpio # http://abyz.me.uk/rpi/pigpio/python.html

# For testing purposes each LCD is refreshed (REFRESH) for
# 100000 microseconds.  In a practical application you probably
# want to use a figure in the region of 1000 microseconds.


' ': 0b00000000,
'0': 0b11111100,
'1': 0b01100000,
'2': 0b11011010,
'3': 0b11110010,
'4': 0b01100110,
'5': 0b10110110,
'6': 0b00111110,
'7': 0b11100000,
'8': 0b11111110,
'9': 0b11100110,
'A': 0b11101110,
'b': 0b00111110,
'C': 0b10011100,
'c': 0b00011010,
'd': 0b01111010,
'E': 0b10011110,
'F': 0b10001110,
'H': 0b01101110,
'h': 0b00101110,
'L': 0b00011100,
'l': 0b01100000,
'O': 0b11111100,
'o': 0b00111010,
'P': 0b11001110,
'S': 0b10110110,

# This defines which gpios are connected to which segments
#          a   b   c   d   e   f   g  dp
SEG2GPIO=[ 4, 17, 18, 22, 23, 10, 24,  9]

# This defines the gpio used to switch on a LCD
#          1   2   3   4   5
LCD2GPIO=[ 5,  6,  7,  8, 11]

wid = None

showing = [0]*len(LCD2GPIO)


def display(lcd, char):
   if char in CHARSET:
      showing[lcd] = CHARSET[char]
      showing[lcd] = 0

def update_display():
   global wid
   wf = []
   for lcd in range(len(LCD2GPIO)):

      segments = showing[lcd] # segments on for current LCD

      on = 0 # gpios to switch on
      off = 0 # gpios to switch off

      # set this LCD on, others off
      for L in range(len(LCD2GPIO)):
         if L == lcd:
            on |= 1<<LCD2GPIO[L] # switch LCD on
            off |= 1<<LCD2GPIO[L] # switch LCD off

      # set used segments on, unused segments off
      for b in range(8):
         if segments & 1<<(7-b):
            on |= 1<<SEG2GPIO[b] # switch segment on
            off |= 1<<SEG2GPIO[b] # switch segment off

      wf.append(pigpio.pulse(on, off, REFRESH))

      print(on, off, REFRESH) # debugging only

   pi.wave_add_generic(wf) # add pulses to waveform
   new_wid = pi.wave_create() # commit waveform
   pi.wave_send_repeat(new_wid) # transmit waveform repeatedly

   if wid is not None:
      pi.wave_delete(wid) # delete no longer used waveform

   print("wid", wid, "new_wid", new_wid)

   wid = new_wid

pi = pigpio.pi()

# Set all used gpios as outputs.

for segment in SEG2GPIO:
   pi.set_mode(segment, pigpio.OUTPUT)

for lcd in LCD2GPIO:
   pi.set_mode(lcd, pigpio.OUTPUT)


ck = CHARSET.keys()

while True:

   # To test loop over character set.

   for d in range(len(LCD2GPIO)):
      display(d, ck[(d+char)%CHARS])


   char += 1




To avoid flickering of the segments, you really do need hard real time control of the multiplexing. Even small variations in the timing will be quite noticeable.

Using the timer on the CPU should work quite well, but as you observed it seems a lot of hassle for one simple thing. Perhaps it's worth doing if it's not just a one-off thing you are making.

Using a smart display, or making one by adding a small micro is probably the easier route. I'd probably opt for the micro since it gives the most flexibility.


If you avoid multiplexing there will be no flickering, but it will cost you higher current usage and extra hardware. Just search for disp7s2 in http://www.e-lab.de/AVRco/DOC_en/DocuStdDriver.pdf document. It will show you an example schematics for non-multiplexed 7-segment display driver using 74HC595 shift register and 8 resistors for each digit. The advantage of this mode is ultra low radiation and therefore no EMR problems.

  • I think maybe the display is already multiplexed - ie 12 pins. – John La Rooy Apr 9 '13 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.