4

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
    clearSegments();
    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?

Lukas
  • 151
  • 1
  • 5

3 Answers3

2

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.

John La Rooy
  • 12,005
  • 9
  • 48
  • 77
1

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.

REFRESH=100000

CHARSET={
' ': 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)

CHARS=len(CHARSET)

def display(lcd, char):
   if char in CHARSET:
      showing[lcd] = CHARSET[char]
   else:
      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
         else:
            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
         else:
            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)

char=0

ck = CHARSET.keys()

while True:

   # To test loop over character set.

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

   update_display()

   char += 1

   time.sleep(2)

pi.wave_delete(wid)

pi.stop()
Ghanima
  • 15,958
  • 17
  • 65
  • 125
joan
  • 71,852
  • 5
  • 76
  • 108
0

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.

avra
  • 1,273
  • 8
  • 9