Chapter 8: Displaying Information



Figure 1: 7-segment LED time display



Last month we looked at motion and position control using the variable resistance of potentiometers. This culminated with labs that lead up to using the turning of a potentiometer knob to control the motion and position of a servomotor.

We've learned a lot of fundamental principles for both computing and electronics and we have reinforced that learning with hands-on laboratory exercises. This month we will go very light on new fundamental information and have some fun with a bunch of labs that deal with my favorite thing: blinking LEDs.

This month we will look at displaying information using LEDs configured as a bar-graph and as a 7-segment single character display.

You can download the Arduino source code for this chapter from:
A101_ch8_supplemental.zip

 

Chapter 8: Displaying Information



Figure 1: 7-segment LED time display



Last month we looked at motion and position control using the variable resistance of potentiometers. This culminated with labs that lead up to using the turning of a potentiometer knob to control the motion and position of a servomotor.

We've learned a lot of fundamental principles for both computing and electronics and we have reinforced that learning with hands-on laboratory exercises. This month we will go very light on new fundamental information and have some fun with a bunch of labs that deal with my favorite thing: blinking LEDs.

This month we will look at displaying information using LEDs configured as a bar-graph and as a 7-segment single character display.

You can download the Arduino source code for this chapter from:
A101_ch8_supplemental.zip

What is information?



Information is something that informs - it provides data - it settles uncertainty - and it is hard to define without eating it's own tail. There is something unknown, then information happens and that something is known. Up to now we have sent information to the Arduino and received information from it using the USB connection to a PC and the Arduino IDE's Serial Monitor. Now we will look at two simple ways to convey information from an Arduino to someone without having to have the USB hooked up to a PC.

First we'll look at an LED bar graph. You've probably seen these on audio equipment where the number of LEDs lit informs you of something like the audio signal volume. One might also be used as a sort of gas gauge where the number of LEDs lit represents the amount of fuel available.

Next we'll look at a 7-segment LED like the four shown in Figure 1. These be used to display numbers, and, if you make allowances, you can crudely display the entire alphabet.

Lab 1: Lighting the bar graph segments - digital


For our first lab exercise we will build a computer controlled electronic bar graph display and we will write a simple program to scroll the LEDs in the display. We will also discuss the source code in detail as a form of review of the coding principles we have learned so far.

Parts Required:
1 Arduino
1 Arduino Proto Shield and jumper wires
7 LEDs
7 1000 Ω resistors

Estimated time for this lab: 30 minutes

 Check off when complete:
Build the circuit shown in Figures 2, 3, 4 and 5. In this circuit each LED has an individual 1k Ω, but each of these resistors is carried to ground by a bundling of wires that may be somewhat difficult to visualize.

Figure 2 - Bar graph breadboard

 

Figure 3 - Bar graph schematic

 

Figure 4 - Bar graph photo

 

Figure 5 - Bar graph wiring details



Either cut and paste, or type in the following program into the Arduino IDE. [Or open the A101_ch8_bar_graph.ino program - note this file is located in A101_ch8_supplemental.zip. You can find a link to this file near the top of this chapter.] 

  
// A101_ch8_bar_graph Joe Pardue 5/31/14

// lowest indication starts with LED 6
// hightest indication ends with LED 12
int low = 6;
int high = 12;

// milliseconds between LED turn ons
#define SPEED 50
#define PAUSE 500

void setup(){
  // Set LED pin modes to output
  for(int i = low; i <=high; i++){
    pinMode(i, OUTPUT);
  }
}

void loop(){ 
 // scroll LEDs on
 for(int i = low; i <= high ; i++)
 {
   digitalWrite(i, HIGH);
   delay(SPEED);             
 } 
 
 delay (PAUSE); // pause between scrolling LEDs
 
 // scroll LEDs off
 for(int i = high; i >= low; i--){
   digitalWrite(i, LOW); 
   delay(SPEED); 
 }  
 
 delay(PAUSE); // pause between scrolling LEDs  
}


Observe the LED scrolling pattern.
Read the following source code discussion to fully understand how this program works and to reinforce the programming concepts shown in this program.
Go to the forum on www.arduinoclassroom.com if you have any questions.

Source code discussion


Let's take a few moments to review each line of this code to reinforce what we have learned so far. If you completely understand all the code shown above, you can safely skip this discussion, but if you are the least iffy, then read it. And if after reading it you still have questions then don’t hesitate to go to the forum at www.arduinoclassroom.com to get some answers.

The first line in the program:
// A101_ch8_bar_graph_data_display Joe Pardue 5/31/14
Identifies the name of the source code, the author and the date the code was released.

The next section defines two variables available for use by functions within this module.

  
int low = 6; // lowest indication starts with LED 6
int high = 12; // hightest indication ends with LED 12


We define variables by first indicating the variable type, in this case they are of the 'int' type that, for the Arduino, can contain numbers from 0 to 65535. The first variable is named 'low' and set to equal the rightmost LED in our design, which is connected to Arduino pin 6. The second variable is named 'high' and set equal to the leftmost LED in our design, which is connected to the Arduino pin 12. Each of the 7 LEDs is connected sequentially from pin 6 to pin 12. Make certain that you can relate this source code for the pin usage to the illustrations shown in Figures 2, 3, 4 and 5. These LEDs can be lit to represent a relative magnitude from 0, non lit, to 7, all lit. Since the pin numbering and the LED numbering are offset by 6, that is to say that the lowest LED is located on pin 6 then a magnitude of 1 would be represented by lighting the LED on pin 6, a magnitude of 2 would be represented by lighting the LEDs on pins 6 and 7, and so on to a magnitude of 7 represented by all the LEDs from pin 6 to pin 12.

The next section of code defines two constant values for milliseconds we will use to provide delays between turning on each LED (SPEED) and between scrolling them all on and all off (PAUSE).

  
// milliseconds between LED turn ons
#define SPEED 50
#define PAUSE 500



The first function in an Arduino program is setup() where we do things once that need to be done before we run the program. In this case we set each of the pins connected to LEDs to be outputs so that we can provide current to turn the LEDs on or off.

  
void setup(){
  // Set LED pin modes to output
  for(int i = low; i <=high; i++){
    pinMode(i, OUTPUT);
  }
}


Inside the setup() function we have a for-loop that is used to set the LED pins to output.

    
  // Set LED pin modes to output
  for(int i = low; i <= high; i++){
    pinMode(i, OUTPUT);
  }


The for-loop has three components, first is the variable 'i' defined as an int and set to the value of 'low', the rightmost LED pin. The next states the 'i' shall be less than or equal to 'high', the leftmost LED pin position. The last element increments 'i' so that on each pass through the for-loop ‘i’ increases in value by 1. In this case the ‘i’ starts out with a value of 6 (low) and then after each pass through the loop it increases by 1 while it is less than or equal to 12 (high). When the 'i++' sets i to 13 which is not less than or equal to 'high' (12) then the code exits the for-loop.

Within the for-loop we see:

pinMode(i, OUTPUT);

We learned that the pinMode() function takes an Arduino pin number as the first parameter and then sets that pin to be either an input or an output depending on the value of the second parameter. We set it to OUTPUT which is a constant defined in the depths of the Arduino library that tells the pinMode function to set the indicated pin to output.

We use a for-loop to run this function 7 times but we could also have avoided the for-loop and written:

  
    pinMode(low, OUTPUT);
    pinMode(low+1, OUTPUT);
    pinMode(low+2, OUTPUT);
    pinMode(low+3, OUTPUT);
    pinMode(low+4, OUTPUT);
    pinMode(low+5, OUTPUT);
    pinMode(low+6, OUTPUT);


Either form will work and which to use is up to the person who writes the code. As a rule of thumb you might just write out the operations as shown if you have 4 or fewer iterations and use a for (or while) loop for more that that.


Next we have the loop() function where the Arduino performs repetitive operations. In this code we will run a for-loop to turn on all the LEDs, pause, then run a for-loop to turn off all the LEDs, pause, and repeat forever.

  
void loop(){ 
 // scroll LEDs on
 for(int i = low; i <= high ; i++)
 {
   digitalWrite(i, HIGH);
   delay(SPEED);             
 } 
 
 delay (PAUSE); // pause between scrolling LEDs
 
 // scroll LEDs off
 for(int i = high; i >= low; i--){
digitalWrite(i, LOW); delay(SPEED); } delay(PAUSE); // pause between scrolling LEDs }


The first for-loop starts with the low (rightmost) LED and turns it on and the sequentially turns on each higher value LED until it gets to the high (leftmost) LED. It uses the digitalWrite() function where the first parameter 'i' is the Arduino pin number to set and the second parameter is HIGH a constant that tell it to provide a high voltage (+5 volts) to that pin. The next function is a delay set to the constant SPEED and the only purpose of that line is to slow down the process so as to animate the LEDs turning on. After the loop finishes, another delay is called using PAUSE to provide another animation effect. The next for-loop starts where the first on left off, with all the LEDs lit, and it turns them off in the opposite order from how they were turned on. It starts with the high LED, turns it off, decrements the value of i and repeats until it has counted down from high to low turning off each LED in sequence. The digitalWrite() function is given the pin number and then told to set it LOW which turns off the +5V. After this there is another pause delay and then the loop begins again at the top and loops forever scrolling the LEDs.

Lab 2: Data display on a bar graph


In Lab 1 we discussed in detail how that source code worked to help provide a reinforcing review of what we have learned so far. Lab 2 takes that program and adds some features so that we can set a given magnitude on the graph - thus providing the user with visual feedback of magnitudes from 0 through 7. In this section we will only discuss those aspects of the new program that differ from the first program.

Parts Required:
1 Arduino
1 Arduino Proto Shield and jumper wires
7 LEDs
7 1000 Ω resistors

Estimated time for this lab: 15 minutes

 Check off when complete:
We will reuse the circuit built in Lab 1 with no modifications.
Either cut and paste, or type in the following program into the Arduino IDE. [Or open the A101_ch8_bar_graph_data_display.ino program - note this file is located in A101_ch8_supplemental.zip. You can find a link to this file near the top of this chapter.]

  
// A101_ch8_bar_graph_data_display Joe Pardue 5/31/14

// lowest indication starts with LED 6
// hightest indication ends with LED 12
#define LOWEST 6
#define HIGHEST 12

// milliseconds between LED turn ons
#define SPEED 50

void setup(){
  
  Serial.begin(57600);
  Serial.println("A101_ch8_bar_graph rev 1.0");  
  
  // Set LED pin modes to output
  for(int i = LOWEST; i <=HIGHEST; i++){
    pinMode(i, OUTPUT);
  }
}

void loop(){ 
  // receive a value to set the bar graph
  if(Serial.available()) {  
     barGraph(Serial.parseInt());  
  }  
}

// sets the bar graph LEDs to the indicated magnitude
void barGraph(int magnitude){
  
  Serial.print("magnitude = ");
  Serial.println(magnitude);
  
  if(magnitude < 8)// show magnitude if 0 to 7
  {
    magnitude = LOWEST + magnitude - 1;   
    alloff(); // turn them all off
      
    // turn on only to the magnitude indicated  
    for(int i = LOWEST; i <= magnitude ; i++)
    {
      digitalWrite(i, HIGH);
      delay(SPEED);     
    }
  } 
  else // scroll once
  {
    alloff(); //turn them all off
    // turn on sequentially  
    for(int i = LOWEST; i <= LOWEST+7 ; i++)
    {
      digitalWrite(i, HIGH);
      delay(SPEED);             
    }    
  }
}

// turn off all the LEDs by setting the pins LOW
void alloff(){
  for(int i = LOWEST; i <= HIGHEST; i++){
    digitalWrite(i, LOW);  
  } 
}

 

Source code discussion


Let's take a few moments to review each line of this code that differs from the program in Lab 1 to reinforce what we have learned so far. We will review the serial communication functions used in this program, then look at the bargraph() and alloff() functions. As before, if the code is clear, then you can skip this discussion.

Serial review
This program sets up the serial communications and sends out a notification of what program is running in the setup() function as follows:

  

Serial.begin(57600);
Serial.println("A101_ch8_bar_graph rev 1.0");


The first line uses the Serial.begin() function to tell the Serial class that the serial port will communicate at 57600 baud. The second line uses Serial.println() function to send out the program name and revision information on the serial port.

In the loop() function the serial port is scanned for input from the serial port and that input is used to acquire the data that will be shown on the bar graph by calling the barGraph() function. The loop runs until the Serial.available() function becomes true, indicating that data has been received on the serial port. It then converts that text data into an integer using the Serial.parseInt() function as a parameter of the barGraph() function:

  
  if(Serial.available()) {  
     barGraph(Serial.parseInt());  
  }  



Note that using a function as a parameter to a function works the same as [using Serial.parseInt() as a parameter for barGraph()]. An alternate way to do this would be:

  
int myInt;

myInt = Serial.parseInt();
  
if(Serial.available()) {  
     barGraph(myInt));  
}  


So we can do it the longer clearer way by defining an integer variable, then setting that integer to the value returned by the Serial.parseInt() function, and then using the variable as the parameter for the barGraph() function. Or we can do the shorter version and directly use the Serial.parseInt() function as the parameter to the barGraph() function where the integer returned by Serial.parseInt() is provided directly to the barGraph() function. This later way of doing things is very commonly done by programmers.

The final Serial function us is in the barGraph() function where we use two lines:

Serial.print("magnitude = ");
Serial.println(magnitude);

The first line sends the string "magnitude = ". The second line then converts the magnitude parameter (sent by the Serial.parseInt()) into a string that is sent out the serial port followed by a line return.

The BarGraph() function


After the barGraph() function sends the magnitude out the serial port, It first checks to see if the magnitude is in an acceptable range:

if(magnitude < 8)// show magnitude if 0 to 7

This checks to see if the magnitude variable is less than 8, meaning it is somewhere from 0 to 7. If magnitude is in the acceptable range then the first block of code is run and the magnitude is shown by lighting the indicated number of LEDs. If the magnitude is out of range then the LEDs are scrolled (turned on sequentially, then turned off). If you see the LEDs scrolling, you know you sent an incorrect number.

To turn on the LEDs indicating the magnitude requested, first the magnitude value is converted to a value that indicates the pin number for the first (lowest value) LED on the barGraph:

magnitude = low + magnitude - 1;

If, for instance, the magnitude is 3, then we see from the variable definitions at the beginning of the program that low is 6, so 6 + 3 - 1 = 8, which becomes the new magnitude. This will allow the LEDs to be turned on from the low LED on pin 6 to the highest LED on pin 8. Next all the LEDs are turned off:

alloff(); // turn them all off

And then the LEDs are turned on one at a time in the for-loop from the low LED to the high LED in a sequence with a speed represented by SPEED, the pin represented by 'i' is set to HIGH providing current for the LED to turn on.

        
    // turn on only to the magnitude indicated  
    for(int i = low; i <= magnitude ; i++)
    {
      digitalWrite(i, HIGH);
      delay(SPEED);     
    }


That was a lot of reviewing and reinforcing. If you are unsure of any aspect of the programs presented in Labs 1 and 2, please don't hesitate to ask questions on the forum at www.arduinoclassroom.com. Be sure and mention the chapter number and the lab exercise.

Lab 3: Dial position display on a bar graph



Parts Required:
1 Arduino
1 Arduino Proto Shield and jumper wires
7 LEDs
7 1000 Ω resistors
1 Potentiometer
1 100 Ω resistor

Estimated time for this lab: 30 minutes

 Check off when complete:
We will reuse the circuit built in Labs 1 and 2 to which we will add a potentiometer with current limiting resistor as shown in Figures 6, 7 and 8.

Figure 6: Bar graph motion indicator breadboard

 

Figure 7: Bar graph motion indicator schematic

 

Figure 8: Bar graph motion indicator photo



Since we have spent so much space reviewing the software, let's assume competence and just refer the reader to the source file: A101_ch8_bar_graph_motion_indicator.ino program - note this file is located in A101_ch8_supplemental.zip. . You can find a link to this file near the top of this chapter..]
Run the code and move the potentiometer dial to verify that the code is working.

Displaying characters with a 7-segment LED display


In the bar graph labs we used 7 LEDs to display a relative magnitude, we could use similar techniques to turn the 7 LEDs into a display to show alphanumeric data (see Figure 9). These 7-segment displays are primarily used to display numbers, but if you are willing to accept some crude approximations (and memorize a few weird substitutions - see Figure 10) you can display the full alphabet. Indeed if you are truly generous, you can turn this device into the world's smallest moving message sign, something we will do as our final lab in this chapter. But first, let's get familiar with the device.

Figure 9: 7-segment LED schematic.



Note that although this is a 7-Segment LED, it actually has 8-segments when you include the decimal point that is useful for using several 7-segment LEDs side by side to show a decimal place. Figure 9 shows a schematic for the 7-segment display we will be using. There are actually many variations on this schematic with different pin-outs. Two basic types are available, common cathode and common anode; we are using the common anode type as shown in the Figure 9. Each LED has a letter designation and each of these is connected to a specific pin (for example, letter a is connected to pin 7). In our case we also have pins 3 and 8 connected to the anode (positive voltage). To use this device we will connect pin 3 to a 100 Ω resistor and each of the LED cathode (negative) pins to Arduino pins that we will configure as outputs. When we want to turn an LED on we will output LOW (ground) so that current flows from the +5, thru the 100 Ω resistor, thru the LED, and into the Arduino pin to ground. When we want to turn the LED off we will set the Arduino pin HIGH (+5V) and no current will flow.

The design we will use for this lab has one major weakness in that we will channel all the current through a single resistor so that the more LEDs are lit, the weaker the current will be and the dimmer the LED will appear. You won't be able to use this in direct sunlight, but for learning purposes it will serve nicely.

We will use a design for a character set that will give us readable likenesses of all numeric and most alphabetic characters shown in Figure 10.

Figure 10: 7-segment font



Generally these are used only to display numerals, which as you can see are clearly readable. The alphabetic characters require a bit of forgiveness on the part of the viewer, but can be used to covey text information for those willing to accept the obvious limits.

Lab 4: The 7-segment LED display



Parts Required:
1 Arduino
1 Arduino Proto Shield and jumper wires
1 7-segment LED
1 100 Ω resistor

Estimated time for this lab: 30 minutes

 Check off when complete:
Build the circuit shown in Figures 11, 12 and 13. Notice that this circuit uses a single 100 Ω resistor between the 7-segment LED anode pin 3 and the 5 volt power supply.

Figure 11: 7-seg breadboard

 

Figure 12: 7-seg schematic

 

Figure 13: 7-seg photo



Either cut and paste, or type in the following program into the Arduino IDE. [Or open the A101_ch8_7seg.ino program - note this file is located in A101_ch8_supplemental.zip. You can find a link to this file near the top of this chapter..]

  
// A101_ch8_7seg Joe Pardue 6/10/14

// lowest indication starts with LED 6
// hightest indication ends with LED 12
int low = 6;
int high = 13;

void setup(){
  // Set LED pin modes to output
  for(int i = low; i <=high; i++){
    pinMode(i, OUTPUT);
  }  
}

void loop(){ 
 // scroll LEDs on
 for(int i = low; i <= high ; i++)
 {
   digitalWrite(i, LOW);
   delay(250);             
 }
 
  // scroll LEDs off
 for(int i = low; i <= high ; i++)
 {
   digitalWrite(i, HIGH);
   delay(250);             
 }


Run the program and you will see each of the 7-segments turn on in sequence and then turn off in a reverse sequence.

Lab 5: The World's Smallest Moving Message Sign?



I've built a library, sevenSegLED, that we will use to create our moving message sign. That library source code is available in A101_ch8_supplemental.zip. Note that we have not gone over some programming concepts contained in that library code and while you have no need to look at the code to use it, if you do decide to look at it be forewarned that it is well advanced of our studies to date. You can, of course, look at the source code for that library, just don’t be too put off by some of the arcane seeming things therein, it will all make sense one day as you continue your Arduino studies.

Several years back I published a similar application for another device using the same title. That title wasn’t quite true then and it still isn’t. Displaying a single character at a time, and having some of them being just plain not like the version you grew up with… well, it is a stretch. However, if you are willing to lean those off-beat characters and accept that some will displayed uppercase while others will be displayed lower case, then you have one really cheap way to get text out of an Arduino.

Parts Required:
1 Arduino
1 Arduino Proto Shield and jumper wires
1 7-segment LED
1 100 Ω resistor

Estimated time for this lab: 30 minutes

 Check off when complete:
We will reuse the last circuit unmodified for this lab.
Unzip the A101_ch8_supplemental.zip file and note the location of the sevenSegLED.zip file. [You can find a link to this file near the top of this chapter.]
In the Arduino IDE Sketch/Import Library/Add Library button as shown in Figure 14.

Figure 14: Add library



This will open a file browser window as shown in Figure 15. Browse to the location where you have stored the sevenSegLED.zip file and click that file to open.

Figure 15: Select sevenSegLED



Verify that the file opens and is added as shown in Figure 16.

Figure 16: Library added



You can now add this library to your code by clicking on the library name as shown in Figure 17.

Figure 17: Use the library



Verify that clicking on the sevenSegLED library causes the include file to be written to the source code as shown in Figure 18.

Figure 18: Adds include file




This process is useful when writing a program from scratch, however, we will use source code that already has this include file so delete the include file.
Either cut and paste, or type in the following program into the Arduino IDE. [Or open the A101_ch8_7seg_message_sign.ino program - note this file is located in A101_ch8_supplemental.zip. You can find a link to this file near the top of this chapter.]

  
// A101_ch8_7seg_message_sign Joe Pardue 6/10/14

#include "sevenSegLED.h"

String readString;

void setup(){
  
  Serial.begin(57600);
  Serial.println("A101_ch8_message_sign rev 1.2");  
    
  setUpLEDs();  
}

void loop(){ 

  String messageString;
  
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow to allow buffer to fill with next character
  }

  if(readString.length() > 0) 
  {
    messageString = readString;
    Serial.print("You sent messageString: ");
    Serial.println(messageString);
  }
  
  for (int i = 0; i < readString.length(); i++)
  {
     setLEDs(readString.charAt(i));
     delay(300);
  }
    
  readString = "";  
}


Compile this code and then open the Serial Monitor.
This code only prints integers and capital letters so to test it in the Serial Monitor enter HELLO WORLD (in all caps) and verify that this message is shown on the LED.
Next enter 1234567890 and verify that the numbers print.

Remember that all the components used in the Arduino 101 series are available from www.smileymicros.com. And if you have any questions about this series, please don't hesitate to visit the forum on www.arduinoclassroom.com and ask.