Controlling a 7 segment 4 digit display with a Raspberry Pi


24 posts
by bertwert » Sun Nov 16, 2014 5:10 pm
http://www.instructables.com/id/Control ... ith-a-Ras/
This instructable I made shows how to control a display.
Here is how:

Wiring:
The pins are connected to the Pi through a resistor and some directly.
See the diagrams for details and pin positionnement.
Image
Image

The python modules; time and RPI.GPIO are required for this code.
Code:
Code: Select all
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

GPIO.setwarnings(False)

GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

segments = (24,12,19,21,23,22,15,11)

for segment in segments:

    GPIO.setup(segment, GPIO.OUT)

    GPIO.output(segment, 0)

digits = (26,18,16,13)

for digit in digits:

    GPIO.setup(digit, GPIO.OUT)

    GPIO.output(digit, 1)

num = {' ':(0,0,0,0,0,0,0),

    '0':(1,1,1,1,1,1,0),

    '1':(0,1,1,0,0,0,0),

    '2':(1,1,0,1,1,0,1),

    '3':(1,1,1,1,0,0,1),

    '4':(0,1,1,0,0,1,1),

    '5':(1,0,1,1,0,1,1),

    '6':(1,0,1,1,1,1,1),

    '7':(1,1,1,0,0,0,0),

    '8':(1,1,1,1,1,1,1),

    '9':(1,1,1,1,0,1,1)}

try:

    while True:

        n = time.ctime()[11:13]+time.ctime()[14:16]

        s = str(n).rjust(4)

        for digit in range(4):

            for loop in range(0,7):

                GPIO.output(segments[loop], num[s[digit]][loop])

        if (int(time.ctime()[18:19])%2 == 0) and (digit == 1)

            GPIO.output(11, 1)

        else:

            GPIO.output(11, 0)

        GPIO.output(digits[digit], 0)

        time.sleep(0.001)

        GPIO.output(digits[digit], 1)

except KeyboardInterrupt:

    GPIO.cleanup()

And we are done!
This will be a clock.
Have fun!
Last edited by bertwert on Fri Nov 27, 2015 11:10 pm, edited 1 time in total.
Please correct me if I am wrong ;-)

Please post your code with these tags:
[code]Your Code Goes Here[/code]

BERTWERT
User avatar
Posts: 585
Joined: Tue Aug 13, 2013 8:15 pm
Location: Golden, BC, Canada
by bertwert » Wed Feb 11, 2015 7:01 pm
EDITED:
There were errors in the code indentation, now corrected!
Please correct me if I am wrong ;-)

Please post your code with these tags:
[code]Your Code Goes Here[/code]

BERTWERT
User avatar
Posts: 585
Joined: Tue Aug 13, 2013 8:15 pm
Location: Golden, BC, Canada
by DougieLawson » Wed Feb 11, 2015 7:59 pm
You're using 12 GPIO lines to drive four displays. Now look at using a shift register or BCD to 7-segment controller chip. You can easily drive 16, 7-segment displays on 8 gpio lines (four for data, four for select).
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

Since 2012: 2B*2, B+, A+, 5Bs, zero, 3B

Please post ALL technical questions on the forum. Do not send private messages.
User avatar
Posts: 25245
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
by icemann1978 » Tue Oct 27, 2015 8:54 am
Hi,

I Come from Germany and my English is bad... Sorry about that.
I try 5 days to run a 7 segment display like this example but it doesn't work. Cable 10 times checked segment for segment tested. Has anything changed python or so?
Posts: 6
Joined: Tue Oct 27, 2015 8:44 am
by DougieLawson » Tue Oct 27, 2015 12:22 pm
How do you have your display wired give us a Fritzing diagram and/or a photo of your wiring? Are you using a BCD to 7-seg decoder? Are you using a shift register? Or are you trying to multiplex the display directly from the GPIO pins?
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

Since 2012: 2B*2, B+, A+, 5Bs, zero, 3B

Please post ALL technical questions on the forum. Do not send private messages.
User avatar
Posts: 25245
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
by icemann1978 » Tue Oct 27, 2015 8:41 pm
hi,

i'am try it exactly like the example in the first post

pict:

Image
Posts: 6
Joined: Tue Oct 27, 2015 8:44 am
by DougieLawson » Tue Oct 27, 2015 9:11 pm
I'll need to run an experiment to work out what's wrong. Watch this space ...
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

Since 2012: 2B*2, B+, A+, 5Bs, zero, 3B

Please post ALL technical questions on the forum. Do not send private messages.
User avatar
Posts: 25245
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
by icemann1978 » Wed Oct 28, 2015 4:52 pm
oh thanks, thats nice
Posts: 6
Joined: Tue Oct 27, 2015 8:44 am
by DougieLawson » Wed Oct 28, 2015 4:58 pm
First question is your 7 seg display common anode or common cathode? The OP doesn't tell us which model he's using. If it's the opposite we're going to have to turn all the logic upside down in his code.
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

Since 2012: 2B*2, B+, A+, 5Bs, zero, 3B

Please post ALL technical questions on the forum. Do not send private messages.
User avatar
Posts: 25245
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
by icemann1978 » Wed Oct 28, 2015 5:03 pm
i have 7seg with common anode, i think he also.
Posts: 6
Joined: Tue Oct 27, 2015 8:44 am
by rugabi94 » Fri Oct 30, 2015 11:30 am
It's not really working for me. I think I have the correct wiring I have 4 digits 7 segment: LTC-5623-HR and I have
File "time.py", line 62
if (int(time.ctime()[18:19])%2 == 0) and (digit == 1)
^
SyntaxError: invalid syntax
Posts: 17
Joined: Fri Oct 30, 2015 11:28 am
by DougieLawson » Fri Oct 30, 2015 3:46 pm
My theory is proven @icemann1978's LED is common anode, the code is written for common cathode LEDs.

So all the logic has to be inverted. We end up with this version of Bert's code
Code: Select all
#!/usr/bin/python
# Bert's code re-written for common anode LED arrays.

import RPi.GPIO as GPIO
import time
import sys

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

#LED pin == GPIO == segment / digit
# 11     ==  24  == a
# 07     ==  12  == b
# 04     ==  19  == c
# 02     ==  21  == d
# 01     ==  23  == e
# 10     ==  22  == f
# 05     ==  15  == g
# 03     ==  11  == dp

segments = (24,12,19,21,23,22,15,11)

for segment in segments:
  GPIO.setup(segment, GPIO.OUT)
  GPIO.output(segment, 1)

# 12     ==  26  == digit 1
# 09     ==  18  == digit 2
# 08     ==  16  == digit 3
# 06     ==  13  == digit 4

digits = (26,18,16,13)
for digit in digits:
  GPIO.setup(digit, GPIO.OUT)
  GPIO.output(digit, 0)

num = {' ':(1,1,1,1,1,1,1),
'0':(0,0,0,0,0,0,1),
'1':(1,0,0,1,1,1,1),
'2':(0,0,1,0,0,1,0),
'3':(0,0,0,0,1,1,0),
'4':(1,0,0,1,1,0,0),
'5':(0,1,0,0,1,0,0),
'6':(0,1,0,0,0,0,0),
'7':(0,0,0,1,1,1,1),
'8':(0,0,0,0,0,0,0),
'9':(0,0,0,0,1,0,0)}

try:
  while True:
    n = time.ctime()[11:13]+time.ctime()[14:16]
    s = str(n).rjust(4)

    for digit in range(4):
      for loop in range(0,7):
        GPIO.output(segments[loop], num[s[digit]][loop])
        if (int(time.ctime()[18:19])%2 == 0) and (digit == 1):
          GPIO.output(11, 0)
        else:
          GPIO.output(11, 1)

      GPIO.output(digits[digit], 1)
      time.sleep(0.001)
      GPIO.output(digits[digit], 0)

except KeyboardInterrupt:
  GPIO.cleanup()
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

Since 2012: 2B*2, B+, A+, 5Bs, zero, 3B

Please post ALL technical questions on the forum. Do not send private messages.
User avatar
Posts: 25245
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
by icemann1978 » Fri Oct 30, 2015 5:16 pm
Wow thanks dougieLawson, I will try this


@rugabi94

Try a : at the end of the line after
== 1)
Posts: 6
Joined: Tue Oct 27, 2015 8:44 am
by icemann1978 » Sat Oct 31, 2015 12:31 pm
PERFECT!!!



DougieLawson you´re the BEST
many many thanks
Posts: 6
Joined: Tue Oct 27, 2015 8:44 am
by blachanc » Fri Nov 06, 2015 4:40 am
Using Dougie's code (Many thanks) I got it working with a 3.3v 4 digit display with built-in resistor.
I wired the display using my raspio Ruler as a reference, so I had to replace:

GPIO.setmode(GPIO.BOARD)
by:
GPIO.setmode(GPIO.BCM)

EBAY 8 SEG LED Board Four 8-Segment Digits Digital Display information Eg:Time Module

Fun an fast (but display is a bit dim, as each segment is on only 25% of the time)

Now, let's see if I can get my kids interested ;)

Ben
Autism/Asperger syndrome: what is your score on this quiz?
http://www.raspberrypi.org/forums/viewtopic.php?f=62&t=70191
User avatar
Posts: 444
Joined: Sat Jan 26, 2013 5:03 am
Location: Quebec,canada(french)
by bertwert » Sat Nov 07, 2015 8:50 pm
Thanks Dougie for covering for me.

I have been inactive on these forums for a while...
Please correct me if I am wrong ;-)

Please post your code with these tags:
[code]Your Code Goes Here[/code]

BERTWERT
User avatar
Posts: 585
Joined: Tue Aug 13, 2013 8:15 pm
Location: Golden, BC, Canada
by alexeames » Wed Nov 11, 2015 4:57 pm
I just went through this and wondered why I wasn't getting more than one digit.

I copied Bertwert's original code, and apart from fixing the missing : eventually I realised the copy & paste had messed up the indents so the loop was not iterating through all four segments.

I append the code in case it will help anyone else with the same issue. (Oh I changed everything to BCM as well, just to be awkward :lol: )


Oh yeah - one more thing. I don't think this line...

Code: Select all
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)


...is doing anything, since there is nothing connected to pin7/GPIO4, and it's not read in the script.

Code: Select all
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
segments = (8,18,10,9,11,25,22,17)

for segment in segments:
    GPIO.setup(segment, GPIO.OUT)
    GPIO.output(segment, 0)
digits = (7,24,23,27)

for digit in digits:
    GPIO.setup(digit, GPIO.OUT)
    GPIO.output(digit, 1)

num = {' ':(0,0,0,0,0,0,0),
    '0':(1,1,1,1,1,1,0),
    '1':(0,1,1,0,0,0,0),
    '2':(1,1,0,1,1,0,1),
    '3':(1,1,1,1,0,0,1),
    '4':(0,1,1,0,0,1,1),
    '5':(1,0,1,1,0,1,1),
    '6':(1,0,1,1,1,1,1),
    '7':(1,1,1,0,0,0,0),
    '8':(1,1,1,1,1,1,1),
    '9':(1,1,1,1,0,1,1)}

try:
    while True:
        n = time.ctime()[11:13]+time.ctime()[14:16]
        s = str(n).rjust(4)
        for digit in range(4):
            for loop in range(0,7):
                GPIO.output(segments[loop], num[s[digit]][loop])
                if (int(time.ctime()[18:19])%2 == 0) and (digit == 1):
                    GPIO.output(17, 1)
                else:
                    GPIO.output(17, 0)
            GPIO.output(digits[digit], 0)
            time.sleep(0.001)
            GPIO.output(digits[digit], 1)

except KeyboardInterrupt:
    GPIO.cleanup()
Alex Eames RasPi.TV, RasP.iO
User avatar
Forum Moderator
Forum Moderator
Posts: 2764
Joined: Sat Mar 03, 2012 11:57 am
Location: UK
by blachanc » Thu Nov 12, 2015 6:00 pm
Next step is converting this in a generic "display_script.py" reading its data from an external source.
The fun part is the display cannot stop/starve (always dynamic).

I am thinking about using the global variable approach os.environ.["7SEGDISP"]="0123":

example:
script "calculate_primes.py" outputs the value in chunck to a system ENV variable "7SEGDISP" , and "display_script.py" loops and constantly update the display according to the ENV variable "7SEGDISP".

I want to avoid passing data via a file (SD card wear), and I know that one flaw in my idea is that both scripts needs to be started in the same terminal.

let me know if you believe there is a better way than what i am thinking about (Maybe a ramdisk file ?)

Ben
Autism/Asperger syndrome: what is your score on this quiz?
http://www.raspberrypi.org/forums/viewtopic.php?f=62&t=70191
User avatar
Posts: 444
Joined: Sat Jan 26, 2013 5:03 am
Location: Quebec,canada(french)
by blachanc » Fri Nov 13, 2015 3:51 am
Well,
I learned something(correct me if I am wrong): a python script does not read the updated env variable value in a terminal. It will keep the values it reads when it is invoked.

SO I reverted back to my second idea of using a file on a ramdisk for communication(and it is working). I still wonder if there would be a better way.

this is the main display loop (display daemon):
display.py
Code: Select all
#!/usr/bin/python
# Bert's code re-written for common anode LED arrays.
#blachanc: used dougie's code and added external data input in ramdisk
import RPi.GPIO as GPIO
import time
import sys
GPIO.setmode(GPIO.BCM)
#GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

#LED pin == GPIO == segment / digit
# 11     ==  24  == a
# 07     ==  12  == b
# 04     ==  19  == c
# 02     ==  21  == d
# 01     ==  23  == e
# 10     ==  22  == f
# 05     ==  15  == g
# 03     ==  11  == dp

segments = (24,12,19,21,23,22,15,11)

for segment in segments:
  GPIO.setup(segment, GPIO.OUT)
  GPIO.output(segment, 1)

# 12     ==  26  == digit 1
# 09     ==  18  == digit 2
# 08     ==  16  == digit 3
# 06     ==  13  == digit 4

digits = (26,18,16,13)
for digit in digits:
  GPIO.setup(digit, GPIO.OUT)
  GPIO.output(digit, 0)

charactere = {' ':(1,1,1,1,1,1,1),
'0':(0,0,0,0,0,0,1),
'1':(1,0,0,1,1,1,1),
'2':(0,0,1,0,0,1,0),
'3':(0,0,0,0,1,1,0),
'4':(1,0,0,1,1,0,0),
'5':(0,1,0,0,1,0,0),
'6':(0,1,0,0,0,0,0),
'7':(0,0,0,1,1,1,1),
'8':(0,0,0,0,0,0,0),
'9':(0,0,0,0,1,0,0)}
counter=100000

##############################
# use a file on ramdisk to get the data to be displayed
# bash commands passed in terminal:
# sudo mkdir /mnt/ramdisk
# sudo mount -t tmpfs -o size=128K tmpfs /mnt/ramdisk
# sudo chown pi:pi /mnt/ramdisk
# echo "1235" > /mnt/ramdisk/display.dat
###############################
def get_data_to_display():
    txt=open("/mnt/ramdisk/display.dat")
    new_string = str(txt.readline())
    txt.close()
    new_string=new_string.rstrip()
   #
   # buf with 0 if less than 4 char
   #
    new_string= str(new_string).rjust(4,"0")
   #
   # limit to 4 chars
   #
    new_string= new_string[0:4]
    return new_string
###########
# main loop
###########
try:
  while True:
    #
   # First we only update the data to display each x loops
   #
    counter +=1
    if (counter > 50):
       counter = 0
       new_string = get_data_to_display()
# for debug only       print  new_string
       data_to_display = new_string

    for digit in range(4):
      for loop in range(0,7):
        GPIO.output(segments[loop], charactere[data_to_display[digit]][loop])
      GPIO.output(digits[digit], 1)
      time.sleep(0.001)
      GPIO.output(digits[digit], 0)

except KeyboardInterrupt:
  GPIO.cleanup()




and this is the data being feed to the display (scrolling numbers) for proof of concept.
feedata.py:
Code: Select all
#!/usr/bin/python

import time
import sys
counter = 0
data_to_display= "    "
###########
# main loop
###########
try:
  while True:
    counter +=1
    if (counter > 9):
       counter = 0
     #
     # shift the data to be displayed
     #
    data_to_display= data_to_display[1] + data_to_display[2] + data_to_display[3]+ (str(counter))[0]
    txt=open("/mnt/ramdisk/display.dat", "w" )
    txt.write(data_to_display)
    txt.close()
# For debug only    print data_to_display
    time.sleep(.5)
   
except KeyboardInterrupt:
  exit()

Autism/Asperger syndrome: what is your score on this quiz?
http://www.raspberrypi.org/forums/viewtopic.php?f=62&t=70191
User avatar
Posts: 444
Joined: Sat Jan 26, 2013 5:03 am
Location: Quebec,canada(french)
by Waynetho » Tue Apr 05, 2016 3:05 am
I'm new to Python and I was wanting to make a digital clock for my bedroom. I tore apart an old LED digital clock that didn't work right, scavenged the digit mask from the old display and build my own display using tiny red axial-leaded "SuperBright" LEDs.

I've got a couple of issues still outstanding with this approach, specifically the LEDs are *VERY" dim (I'll work on that, maybe using a higher voltage to the LEDs, switched by transistors. The second issue is that I would like the clock to be a 12-hour clock (AM/PM indicator is desirable, but not necessary).

My display has an incomplete first digit so it can only display a "1" or nothing for the first digit. It looks like the only way to accomplish this would be to use "time.strftime" instead of "time.ctime" because it has the option of %H for 24-hr hours or %I for 12-hr hours.

Does anyone have any suggestions on how to modify the code to display 12-hr time?
Posts: 1
Joined: Wed Mar 30, 2016 3:12 am
by DougieLawson » Tue Apr 05, 2016 9:39 am
The current code is using time.ctime() and parsing that. Change it to use time.strftime() and you can get the time in any format you need.

Code: Select all
>>> import time
>>> print time.ctime()
Tue Apr  5 09:38:06 2016
>>> print time.strftime('%I')
09
>>> print time.strftime('%I:%M %p')
09:38 AM
>>>
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

Since 2012: 2B*2, B+, A+, 5Bs, zero, 3B

Please post ALL technical questions on the forum. Do not send private messages.
User avatar
Posts: 25245
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
by teddycool » Sat Aug 20, 2016 5:35 pm
Thanx for sharing this!
I used it as a base in my project creating a display device that will show time, temperature and some other information on a 4-digit 7-segment display. The project is available here https://github.com/teddycool/ClockDisplay
Posts: 1
Joined: Sat Aug 20, 2016 5:29 pm
by depauw » Thu Sep 29, 2016 2:28 pm
Hey guys,
does anyone of you how to get this working, using zerogpio istead of the 'normal' gpio.
Been looking around for an example, but haven't found anything yet...... :(

Kind regards,
Christophe
Posts: 30
Joined: Mon Nov 09, 2015 2:12 pm
by Notilix » Mon Dec 05, 2016 9:03 pm
Hi!

I have a question about the code.

In the loop
Code: Select all
for loop in range(0,7):
you’re stating each GPIO to True for every segment needing light. Okay but you don’t light them now, you light them a bit further with
Code: Select all
GPIO.output(digits[digit], 0)
right?

What I don’t understand is this: if I need to display an “8.”, with your code I will power on 8 leds simultaneously for about 0.001s okay? But… every led consume about 13mA and 8*13 = 104. It doesn’t respect the 50mA total rule! Even for a very short perdiod, are you sure it doesn’t damage GPIO controller ?

What about limiting two or tree segments simultaneously for a very short time and then light another bunch of 3 leds but do not allow all leds if needed simultaneously? Wouldn’t be safer?
Posts: 30
Joined: Thu Dec 01, 2016 8:34 pm