Arduino: Driving more advanced LEDs

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.

driving an LED using Arduino UNO R3

Today we will look at what it takes to turn on and off a light that is not part of the Arduino board. Fortunately, this is a very simple task. In future posts we will look at driving the same circuit using a Raspberry Pi and look at a few of the different options available and how they compare to the Arduino code.

Let’s start by talking about an LED light. The design is very simple. When you put a voltage across an LED it emits light. Unfortunately, if you put 5 volts with almost any amperage across the LED it will melt and become unusable. To prevent the LED from melting a resistor is typically placed between the Arduino and the LED to limit the voltage going into the LED.

To begin our discussion let’s look at an electrical schematic of an LED.

When a voltage is places across the LED it emits light. The long leg of the LED is the positive lead and the short leg is the negative lead. Putting a positive voltage on the negative lead and grounding the positive lead will not do anything. Putting a positive voltage on the positive lead and grounding the negative lead will cause the LED to “light up” and emit light.

It is important to note that different LEDs require different voltages to emit light. The higher the voltage, the brighter the light shines. A red LED, for example, needs at least 1.63 volts before it begins emitting light and will burn out if you put more than 2.03 volts across it. A green LED, on the other hand needs at least 1.9 volts and can go as high as 4.0 volts before it overheats.

Fortunately, we can use a resistor in series with the LED to control the brightness. The higher the resistor value, the less light the LED will emit. In the picture below a yellow LED is combined with different resistor values.

Note that a 330 Ohm resistor, which has the least amount of resistance of all resistors shown, caused the LED to be brighter. The 100K Ohm resistor, which is about 1000 times more powerful than a 300 Ohm resistor, barely causes the yellow LED to turn on. Note in this diagram the red wire coming in from the left is supplying a 5 volt DC power and the black wire is providing a ground connection. With the breadboard (the white board that everything is plugged into) the two outer rows provide a connection to all of the holes along the blue line. The ground line is the outermost row and the 5 volt line in the next row in line. Between these two rows is an air gap then more tows of holes. The holes above the air gap run in a different direction. The holed going up and down in this diagram are all connected.

If we turn the board we can see that everything in row 1 is connected between the air gaps. The yellow lines are different from the green lines and different from the red or blue lines. We are trying to tie a resistor and the LED together at one end and put positive voltage and ground across the other ends.

In the diagram above a 220 Ohm resistor is used to limit the voltage going across the green LED. We put 3.3 volts on the red bus on the left and ground on the blue bus on the right. By putting a resistor in hole 17 on the red bus, it connects one end of the resistor to the 3.3 volt supply. By putting the other end of the resistor in the left most pin in row 16 we can then put the positive lead of the LED in any of the holes on row 16 to connect the resistor to the LED. We then put the negative end of the LED in tow 16 on the other side of the air gap and tie it to ground with a wire running from any of the 16 pin holes to any pin on the blue line running up and down. Off screen we connect a voltage supply (or battery) to the red and blue lines with wires somewhere on the breadboard.

To calculate the resistor needed for an LED, we need to know the voltage drop across the LED and the voltage of our supply. For an Arduino the voltage supply is 5 volts.

To calculate the resistor value we use Ohm’s Law which basically is voltage is the product of current and resistance. If we have multiple voltage drops (as with a resistor and an led in series) the equation to calculate the resistance can be expressed as …

A good website to calculate this is available at https://ohmslawcalculator.com/led-resistor-calculator . If we assume a 5 volt source and a 2 volt drop across the LED with 1 milliamp of current going through the LED and resistor we get a 3000 Ohm resistor (otherwise known as a 3K resistor). If we have a 4 volt drop (as is the case with a green LED) we would use a 1K resistor. In this example we would place a 3K resistor in series with a red LED and a 1K resistor in series with a green LED to have them with the same brightness. It is important to note that putting the resistor closer to the 5 volt power or closer to the ground line makes no difference. The only important thing is to put the resistor in series with the LED which means that they share one common plug in point on the breadboard.

A diagram of this configuration would look like …

In the above diagram the black and purple lines are ground lines. The red and yellow lines are digital output lines. If we look at the pinout of the Arduino we note that there are multiple output lines available to us.

In the wiring diagram above we use two of the GND PINS (which are fixed as ground and not programmable) for the black and purple wires. We could have used one of these going to the blue lines along the breadboard and wired from the blue line to the negative side of both LEDs. We also go from the Digital output pins 0 and 1. It is important to note that these pins are also labeled TX Pin an RX Pin because they can be used as input or output pins. In our coding example we will make these pins output to drive the LEDs.

Let’s first begin by driving one LED using GPIO pin 13 from the Arduino board. The wiring diagram looks like …

The code looks like …

Let’s walk through this code. All Arduino programs start with void setup() to set the initial conditions. In this example we call the routine pinMode and set pin 13 as an output. If you wired the LED to another pin you would change the 13 to something else based on where you plugged in your wire.

The second part of the code void loop() executes the desired code to drive the LED. The subroutine call digitalWrite writes a value to the GPIO pin. In the first line we are putting 5 volts on pin 13 with the parameters 13 and HIGH. The delay subroutine causes the computer to pause for a given amount of time in milliseconds, in this case 1000 milliseconds or one full second). The third line takes away the 5 volt signal and drops the voltage to zero on pin 13. The fourth line again delays for a second and the loop begins again.

In the example above we would change all references to pin 13 to pin 9. We could also change the delays of 1000 to something longer or shorter to watch the LED blink on or off faster or slower.

If we wanted to drive three LEDs (as with a traffic light) we would need to add a yellow and greed LED with the appropriate resistors to have the brightness the same as well as change the code to drive two more GPIO pins.

// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(9, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(9, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(9, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}

If we change the circuit to …

The code changes to

// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(9, OUTPUT);

// the loop function runs over and over again forever
void loop() {
digitalWrite(9, HIGH); // turn the Green LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(9, LOW); // turn the Green LED off by making the voltage LOW
delay(1000); // wait for a second


}

The lines in red above are the new lines of code. Copy and paste this into the Arduino IDE and upload it to the Arduino UNO R3. This should blink the green light for a second, yellow light for half a second, and red light for two seconds. In future examples we will drive a much larger number of LEDs using other chips to help minimize the number of GPIO pins to turn on and off lights.

Arduino Install

In last week’s blog post we talked about how to start development with a Raspberry PI. This week it will be a little different in that we will look at a much less powerful computer, the Arduino UNO R3.

The newer version of the UNO board is the Arduino UNO R4 which was released in June 2023.

The size, power requirements, and I/O capabilities of the R3 and R4 are similar. The R4 has a more powerful processor, more memory, and a faster USB connection. The clock speed (16 Mhz vs 48 Mhz) is the biggest difference contributing to performance but the memory sizes (32 Kb of flash memory vs 256 Kb as well as 1 Kb of EEPROM vs 8 Kb) makes a huge difference is what the processor can be programmed to do. The R4 does have higher analog input resolution in that it has 16-bit resolution vs 8-bit resolution for the six analog inputs.

Fortunately, the power supply and form factor don’t change between the processors. The development environment (IDE) is the same with the only change being a pull down in the IDE to select the appropriate microcontroller board to program.

To install the development environment you need a computer to interact with the Arduino. This computer can be Windows, MacOS, or Linux. A good tutorial has been written by the makers of the Arduino and is easy to follow – https://docs.arduino.cc/software/ide-v2/tutorials/getting-started/ide-v2-downloading-and-installing/

The development environment takes a little practice to understand it but once you do it a couple of times it becomes simple. The interface allows you to develop code and upload it to the processor board. The first step is to select the board type then start developing for the board.

Along with the board type you need to select how you will communicate with the Arduino. Newer models support WiFi communications while older models use a USB cable to connect to the board for the initial programming.

Once you have connected to the Arduino through the WiFi or USB connection you can load a program into the development environment and upload it to the processor board. A good place to start is with the blink program which blinks the LED located on the board next to the USB connector. This will show that you not only have a good IDE configuration but a working Arduino that can be programmed from your computer. If you change the sleep time you can change the frequency of the blinking light. This is a simple way to play with the code and verify that everything is properly working.

The blink code addresses the on-board LED and loops with a sleep command between turning on the turning off the light.

The statement “int led = 13;” defines which pin you are addressing on the board. The statement “pinMode(led, OUTPUT)” defines pin 13 as an output pin. The loop command says repeat this operation forever with no limits until power is lost or a new program is uploaded. The “digitalWrite(led, HIGH)” command turns on the LED light. The “delay(1000)” command sleeps for 1000 milliseconds (otherwise known as one second) before executing the next command. The “digitalWrite(led, LOW);” command turns off the LED light. The second delay sleeps for a second as well before looping back to turn the light back on.

If you want to play with this, change the second delay function to 500 which will sleep for a half a second before turning the light back on. If you then change the first delay to 500 as well the light will blink twice as fast. This is a good way to test the development environment and connection to the Arduino.

It is important to note that the Upload function at the top left of the development environment is what is used once you change the code to change the operation of the Arduino. The upload writes your new code to the computer and executes the code as designed. For the blink program it can be loaded by going to the Files pulldown and loading the code from the Examples menu path.

The blink program is located under the 01.Basics menu and comes default with the IDE installation. In future posts we will look at changing this code to control an external LED and not an LED that is on-board. This is useful for showing status or the user in a change of status. A very simple example of that would be attaching three LEDs to the computer with the colors red, yellow, and green to simulate a traffic light. Alternately we would read a volume level or battery charge level and go from green (full) to yellow (half-full) to red (almost empty). This is a more complex example because it requires reading data from a sensor and writing to three different output ports. With the Arduino we could also write an analog output or a pulse width output and change the brightness and color of a more complex LED. We will not only look at doing this with the Arduino but with the Raspberry PI as well.