Micro beginner ==> 5. LED with PWM
Diese Seite in Deutsch (extern):
Lecture 5: To control the intensity of a LED via PWM
So far we used blinkling of a LED. Now we continue blinking, but with a high frequency.
With that blinking we change the intensity from weak to high. And this in an exact
linear manner and not with a non-linear current.
- Introduction to the PWM mode of the timer
- Hardware, components, mounting
- Timer in fast PWM mode
- Timer in phase-correct PWM mode
5.1.1 8 bit PWM
PWM means pulse width modulation. To do this the timer, on restarting, sets or clears
an output (OC0A and/or OC0B). If a compare match occurs (A or B) the polarity of the
output changes (clear, set). By reaching the largest value the polarity of the output
again changes and the cycle starts again.
The later the compare match occurs within the whole cycle the longer gets the first
phase and the shorter gets the second phase. This behaviour allows to control the power
of a DC motor as well as the intensity of LEDs. Please note that during the ON period
the transistor drives the motor with maximum available power and that only the duration
is limited. So the motor power is really linear.
The bits COM0A1 and COM0A0 in the TCCR0A port determine, how the output behaves. With
0b10 the output is set at the beginning of the PWM cycle, with 0b11 it is cleared.
Similar to this COM0B1 and COM0B0 in the same port control the output pin OC0B.
This shows how the voltage on the output OC0A changes in Fast PWM mode with TOP at 255
and a compare match at 100. The resulting pulse width is 100 / 256 = 39% high.
Within the Fast PWM mode the selection of the timer prescaler determines the PWM's
frequency. At the different clock frequencies and prescaler values the following
frequencies result and offer a wide range.
|9.6 Mcs/s||37.5 kcs/s||4.69 kcs/s||586 cs/s||146.5 cs/s||36,6 cs/s|
|4.8 Mcs/s||18.8 kcs/s||2.35 kcs/s||293 cs/s||73.3 cs/s||18.3 cs/s|
|2.4 Mcs/s||9.4 kcs/s||1.68 kcs/s||147 cs/s||36.7 cs/s||9.15 cs/s|
|1.2 Mcs/s||4.69 kcs/s||586 cs/s||73.2 cs/s||18.3 cs/s||4.6 cs/s|
|128 kcs/s||500 cs/s||62.5 cs/s||7.8 cs/s||1.95 cs/s||0.49 cs/s|
At 1.2 and 2.4 Mcs/s all PWM frequencies are in an audible range (with motors this
can result in incomfortable humming). A clock frequency of 128 kcs/s is
inappropriate for that purpose, at a prescaler value of 1,024 we can visually follow
the PWM process.
5.1.2 Phase correct 8 bit PWM
This is the signal process in the phase-correct mode. The timer counts up- and downwards,
each time the compare match is reached the polarity of the output changes. The PWM
frequency is half that in Fast PWM mode.
Phase correct PWM mode is used if the compare value changes very often and with large
changes. The change of the compare match value is buffered, the changed value comes
only into effect when the TOP value has been reached. So there are always two periods
(up-counting, down-counting) performed for each compare value. With this, the jitter is
5.1.3 PWM with different resolution
It is not always necessary to use 8 bit resolution, with 256 counting steps (0.39%
accuracy). In some cases it is sufficient to have only four (6.25%) or five (3.1%) bits
resolution of the PWM signal. For a small motor 8 bits might be overdone. If at a
count of 16 (four bit resolution) the cycle restarts, the PWM frequency increases
accordingly. This can be reached by combining the PWM mode with CTC: In that case
compare match port A is used as CTC and compare match B as PWM signal. Those two
modes are possible, as the mode table shows.
In case of a 4 bit resolution (Compare Match A = 15), with 1.2 Mcs/s clock and
a timer prescaler of 1 the PWM frequency will be at 37.5 kcs/s, well above any
audible regions for humans and most wildlife (excluding bats).
In case of 16 bit timers/counters, of which ATtiny13 has none, the normal phase correct
PWM mode would have a resolution of 16 bits (accuracy: 0.0015%), which is by far higher
than any practical requirements. It is therefore nearly always necessary to reduce the
resolution. To relief Compare Match A from this CTC task and allow it to use as
additional PWM channel, an additional port (ICR) provides this task.
For the PWM intensity regulation the same hardware is used as for the previous lectures.
With the previous information on functions, properties and methods a PWM intensity
regulation can be programmed in a simple way. As PWM cycle frequency we select at
1.2 Mcs/s clock and a prescaler of 1, resulting in 1,200 / 256 = 4.7 kcs/s.
This is fast enough for the human eye and for any digital camera.
5.3.1 Source code for Fast PWM
By changing the polarity of the PWM output we reverse the inversion by the LED. The
source code is here.
One line in this code requires deeper understanding
and some background knowledge:
; * PWM control of a LED in Fast mode *
; * (C)2017 by www.avr-asm-tutorial.net *
; -------- Register -------------------------
.def rmp = R16 ; multi purpose register
; -------- Program --------------------------
; Init output pin OC0A
sbi DDRB,DDB0 ; OC0A as output
; PWM compare value to timer 0
ldi rmp,20 * 256 / 100 ; 20% intensity
out OCR0A,rmp ; to compare match port A
; Timer 0 in Fast PWM mode, output A low at cycle start
out TCCR0A,rmp ; to timer control port A
; Start Timer 0 with prescaler = 1
ldi rmp,1<<CS00 ; Prescaler = 1
out TCCR0B,rmp ; to timer control port B
; Enable sleep mode
ldi rmp,1<<SE ; Sleep enable, mode idle
out MCUCR,rmp ; to Universal control port
sleep ; go to sleep
nop ; in case of wakeup
rjmp Loop ; again to sleep
; End of source code
ldi rmp,20 * 256 / 100 ; 20% intensity
5.3.2 Calculations in assembler
The term 20 * 256 / 100 usually would result in 51.2. Not
so in assembler. All mathmatical expressions in assembler
are integer operations. That means the result is 51, not
51.2. But even more strange: if we write the term
"20 / 100 * 256", which would be - mathmatically
spoken - equivalent, the result would be 0. We can test
that astounding result by adding the line
and reformulate the above line by
; -------- Constants ------------------------
.equ cIntensity = 20 / 100 * 256
If we assemble that changed code using gavrasm and the -s
option (note that other assemblers do not provide such a
symbol list) we will see the following in the symbol list:
List of symbols:
Type nDef nUsed Decimalval Hexvalue Name
T 1 1 18 12 ATTINY13
L 1 2 9 9 LOOP
R 1 8 16 10 RMP
C 1 1 0 0 CINTENSITY
The reason for this is that the assembler ALWAYS a) uses integer
math, including interim results, and b) that he always processes
expressions from left to right, and c) follows priority rules
such as "*" and "/" higher than "+"
and "-". So the constant calculation term is processed
If you want to overrule the standard processing scheme you'll have
use brackets. So the formulation
- Divide 20 by 100 in integer mode, result = 0 (!)
- Multiply result with 250, result = 0 (!)
is always more correct as it overrules any priority and
processing sequences. See
this page for a complete list of mathmatical expressions in
This list is sorted by increasing priority.
.equ cIntensity = (20 * 250) / 100
5.3.3 LED intensities
The PWM intensity control is rather simple code. And here is
The differences in intensities are clearly visible.
Please note that the PWM cannot be set to 0% intensity because the first clock pulse
is always executed. If 0% should be really switching the LED off one has to decouple
the output pin from the PWM control and to set the port pin to high level.
5.3.4 Simulation of the PWM mode
can be used to test the timing characteristics.
After the 6.67 µs init phase the timer 0 is in Fast PWM mode.
The compare value in A is 51, PB0 is cleared on the start and, on compare
match, PB0 will be set.
That means the LED will be on over the first 51 clock cycles and off for
the remaining cycles to 256.
This is the situation after the first compare match comes into effect
(the timer exceeds the compare match value). 42.5 µs are
The first match has set the portbit PORTB0, by that switching the LED
Here, the timer overflowed from 255 to 0 after 212,5 µs
(corresponding to a PWM frequency of 1,200 / 256 = 4.7 kHz).
The overflow has cleared PORTB0, the LED is on again and the PWM
The phase correct PWM mode is achieved by removing the WGM01 bit in the above source
code (WGM01 = 0). Now the PWM works at 2.34 kcs/s. Still fast enough for this
application, but a motor might hum in an audible frequency range.
The difference to Fast PWM mode is that the timer, when it reaches TOP
at 255, it does not restart but it counts downwards, and it clears
PORTB0 only later when the downcount reaches the compare value again
during downcount. If we would have changed the compare value in between,
which we did not in this simple program, this new compare value would
not come into effect immediately but only until TOP has been reached:
the compare value is temporarily stored and loaded only at TOP.
That demonstrates how the timer can be used to largely simplify the
overhead by the controller: complex up-and-down loops with exact
timing and counting are automated, the controller sleeps instead -
or can do other things without disturbing counting and timing (as
we will see in the next lecture). So whenever you need exact pin
switching, use a timer to do the whole work and do not undertake
efforts to use loops and counting - this will leave you frustrated,
unnecessarily twists your brain and inks your hair in direction
to gray. A timer is a clever solution, so you can concentrate on
the other tasks that really need your valuable and full attention.
Be aware that timer controlled output pins are generally fixed to
certain locations in the output port called OCnA and OCnB. Those
pins are sacrosanct and should be banned from other uses, so
respect this design constraint with a very high priority.
©2017 by http://www.avr-asm-tutorial.net