Challenge

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

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#define F_CPU 16000000UL

#define lcd_data_port PORTB

#define lcd_ctrl_port PORTD

#define rs_high PORTD |= (1<<5)

#define rs_low PORTD &= ~(1<<5)

#define en_high PORTD |= (1<<6)

#define en_low PORTD &= ~(1<<6)

double dutyCycle = 0;

void lcd_cmd(unsigned char cmd)

{

lcd_data_port = (lcd_data_port & 0x0F) | (cmd & 0xF0); // Send high nibble

rs_low;

en_high;

_delay_ms(1);

en_low;

_delay_ms(2);

lcd_data_port = (lcd_data_port & 0x0F) | ((cmd << 4) & 0xF0); // Send low nibble

en_high;

_delay_ms(1);

en_low;

_delay_ms(1);

}

void lcd_data(unsigned char data)

{

lcd_data_port = (lcd_data_port & 0x0F) | (data & 0xF0); // Send high nibble

rs_high;

en_high;

_delay_ms(1);

en_low;

_delay_ms(1);

lcd_data_port = (lcd_data_port & 0x0F) | ((data << 4) & 0xF0); // Send low nibble

en_high;

_delay_ms(1);

en_low;

_delay_ms(1);

}

void lcd_init()

{

lcd_data_port &= 0x0F; // Set lower 4 bits of data port as output

lcd_ctrl_port |= (1 << PD5) | (1 << PD6); // Set RS and EN pins as output

_delay_ms(20); // Wait for LCD to power up

// Initialization sequence

lcd_cmd(0x32); // Initialize 4-bit mode

lcd_cmd(0x28); // 4-bit mode, 2 lines, 5x7 font

lcd_cmd(0x0E); // Display on, cursor off, blink off

lcd_cmd(0x06); // Increment cursor

lcd_cmd(0x01); // Clear display

_delay_ms(2); // Wait for command to complete

}

void cursorpos(char row, char col)

{

unsigned char position;

if (row == 1)

{

position = 0x80 + col - 1;

}

else if (row == 2)

{

position = 0xC0 + col - 1;

}

lcd_cmd(position);

}

void lcd_print(char row, char coloumn, unsigned int value, int digits)

{

unsigned int temp;

unsigned int unit;

unsigned int tens;

unsigned int hundred;

unsigned int thousand;

unsigned int million;

unsigned char flag = 0;

if (row == 0 || coloumn == 0)

cursorpos(1, 1);

else

cursorpos(row, coloumn);

if (digits == 5 || flag == 1)

{

million = value / 10000 + 48;

lcd_data(million);

flag = 1;

}

if (digits == 4 || flag == 1)

{

temp = value / 1000;

thousand = temp % 10 + 48;

lcd_data(thousand);

flag = 1;

}

if (digits == 3 || flag == 1)

{

temp = value / 100;

hundred = temp % 10 + 48;

lcd_data(hundred);

flag = 1;

}

if (digits == 2 || flag == 1)

{

temp = value / 10;

tens = temp % 10 + 48;

lcd_data(tens);

flag = 1;

}

if (digits == 1 || flag == 1)

{

unit = value % 10 + 48;

lcd_data(unit);

}

if (digits > 5)

lcd_data('e');

}

void lcd_out(char x, char y, char *str)

{

cursorpos(x, y);

while (*str)

{

lcd_data(*str);

str++;

}

}

int main(void)

{

lcd_init(); // Initialize LCD

DDRD &= ~(1 << PD2); // Set PD2 as input (External Interrupt INT0)

PORTD |= (1 << PD2); // Enable internal pull-up resistor for PD2

PORTC = (1 << PC3); // Set PC3 as input (Motor Enable Switch)

DDRB = (1 << PB3); // Set PB3 as output (PWM Output for Motor)

DDRA = (1 << PA1) | (1 << PA2); // Set PA1 and PA2 as output (Motor Direction Control)

TCCR0 = (1 << WGM00) | (1 << COM01) | (1 << CS00); // Fast PWM, Non-inverted mode, No prescaler

OCR0 = dutyCycle; // Initialize PWM duty cycle

GICR = (1 << INT0); // Enable external interrupt INT0

MCUCR = 0x02; // Falling edge detection for INT0

sei(); // Enable global interrupts

while (1)

{

if ((PINC & (1 << PC3)) == (0 << PC3))

{

lcd_out(1, 1, "Motor is : ON");

if ((PIND & (1 << PD1)) == (1 << PD1))

{

PORTA |= (1 << PA1); // Rotate motor clockwise

PORTA &= ~(1 << PA2);

lcd_out(2, 1, "Dir:CW Speed:");

lcd_print(2, 14, dutyCycle, 3); // Print duty cycle on LCD

}

if ((PIND & (1 << PD1)) == (0 << PD1))

{

PORTA &= ~(1 << PA1); // Rotate motor counter-clockwise

PORTA |= (1 << PA2);

lcd_out(2, 1, "Dir:CCW Speed:");

lcd_print(2, 14, dutyCycle, 3); // Print duty cycle on LCD

}

OCR0 = dutyCycle; // Update PWM duty cycle

}

if ((PINC & (1 << PC3)) == (1 << PC3))

{

lcd_out(1, 1, "Motor is :OFF");

PORTA &= ~(0x06); // Turn off motor

}

}

return 0;

}

ISR(INT0_vect)

{

_delay_ms(100); // Debounce delay

dutyCycle += 10; // Increase duty cycle by 10%

if (dutyCycle > 256)

{

dutyCycle = 0; // Reset duty cycle if it exceeds maximum value

}

}

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.