Netduino Day 3 – Multiplexed Seven-Segment LED displays
|
A visual output always adds value to any project. In this third day tutorial, we are going to display some numeric, alphabetic as well as two symbolic characters on a 4-digit seven segment LED module. The way we are interfacing the seven segments LEDs is known as multiplexing, which allows to save some I/O pins of Netduino as compared to driving them individually. The seven segment LEDs are resource and power hungry, but we are going to do this experiment just to get our feet wet in the microcontroller or embedded world and to understand the basics of a seven segments LED displays.
In today’s experiment, we are going to read an analog voltage from an LDR sensor and display the ADC output on to four seven segment LEDs. As you might know seven segments LED is made with seven plus one LEDs. Each LED has its own name as we can see in the picture. To display digit “1”, we need to send high signal to the LED ‘b’ and ‘c’ only and ground the cathode. Now, let’s say we need to display “12”. The way we do is, we display “1” in one of LED unit then turn it off then we will display “2” in our second LED unit then turn it off too but we will turn on the first one. So, we will cycle the display of each letter in a loop resulting in the entire digit that we like to display. This basically is the multiplexing.
Circuit Setup and Theory
In this tutorial also, we can split our connections into two categories, Analog and Digital. In analog section, we have used an LDR as our analog input device. With the illumination, the resistance of the LDR will change causing change in voltage. This type of connection is sometime referred as voltage divider. The drop or rise in voltage across the LDR will be an input for our analog pin.
In the digital section, connections are straightforward. Each pin (a through g) of the seven segments LED are connected to the digital I/O of the Netduino through a resistor and from our code we are controlling which to turn high or low. The seven segments LED used in this tutorial is a common cathode and there are four units of them combined into one whose internal connection looks like this.
In order to turn the LED on, we need to set the anode pins to high and selected cathode to ground. Question is, how can we ground the selected pin when we need? If we can connect a switch and then toggle the switch when need to ground will work for us. To facilitate this, we can use transistor as a switch. Connecting transistor as a switch is what we already have learned in first tutorial (Basic Input and Output). As shown in the circuit, we have connected the base of each transistor to certain Digital I/O of our Netduino, emitter is grounded and collector is connected to anodes of seven segments LED. When the base of transistor is set to high, transistor’s switch turns on then the corresponding anode gets connected to ground which completes the circuit and turns the LED to ON.
Connection with Netduino or Netduino Plus
C#.NET Program
This time our code looks little intensive as I have created little library (SevenSegments Class) that supports little more than displaying digits. Let’s look at it step by step. In the code below, we first created an instance of AnalogInput class which allows us getting the value from our analog device which is LDR in this case. Then we created a separate instance of SevenSegments class. The constructor of this class takes several pins as arguments. Once we have SevenSetments instance we simply call the Show method and pass the value that we read from Analog device.
public static void Main() { AnalogInput aInPin = new AnalogInput(Pins.GPIO_PIN_A1); //use any analog pin aInPin.SetRange(0, 1234); //give a range. Debug.Print("Analog value: " + aInPin.Read()); // initialize the seven segments LED and pass appropriate pins SevenSegments sevenSegments = new SevenSegments( Pins.GPIO_PIN_D0, Pins.GPIO_PIN_D1, Pins.GPIO_PIN_D2, Pins.GPIO_PIN_D3, Pins.GPIO_PIN_D4, Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D6, new Cpu.Pin[] { Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11 }); // Display value read by analog device sevenSegments.FlickerDelay = 5; // Pause between each letter during repetition in a LED unit sevenSegments.UnitSevenSegmentLedDelay = 1; //Duration of a LED unit being ON sevenSegments.UnitRepetition = 50; // Repetition of entire strip while (true) { sevenSegments.Show(aInPin.Read()); Debug.Print(aInPin.Read().ToString()); } } |
Main heavy lifting is done in the SevenSegment class. So, let’s take a quick look at different sections of this class.
Constructor section of the SevenSegment Class
Here we have defined some Digital I/O for LED segments a through g. To support any number of LED units, the common Anode or Cathode pins are received as an array. Now, to show a letter or an alphabet, I have constructed an array of Boolean. All such arrays are stored in a HashTable with a key that corresponds to a digit or an alphabet or a symbol. Finally a few properties are initialized with some values.
public SevenSegments(Cpu.Pin a, Cpu.Pin b, Cpu.Pin c, Cpu.Pin d, Cpu.Pin e, Cpu.Pin f, Cpu.Pin g, Cpu.Pin[] commonAnodeCathodePin) { // (wire color is for personal reference) OutputPort PinD0Out_a = new OutputPort(a, false); //11 Black OutputPort PinD1Out_b = new OutputPort(b, false); //7 Brown OutputPort PinD2Out_c = new OutputPort(c, false); //4 Red OutputPort PinD3Out_d = new OutputPort(d, false); //2 orange OutputPort PinD4Out_e = new OutputPort(e, false); //1 Yellow OutputPort PinD5Out_f = new OutputPort(f, false); //10 Green OutputPort PinD6Out_g = new OutputPort(g, false); //5 Blue segmentPins = new OutputPort[] { PinD0Out_a, PinD1Out_b, PinD2Out_c, PinD3Out_d, PinD4Out_e, PinD5Out_f, PinD6Out_g }; // initialize commonAnodeCathodePin ledSegmentUnit = new OutputPort[commonAnodeCathodePin.Length]; for (int i = 0; i < commonAnodeCathodePin.Length; i++) { ledSegmentUnit[i] = new OutputPort(commonAnodeCathodePin[i], false); } // create a list of supported display ledSegmentTable = new Hashtable(); ledSegmentTable.Add("0", new bool[] { true, true, true, true, true, true, false }); ledSegmentTable.Add("1", new bool[] { false, true, true, false, false, false, false }); ledSegmentTable.Add("2", new bool[] { true, true, false, true, true, false, true }); ledSegmentTable.Add("3", new bool[] { true, true, true, true, false, false, true }); ledSegmentTable.Add("4", new bool[] { false, true, true, false, false, true, true }); ledSegmentTable.Add("5", new bool[] { true, false, true, true, false, true, true }); ledSegmentTable.Add("6", new bool[] { true, false, true, true, true, true, true }); ledSegmentTable.Add("7", new bool[] { true, true, true, false, false, false, false }); ledSegmentTable.Add("8", new bool[] { true, true, true, true, true, true, true }); ledSegmentTable.Add("9", new bool[] { true, true, true, true, false, true, true }); ledSegmentTable.Add("a", new bool[] { true, true, true, false, true, true, true }); ledSegmentTable.Add("b", new bool[] { false, false, true, true, true, true, true }); ledSegmentTable.Add("c", new bool[] { true, false, false, true, true, true, false }); ledSegmentTable.Add("d", new bool[] { false, true, true, true, true, false, true }); ledSegmentTable.Add("e", new bool[] { true, false, false, true, true, true, true }); ledSegmentTable.Add("f", new bool[] { true, false, false, false, true, true, true }); ledSegmentTable.Add("g", new bool[] { true, true, true, true, false, true, true }); ; ledSegmentTable.Add("h", new bool[] { false, false, true, false, true, true, true }); ledSegmentTable.Add("i", new bool[] { false, true, true, false, false, false, false }); ledSegmentTable.Add("j", new bool[] { false, true, true, true, true, false, false }); ledSegmentTable.Add("l", new bool[] { false, false, false, true, true, true, false }); ledSegmentTable.Add("n", new bool[] { false, false, true, false, true, false, true }); ledSegmentTable.Add("o", new bool[] { false, false, true, true, true, false, true }); ledSegmentTable.Add("p", new bool[] { true, true, false, false, true, true, true }); ledSegmentTable.Add("q", new bool[] { true, true, true, false, false, true, true }); ledSegmentTable.Add("r", new bool[] { false, false, false, false, true, false, true }); ledSegmentTable.Add("s", new bool[] { true, false, true, true, false, true, true }); ledSegmentTable.Add("t", new bool[] { false, false, false, true, true, true, true }); ledSegmentTable.Add("u", new bool[] { false, false, true, true, true, false, false }); ledSegmentTable.Add("y", new bool[] { false, true, true, false, false, true, true }); ledSegmentTable.Add("-", new bool[] { false, false, false, false, false, false, true }); ledSegmentTable.Add("?", new bool[] { false, true, true, false, true, true, false }); ledSegmentTable.Add("?", new bool[] { true, false, false, true, false, false, true }); // Initialize fields to its default FlickerDelay = 5; SevenSegmentsUnits = commonAnodeCathodePin.Length; UnitSevenSegmentLedDelay = 0; UnitRepetition = 50; RightToLeft = true; } |
Public Show Methods
To show a digit or alphabet, we have exposed a Show method in the class. There are three overloads of this Show method. First one takes int as an argument and directly calls second Show method which takes string as an argument. In this method, depending on whether RightToLeft is set to true or false, code jumps to corresponding section. This section basically extracts the right letter to display and then calls the third Show method.
public void Show(string stringToShow) { // this loop will make it appear that all the LED units remained ON. for (int j = 0; j < UnitRepetition; j++) { if (RightToLeft) { int ledUnit = SevenSegmentsUnits - 1; // 0 based index for (int i = stringToShow.Length; i > 0; i--) { string eachLetter = stringToShow.Substring(i - 1, 1); Show(eachLetter, ledUnit); ledUnit -= 1; // If length of stringToShow is greater than SevenSegmentsUnits rest it if (ledUnit < 0) ledUnit = SevenSegmentsUnits - 1; // - 1 as it's 0 based index Thread.Sleep(UnitSevenSegmentLedDelay); } } else { int ledUnit = 0; // 0 based index for (int i = 0; i < stringToShow.Length; i++) { string eachLetter = stringToShow.Substring(i, 1); Show(eachLetter, ledUnit); ledUnit += 1; // If length of stringToShow is greater than SevenSegmentsUnits rest it ledUnit = ledUnit % SevenSegmentsUnits; Thread.Sleep(UnitSevenSegmentLedDelay); } } Thread.Sleep(FlickerDelay); } } |
The third Show method takes two arguments, first one is the string to display and second one is where to display i.e. in which LED unit to display. From the HashTable defined during construction, it finds out the correct array of Boolean then corresponding pin is set to high or low based on this Boolean array. In final step, all common anode or cathode pins are set to low then only the appropriate LED unit is set to high.
public void Show(string numberString, int ledUnit) { bool[] ledSegmentOnOffValues; numberString = numberString.ToLower(); // at this level, string of unit lenght is supported so drop the rest if (numberString.Length > 1) numberString = numberString.Substring(numberString.Length - 1, 1); // Send Low to the common anode/cathode of SevelSegmentLED for (int i = 0; i < ledSegmentUnit.Length; i++) { ledSegmentUnit[i].Write(false); } if (!ledSegmentTable.Contains(numberString)) { // when non supported letter is passed display "-" ledSegmentOnOffValues = (bool[])ledSegmentTable["-"]; } else { // get the true/false array ledSegmentOnOffValues = (bool[])ledSegmentTable[numberString]; } for (int i = 0; i < segmentPins.Length; i++) { //make the corresponding pin high segmentPins[i].Write(ledSegmentOnOffValues[i]); } // Only send signal to the selected Anode/Cathode ledSegmentUnit[ledUnit].Write(true); } |
Expansion of SevenSegments Class with a Counter
With a very few lines of code we can expand or add additional functionality such a counter which counts from min to max value. This Counter is a very simple example that takes two arguments, min value and the max value. A for loop has been setup from this min to max value and the Show method has been called passing the current loop increment. This method enables us to display the counter in our seven segments LED unit.
public void Counter(int minValue, int maxValue) { for (int i = minValue; i <= maxValue; i++) { Show(i); Debug.Print(i.ToString()); } } |
Output
With our SevenSegments class, we have several outputs. First let’s look at the output of our circuit. Here we can see the lower value in our display when LDR is covered however the number goes up as we illuminate our LDR.
Now let’s look at our counter method that we have added to our SevenSegments class. With the following code, we will see the counting numbers in SevenSegments LED from 980 to 1020.
sevenSegments.FlickerDelay = 5; // Pause between each letter during repetition in a LED unit sevenSegments.UnitSevenSegmentLedDelay = 1; //Duration of a LED unit being ON sevenSegments.UnitRepetition = 5; // Repetition of entire strip sevenSegments.RightToLeft = true; while (true) { sevenSegments.Counter(980, 1020); } |
Let’s give a longer string than our Seven Segment LED units are and see what happens.
sevenSegments.FlickerDelay = 10; // Pause between each letter during repetition in a LED unit sevenSegments.UnitSevenSegmentLedDelay = 500; //Duration of a LED unit being ON sevenSegments.UnitRepetition = 1; // Repetition of entire strip sevenSegments.RightToLeft = false; while (true) { sevenSegments.Show("1234567890abcdefghijklmnopqrstuvwxyz"); sevenSegments.Show("????"); sevenSegments.Show("Embedded-Lab"); } |
Now, let’s tweak some of its property and see a rolling effect.
sevenSegments.FlickerDelay = 5; // Pause between each letter during repetition in a LED unit sevenSegments.UnitSevenSegmentLedDelay = 200; //Delay Duration of a LED unit being ON sevenSegments.UnitRepetition = 50; // Repetition of entire strip sevenSegments.RightToLeft = false; while (true) { sevenSegments.Show("-Lab"); } |
What’s Next
In our next tutorial, we will control seven segment LED using MAX7215. As this IC supports SPI communication protocol, only 3 numbers of wires will be required to control our seven segment LED. Eight Digit Seven Segment LED Display with MAX7219
|
Hi,
very nice article could not find any download link for the source code for NETDUINO DAY 3 – MULTIPLEXED SEVEN-SEGMENT LED DISPLAYS.
Pingback: Tutorial Netduino Parte 3 « Soloelectronicos
I am downloading each “Days” code file, and there is no Day 3 file?
I would just copy the C# code, but it loses all formatting when I cut-and-paste to VS2010
Thanks,
–Steve
The figure says “Four units Common Cathode Seven Segments LED”. But isn’t it Common Anode?
Hi Emre,
You are right, we need to fix the picture. Thank you.
Great job, easy to understand tutorial! Hugs from Brazil