Project 1 - Controlling a DC motor using PWM and monitoring its Running status
#include <avr/io.h> //preprocessor with avr i/o header file
#define F_CPU 16000000L //cpu clock frequency
#include "avr/interrupt.h" //interrupt header file
#include <util/delay.h> //delay header file
#define direction (PIND&(1<<1)) //port D pin 1 as input push button
#define speed (PIND&(1<<2)) // port D pin 2 as input push button
#define power (PINC&(1<<3)) //port C as pin 3 as input push button
#define lcdport PORTB //port B as lcdport
#define rs_high() PORTD |=(1<<5); //register select as high port D pin 5
#define rs_low() PORTD &= ~(1<<5);//register select as low port D pin 5
#define en_high() PORTD |= (1<<6); //enable pin high in lcd for port D pin 6
#define en_low() PORTD &= ~(1<<6);//enable pin low in lcd for port D pin 6
unsigned char i; //variable for calculation
void lcd_cmd(unsigned char cmd) //function for lcd commands
{
lcdport = (cmd&0xf0); //storing the cmd value in lcd port
rs_low(); //making rs low
en_low(); //making en low
_delay_ms(1); //delay for 1 ms
en_high(); //making en as high
lcdport = ((cmd<<4)&(0xf0)); //storing the cmd shifting 4 and storing in lcd port
rs_low(); //making the rs as low
en_low(); //making the en as low
_delay_ms(1); //delay for 1 ms
en_high(); //en high
}
void lcd_data(unsigned char dat) //function for lcd data same as lcd command function
{
lcdport = (dat&0xf0);
rs_high(); //making rs high instead of low
en_low();
_delay_ms(1);
en_high();
lcdport = ((dat<<4)&(0xf0));
rs_high();
en_low();
_delay_ms(1);
en_high();
}
void lcd_init() //function for lcd intitializing
{
lcd_cmd(0x28);_delay_ms(5); //4bit mode 5*7 lines
lcd_cmd(0x02);_delay_ms(5); //return to home
lcd_cmd(0x01);_delay_ms(5); //remove the data that is displaying in the screen
lcd_cmd(0x0c);_delay_ms(5); //turn off the cursor and on the display
lcd_cmd(0x06);_delay_ms(5); //makes the shift of cursor to the right side
lcd_cmd(0x80);_delay_ms(5); //shifts the cursor to the primary line
}
void cursorpos(char x, char y) //function for the cursor position
{
if( (x < 1 || x > 2) || (y < 1 || y > 16) ) //checking if x is greater than 2 or less than 1 and y is greater than 16 or less than 1
{
x = 1; //if above condition satisfies the value one stores in x
y = 1;
}
if(x == 1) //if x value is one
lcd_cmd(0x7F+y); //command will be passed to blink the cursor
else
lcd_cmd(0xBF+y);
}
void lcd_out(char x,char y,char *str) //function for the displaying part
{
cursorpos(x,y); //passing the cursor position values to the respected function
while(*str) //iterating till the str
{
lcd_data(*str); //passing the data to the lcd_data function
str++; //incrementing the value
}
}
int adc_read(char ch)//function for reading the adc
{
unsigned int var, ans; //variables for storing
ADMUX = ch; //to select the mux
ADCSRA =0X80; //control and status register for adc conversion
ADCH = 0X00; //higher byte
ADCL = 0X00; //lower byte
ADCSRA |= (1<<6); //to start conversion 6 bit is high
while((ADCSRA&0X40) != 0); //itertring till the conversion becomes zero (0x40 is interrupt pin)
var = ADCL; //storing lower
ans = ADCH; //storing higher
ans = ans<<8; //storing ans and left shifting the ans
ans = ans|var; //adding to get 16 bits
return ans; //returning the answer
}
int main(void) //main function
{
DDRB |= 0XFF; //port B starting
DDRA |= ((1<<0)|(1<<1)); //port A as 0 and 1 as high
DDRD &= ~(1<<1); //port D pin 1 as low
DDRD &= ~(1<<2); //port D pin 2 as low
DDRD |= (1<<5); //port D 5 as high
DDRD |= (1<<6); //port D 6 as high
DDRC &= ~(1<<3); //port C pin 3 as low
PORTD |= (1<<2); //port D pin 2 as high
PORTC |= (1<<3); //port D pin 3 as low
i=64; //storing 64 value for 25% duty cycle
TCCR0 = 0x61; //fast pwm mode
GICR = (1<<INT0); //interrupt
MCUCR = 0X02; //trigerring
sei(); //global interrrupt
lcd_init(); //starting lcd display
while(1) //infinite loop
{
while(power==0) //iterating till power equals zero
{
if(direction==0) //if direction equals zero
{
PORTA = 0b00000001; //value for rotating the motor
lcd_out(1, 1, "Motor Runs CL"); //calling lcd_out function for displaying
} else
{
PORTA = 0b00000010; //value for rotating the motor anti clockwise
lcd_out(1, 1, "Motor Runs ACL");
}
OCR0 = i; //loading the i value to ocr0
}
PORTA = 0x00;
lcd_out(1, 1, "Motor is OFF");
}
}
ISR(INT0_vect) //interrupt service routine
{
i=i+50; //incrementing the values of duty cycles
}