Aim:
Pulse Width Modulation or PWM is a common technique used to vary the width of the pulses in a pulse-train. PWM has many applications such as controlling servos and speed controllers, limiting the effective power of motors and LEDs.
Description:
Pulse width modulation is basically, a square wave with a varying high and low time. A basic PWM signal is shown in the following figure.
There are various terms associated with PWM −
- On-Time − Duration of time signal is high.
- Off-Time − Duration of time signal is low.
- Period − It is represented as the sum of on-time and off-time of PWM signal.
- Duty Cycle − It is represented as the percentage of time signal that remains on during the period of the PWM signal.
Period
As shown in the figure, Ton denotes the on-time and Toff denotes the off-time of signal. Period is the sum of both on and off times and is calculated as shown in the following equation −
Duty Cycle
Duty cycle is calculated as the on-time of the period of time. Using the period calculated above, duty cycle is calculated as −
analogWrite() Function
The analogWrite() function writes an analog value (PWM wave) to a pin. It can be used to light a LED at varying brightness or drive a motor at various speeds. After a call of the analogWrite() function, the pin will generate a steady square wave of the specified duty cycle until the next call to analogWrite() or a call to digitalRead() or digitalWrite() on the same pin. The frequency of the PWM signal on most pins is approximately 490 Hz. On the Uno and similar boards, pins 5 and 6 have a frequency of approximately 980 Hz. Pins 3 and 11 on the Leonardo also run at 980 Hz.
On most Arduino boards (those with the ATmega168 or ATmega328), this function works on pins 3, 5, 6, 9, 10, and 11. On the Arduino Mega, it works on pins 2 - 13 and 44 - 46. Older Arduino boards with an ATmega8 only support analogWrite() on pins 9, 10, and 11.
The Arduino Due supports analogWrite() on pins 2 through 13, and pins DAC0 and DAC1. Unlike the PWM pins, DAC0 and DAC1 are Digital to Analog converters, and act as true analog outputs.
You do not need to call pinMode() to set the pin as an output before calling analogWrite().
analogWrite() Function Syntax
analogWrite ( pin , value ) ;
value − the duty cycle: between 0 (always off) and 255 (always on).
Block Diagram
Schematic
Code
// *********************************************** // Project: Interfacing PWM to 8051 // Author: Hack Projects India // Module description: Operate array of LED's // *********************************************** #include<reg51.h> // PWM_Pin sbit PWM_Pin = P2^0; // Pin P2.0 is named as PWM_Pin // Function declarations void cct_init(void); void InitTimer0(void); void InitPWM(void); // Global variables unsigned char PWM = 0; // It can have a value from 0 (0% duty cycle) to 255 (100% duty cycle) unsigned int temp = 0; // Used inside Timer0 ISR // PWM frequency selector /* PWM_Freq_Num can have values in between 1 to 257 only * When PWM_Freq_Num is equal to 1, then it means highest PWM frequency * which is approximately 1000000/(1*255) = 3.9kHz * When PWM_Freq_Num is equal to 257, then it means lowest PWM frequency * which is approximately 1000000/(257*255) = 15Hz * * So, in general you can calculate PWM frequency by using the formula * PWM Frequency = 1000000/(PWM_Freq_Num*255) */ #define PWM_Freq_Num 1 // Highest possible PWM Frequency // Main Function int main(void) { cct_init(); // Make all ports zero InitPWM(); // Start PWM PWM = 127; // Make 50% duty cycle of PWM while(1) // Rest is done in Timer0 interrupt {} } // Init CCT function void cct_init(void) { P0 = 0x00; P1 = 0x00; P2 = 0x00; P3 = 0x00; } // Timer0 initialize void InitTimer0(void) { TMOD &= 0xF0; // Clear 4bit field for timer0 TMOD |= 0x01; // Set timer0 in mode 1 = 16bit mode TH0 = 0x00; // First time value TL0 = 0x00; // Set arbitrarily zero ET0 = 1; // Enable Timer0 interrupts EA = 1; // Global interrupt enable TR0 = 1; // Start Timer 0 } // PWM initialize void InitPWM(void) { PWM = 0; // Initialize with 0% duty cycle InitTimer0(); // Initialize timer0 to start generating interrupts } // Timer0 ISR void Timer0_ISR (void) interrupt 1 { TR0 = 0; // Stop Timer 0 if(PWM_Pin) // if PWM_Pin is high { PWM_Pin = 0; temp = (255-PWM)*PWM_Freq_Num; TH0 = 0xFF - (temp>>8)&0xFF; TL0 = 0xFF - temp&0xFF; } else // if PWM_Pin is low { PWM_Pin = 1; temp = PWM*PWM_Freq_Num; TH0 = 0xFF - (temp>>8)&0xFF; TL0 = 0xFF - temp&0xFF; } TF0 = 0; // Clear the interrupt flag TR0 = 1; // Start Timer 0 }
No comments:
Post a Comment