Pulse Width Modulation (PWM) is a powerful technique that varies the pulse width by keeping the frequency constant. This technique is currently used in many control systems. The applications of PWM are not limited, it is widely used in motor speed control, measurement, power control, and communication, etc. In PWM technique, analog output signals can be easily generated using digital signals. This article will help you understand PWM, its terminology and how to implement it using microcontrollers. In this article, we will demonstrate PWM using AVR At mega 16 microcontroller by varying the intensity of an LED.

PWM pins in AVR microcontroller Atmega16

Atmega16 has four dedicated PWM pins. These pins are PB3 (OC0), PD4 (OC1B), PD5 (OC1A), PD7 (OC2).

Pulse Width Modulation (PWM) in Atmega16/32

Atmega16 also has two 8-bit timers and one 16-bit timer. Timer0 and Timer2 are 8-bit timers, while Timer1 is a 16-bit timer. In order to generate PWM, we must first understand timers, as timers are used to generate PWM. We know that frequency is the number of cycles per second that a timer runs. Therefore, a higher frequency will give us a faster timer. When generating PWM, a faster PWM frequency will give us better control over the output, as it can respond faster to new PWM duty cycles.

In this Atmega16 PWM tutorial, we will use Timer2. You can choose any duty cycle. If you don’t know what is duty cycle in PWM, then let’s discuss it briefly.

What is a PWM signal?

Pulse Width Modulation (PWM) is a digital signal that is most commonly used to control circuits. The time the signal remains high is called the “on time” and the time the signal remains low is called the “off time”. As described below, PWM has two important parameters:

PWM Duty Cycle

The percentage of time that the PWM signal remains high (on time) is called the duty cycle.

Like a 100ms pulse signal, if the signal is high for 50ms and low for 50ms, it means the pulse is high for half of the time and low for the other half of the time. So we can say the duty cycle is 50%. Similarly, if in the 100ms time, the pulse is in the HIGH state for 25ms and in the LOW state for 75ms, the duty cycle will be 25%. Please note that we only calculate the duration of the HIGH state. You can refer to the picture below for a better understanding. Then the formula for duty cycle is:

  1. Duty Cycle (%) = On Time/(On Time + Off Time)

Copy code

Pulse Width Modulation (PWM) in Atmega16/32

So by changing the duty cycle we can change the width of the PWM which results in a change in the brightness of the LED. We will demonstrate using different duty cycles to control the brightness of the LED. After selecting the duty cycle, the next step will be to select the PWM mode.

PWM mode specifies how you want the PWM to work. There are mainly 3 PWM modes. These are as follows:

1. Fast PWM

2. Phase Correction PWM

3. Phase and frequency correction PWM

Fast PWM is used where phase variation does not matter. By using fast PWM, we can output PWM values ​​quickly. Fast PWM cannot be used where phase variation affects operations like motor control, so other PWM modes are used in such applications. Since we will be controlling the brightness of an LED, phase variation will not affect it much, so we will use the fast PWM mode.

Now to generate PWM we will control the internal timer to count up and then set back to zero at a specific count, this way the timer will count up and then set back to zero over and over again. This sets the period. We can now choose to control the pulse, turning the pulse on at a specific count when the timer goes up. When the counter goes back to 0, turn the pulse off. This has a lot of flexibility as you can always access the count of the timer and provide different pulses with a single timer. This is great when you want to control multiple LEDs at the same time. Now let’s start interfacing an LED to PWM with the Atmega16.

Required Components

● Atmega16 AVR microcontroller

● 16Mhz crystal oscillator

● Button

● Jumper

● Breadboard

● USBASP v2.0

Circuit Schematic

Pulse Width Modulation (PWM) in Atmega16/32

We are using OC2 as PWM i.e. Pin21(PD7). So, connect an LED on the PD7 pin of Atmega16.

Pulse Width Modulation (PWM) in Atmega16/32

Programming Atmega16 for PWM

The complete program is given at the end of this article. Use JTAG and Atmel studio to burn the program in Atmega16 and see the PWM effect on the LED. Due to the different duty cycles of PWM, its brightness will slowly increase and decrease.

Start programming Atmega16 by setting up the Timer2 register. The Timer2 register bits are as shown below and we can set or reset the bits accordingly.

Now we will discuss all the bits of Timer2 so that we can get the desired PWM using the program we wrote.

The Timer2 register has four main parts:

●    FOC2 (Forced Output Compare of Timer2): FOC2 is set to 1 when the WGM bit specifies non-PWM mode.

●    WGM2 (Wave Generation Mode for Timer2): These bits control the counting sequence of the counter, the source of the maximum (TOP) counter value, and the type of waveform generation to be used.

●    COM2 (Compare Timer2 Output Mode): These bits control the output behavior. The complete bit description is explained below.

  1. TCCR2 |= (1<<WGM20)|(1<<WGM21);

Copy code

Set the WGM20 and WGM21 bits high to activate the PWM fast mode. WGM stands for waveform generation mode. The selection bits are as follows.

WGM00
WGM01
Timer2 Mode Operation
0
0
Normal Mode
0
1
CTC (Clear Timer on Compare Match)
1
0
PWM, phase correction
1
1
Fast PWM mode

For more details on the waveform generation modes, refer to the official datasheet of the Atmega16 .

  1. TCCR2 |=(1<<COM21)|(1<<CS20)|(0<<CS21)|(0<<CS22);

Copy code

We are not using any prescaling yet, so we set the clock source register to ‘001’.

Increase the duty cycle from 0% to 100%, so the brightness will increase over time. Take a value from 0-255 and send it to the OCR2 pin.

  1. for(duty=0; duty<255; duty++) // 0 to max duty cycle
  2. {
  3. OCR2=duty; //slowly increase the LED brightness
  4. _delay_ms(10);
  5.        }

Copy code

Likewise, reducing the duty cycle from 100% to 0% gradually reduces the brightness of the LED.

  1. for(duty=0; duty>255; duty–) // max to 0 duty cycle
  2. {
  3. OCR2=duty; //slowly decrease the LED brightness
  4. _delay_ms(10);
  5.   }

Copy code

That’s all we have learned about using PWM in Atmega16/32.

The complete code used in this article:  main.rar (566 Bytes, Downloads: 28)

error: Content is protected !!
Scroll to Top