Pulse Width Modulation(PWM)
Anand RamaswamiShare
Welcome Back, Maker!
So far we learned about digital pins - ON or OFF, and analog input. We saw that sensors like a potentiometer or LDR do not just give ON or OFF values — they give a range of values from 0 to 1023.
That means Arduino can understand how much of something is happening.
But what if we also want the output to work in levels?
For example, what if you want:
- an LED to be dim or bright
- a motor to run slow or fast
- a buzzer to make different sounds
A normal digital pin can only give HIGH or LOW.
So to create an output that feels in-between, Arduino uses PWM.
Now that we understand analog input, let us learn how Arduino creates analog-like output using PWM.
Now that we know why PWM is useful, let us first understand what PWM actually is.
What Is PWM?
PWM stands for Pulse Width Modulation.
It is a technique where the Arduino turns a pin ON and OFF very rapidly , so fast that the device connected to it does not fully turn off between pulses. Instead it behaves as if it is receiving a reduced amount of power.
Think of it like a ceiling fan with a regulator.
The fan is always receiving power — but the regulator keeps cutting it on and off so quickly that the fan spins slower. You don't see the power cutting in and out. You just see a slower fan.
PWM works the same way.
Since PWM needs special pins, the next thing we should know is which pins on the NanoMake Pro actually support PWM.
PWM on the NanoMake Pro
On the NanoMake Pro, the PWM-capable pins are D3, D5, D6, D9, D10, and D11.
These pins can generate Pulse Width Modulation signals, which means they can do more than simple ON and OFF control. With PWM, you can create effects like changing LED brightness, controlling motor speed, generating tones with a buzzer, or moving a servo smoothly.
On this board, pins D5, D6, D9, and D10 are especially useful because they are connected to the onboard LEDs and motor section, while D11 is connected to the servo port. Whenever you use analogWrite(), make sure you choose one of these PWM pins, because regular digital pins cannot give the same smooth control.
Now that we know which pins support PWM, we need the command that sends a PWM signal. That command is analogWrite().
The Command: analogWrite()
analogWrite() is the command used to send a PWM signal to a pin.
Syntax:
|
analogWrite(pin, value); |
Parameters:
- pin → the PWM-capable pin connected to your device
- value → a number from 0 to 255
Returns: nothing.
So instead of just choosing HIGH or LOW, PWM lets us choose a value between 0 and 255. That gives us many levels in between fully OFF and fully ON.
Now let us see that in action with a simple LED project.
Project 1: Control LED Brightness Using PWM
In this project we will make an LED glow at different brightness levels using PWM. Instead of the LED being fully ON or OFF, we will set it to specific brightness levels using analogWrite().
This helps you understand how PWM values map to real visible brightness on an LED.
Code:
|
void setup() { pinMode(9, OUTPUT); // LED connected to pin 9 } void loop() { analogWrite(9, 0); // LED OFF delay(1000); analogWrite(9, 64); // LED dim delay(1000); analogWrite(9, 128); // LED medium brightness delay(1000); analogWrite(9, 192); // LED bright delay(1000); analogWrite(9, 255); // LED fully ON delay(1000); } |
Explanation:
pinMode(9, OUTPUT) sets pin 9 as an output. Pin 9 is a PWM-capable pin on the NanoMake Pro.
analogWrite(9, 0) sends a 0% duty cycle to pin 9 — the LED is completely OFF.
analogWrite(9, 64) sends a 25% duty cycle — the LED glows dimly.
analogWrite(9, 128) sends a 50% duty cycle — the LED glows at medium brightness.
analogWrite(9, 192) sends a 75% duty cycle — the LED glows brightly.
analogWrite(9, 255) sends a 100% duty cycle — the LED is fully ON at maximum brightness.
Each brightness level stays for 1 second before moving to the next. This gives you a clear visual understanding of how PWM values affect brightness.
Output:

This first project shows how PWM creates different output levels. But in many real projects, the value does not come directly from us. It often comes from a sensor or another input, and that means we need to convert one range of numbers into another.
That is where map() helps.
The Command: map()
When working with PWM you will often need to convert one range of numbers into another.
For example, a potentiometer gives values from 0 to 1023 but analogWrite() needs values from 0 to 255.
That is where map() helps.
Syntax:
| map(value, fromLow, fromHigh, toLow, toHigh); |
Parameters:
- value → the number you want to convert
- fromLow → the lowest value of the input range
- fromHigh → the highest value of the input range
- toLow → the lowest value of the output range
- toHigh → the highest value of the output range
In simple words it translates one set of numbers into another set of numbers proportionally.
Now that we know how to convert ranges, we can combine analog input and PWM output in the next project.
Project 2: Control LED Brightness Using Potentiometer
In this project we will use the potentiometer knob on the NanoMake Pro to control the brightness of an LED. Turn the knob one way and the LED gets brighter. Turn it back and it dims.
The potentiometer gives values from 0 to 1023. We use map() to convert this into a PWM range of 0 to 255 that analogWrite() understands.
Code:
|
void setup() { pinMode(9, OUTPUT); // LED connected to pin 9 } void loop() { int potValue = analogRead(A6); // Read potentiometer int brightness = map(potValue, 0, 1023, 0, 255); // Convert to PWM range analogWrite(9, brightness); // Set LED brightness } |
Explanation:
analogRead(A6) reads the current position of the potentiometer knob. The value will be between 0 and 1023.
map(potValue, 0, 1023, 0, 255) converts that value into the 0 to 255 range that analogWrite() needs. For example if the potentiometer reads 512, map() converts it to approximately 127 — half brightness.
analogWrite(9, brightness) sends the PWM signal to the LED. The LED brightness instantly matches the knob position.
There is no delay() in this project so the LED responds smoothly and continuously as you turn the knob.
Output:
Project 3: Breathing LED Effect
In this project the LED will slowly fade in and then slowly fade out — like it is breathing. This creates a smooth glowing effect using PWM.
Instead of jumping between brightness levels like in Project 1, this project increases and decreases the brightness gradually in small steps, creating a continuous smooth animation.
This is one of the most satisfying beginner PWM projects because the result looks polished and professional with very simple code.
Code:
|
void setup() { pinMode(9, OUTPUT); // LED connected to pin 9 } void loop() { // Fade IN for (int i = 0; i <= 255; i++) { analogWrite(9, i); // Increase brightness step by step delay(8); } // Fade OUT for (int i = 255; i >= 0; i--) { analogWrite(9, i); // Decrease brightness step by step delay(8); } } |
Explanation:
for (int i = 0; i <= 255; i++) is a loop that counts from 0 to 255 one step at a time.
analogWrite(9, i) sets the LED brightness to the current value of i. As i increases from 0 to 255, the LED gets brighter step by step.
delay(8) adds a small pause between each step. Without this the fade would happen so fast you wouldn't be able to see it. 8 milliseconds per step means the full fade takes about 2 seconds.
The second for loop counts from 255 back down to 0, gradually dimming the LED until it is completely OFF.
This repeats forever inside loop() — so the LED keeps breathing in and out continuously.
This project shows how PWM can do more than simple control. It can also create smooth, attractive effects.
Output:
After seeing these projects, it becomes easier to understand why PWM is used in so many real systems.
Real-Life Examples of PWM
PWM is one of the most widely used techniques in electronics and engineering.
When you adjust the screen brightness on your phone or laptop, the display is not actually getting more or less power ,the backlight is being switched ON and OFF thousands of times per second. That is PWM.
When you use a dimmer switch for your room lights, it works by rapidly cutting the power to the bulb. The faster the cuts, the dimmer the light appears. That is PWM.
In electric cars, the motor controller uses PWM to control how much power goes to the motor , giving you smooth acceleration from a standstill to full speed. That is PWM.
In RC cars and drones, the speed of each motor is controlled using PWM signals sent from the flight controller. That is PWM.
Cooling fans in computers use PWM to spin faster when the CPU is hot and slower when it is cool ,saving energy while keeping the system safe. That is PWM.
The common idea in all of these is simple , instead of changing the voltage, we change how long the signal stays ON. The result feels like a smooth in-between level of power.
Why PWM Is Important
PWM gives you control over the world in a way that simple ON/OFF signals cannot.
Without PWM you can only turn things fully ON or fully OFF. With PWM you can:
- Dim or brighten LEDs smoothly
- Control motor speed precisely
- Generate tones with a buzzer
- Control servo motor positions
- Adjust fan speeds
Almost every real-world electronics project uses PWM in some form.
Final Thoughts
PWM is one of those concepts that once you understand it, you start seeing it everywhere.
It is the reason your LED can glow softly instead of just blasting at full brightness. It is the reason your robot motor can creep forward slowly instead of only going full speed.
Now that you understand PWM and analogWrite(), you have the tools to build projects that feel smooth, responsive, and professional.
Keep experimenting, keep building, and keep making.