User avatar
DaedalusOS
Posts: 13
Joined: Mon Aug 26, 2019 8:08 pm

Help understanding 74HC595

Mon Aug 26, 2019 8:30 pm

Greetings!

I hope this is the correct area to ask this, if not I apologize!

I've been using the Raspberry Pi for a couple of weeks now and I'm getting the hang of it, however the bane of my existence has been my 74HC595 shift register. I understand the basics of how the Shift Register works, however I'm running into a problem actually writing the code to get the Shift Register to work. I've gotten it all wired up, and using some Python example code that was in the tutorial to test, it works. But now I want to do it on my own and actually understand it.

Below is my code. Currently it just chooses a random LED and lights it up. What I need help understanding is:

1.) Why exactly does 0x01 correspond to output 1, 0x02 correspond with output 2, etc?
2.) The code below limits me to enabling output on only one pin, how can I enable output on more than one pin at a time?

Thanks for the help!

Code: Select all

import RPi.GPIO as GPIO
import time
import random

RCLK = 12
SER = 11
SRCLK = 13
SRCLR = 15

def input(dat):
    for bit in range(0, 8):
        GPIO.output(SER, 0x80 & (dat << bit))
        GPIO.output(SRCLK, GPIO.HIGH)
        time.sleep(0.001)
        GPIO.output(SRCLK, GPIO.LOW)

def latch():
    GPIO.output(RCLK, GPIO.HIGH)
    time.sleep(0.001)
    GPIO.output(RCLK, GPIO.LOW)

ledList = {
    1: 0x01,
    2: 0x02,
    3: 0x04,
    4: 0x08,
    5: 0x10,
    6: 0x20,
    7: 0x40,
    8: 0x80
}

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(RCLK, GPIO.OUT)
    GPIO.setup(SRCLK, GPIO.OUT)
    GPIO.setup(SER, GPIO.OUT)
    GPIO.setup(SRCLR, GPIO.OUT)
    GPIO.output(SER, GPIO.LOW)
    GPIO.output(RCLK, GPIO.LOW)
    GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(SRCLR, GPIO.HIGH)
    
def clear():
    GPIO.output(SRCLR, GPIO.LOW)
    time.sleep(0.1)
    GPIO.output(SRCLR, GPIO.HIGH)
    latch()

def runRandom():
    clear()
    
    time.sleep(1)
    
    while 1:
        input(ledList[random.randint(1, 8)])
        latch()
        time.sleep(.1)

setup()
runRandom()

if __name__ == '__main__':
    setup()
    try:
        runRandom()
    except:
        GPIO.cleanup()
        print("exiting...")


danjperron
Posts: 3526
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: Help understanding 74HC595

Tue Aug 27, 2019 12:56 am

1.) Why exactly does 0x01 correspond to output 1, 0x02 correspond with output 2, etc?
is the binary weight

The 74HC595 is a shift register. When you clock the pin, bit 0 go to bit 1 and so on.

bit 0 = 2 power 0 = 0x1
bit 1 = 2 power 1 = 0x2
....
bit 7 = 2 power 7 = 0x80 (128 in decimal)

The binary weight is used to set the corect pin. Just set the bit you want to enable multiple pin to be on.
2.) The code below limits me to enabling output on only one pin, how can I enable output on more than one pin at a time?
Not really just use the 'or' command

ex: input(ledList[random.randint(1, 8) | ledList[random.randint(1, 8))

The function input, which is a bad name to use, accepts 8 bits value then you could turn ON all pin with "input(255)"

User avatar
DaedalusOS
Posts: 13
Joined: Mon Aug 26, 2019 8:08 pm

Re: Help understanding 74HC595

Fri Aug 30, 2019 7:52 pm

danjperron wrote:
Tue Aug 27, 2019 12:56 am
1.) Why exactly does 0x01 correspond to output 1, 0x02 correspond with output 2, etc?
is the binary weight

The 74HC595 is a shift register. When you clock the pin, bit 0 go to bit 1 and so on.

bit 0 = 2 power 0 = 0x1
bit 1 = 2 power 1 = 0x2
....
bit 7 = 2 power 7 = 0x80 (128 in decimal)

The binary weight is used to set the corect pin. Just set the bit you want to enable multiple pin to be on.
2.) The code below limits me to enabling output on only one pin, how can I enable output on more than one pin at a time?
Not really just use the 'or' command

ex: input(ledList[random.randint(1, 8) | ledList[random.randint(1, 8))

The function input, which is a bad name to use, accepts 8 bits value then you could turn ON all pin with "input(255)"
Alright, I *think* I'm starting to pick this up somewhat. I've updated my code to this:

Code: Select all

import RPi.GPIO as GPIO
import time

RCLK = 36
SER = 32
SRCLK = 38
SRCLR = 40

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setwarnings(False)
    GPIO.setup(RCLK, GPIO.OUT)
    GPIO.setup(SRCLK, GPIO.OUT)
    GPIO.setup(SER, GPIO.OUT)
    GPIO.setup(SRCLR, GPIO.OUT)
    GPIO.output(SER, GPIO.LOW)
    GPIO.output(RCLK, GPIO.LOW)
    GPIO.output(SRCLK, GPIO.LOW)
    GPIO.output(SRCLR, GPIO.HIGH)

def clear():
    GPIO.output(SRCLR, GPIO.LOW)
    time.sleep(0.001)
    GPIO.output(SRCLR, GPIO.HIGH)
    latch()

def shift():
    GPIO.output(SRCLK, GPIO.HIGH)
    time.sleep(0.001)
    GPIO.output(SRCLK, GPIO.LOW)

def inputBits(dat):   
    for bit in range(0, 8):
        GPIO.output(SER, 0x80 & (dat << bit))
        shift()
        
    latch()
        
def latch():
    GPIO.output(RCLK, GPIO.HIGH)
    time.sleep(0.001)
    GPIO.output(RCLK, GPIO.LOW)
    
setup()
clear()
inputBits(0x1 | 0x2)
The part that is puzzling me now is that if I call "clear()", it will only light up the first LED. If I *don't* call "clear()", it will light up the 1st and 2nd LED, as expected, but if I run it again it only lights up the 1st one, then both, then seemingly random either one or both.

What am I doing wrong here/not understanding?

Thanks!

ghp
Posts: 1591
Joined: Wed Jun 12, 2013 12:41 pm
Location: Stuttgart Germany
Contact: Website

Re: Help understanding 74HC595

Sat Aug 31, 2019 5:04 am

Calling clear() at the beginning of the operations, just after setup(), is needed. This avoids problems by GPIO having unknown state because program is stopped and restarted with again calling setup().
I would propose to change the code a bit. Instead of the block

Code: Select all

def inputBits(dat):   
    for bit in range(0, 8):
        GPIO.output(SER, 0x80 & (dat << bit))
        shift()
        
    latch()
use instead

Code: Select all

def inputBits(dat):   
    # shift out bit7 first, then bit6, down to bit0
    for bit in [7,6,5,4,3,2,1,0]:    # to avoid range(7,-1,-1)
        # get the value of the bit number 'bit'. Set gpio output according LOW, HIGH
        gpio_value = GPIO.LOW
        if 0 != ( dat & (1 << bit)):
            gpio_value = GPIO.HIGH
            
        GPIO.output(SER, gpio_value )
        shift()
        
    latch()
The loop's for expression is changed to make it more meaningful. Bit 7 is shifted out first, down to bit 0.
For the GPIO.output command, the value to be set is determined using GPIO.LOW, GPIO.HIGH. I do not know how rpi.gpio behaves with values outside [LOW, HIGH], so using these values is quite save.

To avoid the restart program problem, just add some more lines to the patterns. Do you have LED connected to the chip ?

Code: Select all

print("0x1 | 0x2")
inputBits(0x1 | 0x2)
time.sleep(1)

print("0x1")
inputBits(0x1 )
time.sleep(1)

print("0x2")
inputBits(0x2 )
time.sleep(1)
If these things do not help, then possibly your setup is not perfectly wired ?

Return to “Python”