5 Ways to Blink an LED with Arduino

Learn about the internals of the Arduino Uno microcontroller by looking at 5 different approaches for a seemingly simple task: blinking an LED!

5 Ways to Blink an LED with Arduino

Blinking an LED is the "Hello World" program of hardware. It is also one of the most popular Arduino program, and I bet electronics enthusiast has run it at least once in their life.

In this blog post, I am going to show you 5 different ways of blinking an LED on Arduino: blinking an LED by turning it on/off roughly once a second.

We'll start with the LED Blink example that comes with the Arduino IDE:

5 ways to toggle an LED using Arduino

Below is the code for blinking an LED with standard built in example:

5 ways to blink an LED in Arduino - Standard Blink Example

This is pretty straightforward: LED_BUILTIN is a constant that contains the number of the pin connected to the on-board LED, pin 13 in Arduino Uno. We set this pin to output in the setup() function, and then repeat the following code:

  1. Set the pin to HIGH (5V), this will turn the LED on.
  2. Wait for 1000 milliseconds, or one second.
  3. Set the pin to LOW (0V), cutting the power to the LED and turning it off.
  4. Wait for another second, and then repeat everything again.

You can try it yourself on the free online Arduino blink code simulator playground.

Can we achieve the same with less code?

The Two-Liner

We can easily cut the loop() code in the LED blink program down to two lines by toggling the value of the pin:

5 ways to blink an LED in Arduino - Using Inversion

Here's the trick: digitalRead() returns the current output value of the pin: 1 if the pin is high and the LED is on, 0 otherwise. We use the ! (not) operator to invert that value, and thus toggle the state of the LED. So basically the code above could be read as:

  1. Toggle the state of the LED.
  2. Wait one second, repeat.

The One-Liner

This is my favorite one, which was first presented to me by my friend Avi Ostfeld. By using a clever trick, we no longer need to call delay() in our code to blink the LED using Arduino. The one-liner code to toggle the LED is shown below:

5 ways to blink an LED in Arduino - Using millis()

We take advantage of Arduino's millis() function, which returns the number of milliseconds since the program has started running. We then divide this value by 1000, so we get the number of seconds passed so far. Finally, we take the number of seconds and calculate the remainder of dividing it by two, using the modulus (%) operator. This calculation returns 0 for even numbers and 1 for odd numbers:

In other words, we repeatedly take the number of seconds passed since the program started running, and set the value of the LED based on that: ON if the number if currently odd, OFF if it is currently even. This is how we achieve the desired blink.

This solution of not using delay() has a big advantage over the previous approaches to toggle an LED: we can perform additional tasks inside our loop, as it is no longer blocking on the delay() function. For example, you can blink three LEDs in different intervals: one every second, one every 1.26 seconds, and one every 380 milliseconds. Can you write the code for that?

A similar, but more verbose approach can also be found in Arduino's documentation. You can also tinker with this code in the online Arduino simulator: blinking three LEDs without delay() playground.

Blinking with Timers ⌚

Our solutions to blink an LED with Arduino so far relied on Arduino's built-in functions, so they would virtually work on any board supported by the Arduino environment. However, if we focus just on the Uno board, we can start taking advantage of its specific hardware features - namely, timers and interrupts.

Hardware timers in Arduino are simply counters that go up every predetermined interval. This interval is usually tied to the clock speed of the microcontroller. Uno boards use the ATmega328 microcontroller, and run it with a clock speed of 16 MHz, or 16 million times per second.

The following code sets up one of Arduino's hardware timers and uses it to toggle the LED roughly every second:

5 different ways to toggle an LED on Arduino - using hardware timers

You probably noticed a few weird things here. First of all, our loop() function is empty, is the Uno doing nothing? Second, what are all these strange acronyms: OVF, ISR, TCCR1A, etc.?

For starters, here is some more background about the Uno timers. It has 3 timers, numbered 0 to 2. Timer0 and Timer2 are 8-bit timers, so they count from 0 to 255, Timer1, on the other hand, is a 16-bit timer, so it counts from 0 to 65535:

Timer 0
000
Timer 1
00000
Timer 2
000

But how fast do these timers count? What do they do when they reach their maximum value? This is exactly what we define in lines 2-5. Each of the timers is controlled by special CPU variables called "registers". Our code uses Timer1, and starts by initializing the timer control registers TCCR1A and TCCR1B t0 0 (lines 2-3).

In line 4 we set a flag called CS12 in the TCCR1B register. This flag tells the microcontroller that we want the counter to go up exactly every 256 clock cycles, or 16,000,000 / 256 = 62500 times a second (remember that our clock ticks 16 million times a second).

Where does the "magic" number 256 comes from? You can find it in table 16-5 in page 143 of the ATmega328 Datasheet:

5 ways to toggle an LED using Arduino
1, 8, 64, 256, or 1024 - the choice is all yours!

The next line (number 5) tells the CPU to generate a hardware interrupt whenever the timer reaches the maximum number (or overflow). An interrupt is an event generated by the hardware, which calls a predefined routine in our code, an interrupt service routine (ISR or interrupt handler).  This is exactly what TIMER1_OVF_vect is:
a piece of code that runs whenever Timer1 overflows (OVF stands for overflow).

To recap, our code sets a timer that goes up 62500 times a second. Whenever the timer reaches its maximum value, 65535, the interrupt service routine runs and toggles the LED (in line 10). The timer is then reset to zero, and starts counting up again. As you can probably tell, this code will blink the LED a bit slower than once a second, rather once every 1.05 seconds (that is 65536 divided by 62500).

But wait, there is another trick up my sleeve!

Hardware Blinking ?

In the previous Arduino program, we made the hardware count for us, and run some code we provided every certain amount of time. But what if the hardware could also take care of toggling the pin for us?

Actually, it can, if we accept some constraints. For the next Arduino program, you will need to connect an LED to pin 9 of your Uno board:

5 different ways to toggle an LED on Arduino
This time you need to connect an LED to pin 9. Don't forget to add a resistor!

And here is the program itself:

5 Different ways to toggle an LED on Arduino - using Timer output

As you can see, this time we are setting pin number 9 as an output pin, but there are no digitalWrite() calls in the code - yet tthe LED blinks every single second. How does it work then?

The magic lies in lines 5 and 6. First, we set the OCR1A register to 62500. This register is the Timer 1 Output Compare A register, and its value is continuously compared with the value of Timer1. In other words, we tell the microcontroller to do something whenever Timer1 gets to 62500. But what does it do when there is a match?

This is exactly what line 6 takes care of. Setting the COM1A0 flags tells our chip that we want to toggle a specific pin whenever the timer hits our target value. The timer is then automatically reset to zero, and starts counting up again. We can find this information in the chip's datasheet (page 140):

Five different ways to toggle an LED on Arduino
Setting COM1A0 toggles the OC1A pin whenever the timer reaches the target value

For me, this was a little confusing, as the datasheet says that the hardware will toggle OC1A on Compare match. But who is this mysterious OC1A pin?
Another quick search in the datasheet reveals the answer:

5 ways to blink an LED on Arduino
OC1A is actually PB1, or Arduino's pin 9

Then, all you need to do is google for "Arduino PB1" and find that it is Arduino's digital pin number 9.

Bonus: The Serial Port ?

After sharing this post in the Arduino Facebook group, some users shared their insights about how they'd blink an LED. This is in turn the 6th way of blinking an LED on Arduino.

My personal favorite was using the Arduino's serial port. I decided to try blinking the LED using serial port on Arduino myself, connected a green LED to pin 1 (TX) of the Arduino, and came up with the following code:

byte blink[256];

void setup() {
  for (byte i = 0; i < 128; i++) {
    blink[i] = 0xff;
  }
  Serial.begin(1200);
}

void loop() {
  Serial.write(blink, 256);
}

Note that this approach doesn't truly blink the LED, only toggles it between high brightness and low brightness (due to the start/stop bits in the UART protocol). Creative thinking, nevertheless!

The Takeaways

We have seen five different ways of blinking an LED on Arduino:

  1. Blinking an LED using standard Arduino Blink example
  2. Blinking an LED using the Arduino ! (not) operator
  3. Blinking an LED using Arduino's millis() function
  4. Blinking an LED using built in Arduino hardware timers
  5. Blinking an LED using Arduino's Timer output pins

I hope this shows you how much room for creativity Arduino has to blink an LED, and how versatile the platform is - even a simple task of toggling an LED can be solved in a variety of ways.

You can use the millis() trick in your project whenever you want to perform more than a single task in your loop().

The timers you saw can come handy when you have a task that blocks the loop() (for instance, polling an ultrasonic distance sensor), and you need to accurately time another task, such as blinking an LED or driving a stepper motor. In fact, several Arduino functions use these timers under the hood, e.g. analogWrite() and tone()  

Finally, Arduino goes a long way making your life simple, but in order to take advantage of all the capabilities of the Uno, you definitely want to consult the ATmega328 Datasheet. With over 600 pages, the datasheet can be overwhelming at first sight, but it's a very valuable resource which you can refer to whenever you want to know more about the specifics of this chip.

If you want to learn more about using the Arduino timers, check out this tutorial:

You are also invited to visit wokwi.com Arduino Simulator for more fun, interesting and interactive projects. I'll leave you with some sample Arduino projects from Wokwi: