Project 1 - Controlling a DC motor using PWM and monitoring its Running status
Controlling a DC motor using PWM and monitoring its Running status
CODE
#include <avr/io.h>//I/O registers for avr
#define F_CPU 16000000L//clock frequency of 16MHz
#include <util/delay.h>//delay functions
#include "avr/interrupt.h"//for using external interupts
#define lcdport PORTB //portB pins are for lcd data
#define rs_high PORTD |= (1<<0)//pin 0 of portD is used as register select(RS) of lcd
#define rs_low PORTD &= ~(1<<0)
#define en_high PORTD |= (1<<1)//pin 1 of portD is used as Enable pin(En) of lcd
#define en_low PORTD &= ~(1<<1)
#define power_SW (PINC &(1<<1))//pin 1 of portC is declared as push button for power
#define direction_SW (PIND &(1<<3))//pin 3 of portD is declared as push button for direction control
#define speed_SW (PIND &(1<<2))//pin 2 of portD is declared as push button for speed control
unsigned char direction_flag;//for direction toggling
void lcd_cmd(unsigned char cmd);
void lcd_data(unsigned char data);
void lcd_init();
void cursor_pos(char x,char y);
void lcd_out(char x,char y,char*str);
int adc_read(char channel);
int main(void)
{
DDRB=0XFF;//enable all pins of PortB as output for lcd dataline
DDRD|=(1<<0);//lcd rs pin
DDRD|=(1<<1);//lcd en pin
DDRD &= ~(1<<2);//set D2 as input for direction Pb
DDRC &= ~(1<<1);//set C1 as input for power Pb
DDRA|=(1<<0)|(1<<1);//set portC pin0,1 (A0,A1) as outputs
sei();//enable global interrupt
GICR=(1<<6); //enable INT0 for direction control pushbutton
PORTD=(1<<2); //enable internal pull up resistor for pin2 of PortD
PORTC=(1<<1);//enable internal pull up resistor for pin1 of PortC
TCCR0=0X61;//set as phase correct PWM ,no prescaler ,non-inverted mode
MCUCR=0X02;//set interrupt generation triggered at falling edge
lcd_init();//function to initialize lcd
direction_flag=0;//used for motor direction toggling
while (1)
{
while(power_SW==0)//while Power switch is pressed
{
if(direction_flag!=0) //each press of direction switch changes motor direction,motor is rotating in clockwise direction
{
PORTA |=(1<<0);//pin0 of portA is set
PORTA &= ~(1<<1);//pin1 of portA is off
lcd_out(1,1,"MOTOR_ON CW ");//prints message on 1st row,1st column
lcd_out(2,1,"CLOCKWISE");//prints message on 2nd row,1st column
}
else//motor rotates in counter clockwise direction
{
PORTA |=(1<<1);//pin1 of portA is set
PORTA &= ~(1<<0);//pin0 of portA is off
lcd_out(1,1,"MOTOR_ON CCW");//prints message on 1st row,1st column
}
OCR0=(adc_read(3)>>2); //adc_read() is divided by 4(bitshift right 2) to convert 10-bit to 8-bit value and assigned to OCR0
}
PORTA=0X00;//motor is in inactive state
lcd_out(1,1,"MOTOR_OFF ");//prints message on 1st row,1st column
}
}
ISR(INT0_vect)//interrupt service routine
{
direction_flag=~direction_flag;//during each ISR execution ,direction_flag gets toggled
}
void lcd_cmd(unsigned char cmd)//command function for lcd
{
lcdport=(cmd & 0XF0);//cmd is assigned to lcdport in 4-bit lcd mode(send upper nibble)
rs_low;
en_low;
_delay_ms(1);//1 Millisecond delay
en_high;
lcdport=((cmd<<4)&(0XF0));//send lower nibble
en_low;
rs_low;
_delay_ms(1);
en_high;
}
void lcd_data(unsigned char data)//data function for lcd
{
lcdport=(data & 0XF0);//data is assigned to lcdport in 4-bit lcd mode(send upper nibble)
rs_high;
en_low;
_delay_ms(1);// 1 Millisecond delay
en_high;
lcdport=((data<<4)&(0XF0));//send lower nibble
en_low;
rs_high;
_delay_ms(1);
en_high;
}
void lcd_init()//initialization function for lcd
{
lcd_cmd(0X28);//2 line, 5*7 matrix in 4-bit mode
_delay_ms(5); //5 ms delay
lcd_cmd(0X02);//return home
_delay_ms(5);
lcd_cmd(0X01);//clear display
_delay_ms(5);
lcd_cmd(0X0C);//display on,cursor off
_delay_ms(5);
lcd_cmd(0X06);//increment cursor
_delay_ms(5);
lcd_cmd(0X80);//force cursor begin in 1st line
_delay_ms(5);
}
void cursor_pos(char x,char y)//function for entering cursor position
{
if((x<1 || x>2) || (y<1 || y>16))//if cursor row selected is beyond its max or min range it gets reseted
{
x=1;//x=row
y=1;//y=column
}
if(x==1)
{
lcd_cmd(0X80);//force cursor begin 1st line
}
if(x==2)
{
lcd_cmd(0XC0);//force cursor begin 2nd line
}
}
void lcd_out(char x,char y,char *str)//function to print at specified position
{
cursor_pos(x,y);
while(*str)
{
lcd_data(*str);
str++;
}
}
int adc_read(char channel)//adc read function for analog reading
{
unsigned int a,result;
ADMUX=channel;//for selecting the analog input channel by selcting mux using 2 bits
ADCSRA=0X80;//enable adc conversion
ADCH=0X00;//initially 0
ADCL=0X00;
ADCSRA|=(1<<6);//adc start conversion
while((ADCSRA &0X40)!=0);
a=ADCL;//lower bits of 10-bit adc value is assigned to a(ADC0-ADC7)
result=ADCH;//upper bits of 10-bit adc value is assigned to result(ADC8,ADC9)
result=result<<8;//for getting aligned value, bit shift to left
result=result|a;//ADCL+ADCH
return result;
}






Simulation using SimulIDE
Motor in off state

Motor ON, Direction of rotation in Clockwise at speed of 60%

Motor ON, Direction of rotation in Counter Clockwise at speed of 60%

Motor ON, Direction of rotation in Counter Clockwise at speed of 10%
