You are on page 1of 5

Variable Frequency PWM(Pulse Width Modulation) signal

generation using Timers of Arduino(Atmega328p


Microcontroller)/Arduino Fast PWM

August 13, 2019 By EG Projects

In this post i am going to explain how to generate PWM of variable frequency using Atmega328
microcontroller? OR how to generate a variable frequency PWM signal using Arduino Uno? Arduino uno board
contains an atmel Atmega328 microcontroller on it. I am going to generate a PWM of 50% duty cycle on
frequencies between 10Hz to 100Hz. Frequency is changed using a potetiometer/variable resistor connected
to an analog pin of the Arduino. Changing frequency value is displayed on 16×2 character lcd.
Atmega/Arduino Timers
First of all you need to understand about the timers of Atmega328 microcontroller and the registers associated
with them. Atmega328 has 3 timers. Timer-0, Timer-1 and Timer-2. To generate a variable frequency we have
to configure the registers associated with these timers.
Arduino Pins associated with its timers
We can generate variable frequency or output variable frequency pwm on Atmega328 microcontroller pins
(OC0A, OC0B, Oc1A, OC1B, OC2A, Oc2B). All these pins are associated with timers of Atmega328p. OCnX
represents “Output Compare” match. When ever timer/counter value is matched with the predefined value in a
register OCR1A or ICR1 the OCnx pins gets control and now you can do different things. With this “Output
compare match” principle we can accomplish different tasks. Output a variable pwm (pulse width modulation)
signal and so on. I am going to output a variable frequency pwm signal using this principle. Timers registers
with associated timers and arduino pin numbers is shown below..

Arduino(Atmega328p) pins on variable frequency signal can be outputted

Arduino variable frequency signal output – Diy project


I am going to output a variable frequency pwm signal on Pin-9 of arduino board. The register associated with
pin#9 is OC1A. OC1A means output compare using Timer-1. To output a variable frequency Pwm we have to
set the timer in “Phase and Frequency correct PWM mode”. In this mode the output frequency formula is given
in datasheet as below.
Where

Fclk_IO=Input frequency to microcontroller(In


my case Arduino Uno 16MHz)
N(Prescalar Value)=In my case 8
Top(ICR1)= Value in ICR1 Register

Arduino variable frequency generation formula

So to Output a variable frequency we have to calculate the value for ICR1 register. For example to generate a
100Hz frequency using 16MHz timer and prescaler of 8 the value for ICR1 comes out to be.

Arduino(Atmega328p) variable frequency pwm generation formula example

Now to output a PWM on variable frequency we have to configure OCR1A register. I am going to output a
PWM of duty cycle 50%. Take the above generated frequency 100Hz as reference. To generate PWM of 50%
duty cycle. We have to invert the signal output from low to high and high to low after every 5ms since the
frequency in 100Hz.

For this to happen we have to set some bits in timer registers TCCR1A and TCCR1B. In TCCR1A set the
mode of the timer. I set Fast PWM. By selecting bits COM1A1,COM1B1. Selecting these bits will make your
pins OC1A and OC1B to output fast PWM.
Arduino mode selection bits for Non-Inverted Mode

Now when mode is selected we have to do one more thing select the wave form. I selected PWM phase and
frequency correction mode.

Arduino Wave Form Selection Bit

To study about the mode please consult the datasheet topic 16.9.5 Phase and Frequency Correct PWM Mode.
I bet reading the topic “16.9.5 Phase and Frequency Correct PWM Mode” will clear you all about generating
variable frequency PWM using Arduino(Atmega328p).

#include <LiquidCrystal.h>
LiquidCrystal lcd(13, 12, 5, 4, 3, 2);
int Pwmpin=9;//Pwm Output Pin
int Fchange= A0;//Frequency change through Potentiometer
//int Button=1;//Button to change the frequency
void setup()
{
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
pinMode(Pwmpin, OUTPUT);//Pwm pin as Output
//pinMode(Button, INPUT);//Button as Input
TCCR1A=_BV(COM1A1)|_BV(COM1B1);//Non-inverted Mode
TCCR1B=_BV(WGM13)|_BV(CS11);//Prescalar 8
lcd.setCursor(0, 0);//Lcd Coulomb 0 Row 1
lcd.print("Pwm Period = 50%");
}

void loop(){
float freq=0;
float count=10000,countt=0,Pinput=0;
while(1){
ICR1=count;//variable Frequency
countt=2*8*count;
freq= int(16000000/countt);
OCR1A=int(count/2);
lcd.setCursor(0, 1);//Lcd Coulomb 0 Row 2
lcd.print("Pwm Freq =");
lcd.print(freq);
count=10000;
Pinput=analogRead(A0);//Read input value
Pinput=(Pinput/0.0113);
count=count+Pinput;
if(count>=100000)
{
count=10000;
}
delay(1000);
}
}

generating-variable-frequency-with-arduino.ino hosted with   by GitHub view raw

Important Update: Due to many questions on what is 0.0113 in code? Here is its explanation. Since i am
generating variable frequency between 10 Hz to 100 Hz. For generating frequency of 10 Hz count(in code) or
ICR1 value is 100000 and for 100Hz count or ICR1 value is 10000(You can calculate values in upper given
formula). You know that analogread() function of arduino reads 1023 when voltage at corresponding analog pin
is 5 volts. 0.0113 is increasing this 5v corresponding value to match the needed input for pwm function. For
example
For generating 10Hz signal. You input 4.8 volts.

Code Flow
Pinput will be Pinput=1015; // 4.8 volts at arduino analog pin reading
Pinput=(1015/0.0113); —> Pinput=89823;
count= 10000+89823;
count=99823; //If we put this count value back in above formula we get 10.01 Hz frequency

The maximum analog channel can read is 1023 and Pinput value goes to 1023/0.0113=90530 or
count=10000+90530= 100530. Which lower down the frequency to 9.9 Hz and since we want to remain in the
bracket of 10 to 100Hz so we can not go more high. I hope 0.0113 makes sense now. Its just a value to remain
in 10000 to 100000 bracket.
Variable Frequency PWM(Pulse Width Modulation) signal generation using Timers of Arduino(Atmega328p Microcontroller)/Arduino Fast
PWM

Download the project code, folder includes project simulation on proteaus and Arduino Project
.ini file. If you have any questions regarding project code write them below in the projects
section.

You might also like