Home ==> Micro beginner ==> 5. LED with PWM

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.

5.0 Overview

  1. Introduction to the PWM mode of the timer
  2. Hardware, components, mounting
  3. Timer in fast PWM mode
  4. Timer in phase-correct PWM mode

5.1 Introduction to the PWM mode of the timer

5.1.1 8 bit PWM

Pulse width modulation 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.

PWM motor driver 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.

Fast PWM output A control 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.

Fast PWM example 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/s37.5 kcs/s4.69 kcs/s586 cs/s146.5 cs/s36,6 cs/s
4.8 Mcs/s18.8 kcs/s2.35 kcs/s293 cs/s73.3 cs/s18.3 cs/s
2.4 Mcs/s9.4 kcs/s1.68 kcs/s147 cs/s36.7 cs/s9.15 cs/s
1.2 Mcs/s4.69 kcs/s586 cs/s73.2 cs/s18.3 cs/s4.6 cs/s
128 kcs/s500 cs/s62.5 cs/s7.8 cs/s1.95 cs/s0.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

Phase correct 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 strongly reduced.

5.1.3 PWM with different resolution

PWM with CTC 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 (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.

5.2 Hardware, components and mounting

For the PWM intensity regulation the same hardware is used as for the previous lectures.

Home Top Introduction Hardware Fast PWM Phase correct PWM mode

5.3 Fast PWM mode

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 4.7 kcs/s. This is fast enough for the human eye and for any digital camera.

By changing the polarity of the PWM output we reverse the inversion by the LED. The source code is here.

; ***************************************
; * PWM control of a LED in Fast mode   *
; * (C)2017 by www.avr-asm-tutorial.net *
; ***************************************
.INCLUDE "tn13def.inc"
; -------- 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
	ldi rmp,(1<<COM0A1)|(1<<COM0A0)|(1<<WGM01)|(1<<WGM00)
	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

One line in this code requires deeper understanding and some background knowledge:

	ldi rmp,20 * 256 / 100 ; 20% intensity

The term 20 * 256 / 100 usually would result in 51.2. Not so in assembler. All mathmatical expressions 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

; -------- Constants ------------------------
.equ cIntensity = 20 / 100 * 256

and reformulate the above line by

	ldi rmp,cIntensity

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
   No macros.
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 as follows:
  1. Divide 20 by 100 in integer mode, result = 0 (!)
  2. Multiply result with 250, result = 0 (!)
If you want to overrule the standard processing scheme you'll have use brackets. So the formulation

.equ cIntensity = (20 * 250) / 100

is always more correct as it overrules any priority and processing sequences. See this page for a complete list of mathmatical expressions in assembler. This list is sorted by increasing priority.

The PWM intensity control is rather simple code. And here is the result:
0% 1% 2% 3% 4%
5% 10% 20% 50% 100%

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.

Home Top Introduction Hardware Fast PWM Phase correct PWM mode

5.4 Timer in phase correct PWM mode

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.

Home Top Introduction Hardware Fast PWM Phase correct PWM mode

©2017 by http://www.avr-asm-tutorial.net