Chapter 16 74HC595 & Bar Graph LED

We have used LED Bar Graph to make a flowing water light, in which 10 GPIO ports of RPi are occupied. More GPIO ports mean that more peripherals can be connected to RPi, so GPIO resource is very precious. Can we make flowing water light with less GPIO ports? In this chapter, we will learn a component, 74HC595, which can achieve the target.

Project 16.1 Flowing Water Light

Now let us learn how to use the 74HC595 IC Chip to make a flowing water light using less GPIO.

Component knowledge

Bar Graph LED

A Bar Graph LED has 10 LEDs integrated into one compact component. The two rows of pins at its bottom are paired to identify each LED like the single LED used earlier.

../../../_images/Chapter16_00.png

74HC595

A 74HC595 chip is used to convert serial data into parallel data. A 74HC595 chip can convert the serial data of one byte into 8 bits, and send its corresponding level to each of the 8 ports correspondingly. With this characteristic, the 74HC595 chip can be used to expand the IO ports of a Raspberry Pi. At least 3 ports on the RPI board are required to control the 8 ports of the 74HC595 chip.

../../../_images/Chapter16_01.png

The ports of the 74HC595 chip are described as follows:

Pin name

Pin number

Description

Q0-Q7

15, 1-7

Parallel Data Output

VCC

16

The Positive Electrode of the Power Supply, the Voltage is 2~6V

GND

8

The Negative Electrode of Power Supply

DS

14

Serial Data Input

OE

13

Enable Output,

When this pin is in high level, Q0-Q7 is in high resistance state

When this pin is in low level, Q0-Q7 is in output mode

ST_CP

12

Parallel Update Output: when its electrical level is rising, it will update the

parallel data output.

SH_CP

11

Serial Shift Clock: when its electrical level is rising, serial data input

register will do a shift.

MR

10

Remove Shift Register: When this pin is in low level, the content in shift

register will be cleared.

Q7’

9

Serial Data Output: it can be connected to more 74HC595 chips in series.

For more details, please refer to the datasheet on the 74HC595 chip.

Component List

Freenove Projects Board for Raspberry Pi

Chapter01_04

Raspberry Pi

Chapter01_05

GPIO Ribbon Cable

Chapter01_06

Bar Graph LED

Chapter16_02

Circuit

Schematic diagram

Chapter16_03

Hardware connection:

Chapter16_04

Hint

If it dosen’t work, rotate the LED bar graph for 180°.

Note

If you have any concerns, please send an email to: support@freenove.com

Code

In this project we will make a flowing water light with a 74HC595 chip to learn about its functions.

C Code LightWater02

First, observe the project result, and then learn about the code in detail.

If you have any concerns, please send an email to: support@freenove.com

  1. Use cd command to enter 16_FlowingLight02 directory of C code.

$ cd ~/Freenove_Kit/Code/C_Code/16_FlowingLight02
  1. Use following command to compile “FlowingLight02.c” and generate executable file “FlowingLight02”.

$ gcc FlowingLight02.c -o FlowingLight02 -lwiringPi
  1. Then run the generated file “FlowingLight02”.

$ ./FlowingLight02

After the program runs, you will see that Bar Graph LED starts with the flowing water pattern flashing from right to left and then back from left to right.

The following is the program code:

 1/**********************************************************************
 2* Filename    : FlowingLight02.c
 3* Description : Control LED by 74HC595
 4* Author      : www.freenove.com
 5* modification: 2024/07/29
 6**********************************************************************/
 7#include <wiringPi.h>
 8#include <stdio.h>
 9#include <wiringShift.h>
10
11#define dataPin  22   //DS Pin of 74HC595(Pin14)
12#define latchPin 27   //ST_CP Pin of 74HC595(Pin12)
13#define clockPin 17   //CH_CP Pin of 74HC595(Pin11)
14
15void _shiftOut(int dPin,int cPin,int order,int val){   
16	int i;  
17    for(i = 0; i < 10; i++){
18        digitalWrite(cPin,LOW);
19        if(order == LSBFIRST){
20            digitalWrite(dPin,((0x01&(val>>i)) == 0x01) ? HIGH : LOW);
21            delayMicroseconds(10);
22		}
23        else {
24            digitalWrite(dPin,((0x80&(val<<i)) == 0x80) ? HIGH : LOW);
25            delayMicroseconds(10);
26		}
27        digitalWrite(cPin,HIGH);
28        delayMicroseconds(10);
29	}
30}
31
32int main(void)
33{
34	int i;
35	unsigned long x;
36	
37	printf("Program is starting ...\n");
38	
39	wiringPiSetupGpio();//Initialize wiringPi. Use BCM Number.
40	
41	pinMode(dataPin,OUTPUT);
42	pinMode(latchPin,OUTPUT);
43	pinMode(clockPin,OUTPUT);
44	while(1){
45		x=0x0001;
46		for(i=0;i<10;i++){
47			digitalWrite(latchPin,LOW);		// Output low level to latchPin
48			_shiftOut(dataPin,clockPin,LSBFIRST,x);// Send serial data to 74HC595
49			digitalWrite(latchPin,HIGH);   //Output high level to latchPin, and 74HC595 will update the data to the parallel output port.
50			x<<=1;      //make the variable move one bit to left once, then the bright LED move one step to the left once.
51			delay(100);
52		}
53		x=0x0200;
54		for(i=0;i<10;i++){
55			digitalWrite(latchPin,LOW);
56			_shiftOut(dataPin,clockPin,LSBFIRST,x);
57			digitalWrite(latchPin,HIGH);
58			x>>=1;
59			delay(100);
60		}
61	}
62	return 0;
63}
64

In the code, we configure three pins to control the 74HC595 chip and define a one-byte variable to control the state of the 10 LEDs (in the Bar Graph LED Module) through the 10 bits of the variable. The LEDs light ON when the corresponding bit is 1. If the variable is assigned to 0x01, that is 00000001 in binary, there will be only one LED ON.

1x=0x0001;

In the “while” loop of main function, use two loops to send x to 74HC595 output pin to control the LED. In one cycle, x will shift one bit to the LEFT in one cycle, then when data of x is sent to 74HC595, the LED that is turned ON will move one bit to the LEFT once.

1for(i=0;i<10;i++){
2	digitalWrite(latchPin,LOW);		// Output low level to latchPin
3	_shiftOut(dataPin,clockPin,LSBFIRST,x);// Send serial data to 74HC595
4	digitalWrite(latchPin,HIGH);   //Output high level to latchPin, and 74HC595 will update the data to the parallel output port.
5	x<<=1;      //make the variable move one bit to left once, then the bright LED move one step to the left once.
6	delay(100);
7}

In second cycle, the situation is the same. The difference is that x is shift from 0x80 to the RIGHT in order.

<< operator

“<<” is the left shift operator, which can make all bits of 1 byte shift by several bits to the left (high) direction and add 0 on the right (low). For example, shift binary 00000001 by 1 bit to left:

byte x = 1 << 1;

../../../_images/Chapter16_05.png

The result of x is 2(binary 00000010).

../../../_images/Chapter16_06.png

There is another similar operator” >>”. For example, shift binary 00000001 by 1 bit to right:

byte x = 1 >> 1;

../../../_images/Chapter16_07.png

The result of x is 0(00000000).

../../../_images/Chapter16_08.png

X <<= 1 is equivalent to x = x << 1 and x >>= 1 is equivalent to x = x >> 1

About shift function

void _shiftOut(uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val);

This is used to shift a 10-bit data value out with the data being sent out on dPin and the clock being sent out on the cPin. order is as above. Data is clocked out on the rising or falling edge - ie. dPin is set, then cPin is taken high then low - repeated for the 10 bits.

Python Code LightWater02

First, observe the project result, and then learn about the code in detail.

If you have any concerns, please send an email to: support@freenove.com

  1. Use cd command to enter 16_FlowingLight02 directory of Python code.

$ cd ~/Freenove_Kit/Code/Python_GPIOZero_Code/16_FlowingLight02
  1. Use python command to execute Python code “FlowingLight02.py”.

$ python FlowingLight02.py

After the program runs, you will see that Bar Graph LED starts with the flowing water pattern flashing from right to left and then back from left to right.

The following is the program code:

 1#!/usr/bin/env python3
 2#############################################################################
 3# Filename    : LightWater02.py
 4# Description : Control LED with 74HC595
 5# Author      : www.freenove.com
 6# modification: 2024/07/29
 7########################################################################
 8from gpiozero import OutputDevice
 9import time
10# Defines the data bit that is transmitted preferentially in the shiftOut function.
11LSBFIRST = 1
12MSBFIRST = 2
13# define the pins for 74HC595
14dataPin   = OutputDevice(22)      # DS Pin of 74HC595(Pin14)
15latchPin  = OutputDevice(27)      # ST_CP Pin of 74HC595(Pin12)
16clockPin  = OutputDevice(17)      # CH_CP Pin of 74HC595(Pin11)
17   
18# shiftOut function, use bit serial transmission. 
19def shiftOut(order,val):      
20    for i in range(0,8):
21        clockPin.off()
22        if(order == LSBFIRST):
23            dataPin.on() if (0x01&(val>>i)==0x01) else dataPin.off()
24        elif(order == MSBFIRST):
25            dataPin.on() if (0x80&(val<<i)==0x80) else dataPin.off()
26        clockPin.on()
27
28def showLedbar(order,val):
29    val1 = val >> 8 & 0xff
30    val2 = val & 0xff
31    shiftOut(order, val1)
32    shiftOut(order, val2)
33
34def loop():
35    while True:
36        x=0x001
37        for i in range(0,10):
38            latchPin.off()# Output low level to latchPin
39            showLedbar(MSBFIRST,x) # Send serial data to 74HC595
40            latchPin.on()   # Output high level to latchPin, and 74HC595 will update the data to the parallel output port.
41            x<<=1 # make the variable move one bit to left once, then the bright LED move one step to the left once.
42            time.sleep(0.1)
43        x=0x200
44        for i in range(0,10):
45            latchPin.off()
46            showLedbar(MSBFIRST,x)
47            latchPin.on()
48            x>>=1
49            time.sleep(0.1)
50
51def destroy():  
52    latchPin.off()
53    shiftOut(MSBFIRST, 0x00)
54    shiftOut(MSBFIRST, 0x00)
55    latchPin.on() 
56    dataPin.close()
57    latchPin.close()
58    clockPin.close() 
59
60if __name__ == '__main__': # Program entrance
61    print ('Program is starting...' )
62    try:
63        loop()  
64    except KeyboardInterrupt:  # Press ctrl-c to end the program.
65        print("Ending program")
66    finally:
67        destroy()

In the code, we define a shiftOut() function, which is used to output values with bits in order, where the dPin for the data pin, cPin for the clock and order for the priority bit flag (high or low). This function conforms to the operational modes of the 74HC595. LSBFIRST and MSBFIRST are two different flow directions.

1def shiftOut(order,val):      
2    for i in range(0,8):
3        clockPin.off()
4        if(order == LSBFIRST):
5            dataPin.on() if (0x01&(val>>i)==0x01) else dataPin.off()
6        elif(order == MSBFIRST):
7            dataPin.on() if (0x80&(val<<i)==0x80) else dataPin.off()
8        clockPin.on()

In the loop() function, we use two loops to achieve the action goal. First, define a variable x=0x0001. When it is transferred to the output port of 74HC595, the low bit outputs high level, then an LED turns ON. Next, x is shifted one bit, when x is transferred to the output port of 74HC595 once again, the LED that turns ON will be shifted. Repeat the operation, over and over and the effect of a flowing water light will be visible. If the direction of the shift operation for x is different, the flowing direction is different.

 1def loop():
 2    while True:
 3        x=0x001
 4        for i in range(0,10):
 5            latchPin.off()# Output low level to latchPin
 6            showLedbar(MSBFIRST,x) # Send serial data to 74HC595
 7            latchPin.on()   # Output high level to latchPin, and 74HC595 will update the data to the parallel output port.
 8            x<<=1 # make the variable move one bit to left once, then the bright LED move one step to the left once.
 9            time.sleep(0.1)
10        x=0x200
11        for i in range(0,10):
12            latchPin.off()
13            showLedbar(MSBFIRST,x)
14            latchPin.on()
15            x>>=1
16            time.sleep(0.1)