Arduino analogWrite() Function Tutorial

In this tutorial, you’ll learn how to use Arduino analogWrite() function to generate PWM output signals with Arduino. We’ll start from the basics of PWM signal, its frequency, duty cycle, and resolution, and discuss in detail how it works and how to use it in various Arduino control projects.

Then, we’ll move to the Arduino analogWrite() function and see how it works and how to use it for generating PWM output signals to control the brightness of an LED and the speed of a DC motor. We’ll implement a couple of projects in this tutorial to practice what we’re going to learn. Without further ado, let’s get right into it!

Table of Contents

  1. Arduino PWM Introduction
  2. Arduino analogWrite() Function
  3. Using analogWrite() Function in Arduino
  4. LED Brightness Control Using analogWrite() Function
  5. DC Motor Speed Control Using analogWrite() Function
  6. Arduino analogWrite Wrap Up

Arduino PWM Introduction

Pulse Width Modulation (PWM) is a technique for generating a continuous HIGH/LOW alternating digital signal and programmatically controlling its pulse width and frequency. Certain loads like (LEDs, Motors, etc) will respond to the average voltage of the signal which gets higher as the PWM signal’s pulse width is increased.

This technique is widely used in embedded systems to control LEDs brightness, motor speed, and other applications. And here is a graphical animation that shows you the effect of a PWM signal on an LED’s brightness.

As you can see, the LED gets brighter as the pulse width (duty cycle) increases, and it gets dimmer as the pulse width decreases. And this is typically what we use the PWM output for.

PWM Frequency

The PWM signal you’ve seen above captures a few features. The first of which is the frequency, which is basically a measure of how fast the PWM signal keeps alternating between HIGH and LOW. The frequency is measured in Hz and it’s the inverse of the full period time interval. Here is how it looks graphically and its mathematical formula.

Arduino-PWM-Signal-DutyCycle-Frequency-Equation

❕ Note

We control the Arduino PWM frequency using dedicated PWM libraries. And this can be important in a lot of applications because the switching frequency of the PWM can have a huge impact on the Switching Device and/or the Load itself.

PWM Duty Cycle

The PWM’s duty cycle is the most important feature that we’re always interested in. It’s a measure of how long the PWM signal stays ON relative to the full PWM’s cycle period. The PWM’s duty cycle equation is as follows:

The duty cycle is usually expressed as a percentage (%) value because it’s a ratio between two-time quantities. And it directly affects the PWM’s total (average) voltage that most devices respond to. That’s why we typically change the duty cycle to control things like LED brightness, DC motor speed, etc.

The Arduino’s PWM has a resolution of 8 bits by default, which means the duty cycle can have any value between 0 and 255. We write a 0 to get a 0% duty cycle, 255 to get a 100% duty cycle, and any value in between will have the same mapping. You can use the interactive tool below to test the effect of the duty cycle on the average voltage and LED brightness. And also to better understand the concept of PWM Resolution.

Average voltage:

LED

PWM Duty Cycle:

50%

PWM Frequency:

x Hz

PWM Duty Cycle Resolution:

Arduino PWM Pins

The pins indicated by the “~” on the Arduino board are the PWM output pins. There are 6 PWM output pins on the Arduino UNO board (pins 3, 5, 6, 9, 10, and 11).

Arduino-UNO-PWM-Pins

This is a table for the PWM pins available in different Arduino boards and the default PWM output frequency for those pins.

Arduino BoardPWM PinsPWM Default Frequency
Uno, Nano, Mini3, 5, 6, 9, 10, 11490 Hz (pins 5 and 6: 980 Hz)
Mega2 - 13, 44 - 46490 Hz (pins 4 and 13: 980 Hz)
Leonardo, Micro, Yún3, 5, 6, 9, 10, 11, 13490 Hz (pins 3 and 11: 980 Hz)

Arduino analogWrite() Function

Writes an analog value (PWM's duty cycle) to a pin. Can be used to light an LED at varying brightnesses or control a DC motor's speed. After a call to the  analogWrite() function, the pin will generate a steady PWM signal with the specified duty cycle until the next call to  analogWrite() to update the duty cycle value.

analogWrite Syntax

analogWrite Parameters

pin: the Arduino pin to write to. Allowed data types:  int.
value: the duty cycle: between 0 (always off) and 255 (always on). Allowed data types:  int.

analogWrite Example

What's The Range of Arduino analogWrite()?

The range for Arduino analogWrite() is from 0 up to 255. As stated earlier, the default PWM's frequency is around 490Hz at which the PWM's duty cycle resolution is 8 bits. Therefore, the PWM duty cycle range is from 0 up to 255.

❕ Note

Arduino PWM output is also called Analog Output and this is most likely because of its analogWrite() function. However, it's not an analog output, it's still a digital (HIGH/LOW) signal. The effect of the PWM signal on some devices that respond to the average voltage of the PWM makes it seem like an analog output despite the fact that it's a digital signal in nature.


Using analogWrite() Function in Arduino

We typically use the analogWrite() function to generate a PWM output signal on a digital pin that has to be one of those which support PWM output. Those pins are marked with a (~) symbol next to their numbers on the Arduino Board.

You need first to set the pin mode to be output for the pin you've selected using the pinMode() function.

Then you can start the PWM output signal on this pin using the analogWrite() function by setting the desired duty cycle value. And you can update the PWM's duty cycle as you need during the application runtime.

Note that changing the PWM's frequency is not possible without extra libraries for PWM which will affect the hardware timers that are being used by the millis() and other timing functions in Arduino. The operation of these function will be disrupted if changes has been introduced to the hardware timer with the intention of changing the PWM frequency.


LED Brightness Control Using analogWrite() Function

In this example project, we'll control an LED brightness with an Arduino PWM output pin. Using two for loops, we'll gradually increase the duty cycle from 0% up to 100%. Then, gradually decrease it from 100% down to 0%. And keep repeating!

So, let's put what we've learned so far to practice and see the results on the LED and use an oscilloscope to check the output PWM signal as well.

Wiring

Here is the wiring diagram for this example showing how to connect the LED output and the oscilloscope channel.

Arduino-PWM-LED-Fading-Example-Wiring

Example Code

Here is the full code listing for this example.

Code Explanation

First of all, we define the IO pin used for the LED output. It has to be a PWM-enabled IO pin (for UNO: 3, 5, 6, 9, 10, or 11).

setup()

in the setup() function, we'll set the pinMode to be output.

loop()

in the loop() function, we'll create 2 for loops. The first for loop will gradually increase the output PWM's duty cycle with a small 5ms delay time after every PWM duty cycle update operation. The second loop will gradually decrease the output PWM's duty cycle from 100% down to 0%, and everything will repeat forever.

Simulation

Here is the simulation result for this project on the TinkerCAD simulator.

You can check this simulation project on TinkerCAD using this link.

Testing Results

Here is the result of testing this project code example on my Arduino UNO board.

As you have might noticed in the demo video testing, The PWM signal's frequency is 490Hz exactly. Which is what we expect as a default frequency on pin3.


DC Motor Speed Control Using analogWrite() Function

In this example project, we'll control a DC Motor's speed with an Arduino PWM output pin + a BJT Transistor. We'll use a potentiometer and the analogRead() function to get the potentiometer reading and use it to control the PWM's duty cycle and consequently the motor's speed.

Wiring

Here is the wiring diagram for this example showing how to connect the BJT Transistor (TIP120) with the DC Motor, Battery, and Arduino PWM output pin. Pay attention to the common ground between the external power source (battery) and the Arduino board.

Arduino-analogWrite-DC-Motor-Speed-Control-Example

Example Code

Here is the full code listing for this example.

Code Explanation

First of all, we define the IO pin used for the motor speed control output. It has to be a PWM-enabled IO pin (for UNO: 3, 5, 6, 9, 10, or 11).

setup()

in the setup() function, we'll set the pinMode to be output.

loop()

in the loop() function, we'll read the analog input pin of the potentiometer (which is 10-Bit resolution) and convert it to 8-Bit resolution by dividing by 4 (or right-shifting twice). Now, we've mapped the analog input value to the PWM duty cycle range.

Using Arduino analogWrite() function, we' will'll write-back the ADC scaled reading as a duty cycle for the PWM to control the speed of the motor accordingly.

Simulation

Here is the simulation result for this project on the TinkerCAD simulator. Don't pay much attention to the motor rotation animation, it may not be rendering in real-time or it's spinning really fast so we can't judge the motor speed or anything other than the DC current drawn from the power supply which correlates with the speed change.

You can check this simulation project on TinkerCAD using this link.

Testing Results

Here is the result of testing this project code example on my Arduino UNO board.


Parts List

Here is the full components list for all parts that you'd need in order to perform the practical LABs mentioned here in this article and for the whole Arduino Programming series of tutorials found here on DeepBlueMbedded. Please, note that those are affiliate links and we'll receive a small commission on your purchase at no additional cost to you, and it'd definitely support our work.

Download Attachments

You can download all attachment files for this Article/Tutorial (project files, schematics, code, etc..) using the link below. Please consider supporting my work through the various support options listed in the link down below. Every small donation helps to keep this website up and running and ultimately supports our community.


Arduino analogWrite Wrap Up

To conclude this tutorial, we'd like to highlight the fact that you can easily generate PWM signals with Arduino using the analogWrite() function. Which generates a fixed-frequency PWM signal that we can change its duty cycle from 0 up to 255. This tutorial is a fundamental part of our Arduino Series of Tutorials because we’ll use it in so many tutorials and projects hereafter. So make sure, you’ve learned all the concepts and implemented the practice examples whether on your Arduino board or at least in the simulation environment.

If you're just getting started with Arduino, you need to check out the Arduino Getting Started [Ultimate Guide] here.

And follow this Arduino Series of Tutorials to learn more about Arduino Programming.

???? Also Read
Arduino PWM analogWrite Tutorial

This tutorial will provide you with more in-depth information about Arduino PWM output. Starting from the basics of PWM signal, its frequency, duty cycle, and resolution, and will discuss in detail how it works and how to use it in various Arduino control projects.


FAQ & Answers

What is analogWrite in Arduino?

Arduino analogWrite function is used to write an analog value (PWM's duty cycle) to a pin. Can be used to light an LED at varying brightnesses or control a DC motor's speed. After a call to the  analogWrite() function, the pin will generate a steady PWM signal with the specified duty cycle until the next call to  analogWrite() to update the duty cycle value.

Which Arduino pins can be used with analogWrite?

The Arduino pins that can be used with analogWrite depend on the Arduino board you've got. For Arduino (UNO, Nano, Mini): the PWM pins are 3, 5, 6, 9, 10, and 11. For Arduino Mega: the pins are 2 - 13, 44 - 46. For Arduino (Leonardo, Micro, Yun): the pins are 3, 5, 6, 9, 10, 11, and 13.

Can you analogWrite to a digital pin?

Of course, you can analogWrite to a digital pin. Because the analogWrite generates a PWM output signal which is digital in nature, so there is no contradiction. However, not all pins support PWM output, so you can't do analogWrite on all digital pins. Only the pins which support PWM output that can be used for this. PWM output pins are marked with the (~) symbol next to their numbers on the Arduino board.

Share This Page With Your Network!
Join Our +25,000 Newsletter Subscribers!

Stay Updated With All New Content Releases. You Also Get Occasional FREE Coupon Codes For Courses & Other Stuff!

Photo of author
Author
Khaled Magdy
Embedded systems engineer with several years of experience in embedded software and hardware design. I work as an embedded SW engineer in the Automotive & e-Mobility industry. However, I still do Hardware design and SW development for DSP, Control Systems, Robotics, AI/ML, and other fields I'm passionate about.
I love reading, writing, creating projects, and teaching. A reader by day and a writer by night, it's my lifestyle. I believe that the combination of brilliant minds, bold ideas, and a complete disregard for what is possible, can and will change the world! I will be there when it happens, will you?

Leave a Comment