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.

Seven Segments LED displaying Letter 'A'

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.

Seven Segments LEDs Names

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.

Four units Common Cathode Seven Segments LED

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.

Circuit Digram connecting Seven Segments LED and LDR

Connection with Netduino or Netduino Plus

Breadboard Connection: Seven Segments LED and Netduino

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.

 

Seven Segments LED displaying letter 'L'

 

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

3 comments

Leave a Reply

Your email address will not be published. Required fields are marked *