Learn about the internals of the Arduino Uno microcontroller by looking at 5 different approaches for a seemingly simple task: blinking an LED!
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.
visit goodarduinocode.com to have access to many interesting Arduino projects, as well to subscribe for weekly curated Arduino projects.
We?ll start with the Blink example that comes with the Arduino IDE:
Below is the code for blinking an LED with standard built-in example:
5 ways to blink an LED in Arduino ? the standard 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:
- Set the pin to HIGH (5V), this will turn the LED on.
- Wait for 1000 milliseconds, or one second.
- Set the pin to LOW(0V), cutting the power to the LED and turning it off.
- 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 down to two lines by toggling the value of the pin:
5 ways to blink an LED in Arduino ? using inversion operator
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:
- Toggle the state of the LED.
- Wait one second, repeat.
The One-Liner
This one is my favorite, 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:
5 different ways to toggle an LED using Arduino ? using one line of code
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 method has a big advantage over the previous approaches: 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 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 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 16MHZ, 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.
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:
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 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 program, you will need to connect an LED to pin 9 of your Uno board:
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 the 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):
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:
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 digital pin number 9 in Arduino.
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 try blinking the LED using serial port on Arduino myself, 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.
- Blinking an LED using standard Arduino Blink example
- Blinking an LED using two lines code using ! (not) operator
- Blinking an LED using one line of code using Arduino?s millis() function
- Blinking an LED using built in Arduino hardware timers
- Blinking an LED using Timer output on Arduino
I hope this shows you how much room for creativity Arduino has, and how versatile the platform is ? even a simple task 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 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:
Or, if you prefer a blog post: How to Measure the Speed of your Arduino code
Which method is your favorite one? Can you come up with more creative ways to blink an LED on Arduino Uno?
Interested in many more LED and Arduino projects? I collected some relevant links and posts for you:
How to Build a Wireless Powered LED with Arduino
Last weekend, I decided to create my first “Wireless Power” project. I wanted to make it as simple as possible, with?
blog.wokwi.com
Electronic Safe – Good Arduino Code
Complete source code, schematics, and more. Arduino-powered Digital Safe Box by Uri Shaked
goodarduinocode.com
How to write clean Arduino Code, clean coding guidelines for beginners
If you recently started to code for Arduino you probably have already run into what every good coder eventually faces?
blog.wokwi.com
Originally published at https://blog.wokwi.com on November 7, 2019.