ACROBOTIC Industries ACROBOTIC Industries

Arduino Activity 2: LEDs


Time to complete: 2–10min; Level of difficulty: Beginner

In this activity, we’ll build an electronic circuit with LEDs and control their brightness using our Arduino board.

List of Materials

Obtaining the Code

For this activity, we'll be loading 3 different programs to our Arduino Uno board, which are available in our Github repository:

We can open a new window in the Arduino environment and copy-paste the code.  We'll start out with the program Blink External.


Before jumping into this activity, let's discuss a few important details about Light-Emitting Diodes (or LEDs, for short).

Diodes (and transistors!) have been a fundamental part of the evolution of the digital electronics world.  In fact, LEDs are a type of diode that are capable of transforming electric current into light!  These devices come in all shapes and sizes, and are used ubiquitously around us.  Likely, the next artificial light you see will be emmitted by an LED.

The low energy consumption, low maintenance and small size of LEDs make them very usful as status indicators and displays on a variety of equipment and installations.  In addition, advances in high-power and high-efficiency have made them useful for general lighting purposes, such as in traffic stop lights, car headlights, and in a large number of different applications.

LED costume for professional stage performers, created by the artist Beo Beyond.

There are a couple of practical things we need to remember when working with these devices:


LEDs are made from a variety of semiconductor compounds mixed at different ratios to produce a distinct wavelength of color.  Different compounds emit light in specific regions of the visible light spectrum and therefore produce different intensity levels.  

Note that the color of an LED is not given by the plastic casing around it, but rather by the compounds that comprise it as shown by the color of the clear-capsule LEDs above!


Similar to regular diodes, LEDs only allow current flow in one direction.  Thus, reversing the polarity of the power supply to an LED will not damage it (fortunately!), but no light will be emitted either.

LED Anatomy

For LEDs that have terminals (or legs)—like those used in this activity—the positive terminal (anode) is denoted by a longer lead.  In addition, the negative terminal (cathode) is also denoted by a flat side on the capsule around the LED itself!

Forward Voltage

In order to emit light, LEDs need to operate under what's called a "forward bias" condition.  For doing so, a power supply should provide enough power (current and voltage) to meet that condition.  The specific voltage and current values for this condition vary for each LED model, and they're specificied in the corresponding datasheet (a technical user guide for the component).

Forward Voltage vs Forward Current Chart

Typically, we would connect a resistor in series with the LED to protect if from excessive current flow.  The value of the resistor will depend on the forward voltage and current of the LED.  For this activity we'll use a 1KOhm resistor and a red LED.  Note that different colors and types of LEDs will need different current and voltage levels to emit light at the same intensity and brightness.

Luminous Flux vs. Luminous Intensity

Characterizing the brightness of LEDs is typically done using two measurements:  luminous flux (in lumens), which is a measure of the total light output from a source; and, luminous intensity (in candelas), which is a measure of how bright the beam of light is in a particular direction.

LED Cone Angles

A great example of this, illustrated above, can be seen by comparing two LEDs with identical luminous flux of 0.2 lumens (at a current of 30mA).  Because the LED on the left has a lens that narrows the cone of light emitted to 15°, in contrast to the one on the right that uses a lens that concentrates the light in a cone of 30°, the luminous intensity is 3.7 candelas for the former, and 0.9 candelas for the latter.

Wiring: Blink External

It is important to disconnect the Arduino board from any power source including the USB port from our computer.  This allows us to catch any wiring mistakes before turning it on, preventing components from being damaged.  Once power is off, we can proceed with wiring the following circuit:

A few things to note about the wiring are:

  • The positive lead (anode) of the LED is connected to pin 13 on the Arduino Uno; this can be done directly or using a jumper wire (as illustrated).  It's important to remember that the wiring diagrams denote the anode with a little kink near the casing of the LED
  • The negative lead is connected to the same row as one of the leads of our 1KOhm resistor (note that the resitor markings should be Brown-Black-Red)
  • The other lead of the resistor is connected to a ground (GND) pin on the Arduino Uno; this can be done directly or using a jumper wire

After ensuring that we've wired up things correctly, we can upload the Blink External program to our Arduino Uno board.  To do so, we connect the board to the computer's USB port, we select the port and board model, and hit the upload button (more details on doing this can be found in our "Blink" tutorial).

Code Walkthrough: Blink External

We've already dissected the operation of the code in a previous tutorial!  However, after uploading it to the board a couple of things are worth noting.

The ‘L’ LED turns on and off simultaneously with the LED we've connected to pin 13!  This is not an error, but a consequence of the ‘L’ LED being connected internally on the Arudino board to pin 13.

Remember that it's useful to use this built-in mechanism for quickly testing the operation of the board.  Thus, connecting a simple device with perceivable output (such as an LED) to one of the Input/Output pins of the microcontroller is a great way of doing this.  Thanks to the Open-Source licenses of the Arduino hardware, we can verify on the schematic diagram of the board that this connection is included in the board design.

Wiring: Blink Compare

In our Getting Started with Arduino tutorial we learned that by modifying the two time delays in the program we could alter the blink rate of the LED.  Naturally, we wonder:

What happens if we set the delays to very small values?

To address this question we can setup a quick experiment where we wire up a second LED connected to pin 12.  Then, we can have one of the two blinking while the other is always on (using the program Blink Compare listed above).  This will allow us to compare their brightness and convince ourselves of the difference.

Code Walkthrough: Blink Compare

The short answer to the question above is that as the delays in the program get shorter our eyes will have a harder time observing the period in which the LED is off due to a phenomenon called flicker fusion.  However, even if we set the value of the delays to 0 (delay(0);) the LED will be off for a very short amount of time due to the digitalWrite(led_flicker, LOW) instruction on the code. Despite not being able to see the light go off, our eyes will perceive a lower LED brightness than if the LED was always on.

// the loop routine runs over and over again forever:
void loop()
  digitalWrite(led_flicker, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1); // wait for 1ms
  digitalWrite(led_flicker, LOW);// turn the LED off by making the voltage LOW

Despite having very short delays between the on-off switching of the LED, its brightness is noticeably lower than that of the one where we apply power constantly.  Although we'd need a high-speed video camera to clearly show the difference, setting a fast shutter speed on a DSLR and taking multiple shots gives us some insight:

Although the LED's luminance alternates between fully on and fully off, we perceive it as something of an averaged value.  Thus, considering the average power (voltage x current) applied to each LED—1/10th of a watt for the constant case, and 1/5th in the flickering one—it's understandable that there be a difference between the two.  After all, the relative intensity of an LED is a function of its forward voltage (current).  We'll go into more detail about this topic in a future tutorial, but for now we can use this to make a dimmable LED. 

Brightness Control and PWM

We can modify our Blink External program in order to control the brightness of an LED.  As we've seen, thanks to flicker fusion if we shorten the delays between switching the on-off state of the LED, its brigtness will increase.  If we increase the delays, the LED will be dimmer.  However, increasing the delay up to a certain threshold will allow us to notice the on-off flicker, which is undesirable.

We could then change our code to allow for the following 3 cases:

  • Fully ON: no delay and no digitalWrite(ledPin,LOW); statement
  • Dimming: increase the delay from 1ms to 30ms (flicker fusion stops at around 30Hz for the human eye)
  • Fully OFF: no digitalWrite(ledPin,HIGH); statement

As explained in our Pulse-Width Modulation (PWM) tutorial, controlling the on-off duration of a digital signal is very common (and useful), thus there are easier ways to proceed than what we've outlined above.  In the Arduino environment, we can use the function:

  • analogWrite(pin, value);

We can write the maximum value (255) for the fully ON case, the minimum value (0) for the fully OFF case, and anything in between for dimming the emitted light.

Wiring: Heartbeat

The PWM functionality is so useful in electronics that it's been implemented in the hardware itself (though we can also use software implementations).  However, because of the many special functions that a microcontroller can contain, only certain pins are capable of hardware PWM.  We can immediately recognize these pins on the Arduino Uno board by the tilde (~) symbol preceding the pin number (on pins 3, 5, 6, 9, 10, 11).

In this activity we change the led pin to 11 to make use of PWM, which is available on that pin.

Code Walkthrough: Heartbeat

After wiring, we can upload the last piece of code (Heartbeat) of this activity.  This program was written to increase and decrease the brightness of the LED in a pulsating fashion that resembles the expansion and contraction of a beating heart.

In our setup() contains all the standard calls for setting up the hardware.  In our loop() we do 2 things, we start by setting the brightness value, which starts at 0.  We hold that value for a short amount of time (pre-defined as 5ms).  And, we increase (or decrease if step_size is negative) the brightness value for the next cycle.

  analogWrite(led_pin, value); //set the current LED brightness  
  delay(step_delay_ms); //hold the value for a short time
  value+=step_size; //increase the current value for the next iteration

Before going back to the top of the loop, we check that the brightness value is within bounds (0 to value_max).  If this check is false we return to the top of loop().  If it is true, then value is out of the bounds, thus we change the direction by reversing the sign of step_size, we force value to be within bounds, and if we're at the lower bound (i.e., 0) we pause for 1000ms.

  // if we've reached the maximum or minimum value, change direction of
  // change in brightness (i.e., increasing -> decreasing or viceversa)
  if( (value>value_max)||(value<0) )
    step_size *= -1;
    value+=step_size; // ensure that value stays within bounds
    if(value == 0)
      delay(cycle_delay_ms); // hold 1 second off starting each cycle

Code Tinkering

As an exercise, we encourage you to make the heartbeat a little more ‘realistic’.  Recalling that diastole (relaxation) takes about twice as long as systole (contraction), we can attempt to change the code so that the increase in brightness takes longer than the decrease.

Hint: an easy way to do this is to separate the conditional of the loop into two separate cases.

Comments, questions, or concerns? Drop us a line!.