In previous posts, we looked at driving an LED using an Arduino and Raspberry Pi. For a quick review, an LED is short for a light emitting diode. The light emitting part is obvious. When you put a voltage across an LED it will shine a light. If you put too much voltage the LED will melt and burn out. Typically a resistor is put in series with the LED to limit the voltage. The diode part of the LED only allows a voltage to be places in one direction. Typically, the anode or positive leg of the diode is attached to the positive voltage and the cathode is attached to ground.
There are two ways to limit the intensity of the LED. You can either increase/decrease the resistor or increase/decrease the voltage. To change the resistance a potentiometer or variable resistor is needed. Most potentiometers are mechanical and not programmable. Voltages usually can’t be changed for the Arduino or Raspberry Pi. The output pins are either 3 volts or 5 volts. What you can do is change how long the voltage is on in relation to how long it is off.
As long as the cycle is less than 60 cycles per second, the human eye typically can’t see the light turn on and off. If you use a 25% duty cycle, the light will be dimmed to a quarter of the maximum brightness. A duty cycle of 50% will dim the LED to half the maximum brightness.
More complex LEDs
More complex LEDs are available to provide additional functionality. Typical LEDs allow for single colors. The traditional colors are red, green, and blue. If you need something like yellow or orange you typically have to combine two colors together. This is difficult to do with LEDs that are one color. What you want is a single LED that has all three colors built into a single lens so that you can control the different colors at the same time and have them blended in the LED. Multicolored LEDs are available and have multiple leads for the different colors.
The key difference from our previous example with one LED is that we now need to drive three output pins from the Arduino or Raspberry Pi. We also need to know how to combine the colors of red, green, and blue to get the color that we want.
If we turn on the red and green at the same time, the light should be yellow. If we want orange, we need to have a little more red than we do green.
If we apply a 25% duty cycle or intensity on the green and a 75% duty cycle or intensity on the red we will have a color more orange than yellow. If we apply a 50% duty cycle or intensity on the green and a 50% duty cycle or intensity on the red we will have more yellow than orange. It is important to calibrate the resistors according to the voltage drop for the different color LEDs.
Note that green ranges from 2 volts to 3 volts while red ranges from 1.8 volts to 2 volts. What we should do is put a much larger resistor on the red LED to get more of a voltage drop on the resistor and less on the Red LED. If we put the same size resistor, 330 Ohms for example, the green LED will shine brighter than the red. TO correct for this we need to reduce the green intensity by half or two thirds to get yellow when both are turned on.
// Define Pins
#define BLUE 3
#define GREEN 5
#define RED 6
void setup()
{
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
digitalWrite(RED, HIGH);
digitalWrite(GREEN, LOW);
digitalWrite(BLUE, LOW);
}
// define variables
int redValue;
int greenValue;
int blueValue;
// main loop
void loop()
{
#define delayTime 100 // intensity time factor to change brightness
// yellow is half red and half green
redValue = 255 ; // choose a value between 1 and 255 to change the color.
greenValue = 255 / 3 ; // set to 2/3 brightness to compensate for using 330 Ohm resistor on both red and green
// to get orange change the greenValue = 255 / 9;
blueValue = 0;
#define delayTime 100
// this is unnecessary as we’ve either turned on RED in SETUP
for(int i = 0; i < 1000; i += 1) // fades out red bring green full when i=255 {
analogWrite(RED, redValue);
analogWrite(GREEN, greenValue);
delay(delayTime);
}
}
If we want an orange light we simply change the greenValue to 255/9 which adds more red than green. If we want to change the brightness of the light we add an analogWrite(RED, 0) and analogWrite(GREEN, 0) after the delay(delayTime). We will also need to add a delay(delayTime) after the write of zeros to create a duty cycle. In the code example we have a delayTime of 100 resulting in a 100 microseconds that the light is on and 100 microseconds that the light is off. Adding a multiplication factor changes the mix to 2 milliseconds on and 1 millisecond off.
analogWrite(RED, redValue);
analogWrite(GREEN, greenValue);
delayMicroseconds(delayTime * 20 );
analogWrite(RED,0);
analogWrite(GREEN,0);
delayMicroseconds(delayTime * 10 );
For this example we use delayMicroseconds() rather than delay() to reduce flicker but give us a duty cycle that we can change by changing the multiplication factor. This the example above we are on 2/3 of the time and off 1/3 of the time thus reducing the brightness of the yellow or orange light.
7 segment LED
A more complex LED is the seven segment LED to display numbers and letters. The key difference between the multi-color LED and the 7 segment LED is that the 7 segment is arranged to light up bars that can combine to make a letter. The multi-color LED has three cathode leads. The 7 segment LED has seven cathode leads.
To display the number “1” segments b and c need to be turned on. To display the number “2” segments a, b, g, e, and d need to be turned on. A table can be created correlating which segments need to be turned on for what number and letter you want to display.
If we connect the Arduino directly to the 7 segment LED it requires resistors to limit the voltage across the 7 segment LED.
The code to drive the 7 segment LED is a little more complex in that it introduces something called arrays. For each number that can be represented, the table of which segment needs to be turned on can be defined in an array.
// make an array to save Sev Seg pin configuration of numbers
int num_array[10][7] = { { 1,1,1,1,1,1,0 }, // 0
{ 0,1,1,0,0,0,0 }, // 1
{ 1,1,0,1,1,0,1 }, // 2
{ 1,1,1,1,0,0,1 }, // 3
{ 0,1,1,0,0,1,1 }, // 4
{ 1,0,1,1,0,1,1 }, // 5
{ 1,0,1,1,1,1,1 }, // 6
{ 1,1,1,0,0,0,0 }, // 7
{ 1,1,1,1,1,1,1 }, // 8
{ 1,1,1,0,0,1,1 }}; // 9
//function header
void Num_Write(int);
void setup()
{
// set pin modes
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
}
void loop()
{
//counter loop
for (int counter = 10; counter > 0; –counter)
{
delay(1000);
Num_Write(counter-1);
}
delay(3000);
}
// this functions writes values to the sev seg pins
void Num_Write(int number)
{
int pin= 2;
for (int j=0; j < 7; j++) {
digitalWrite(pin, num_array[number][j]);
pin++;
}
}
In the code we define num_array as a two dimensional array. The second part of the array defines the segments that need to be turned on or off. Note that there are seven values for the second part of the array. The first part of the array defines the number to be displayed. Note that there are ten values for the first part of the array. Arrays start indexing with a zero rather than a one. If we talk about num_array[0][0] we are talking about the first row of the array that contains all “1”‘s and one zero and specifically the first 1 in the second part of the array. The subroutine Num_Write takes an input of a number that should range from 0 to 9 (although it is not checked in the subroutine which can cause errors) and walks through the each segment value and outputs it to the output pin to drive the 7 segment LED. If the input number is a 0 then num_array[0][0] through num_array[0][6] are all “1”‘s. The num_array[0][7] value is a “0” and gets written to the output pin. Note that we start with pin 2 which correlates to the “a” segment and walks through all seven segments that correlate to pins 2-8 on the Arduino.
4 digit 7 segment LED
To make this more complex, we can attach to a 4 digit 7 segment LED by adding four additional control lines to select which of the 7 segment LEDs we are talking to.
Wiring for this example looks like
TM1637 4 digit 7 segment LED
Alternatively we can use a chip between the Arduino and the LEDs to reduce the number of output lines that are needed. The TM1637 4 digit 7 segment LED is a combination of LEDs and a controller chip that know how to “clock” in data rather than driving the LEDs with 12 lines. With this chip we only need two output lines along with power and ground. One output line, CLK, is a clock that strobes the values into the LEDs. The second line, DIO, contains commands that sequence through the segments on the LEDs and which digit is being addressed.
For an Arduino there is a header file called “TM1637Display.h” that defines how to talk to the libraries and TM1637 component.
Some examples of what can be done with a TM1637 component include a countdown timer, a clock showing the time of day, a temperature or humidity gauge, or anything that can be represented with numbers and some limited characters (“C” or “F” for temperature or a “:” in the middle to differentiate hours and minutes). We won’t go into a detailed example on how to use this chip but will save an example when we look at building a more complex system with inputs to create a real world example.