Controlling 8-digit 7-segment displays using 74HC595 using Raspberry Pi Python

1.3k Views Asked by At

I have an 8-digit LED display board, but I'm getting odd results. Line 21 defines which segments are lit AND which displays are used. So [1,0,0,0,1,0,0,0] turns off the 1st and 5th segments and lights the 4th and 8th displays (displays are in the order 4, 3, 2, 1, 8, 7, 6, 5). So the first 1 in the list on Line 24 turns off the decimal point and illuminates the fourth display. The 5th 1 turns off the bottom segment and illuminates the eighth display.

8 digit seven-segment display

What I would like is to be able to specify which display to use and which segments of that display to light / unlight.

Here is the Python 3 code:

import RPi.GPIO as IO
import time

# Ignore warnings
IO.setwarnings(False)

# Set pinouts
dataPin  = 11
latchPin = 15
clockPin = 13

IO.setmode (IO.BOARD)
IO.setup(dataPin, IO.OUT)
IO.setup(clockPin, IO.OUT)
IO.setup(latchPin, IO.OUT)

# 7-segment displays are in the following
# order:   4 3 2 1 8 7 6 5

# Segments to light (0 = on / 1 = off)
segsLit = [1,0,0,0,1,0,0,0] # Line 21

# Iterate through 7-seg displays
for j in range(8):
  IO.output(latchPin, 0)

  # Iterate through list1 to light segments
  for i in range(8):
    IO.output(clockPin, 0)
    IO.output(dataPin, segsLit[i])
    IO.output(clockPin, 1)
  IO.output(latchPin, 1)

IO.cleanup()

print("Done")

I've found a couple of guides, but they are for driving only a single display or just 8 LEDs. There are lots of guides for the Arduino, which I've tried to convert, but I just keep getting similar issues with the wrong digits displaying.

2

There are 2 best solutions below

0
RufusVS On

Based on a schematic I found for your board, it looks like to drive 8 leds you'd need a program similar to this. The main idea is the led's have to be continuously refreshed to display multiple digits. only one segment pattern will be enabled per shifting cycle (though you COULD make it appear on multiple digits, which would be an unusual application for sure.)

I didn't bother to try to get the digit positions and segment positions all correct, that's up to you. Also digit select polarity might need to be reversed. But this edit to your code should get you closer:

import RPi.GPIO as IO

REFRESH_NS = 1_000_000_000 / 30 / 8  # refresh 30 times per second, 8 digits

# Ignore warnings
IO.setwarnings(False)

# Set pinouts
dataPin  = 11
latchPin = 15
clockPin = 13

IO.setmode (IO.BOARD)
IO.setup(dataPin, IO.OUT)
IO.setup(clockPin, IO.OUT)
IO.setup(latchPin, IO.OUT)

# 7-segment displays are in the following
# order:   4 3 2 1 8 7 6 5

# Segments to light (0 = on / 1 = off)
segsLit = 
[
[1,0,0,0,0,0,0,0],
[0,1,0,0,0,0,0,0],
[0,0,1,0,0,0,0,0],
[0,0,0,1,0,0,0,0],
[0,0,0,0,1,0,0,0],
[0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,1,0],
[0,0,0,0,0,0,0,1],
]

update_time = time.monotonic_ns()

# Iterate through 7-seg displays (8 bits with decimal point)
while True:
    IO.output(latchPin, 0) # start shift operation
    
    for digit in range(8):

        # digit select shifts out first
        for pos in range(8):
            IO.output(clockPin, 0)
            IO.output(dataPin, 1 if pos==digit else 0)
            IO.output(clockPin, 1)

        # Iterate through to light segments
        for seg in range(8):
            IO.output(clockPin, 0)
            IO.output(dataPin, segsLit[digit][seg])
            IO.output(clockPin, 1)


    IO.output(latchPin, 1) # end shift operation
    
    while time.monotonic_ns() < update_time + REFRESH_NS: # delay to energize led
        pass # spin loop
    
    update_time = time.monotonic_ns() # prepare for next update
    
IO.cleanup()

print("Done")
0
wibbleface On

16 bits of data needed to be sent to the board. The first 8 bits are to light specific segments, the subsequent 8 bits are to indicate which display(s) to use.

In the updated code below, the 8th (right-most) display will show the letter 'A'.

import RPi.GPIO as IO
import time

# Ignore warnings
IO.setwarnings(False)

# Set pinouts
dataPin  = 11
latchPin = 15
clockPin = 13

IO.setmode (IO.BOARD)
IO.setup(dataPin, IO.OUT)
IO.setup(clockPin, IO.OUT)
IO.setup(latchPin, IO.OUT)

# 7-segment displays are in the following
# order:   4 3 2 1 8 7 6 5

# First 8 bits = segments to light // Second 8 bits = position
segsLit = [1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0] # Line 21

# Iterate through 7-seg displays
IO.output(latchPin, 0)

# Iterate through list1 to light segments
for i in range(16):
  IO.output(clockPin, 0)
  IO.output(dataPin, segsLit[i])
  IO.output(clockPin, 1)
IO.output(latchPin, 1)

IO.cleanup()

print("Done")