Challenge

Project 1 - Controlling a DC motor using PWM and monitoring its Running status

Solution :-

#include <avr/io.h>   
#define F_CPU 16000000L 
#include "avr/interrupt.h" 
#include <util/delay.h> // delay function purpose
#define sw_dir (PIND & (1<<1)) // d1 pin is declared as push button for direction control.
#define sw_dspd (PIND & (1<<2)) // d2 pin is declared as push button for speed control.
#define pw (PINC & (1<<3)) // c3 is declared as push button for power ON/OFF

#define lcd_port PORTB //PORTB pins are for LCD data
#define RS_high PORTD |= (1<<5) // d5 pin is used for Register Select(RS)
#define RS_low PORTD &=~ (1<<5) // d5 pin is used for RS
#define EN_high PORTD |= (1<<6) // d6 pin is used for Enable
#define EN_low PORTD &=~ (1<<6) // d6 pin is used for En.
unsigned char i;

void lcd_cmd(char cmd) //command for lcd display
{
	lcd_port = (cmd & 0xf0); //4 bits for 4 bit lcd mode
	RS_low;
	EN_low;
	_delay_ms(1); //after 1ms disable lcd
	EN_high; //enable the lcd
	lcd_port = ((cmd<<4) & (0xf0)); //lcd port
	RS_low;
	EN_low;
	_delay_ms(1); //after 1ms disable lcd
	EN_high; //enable the lcd
}

void lcd_data (char data) //send the data to lcd
{
	lcd_port = (data & 0xf0); //4 bits for 4 bit lcd mode
	RS_high; //access data register
	EN_low;
	_delay_ms(1);
	EN_high;
	lcd_port = ((data<<4) & (0xf0)); //4 bits for 4 bit lcd mode
	RS_high; //access data register
	EN_low;
	_delay_ms(1);
	EN_high;
}

void lcd_init()
{
	lcd_cmd(0x28);// used for 4 bit lcd mode
	_delay_ms(5);
	lcd_cmd(0x02); // return home
	_delay_ms(5);
	lcd_cmd(0x01); // clear screen
	_delay_ms(5);
	lcd_cmd(0x0C); // display on cursor off
	_delay_ms(5);
	lcd_cmd(0x06); // increment the display cursor
	_delay_ms(5);
	lcd_cmd(0x80); // force cursor to begin from 1st line
	_delay_ms(5);
}

void cursorpos(char x,char y)
{
	if((x<1 || x>2) || (y>16 || y<1 )) //condition will checks the 2 rows and 16 columns
	{
		x=1; //x= row
		y=1; //y= column
	}
	if(x==1)
	{
		lcd_cmd(0x7F + y); //{ 80-1 = 7F} for starting the 1st line hex decimal value (80) {y we r using the 7F+y means we need to dtart from that column}
	}
	else //(x==2)
	{

		lcd_cmd(0xBF + y); //{0C-1 = 0B} for starting the 2nd line, 2nd row.
	}
}


void lcd_out(char x, char y, char *str) //here we are checking which position we want to print
{
	cursorpos(x,y);
	while(*str)
	{
		lcd_data(*str);
		str++;
	}
}

int adc_read(char channel) // we r configuring the adc value
{
	unsigned int a, result;
	ADMUX = channel; 
	ADCSRA = 0X80;
	ADCH = 0X00; 
	ADCL = 0x00; 
	ADCSRA |= (1<<6); 
	while((ADCSRA & 0x40) != 0); 
	a= ADCL; //dummy data type a and ais stored the ADCL register (ADC0-ADC7)
	result = ADCH; // Store the high value (ADC8-ADC9)
	result = result<<8; //to get proper result or alined value we need to do left shift
	result = result | a ; // we r adding the ADCL + ADCH to get the 16 bits
	return result;
}

int main(void)
{
	DDRB = 0XFF; //Declaring all 8-pins as output.
	DDRA |= ((1<<0)| (1<<1)); //Declaring A0 & A1 pins as output.
	DDRD &=~ (1<<1); //Declaring D1 pin as input.
	DDRD &=~ (1<<2); //Declaring D2 pin as input.
	DDRD |= (1<<5); //Declaring D5 pin as output.
	DDRD |= (1<<6); //Declaring D6 pin as output.
	DDRC &=~ (1<<3); //Declaring C3 pin as input.
	PORTD |= (1<<2); //enabling internal pull up resistor for D2.
	PORTC |= (1<<3); //enabling internal pull up resistor for D3.
	i=64; //initializing i=64 because we are running the motor with 25% duty cycle.
	TCCR0=0X61; //Non-Inverting mode, PWM phase correct mode,NO prescalar.
	GICR=(1<<INT0); //using INT0 for interrupt
	MCUCR=0X02; //make interrupt negative edge triggered
	sei(); //Enable global interrupt
	lcd_init(); //Initialize lcd
	/* Replace with your application code */
	while (1)
	{
		while(pw==0) //continue till the push button is released.
		{
			if(sw_dir == 0) //if the direction control push button is released.
			{
				PORTA = 0b00000001; // 0 1 to respective 1A 2A pins to rotate in clockwise direction.
				lcd_out(1,1,"Motor ON- CL "); //Running clock wise direction

			}
			else
			{
				PORTA = 0b00000010; // 1 0 to respective 1A 2A pins to rotate in Anti-Clockwise direction.
				lcd_out(1,1,"Motor ON- ACL");

			}
			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 is TURNOFF");
	}
}
ISR(INT0_vect) //interrupt service routine
{
	i=i+20; // as i increases the duty cycle also increases. i increases by 20 in each push//
	
}

The Screenshot of Program in Microchip Studio shown below:-

Output of the Program:-

1) When Power Switch: OFF, Direction Switch: OFF, Speed Switch: OFF :: Motor is TURN OFF Condition

2) When Power Switch: ON, Direction Switch: OFF, Speed Switch: OFF :: Motor is TURN ON Condition

3) When Power Switch: ON, Direction Switch: ON, Speed Switch: OFF :: Motor is TURN ON and Direction of Rotation: AntiClockwise

4) When Power Switch: ON, Direction Switch: OFF, Speed Switch: ON :: Motor is TURN ON and Speed of Motor: INCREASED

See the above green portion of the DC Motor increses as compared to the first fig shown.

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.