Project 1 - Controlling a DC motor using PWM and monitoring its Running status
Abhinaya Inbamani mam Live batch
#define F_CPU 16000000L //defines the CPU frequency of the microcontroller to 16MHz.
#include <avr/io.h> //AVR Input/Output library for handling input/output operations of the microcontroller.
#include <util/delay.h> // AVR Delay library for adding delay in the program.
#include "avr/interrupt.h" // AVR Interrupt library for handling interrupts in the program.
#define SW_Dir (PIND&(1<<1)) //d1 pin is input pushbutton for switch direction control
#define SW_Spd (PIND&(1<<2)) //d1 pin is input pushbutton for speed control
#define Power_bu (PINC&(1<<3)) //c3 pin is input power button for switch on/off
#define Rs_high PORTD|=(1<<5) //d5 pin for RS
#define Rs_low PORTD&=(1<<5)
#define En_high PORTD|=(1<<6) //d6 pin for EN
#define En_low PORTD&=(1<<6)
#define LCD_port PORTB //portb pins for LCD
unsigned char i; //variable declaration to increase duty cycle of PWM
void Lcd_cmd(char cmd) //This function is used to send a command to the LCD.
{
LCD_port = (cmd & 0XF0); //sends the upper nibble of the command to the LCD.
Rs_low; //sets the RS pin to low for sending commands.
En_low;
_delay_ms(1);
En_high;
LCD_port = ((cmd<<4)&(0XF0));//sends the lower nibble of the command to the LCD.
Rs_low;
En_low;
_delay_ms(1);
En_high;
}
void Lcd_data(char data) //This function is used to send data to the LCD.
{
LCD_port = (data & 0XF0);//sends the upper nibble of the data to the LCD.
Rs_high; //sets the RS pin to high for sending data.
En_low;
_delay_ms(1);
En_high;
LCD_port = ((data<<4)&(0XF0)); ////sends the lower nibble of the data to the LCD.
Rs_high;
En_low;
_delay_ms(1);
En_high;
}
void cursorpos (char x, char y) //This function is used to set the cursor position on the LCD.
{
if ((x<1||x>2)||(y>16||y<1))
{
x=1;
y=1;
}
if (x==1)
{
Lcd_cmd(0X7F+y);
}
else
{
Lcd_cmd(0XBF+y);
}
}
void Lcd_out(char x, char y, char *str)//This function is used to display a string on the LCD.
{
cursorpos(x,y);
while (*str)
{
Lcd_data(*str);
str++;
}
}
Lcd_Init()
{
Lcd_cmd(0X02); _delay_ms(5); //return cursor to home
Lcd_cmd(0X01); _delay_ms(5); //clear screen
Lcd_cmd(0X0C); _delay_ms(5); //display ON cursor OFF
Lcd_cmd(0X06); _delay_ms(5); //increment cursor
Lcd_cmd(0X80); _delay_ms(5); //force cursor to begin 1st line
Lcd_cmd(0X28); _delay_ms(5); //used for 4 bit lcd mode
}
int main()
{
DDRB |= 0XFF; //sets all pins of Port B as outputs.
DDRA |= (1<<0)|(1<<1); //sets pins 0 and 1 of Port A as outputs.
DDRD &= (1<<1); //sets pin 1 of Port D as an input.
DDRD &= (1<<2); //sets pin 2 of Port D as an input.
DDRC &= (1<<3); //sets pin 3 of Port c as an input.
DDRD |= (1<<5); //set pins 5 of Port D as outputs
DDRD |= (1<<6); //set pins 6 of Port D as outputs
PORTD |= (1<<2); //set the pull-up resistors for pin 2 of Port D
PORTC |= (1<<3);//set the pull-up resistors for pin 3 of Port D
i = 64; // for 25% duty cycle
TCCR2 = 0X71;//TCCR2 values are here FOC2 =0,WGM20=1,COM21=1,COM20=1(set OC2),WGM21=0(PWM,Phase correct),CS22=0,CS21=0,CS20=1(No prescaler))
MCUCR = 0X02; //external interrupt INT0 to be triggered on the falling edge.
sei(); //enables interrupts by setting the global interrupt enable bit.
GICR = (1<<IVSEL)|(1<<IVCE); //enable IVSEL & IVCE
Lcd_Init(); //Initialize LCD
while (1)
{
while(Power_bu==0) //control till the power push button is released
{
if(SW_Dir==0) //If the direction control push button is released
{
PORTA = 0X01; //(0b00000001)set A1 as 1 and A2 as 0 to rotate in clockwise direction
Lcd_out(1,1,"Motor is Running");
Lcd_out(2,3,"clockwise");
}
else
{
PORTA = 0X02; //(0b00000010)set A1 as 0 and A2 as 1 to rotate in clockwise direction
Lcd_out(1,1,"Motor is Running");
Lcd_out(2,3,"Anticlockwise");
}
OCR2 = i; //as i increase corresponding value is to be loaded into OCR2
}
PORTA = 0X00; //set A1 & A2 pins to 0 0 to stop rotation
Lcd_out(1,1,"Motor is OFF");
Lcd_out(2,3,"CAUTION!!!");
}
}
ISR(INT0_vect) //interrupt service routine
{
i = i+64; // i will increase by 64 duty cycle will increase from 25% - 50% - 75% - 100% in each push
}