Project 1 - Controlling a DC motor using PWM and monitoring its Running status
/*
* Project1 practice.c
*
* Created: 25-02-2023 21:17:21
* Author : Hp
*/
#include
#define F_CPU 16000000L //define the crystal frequency
#include "avr/interrupt.h" // using the external interrupt
#include
#define sw_dir (PIND &(1<<1)) //D1 pin as pushbutton for direction control.
#define sw_dspd (PIND &(1<<2)) //D2 pin as pushbutton for speed control.
#define pw (PINC &(1<<3)) //C3 pin as pushbutton for power ON/OFF.
#define lcd_port PORTB //lcd data on PORTB
#define rs_high PORTD |= (1<<5) //D5 pin is used for Register select
#define rs_low PORTD &= ~(1<<5) //D5 pin is used for Register select
#define en_high PORTD |= (1<<6) //D6 pin is used for enable
#define en_low PORTD &= ~(1<<6) //D6 pin is used for enable
unsigned char i;
void lcd_cmd(char cmd) //command for lcd display
{
lcd_port=(cmd & 0xf0); //4 bit for 4 bit lcd mode
rs_low;
en_low;
_delay_ms(5); //after 5 ms disable lcd
en_high; //enable the lcd
lcd_port=((cmd<<4) & (0xf0));
rs_low;
en_low;
_delay_ms(5); //after 5 ms disable lcd
en_high; //enable the lcd
}
void lcd_data(char data) //send the data to lcd
{
lcd_port=(data & 0xf0); //4 bit for 4 bit lcd mode
rs_high;
en_low;
_delay_ms(5); //after 5 ms disable lcd
en_high; //enable the lcd
lcd_port=((data<<4)&(0xf0));
rs_high;
en_low;
_delay_ms(5); //after 5 ms disable lcd
en_high; //enable the lcd
}
void lcd_init()
{
lcd_cmd(0x38);_delay_ms(1); //used for 4 it lcd mode
lcd_cmd(0x02);_delay_ms(1); //return Home
lcd_cmd(0x01);_delay_ms(1); //clear screen
lcd_cmd(0x0C);_delay_ms(1); //increment the display cursor
lcd_cmd(0x06);_delay_ms(1); //display the cursor off
lcd_cmd(0x80);_delay_ms(1); //force cursor to begin from 1st line
}
void cursorpos(char x, char y)
{
if((x<1 || x>2) || (y>16 || y<1)) //condition will check the 2 rows & 16 coloumns
{
x=1; //x=row
y=1; //y=column
}
if(x==1)
{
lcd_cmd(0x7F+y); //{80-1=7f}
}
else //(x == 2)
{
lcd_cmd(0xBF+y); //{0C-1=0B}
}
}
void lcd_out(char x, char y, char *str) //check the position of cursor
{
cursorpos(x,y);
while(*str)
{
lcd_data(*str);
str++;
}
}
int adc_read(char channel) //configure the adc value
{
unsigned int a, result;
ADMUX=channel;
ADCSRA= 0X80; //control and status register to enable the adc conversion,enable the interrupt flag, adc interrupt. ADEN=1
ADCH = 0X00; //clear the adc register by showing value 0
ADCL = 0X00;
while((ADCSRA & 0X40)!=0); //the conversion becomes 0 means the conversion of adc(0x40 means interrupt pin)
a = ADCL;
result = ADCH;
result = result<<8;
result = result | a;
return result;
}
int main(void)
{
DDRB = 0xFF;
DDRA |=((1<<0)|(1<<1)); //declaring the A0 & A1 pins are output
DDRD &=~(1<<1); //declaring D1 pin as output
DDRD &=~(1<<2); //declaring D2 pin as output
DDRD |=(1<<5); //declaring D5 pin as output
DDRD |=(1<<6); //declaring D6 pin as output
DDRC &=~(1<<3); //declaring D3 pin as input
PORTD |=(1<<2); //enabling internal pull up register D2
PORTC |=(1<<3); //enabling internal pull up register D3
i=64; //initializing i=64 becoz Motor running with 25% duty cycle
TCCR0=0x61; //Non inverting mode, PWM phase correct mode , NO prescalar
GICR=(1<
sei(); //enable global interrupt
lcd_init(); //lcd initialization
while(1)
{
while(pw==0) //continue till the pushbutton is released
{
if(sw_dir == 0) //if the direction control pushbutton is released
{
PORTA = 0b00000001; //1 0 to respective 1A 2A pins to rotate in clockwise direction
lcd_out(1,1," Motor ON-CL "); //running clockwise direction (CL=clockwise)
}
else
{
PORTA = 0b00000010; //1 0 to respective 1A 2A pins to rotate in anti clockwise direction
lcd_out(1,1," Motor ON-ACL "); //running in anticlockwise direction (ACL=Anti-clockwise)
}
OCR0 = i; //i increases in ISR, the corresponding value is to be loaded into OCR0
}
PORTA = 0x00; //0 0 to respective 1A 2A pins to stop rotation
lcd_out(1,1," Motor Turn OFF "); // motor off condition
}
}
ISR(INT0_vect) // interrupt service routine
{
i=i+20; //as i increases the duty cycle also increases
}