Project 1 - Controlling a DC motor using PWM and monitoring its Running status
#include <avr/io.h>
#include <util/delay.h>
#include<stdlib.h>
# define F_CPU 8000000L
// Function to initialize PWM
void PWM_init() {
TCCR0 |= (1 << WGM00) | (1 << WGM01) | (1 << COM01) | (1 << CS00);
DDRB |= (1 << PB3); // Set OC0 pin as output
}
// Function to set PWM duty cycle
void set_PWM_duty_cycle(uint8_t duty_cycle) {
OCR0 = duty_cycle;
}
// Function to initialize direction control pins
void Direction_init() {
DDRC |= (1 << PC0) | (1 << PC1); // Set direction control pins as output
}
// Function to set motor direction
void set_motor_direction(uint8_t direction) {
if (direction == 0) {
PORTC &= ~(1 << PC0); // Set direction pin 1 to LOW
PORTC |= (1 << PC1); // Set direction pin 2 to HIGH
} else {
PORTC |= (1 << PC0); // Set direction pin 1 to HIGH
PORTC &= ~(1 << PC1); // Set direction pin 2 to LOW
_delay_ms(1000);
}
}
// Function to initialize LCD
void LCD_init() {
// Configure GPIO pins for LCD
DDRA = 0xFF; // Set all PORTA pins as output
DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2); // Set RS, RW, E pins as output
_delay_ms(20); // Wait for LCD to power up
LCD_command(0x38); // 2 lines, 5x8 matrix
LCD_command(0x0C); // Display on, cursor off
LCD_command(0x06); // Entry mode: increment cursor
LCD_command(0x01); // Clear display
_delay_ms(2); // Delay after LCD initialization
}
// Function to send command to LCD
void LCD_command(unsigned char command) {
PORTB &= ~(1 << PB0); // RS = 0 (Command mode)
PORTB &= ~(1 << PB1); // RW = 0 (Write mode)
PORTA = command; // Send command to LCD
PORTB |= (1 << PB2); // E = 1
_delay_ms(1);
PORTB &= ~(1 << PB2); // E = 0
_delay_ms(3); // Delay after sending command
}
// Function to send data to LCD
void LCD_data(unsigned char data) {
PORTB |= (1 << PB0); // RS = 1 (Data mode)
PORTB &= ~(1 << PB1); // RW = 0 (Write mode)
PORTA = data; // Send data to LCD
PORTB |= (1 << PB2); // E = 1
_delay_ms(1);
PORTB &= ~(1 << PB2); // E = 0
_delay_ms(1); // Delay after sending data
}
// Function to display status on LCD
void display_status(uint8_t duty_cycle, uint8_t direction) {
LCD_command(0x80); // Set cursor to the beginning of the first line
// Convert duty cycle to string
char duty_cycle_str[4];
itoa(duty_cycle, duty_cycle_str, 10);
// Display duty cycle on LCD
for (int i = 0; i < 3; i++) {
if (duty_cycle_str[i] != '\0') {
LCD_data(duty_cycle_str[i]);
} else {
LCD_data(' ');
}
}
LCD_command(0xC0);
// Display direction on LCD
if (direction == 0) {
LCD_data(' '); // Space for forward direction
LCD_data('F');
} else {
LCD_data(' '); // Space for reverse direction
LCD_data('R');
}
}
int main() {
// Initialize PWM, direction control, and LCD
PWM_init();
Direction_init();
LCD_init();
uint8_t duty_cycle = 128; // Initial duty cycle (50%)
uint8_t direction = 0; // Initial direction (forward)
while (1) {
// Set the duty cycle
set_PWM_duty_cycle(duty_cycle);
// Set the motor direction
set_motor_direction(direction);
// Display the status on LCD
display_status(duty_cycle, direction);
// Delay for some time
_delay_ms(500);
// Increase the duty cycle gradually
if (duty_cycle < 255) {
duty_cycle++;
}
// Change the direction
if (duty_cycle == 255) {
direction = 1; // Toggle direction
}
}
return 0;
}
