If you want to understand the fundamentals of how to dim a LED so you can build your own dimmer, or you simply want to understand how this process works then you have come to the right place!
In this article we will cover the basics of pulse width modulation, or PWM. This is the magic technique that we can use to dim a LED.
Don’t let the technical jargon in the name worry you, the concept of PWM is very simple. It uses the same principle that a television uses to produce a motion picture.
Persistence of vision
Persistence of vision is somewhat of an optical illusion, whereby light entering the eye is perceived to be still present for some time after the the light ceases to enter the eye.
What this means is if you were to look at a lamp that was flashing at an increasing rate, there would come a point where the lamp was flashing so quickly it would appear to always be on.
Once the brain is unable to perceive the pattern of switching on and off, it starts to average out the pattern and interprets it as brightness.
If the lamp is spending 50% of the time switched on and 50% of the time switch off, the brain would interpret the brightness as half of the total brightness.
Therefore the lamp would appear to be half as bright as it actually was when switched on continuously.
If we take our flashing lamp and then plot the cycle of on and off, it will look something like this. As you can see from the graph the lamp is transitioning from 0% brightness to 100% brightness and then back to 0%.
You should be able to see that this pattern is repeating every 10 units of time. Therefore from 0 to 10 we can see one complete iteration of this pattern and then afterwards the pattern just repeats over and over again.
The unique portion of the pattern from 0 to 10 units of time is called a cycle. The cycle repeats at between 10 and 20 units of time and begins again at 20 units and so on. The following graph shows a single on off cycle.
50 percent duty cycle
Now here is the clever bit, when the light is flashing very quickly or we can say that when the duty cycle is fast enough so that the eye cannot perceive the change in off to on and back to off, the percentage of time that the light is on in each cycle is directly proportional to the perceived brightness.
This means that the light represented by this graph will appear to be at 50% of its total brightness.
75 percent duty cycle
The ratio of time that the light is on compared with off is known as the duty cycle. If we are to illuminate our lamp for 75% of the time, we produce a duty cycle of 75%, which will also have a perceived brightness of 75%.
Pulse width modulation
As we are repeatedly sending an on and off signal to our light, we can say that we are continuously pulsing it. When we change the duty cycle we are changing, or modulating the width of the pulse.
This is where we get the terminology pulse width modulation. It means that we must modulate the pulse width in order to control the brightness. This is exactly how we can control the brightness of our LED.
You may already know from high-school electronics class that you can dim an incandescent bulb simply by altering the voltage. This is also how a simple domestic dimmer switch works.
Firstly we need to understand that an incandescent bulb is just a resistor sealed in a glass chamber containing an inert gas. The filament within the bulb has a low level of resistance, meaning it will dissipate a lot of power when we pass a current through it.
As the filament is made from a metal (usually tungsten) with a very high melting point it can glow white hot without melting. The inert gas provides an oxygen-free environment for the filament, also preventing it from burning up.
The current passed through the filament is dissipated as both heat and light. As you can imagine a lot of heat is produced, which is why this type of light is not so efficient. Most of the power creates heat and the remainder is given off as light from the bulb.
In order to control the brightness of the incandescent bulb we need to control the amount of power that it dissipates. This can be explained using Watt’s law, which says that the power dissipated is equal to the current multiplied by the voltage.
P = I x V
The problem here is that want to use voltage (v) to control our power (p) but we don’t know the value of current (I). Therefore we must substitute it using Ohm’s law, which says that voltage is equal to current multiplied by the voltage.
V = I x R
First we must rearrange this in terms of current (I). The backslash denotes “divided by.”
I = V / R
Now we can replace current (I) in Watt’s law with the volts divided by resistance from our rearranged Ohm’s law equation.
P = (V / R) x V
If we plot this as a chart using an arbitrary value for the resistance of 100 ohms we can see that the plot is very close to linear.
Although it is a little beyond the scope of this article, it should be said that the human eye does not have a linear response to an increase in brightness. We can compensate for this by applying a gamma correction of 2 to the original curve.
The resulting graph gives us the actual perceived brightness increase as the voltage increases. As you can see the “real world” perceived increase brightness is linear with respect to voltage.
The most important thing to understand here is that it is possible to dim an incandescent bulb using a change in voltage and domestic dimmer switches usually consist of a simple variable resistor that changes the voltage across the bulb in order to change its brightness.
PWM dimming a LED
The acronym LED stands for light-emitting diode, therefore the humble LED is simply a diode that emits light. A diode is a semiconductor device and therefore its behaviour is non-linear.
We won’t dive to deep into the characteristics of LEDs but if you would like to understand this principle further, you should check out my tutorial about LEDs and resistors.
What this means is that it is not possible to reliably control a LED by simply adjusting the voltage, like we do with incandescent bulbs. Instead we must use the PWM technique to control the brightness.
There is also another huge benefit to using PWM to control the brightness of a LED. As the technique requires us to only turn the LED on and off, it lends itself perfectly to digital electronics.
In mostly all applications we will want to control our LED with a microcontroller or some kind of digital circuit.
As the whole principal of digital electronics is based on signals that are either only on or off, PWM is the perfect choice for implementing a microcontroller based LED dimming circuit.
If we break digital electronics down to its most basic form, it consists only of an on and off signal, denoted by a 0 and 1 respectively. Therefore we can represent the on and off states of our PWM signal by 0s and 1s.
What is binary
You will most likely be familiar with the decimal numbering system. It consists of the numbers 0 through to 9, so a total of 10 numbers.
Binary is also a numbering system like decimal, only it contains two numbers, 0 and 1.
There are other numbering systems found in computing such as octal, which contains 8 numbers.
You may have also heard of hexadecimal if you do any kind of programming. For example it is used to represent colours in web design and contains 16 numbers represented by the characters 0 to 9 and then A to F.
Converting number systems
It is possible to convert between all of these numbering systems using simples maths. What is of interest to us is the ability to convert between binary and decimal and it will become clear why later in the tutorial.
Firstly lets recap on some basic maths from the earlier days of school. A decimal number can be split into ones, tens, hundreds and thousands.
For example the number “232” contains 2 hundreds, 3 tens and 2 ones. We can write this in a table for clarity.
Let’s look at another example, the number “2439.” It contains 2 thousands, 4 hundreds, 3 tens and 9 ones.
Easy, right?! So we can apply the same concept to binary in order to convert a decimal number to binary. All we need to do is replace the ones, tens and hundreds etc.
Let’s look at our first example of “232.” If we create a table with ones, twos, fours, eights and continue to double this number, we can reproduce any decimal number in binary.
128 + 64 + 32 + 8 = 232
Finally we can look at our second example for “2439.”
2048 + 256 + 128 + 4 + 2 + 1 = 2439
Of course we don’t have to rely on this manual method to convert numbers, it simply serves as an explanation so that you understand how to convert the numbers. You can use this handy online converter to do the maths for you!
Bits and bytes
The number of binary numbers that we can use in this system can also be referred to the number of bits. For example the number of digits in our example for 232 is 8 bits.
We call the bit to the far left the most significant bit and the bit to the far right the least significant bit.
If we add up all of the decimal numbers in our table for our 8 bit example, we get 255.
We need to take into account that we can also represent zero with all 0s, therefore we can represent a total of 256 decimal numbers in an 8-bit system.
To represent the number 2439 in our second example we need 12 bits. Therefore the maximum decimal number that a digital system can represent is limited by the number of bits in the system.
We can refer to 8 bits as one byte of data. Therefore to represent a number greater than 256 in an 8-bit system, we would need to use two bytes of data. For example if we wanted to represent “2439” in an 8-bit system, we would need to use two bytes of data.
"00001001" and "10000111"
So what does this all mean? We need to represent the value of our duty cycle in binary in order to make it compatible with a digital system.
If we are using an 8-bit system to control our PWM, the lowest value we can represent will be 0, which will be a 0% duty cycle. The highest value we can represent will be 255, which will be a 100% duty cycle.
This means that we can have 256 steps of brightness. More steps of brightness mean we can have a smoother fade of brightness and we can also represent more colours if we are controlling an RGB LED.
If we were to use a 4-bit system, we could only have 4 steps in brightness. This would not produce a smooth fade! A 4-bit system would give us 16 steps of brightness, which would be better but still not smooth.
An 8-bit system is usually thought of as a good compromise between cost and performance, although a 12-bit or even 16-bit system would give noticeably better results.
So the higher the number of bits, the better the resolution that we can achieve. The effect also applies exponentially for each bit we add.
An 8-bit system can represent up to 256 steps but a 16-bit system does not represent 512 steps, it represents 65,535 steps!
Let’s look at a simple calculation that we can use to convert a step number into a value of percentage that makes sense in terms of our duty cycle.
100 / total number of steps * step number
Let’s pick an arbitrary number of 200 for the step in an 8-bit system. We know the maximum number of steps is 256 so we can calculate the duty cycle for step 200.
100 / 256 * 200 = 78.125%
Now let’s calculate the percentage value for the next step, 201.
100 / 256 * 201 = 78.516%
We can see here that 1 step in an 8-bit system makes a 0.39% change to the PWM duty cycle. We can also calculate this directly.
100 / total number of steps
100 / 256 = 0.39%
Now let’s take a look at the resolution for a 12-bit system. We know that a 12-bit system can represent up to 4096 steps, so we can apply this to the formula above.
100 / 4096 = 0.024%
That is a huge difference! In a 12-bit system there are a little over 16 steps for every single step in an 8-bit system. This means a 12-bit system has a resolution 16 times finer than an 8-bit system.
This makes a very noticeable difference to how smoothly we can fade brightness. It also means we can reproduce many more colours using an RGB LED.
Which system is best?
So you may be thinking why don’t we just use a system that has millions of bits for a near-infinite resolution?
The answer lies in the hardware limitation. For each “bit” in our system, there needs to be a wire inside our chip to represent the bit. It is just not feasible to cram this many wires inside a tiny little chip.
It is also more costly to produce a chip with more bits, therefore there is a tradeoff between cost and performance.
For many digital dimming systems an 8-bit resolution provides a good balance between cost and performance. Most 8-bit microcontrollers provide the ability to implement a PWM system with more than 8-bits, however this can be at the expense of performance or resources available within the chip.
Some microcontrollers feature dedicated hardware to produce a PWM output that we can use for dimming. It is also possible to implement it with software.
We will take a look at manually implementing an 8-bit system in order to gain an understanding of how it works.
Another factor that we did not discuss yet is cycle time. This is the time that it takes our PWM to complete one cycle. Let’s go back to our graph from earlier and consider a unit for our time axis.
We can say that the unit of time for our graph is milliseconds. There are 1000 milliseconds in 1 second.
1ms = 0.001 seconds
We already know that one cycle of the PWM signal takes 10 units of time, therefore we can say that the cycle time for this PWM is 10ms.
The speed in which a PWM signal repeats over and over is usually expressed as frequency. Now that we know the cycle time, we can calculate the frequency (f).
f = 1 / cycle time in seconds
f = 1 / 0.01
f = 100 Hz
The frequency of the PWM signal in our example graph is 100 Hz, or we can say that the cycle repeats 100 times per second.
This is enough to produce the PWM effect but it is probably a little too slow and some flicker of the LED may be noticable. A better frequency to use would be something like 10,000 Hz, or we can say 10kHz.
We can rearrange our formula to calculate the required cycle time (t) in seconds from our given frequency.
t = 1 / frequency
t = 1 / 10,000
t = 0.0001
Our calculated cycle time is for a frequency of 10KHz is therefore 0.1ms. We can use this calculated time to implement our PWM system in a digital microcontroller.
A common peripheral found within a microcontroller is a timer, you can think of it like a stopwatch. In our microcontroller code we can start and stop the timer. We can also read the current time and use it in our program.
The timer within a microcontroller is fundamentally a circuit within the chip that counts from zero up to its maximum value and then resets back to zero. It will continue to do this whilst it is enabled.
As the timer is a hardware peripheral, the number that it can count up to is determined by the number of bits used in its circuitry. For example an 8-bit timer can count from 0 to 255. A 16-bit timer can count from 0 to 4096.
The time in which it takes to get from zero to its maximum value is linked to the master clock speed of the chip. For example a common clock speed used by the ATMega microcontrollers found on many Arduino boards is 16MHz, or 16,000,000 Hz.
Timer clock speed
We can change the settings in the programming on our chip so that our timer divides up the master clock speed, giving us a specific time that it will take for it to fully elapse to its maximum value.
Using our example from earlier, we will divide the master clock speed so that the time it takes our timer to fully elapse will be our desired PWM cycle time of 0.1 ms. We will use an 8-bit timer, which will give us an 8-bit PWM resolution.
Our timer will store its current value in a register within the microcontroller. This is simply a location within the memory of the microcontroller.
We also need to store our desired PWM value in another register location within the memory. We know this value first by starting with our desired duty cycle. Let’s pick an arbitrary value of 60% and convert it to an 8-bit number that represents the required step.
We can do this by rearranging the formula that converts between steps and duty cycle.
step = total number of steps * (duty cycle / 100)
step = 154
Now we need to convert this to a binary value. We could use the table method from earlier, but it will be quicker to use the handy converter.
154 = 10011010
Therefore to produce our PWM signal at one of the digital pins on the microcontroller we need to write a program that repeatedly compares the value of the timer register to the value in the PWM register.
We can say that if the timer value is lower than the PWM value, switch the digital pin on. If the timer value is higher than the PWM value, switch the digital pin off.
As the time continually elapses in the time specified by our cycle time calculation, the digital pin will be on for the length of time stored in our PWM value register.
This will create a loverly PWM signal to dim our LED to the desired value stored in the PWM register. We can then write a program to control the brightness of the LED simply by changing the value in the PWM register!
In this tutorial we have covered the complete theory of how PWM works and how it can be implemented into a digital system.
PWM is a superb way to accurately control the brightness of a LED and can be be easily implemented into the most basic digital systems.
I hope that you found this tutorial useful and congratulations if you made it to the end! Please let me know what you thought in the comments and feel free to ask any questions that you may have.
Next go check out my tutorial on LEDs and resistors for some further information about how LEDs work!