2012-07-21

Raspberry Pi 7 segment displays

This post shows how to drive two 7 segment displays from 6 gpio pins on the Raspberry Pi without a continual refresh loop. The software is simple with very low cpu usage - only processing when you want to change the displayed numbers. The electronics are pretty easy too (I'm a novice myself!) It's also a fun way to learn about BCD (Binary-coded decimal) and latches.

Hardware

To put this together I've used:
Basically you take 6 gpio pins through current limiting resistors and then on to the second breadboard. You'll see from the picture below that I have added an LED as a confidence indicator for each gpio pin. I've labelled these in the picture for the latches and data lines that then need to be wired up to the HEF4543Bs:
If you look at the data sheet for the HEF4543B you'll see that the labels I've put on this picture match. These  labels are also used in the software later.
  • LD = Latch disable (for first digit)
  • DD = 8 (BCD bit)
  • DC = 4 (BCD bit)
  • DB = 2 (BCD bit)
  • DA = 1 (BCD bit)
  • LD2 = Latch disable (for second digit)
The gpio pins for the latches are then connected directly to the two ICs, The data pins are connected in parallel to both ICs:
Now follow the data-sheets for the ICs and the displays to connect the IC output pins to the 7 segment displays. The phase input (PH) and the blanking input (BI) should both be connected to ground. I left a longer loop of wire on the blanking input as I was considering using it to blank the display but this would have used another gpio pin. Instead, if you check the data-sheet, you'll find that if you set the data to a decimal number higher than 9 it will blank the display anyway.
Note, this is all 3.3v and I've used another couple of 220ohm resistors to limit the current into the ICs.

Software

To set a number on the display you follow this sequence:
  1. Keep what's on the display now - latch disable = off
  2. Set the data pins for the required number
  3. Disable the latch to take the value to the display - latch disable = on
  4. For timing purposes wait for a short period
  5. Keep what's on the display now - latch disable = off
The Python below counts from 0 to 99 in a continuous loop as seen in the video above.
'''
Created on 7 Jul 2012

@author: Jeremy

numdisplay - counts from 0 to 99 in a loop using two 7 segment displays

Read the blog entry at http://jeremyblythe.blogspot.com for more information
'''
import time
import RPi.GPIO as GPIO


LD = 13
DD = 12
DC = 11
DB = 15
DA = 16
LD2 = 18


GPIO.setup(LD, GPIO.OUT)
GPIO.setup(DD, GPIO.OUT)
GPIO.setup(DC, GPIO.OUT)
GPIO.setup(DB, GPIO.OUT)
GPIO.setup(DA, GPIO.OUT)
GPIO.setup(LD2, GPIO.OUT)

def write_gpo(pin,state):
    GPIO.output(pin,state)

last_tens = None
    
def write(tens,units):
    global last_tens
    if last_tens != tens:
        #tens
        #keep what's on the display now - latch
        write_gpo(LD,False)
        write_digit(tens) 
        #disable the latch to take the value to the display
        write_gpo(LD,True)
        time.sleep(0.1)
        #keep what's on the display now - latch
        write_gpo(LD,False)
        last_tens = tens

    #units
    #keep what's on the display now - latch
    write_gpo(LD2,False)
    write_digit(units) 
    #disable the latch to take the value to the display
    write_gpo(LD2,True)
    time.sleep(0.1)
    #keep what's on the display now - latch
    write_gpo(LD2,False)
         
    
def write_digit(digit):    
        if digit == None:
            #blank
            write_gpo(DD,True)
            write_gpo(DB,True)
        else:
            if digit & 8 > 0:
                write_gpo(DD,True)
            else:
                write_gpo(DD,False)
            
            if digit & 4 > 0:
                write_gpo(DC,True)
            else:
                write_gpo(DC,False)
            
            if digit & 2 > 0:
                write_gpo(DB,True)
            else:
                write_gpo(DB,False)
                
            if digit & 1 > 0:
                write_gpo(DA,True)
            else:
                write_gpo(DA,False)

if __name__ == '__main__':
    t = 0
    u = 0
    while True:
        u=u+1
        if u > 9:
            t=t+1
            u = 0
        if t > 9:
            t = 0
        write(t,u)

        
On my live site (http://jerbly.uk.to/picam) you can enter a number that you want to send to the display. Here's the code to achieve that using the Flask web framework:

'''
Created on 8 Jul 2012

@author: Jeremy

numweb - writes the incoming 2 digit number to a pair of 7 segment displays

Read the blog entry at http://jeremyblythe.blogspot.com for more information
'''
import numdisplay
from datetime import datetime

from flask import Flask
app = Flask(__name__)

@app.route("/num/")
def num(number=None):
    if number == None:
        numdisplay.write(None, None)
    else:
        n = number % 100
        u = n % 10
        t = (n-u) / 10
    numdisplay.write(t, u)
    log(number)
    return "OK"

def log(number):
    with open('/tmp/numweb.log','a') as f:
        f.write('%s - %s\n' % (str(datetime.now()),number))

if __name__ == "__main__":
    app.run('0.0.0.0',8092)

This uses numdisplay.py and adds a very simple web interface. Run this up and go to http://{ip address}:8092/num/{number}. e.g. http://192.168.0.2:8092/num/12 to display 12.

Kits

I'm considering putting some kits together with the resistors, ICs and displays for people to buy if there's enough interest. It may turn out to be more cost effective if I buy some in bulk and then sell on to you. Let me know if you would be interested by leaving a comment below. Thanks.
Post a Comment