Challenge

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

/*
* Project_1_AVR.c
*
* Created: 16-02-2023 01:42:36
* Author : ELCOT
*/

#include //Header will have the I/O registers of AVR micro-controller
#define F_CPU 16000000UL //Defining the system frequency
#include "avr/interrupt.h" //We are using external interrupt pin
#include //To make the delay

#define dir_con (PIND & (1<<1)) //PORT D pin 1 having the push button to control the direction of the DC Motor
#define spd_con (PIND & (1<<2)) //PORT D pin 2 having the push button to control the speed of the DC Motor
#define pow_con (PINC & (1<<3)) //PORT C pin 3 having the push button for Power ON/OFF.

#define lcd_port PORTB //PORT B pins for lCD
#define RS_high PORTD |= (1<<5) //PORT D pin 5 is used for Register Select (high)
#define RS_low PORTD &= ~(1<<5) //PORT D pin 5 is used for Register Select (low)
#define EN_high PORTD |= (1<<6) //PORT D pin 6 is used for Enable (high)
#define EN_low PORTD &= ~(1<<6) //PORT D pin 5 is used for Enable (low)

unsigned char i; //To increase the duty cycle value and load it to the OCR0 register

void lcd_init (void);
void lcd_cmd (char cmd);
void lcd_data (char data);
void cur_pos (char a, char b);
void lcd_out (char a, char b, char *str);
int adc_read (char ch);

int main(void)
{
DDRB = 0xff; //Declaring all the pins of PORT B as output
DDRC = 0xff;
DDRC &= ~(1<<3); //Declaring PORT C 3rd pin as an input power supply button
PORTC &= ~(1<<3); //Enabling the Pull-up resister at PORT C 3rd pin
DDRA |= ((1<<0) | (1<<1) ); //Declaring PORT A 0th pin and 1st pin as output
DDRD &= ~(1<<1); //Declaring PORT D 1st pin as input Direction control button
DDRD &= ~(1<<2); //Declaring PORT D 2nd pin as input Speed control button
PORTD &= ~(1<<2); //Enabling the pull up resister at PORT D 2nd pin
DDRD |= (1<<5); //Declaring PORT D 5th pin as output
DDRD |= (1<<6); //Declaring PORT D 6 th pin as output

i = 128; //Initializing the variable i with the value 64 for 25% duty cycle signal fed into the Motor
TCCR0 = 0x61; //Timer 0, Phase Correct PWM Mode, Non-inverting Mode with no prescaler

GICR = (1<<3); //Enabling the INT0 pin for external Interrupt
GICR = (1< MCUCR = 0x80; //Make the interrupt as negative edge triggered (only one time)
sei(); //Enabling the Global Interrupt

lcd_init(); //Calling the function to initialize the LCD

while (1)
{
while (pow_con == 0) //Continue till the push button is released
{
if (dir_con == 0) //If the direction control push button is released
{
PORTA = 0x01; //1 0 to respective 1A and 2A pins to rotate the motor in a clock-wise direction
lcd_out(1,1,"CL Rotation "); //Message printed on the LCD
}
else
{
PORTA = 0x02; //0 1 to respective 1A and 2A pins to rotate the motor in a Anti-clock-wise direction
lcd_out(1,1,"ACL Rotation "); //Message printed on the LCD
}
OCR0 = i;

}
if (pow_con == 1)
{
PORTA = 0b00000000; //0 0 to respective 1A and 2A pins to stop the rotation
lcd_out(1,1,"Motor is OFF");
}
}
return 0;
}
ISR(INT1_vect) //Interrupt Service Routine
{
i = i+10; //Duty cycle will increase when the i value is increased. i value is increased by 10 in each push and that value is
// loaded in the OCR0 in a while
}


void lcd_init (void)
{
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 and Cursor OFF
_delay_ms(5);
lcd_cmd(0x06); //Increment the Display Cursor
_delay_ms(5);
lcd_cmd(0x80); //Force cursor to begin from the 1st line
_delay_ms(5);
}

void lcd_cmd(char cmd)
{
lcd_port = (cmd & 0xf0); //4 bits for 4 bit lcd mode
RS_low;
EN_low;
_delay_ms(1); //After 1 ms disable lcd
EN_high; //Enabling the LCD


lcd_port = ( (cmd<<4) & (0xf0) ); //4 bits for 4 bit lcd mode
RS_low;
EN_low;
_delay_ms(1); //After 1 ms disable lcd
EN_high;
}

void lcd_data(char data)
{

lcd_port = (data & 0xf0); //4 bits for 4 bit lcd mode
RS_high; //Accessing the Data Register
EN_low;
_delay_ms(1); //After 1 ms disable lcd
EN_high;


lcd_port = ( (data<<4) & (0xf0) ); //4 bits for 4 bit lcd mode
RS_high; //Accessing the Data Register
EN_low;
_delay_ms(1); //After 1 ms disable lcd
EN_high;
}

void cur_pos (char a, char b)
{
if( ((a<1) || (b<1)) || ((b<16) || (b<1)) ) //Checks the condition for 2 rows and 16 columns
{
a=1; //a act as row
b=1; //b act as column
}
if(a==1)
{
lcd_cmd(0x7F + b); //(80-1 = 7f)for starting the 1st line (80 hex decimal value) 7f+b for starting from that column
}
else
{
lcd_cmd(0xBF + b); //(0C-1 = BF) for starting the second line and second row
}
}

void lcd_out(char a, char b, char *str)
{
cur_pos(a,b); //Calling the cursor position function
while(*str)
{
lcd_data(*str); //Calling the lcd data function with the string
str++;
}
}

int adc_read(char ch) //Configuring the ADC value
{
unsigned char x, res;
ADMUX = ch; //Here we are using the channel which we need to select in MUX (here using 2nd bit)
ADCSRA = 0x80; //Control and Status Register to enable the ADC conversion, ADC interrupt, enabling the interrupt flag, ADEN=1
ADCH = 0x00; //Clearing the ADC register (showing the value 0 higher byte)
ADCL = 0x00; //Showing the value 0
ADCSRA |= (1<<6); //Start the conversion 6 bit ADSC high

while ((ADCSRA & 0x40) != 0); // When the conversion of ADC become zero
x = ADCL; //Dummy data type to store the ADCL register (ADC0 - ADC7)
res = ADCH; //Dummy data type to store the ADCH register (ADC8 - ADC9)
res = res << 8; //To get the proper result [alained value] we need to do left shift
res = res | x; //Adding the ADCL+ADCH to get the 16 bits
return res;
}




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.