Multiplexing 7-Segment Displays
As a small aside project I had some 7-Segment-LED's lying around and didn't really have a purpose for them - Until Now!
Wednesday 21st June 2017
I decided that to learn how to use 7-Segment Displays, it would be a good idea to try and make a digital clock. It was all going well until I realised that I couldn't really plug in all of the pins of the 7-Segment Displays to the Pi because there were so many of them - Instead I learned all about multiplexing!
Multiplexing means that all of the displays are effectively wired in parallel to each other and the grounds of each displays go through transistors (4 in total) so that each display can be turned on individually while only using 13 wires instead of to 36 that would be required otherwise. This is calculated by the sum of the number of input pins of one display plus the number of displays that are being used: 9 + (number of displays) = 13
Below is the schematic for this project. Essentially I have 8 wires coming from the Pi that are connected straight to GPIO outputs (One for each segment) that are then wired in parallel to all of the displays. There is another wire that connects to ground on the Pi and this gets switched through 4 transistors - One for each display so that i can turn them on individually.
Pin Numbers/Pin Outs
Firstly there are 4 displays on this project. The Displays are numbered 1, 2, 3, 4, from left to right and they are connected to ground though a resistor and transistor. This table shows how the base of each transistor should be connected to the Pi (Through a resistor - 10K ohms or greater)
Each of the displays has 10 Pins, 2 for ground and the rest each control a single segment. This means that all you have to do is connect each display pin in parallel. For example, you would connect all of the 'A' pins together, 'B' Pins together etc.
How It Works
Multiplexing works around the fact that the human eye is relatively slow at seeing fast changes, meaning if we can turn the segment on and off fast enough we can trick our eyes into seeing a static display. This is easily achievable with modern processors. In this program there is no pause on each loop meaning it is running as fast as it can.
The first thing I tried to do when developing this idea was to create a simple counter that would display a countdown from 9999 and then moving on to creating the clock later on.
Once a number has been chosen to be displayed, for example 1234, the program will first calculate how many digits there are to display. This is important as it will define how many of the displays are to be used. A 1 digit number will use 1 display, 2 digit numbers will use 2 displays and so on. I achieved this by simply having an if condition that compares the number to be displayed to a range checker. What I mean by this is that a 1 digit number will be between 0 and 9, in other words, less than 10:
A two digit number will be 10 or greater and less than 100, similarly a 3 digit number will be greater than or equal to 100 and less than 1000. A 4 digit number will follow the same sort of pattern:
Once the number of displays to be used has been calculated, the next step it to break the number down into each individual number for each display. In our example; Display 1 will have the number 1, Display 2 will have the number 2, Display 3 = 3 and Display 4 = 4. This is figured out by using a substring function to get each number.
Now that the program has the number to be display on each display, it is now time to work out what segments must be illuminated to construct it. For the number 1 to be displayed on the 1st display, then segments B and C must be used. The program works out what segments are needed by referring to a pre-defined dictionary that holds these values. The segments that must be illuminated are then stored in variables so that they can be passed into a function later to turn them on:
Finally all that is left to do is turn on the appropriate segments on each display. To do this, the program runs in chronological order. At first, the transistor for the first display is enabled and the rest of the displays are disabled, this means the number will only appear on one display. Next a function is called and the string of segments that have to be enabled is passed in, in this case B and C. This function will go through each letter in the string and turn on the correct pin, again based on dictionary values that have been pre-defined. Once the first number is 'written' to the display, the second display is turned on and the rest are turned off. The process repeats and now the string ABGED is passed in to enable the correct segments for the number 2. This continues for each of the numbers and then repeats 100 times to add a sort of artificial delay without explicitly defining a pause in the program. This creates the illusion that a 4 digit number is being displayed when in fact 4, 1 digit numbers are being displayed individually but we just can't see it with our own eyes.
And there it is! A working, functional countdown 7-segment display capable of displaying up to 4 digits at a time. It is relatively easy to modify the code to make this into a clock instead. Where the counter is defined/modified on lines 134-139 by taking 1 away from the current number, this can be changed to read the time in HHMM form without a colon in the middle. The 7-segment displays actually have 8 segments, the 8th being a dot in the bottom right (usually). This can be defined to always be on for the second display to represent the dot in between HH and MM.
Click Here to Show Entire Code
I really enjoyed this mini project as I learned how multiplexing worked and I will now be able to use it in situations where I normally wouldn't have enough pins to otherwise connect as many devices. Going into this project I had a small idea of how multiplexing would work but deliberately avoided Google for once so that I could see how I would approach the problem in my own way. I love problem solving like this and it's great when I can think of scenarios to learn more and develop my skills further. I am very aware that this code could be cleaned up a lot and made more efficient by the likes of replacing all of the IF conditions for the length of the number to be displayed with just the 4 digit number condition and adding blank placeholders onto the start. I wanted to share how my first, unpolished projects come around and I believe that I did quite well :)