User avatar
clemsy
Posts: 7
Joined: Sat Aug 18, 2018 9:44 am

Using shift registers for 7 segments led displays

Sat Aug 18, 2018 10:07 am

Hi all,

We are building a sport scoreboard (for bikepolo) with a raspberry pi, python, leds stripes as 7 segments displays and using TPIC6B595N shift registers.

It's quite OK but I don't know how to prevent that all the leds are ON for a microtime between each second...

Here is a video to understand :

View My Video


And the Python code :

Code: Select all

#!/usr/bin/python

import RPi.GPIO as GPIO
import time
from time import sleep

# Setup time in seconds
time_left = 720

# GPIO Setup
GPIO.setmode(GPIO.BOARD)

# Setup RPi TPIC6B595N
DATAIN = 37  # serin
LATCH = 33   # RCK
CLOCK = 31   # SRCK
CLEAR = 35   # SRCLR
OE = 11      # Output Enable Low

GPIO.setup(DATAIN, GPIO.OUT)
GPIO.setup(CLOCK, GPIO.OUT)
GPIO.setup(LATCH, GPIO.OUT)
GPIO.setup(CLEAR, GPIO.OUT)
GPIO.setup(OE, GPIO.OUT)

GPIO.output(LATCH, False)    # Latch is used to output the saved data
GPIO.output(CLEAR, True)     # Clear must always be true. False clears registers
GPIO.output(OE, False)       # Output Enable speaks for itself. Must be False to display
GPIO.output(CLOCK, False)    # Used to shift the value of DATAIN to the register
GPIO.output(DATAIN, False)   # Databit to be shifted into the register


# Setup led segments

numbers = [
    "00111111",  # 0
    "00000110",  # 1
    "01011011",  # 2
    "01001111",  # 3
    "01100110",  # 4
    "01101101",  # 5
    "01111101",  # 6
    "00000111",  # 7
    "01111111",  # 8
    "01101111",  # 9
]


def print_to_leds(time_left):

    m, s = divmod(time_left, 60)

    secs = str(s)
    mins = str(m)
    secs_d = int(secs[:1]) if s >= 10 else 0
    secs_u = int(secs[1:]) if s >= 10 else s
    mins_d = int(mins[:1]) if m >= 10 else 0
    mins_u = int(mins[1:]) if m >= 10 else m

    for i in numbers[secs_u]:
        GPIO.output(DATAIN, False if i == "0" else True)
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)
        GPIO.output(LATCH, True)
        GPIO.output(LATCH, False)
    sleep(0.001)
    for i in numbers[secs_d]:
        GPIO.output(DATAIN, False if i == "0" else True)
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)
        GPIO.output(LATCH, True)
        GPIO.output(LATCH, False)
    sleep(0.001)
    for i in numbers[mins_u]:
        GPIO.output(DATAIN, False if i == "0" else True)
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)
        GPIO.output(LATCH, True)
        GPIO.output(LATCH, False)
    sleep(0.001)
    for i in numbers[mins_d]:
        GPIO.output(DATAIN, False if i == "0" else True)
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)
        GPIO.output(LATCH, True)
        GPIO.output(LATCH, False)


try:
    while True:
        while time_left >= 0:
            print_to_leds(time_left
            print(str(mins_d) + str(mins_u) + ":" + str(secs_d) + str(secs_u))  # print to console
            time.sleep(1)
            time_left -= 1

except KeyboardInterrupt:
  GPIO.cleanup()

It is not such a big issue but...

Thanks for your help :)

User avatar
OutoftheBOTS
Posts: 664
Joined: Tue Aug 01, 2017 10:06 am

Re: Using shift registers for 7 segments led displays

Sat Aug 18, 2018 11:26 pm

OK I have only once before had to program a shift register (hacking a NESS controller)

So these r your pins

Code: Select all

DATAIN = 37  # serin
LATCH = 33   # RCK
CLOCK = 31   # SRCK
CLEAR = 35   # SRCLR
OE = 11      # Output Enable Low
OE needs to be low because even though it is called enable it works like a disable :(
LATCH needs to init low
CLOCK needs to init to low
CLEAR should do a low then high on init to clear everything and reset on startup then remain high.

To transfer data this is the sequence
LATCH goes low
Data is read by the shift-register on the DATAIN pin on the rising edge of the CLOCK line
then when all data has been send the LATCH goes high

I had a little play with your code and come up with this. It has just been typed in editor and not tested but should give you some food for though if it doesn't work

Code: Select all

#!/usr/bin/python

import RPi.GPIO as GPIO
import time
from time import sleep

# Setup time in seconds
time_left = 720

# GPIO Setup
GPIO.setmode(GPIO.BOARD)

# Setup RPi TPIC6B595N
DATAIN = 37  # serin
LATCH = 33   # RCK
CLOCK = 31   # SRCK
CLEAR = 35   # SRCLR
OE = 11      # Output Enable Low

GPIO.setup(DATAIN, GPIO.OUT)
GPIO.setup(CLOCK, GPIO.OUT)
GPIO.setup(LATCH, GPIO.OUT)
GPIO.setup(CLEAR, GPIO.OUT)
GPIO.setup(OE, GPIO.OUT)

GPIO.output(LATCH, False)    # Latch is used to output the saved data
GPIO.output(CLEAR, True)     # Clear must always be true. False clears registers
GPIO.output(OE, False)       # Output Enable speaks for itself. Must be False to display
GPIO.output(CLOCK, False)    # Used to shift the value of DATAIN to the register
GPIO.output(DATAIN, False)   # Databit to be shifted into the register


# Setup led segments

numbers = [
    "00111111",  # 0
    "00000110",  # 1
    "01011011",  # 2
    "01001111",  # 3
    "01100110",  # 4
    "01101101",  # 5
    "01111101",  # 6
    "00000111",  # 7
    "01111111",  # 8
    "01101111",  # 9
]


def print_to_leds(time_left):

    m, s = divmod(time_left, 60)
	
	'''
	#this might be a little better to convet into singal digits
	secs_d = secs // 10
	secs_u = secs - (secs_d * 10)
	mins_d = mins // 10
	mins_u = min - (mins_d * 10)
	'''

    secs = str(s)
    mins = str(m)
    
 
	
	secs_d = int(secs[:1]) if s >= 10 else 0
    secs_u = int(secs[1:]) if s >= 10 else s
    mins_d = int(mins[:1]) if m >= 10 else 0
    mins_u = int(mins[1:]) if m >= 10 else m

    
	#set Latch low to start sending data
	GPIO.output(LATCH, False)
	for i in numbers[secs_u]:
        #send data
		GPIO.output(DATAIN, i)
		#pulse clock line
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)
    
	sleep(0.001)#not sure if you need this sleep or not
    
	for i in numbers[secs_d]:
        GPIO.output(DATAIN, i)
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)

    sleep(0.001)
    for i in numbers[mins_u]:
        GPIO.output(DATAIN, False if i == "0" else True)
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)
    sleep(0.001)
    
	for i in numbers[mins_d]:
        GPIO.output(DATAIN, False if i == "0" else True)
        GPIO.output(CLOCK, True)
        GPIO.output(CLOCK, False)
    
	#set Latch high to finish data transfer
	GPIO.output(LATCH, True)


try:
    while True:
        while time_left >= 0:
            print_to_leds(time_left)
            print(str(mins_d) + str(mins_u) + ":" + str(secs_d) + str(secs_u))  # print to console
            time.sleep(1)
            time_left -= 1

except KeyboardInterrupt:
  GPIO.cleanup()


User avatar
clemsy
Posts: 7
Joined: Sat Aug 18, 2018 9:44 am

Re: Using shift registers for 7 segments led displays

Sun Aug 19, 2018 7:38 am

Wow

It worked well as soon as I only put latch low before sending data and put hugh again after all the data is sent..
thank you :-)

What do you mean here :
#this might be a little better to convet into singal digits
Thank you :-)

Clément

User avatar
OutoftheBOTS
Posts: 664
Joined: Tue Aug 01, 2017 10:06 am

Re: Using shift registers for 7 segments led displays

Sun Aug 19, 2018 9:16 pm

OK you have a 2 digit decimal number and you need to turn it in to 2 x 1 digit numbers. You do this by conveting it to a string the cutting up the string and then turning it back to an integer. You should be able to do the same thing by the first digit will be integer division by 10 and the second digit will be modulo division by 10.

This is even better and will be much more efficient

Code: Select all

	secs_d = secs // 10
	secs_u = secs % 10
	mins_d = mins // 10
	mins_u = min % 10
Also in your original code you where doing this

Code: Select all

GPIO.output(DATAIN, False if i == "0" else True)
Any time you write True the interrupter will replace it with 1 and anytime you write False the interrupter will replace it with 0. Remember a computer doesn't understand the words True or False but does understand 1 or 0 so when you run your program the interrupter translates your human speak into computer speak.

Return to “Python”