0% found this document useful (0 votes)
15 views12 pages

Experiment 6

The document outlines an experiment focused on controlling the velocity of a DC motor using Pulse Width Modulation (PWM) with an ATmega 2560 microcontroller. It describes the procedure for setting up the robot to accelerate and decelerate based on boot switch presses, displaying the current speed on an LCD. The document includes code snippets and function descriptions necessary for implementing the PWM control and LCD display functionalities.

Uploaded by

amul.kumar28111
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views12 pages

Experiment 6

The document outlines an experiment focused on controlling the velocity of a DC motor using Pulse Width Modulation (PWM) with an ATmega 2560 microcontroller. It describes the procedure for setting up the robot to accelerate and decelerate based on boot switch presses, displaying the current speed on an LCD. The document includes code snippets and function descriptions necessary for implementing the PWM control and LCD display functionalities.

Uploaded by

amul.kumar28111
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Experiment 6: Velocity control of DC motor using PWM

The aim of this experiment is to get you familiar with Pulse Width Modulation (PWM) using
ATmega 2560 micro-controller present on Firebird V robot.
Your task is to accelerate and decelerate the robot from its minimum to maximum speed and
vice versa using the Boot switch and indicate the robot’s current speed on the LCD.
Divide the entire velocity range (maximum - minimum) into approximately 4 equal parts. The
robot’s velocity is proportional to the values passed in the Output Compare Registers
(OCR5AL and OCR5BL).
When the robot is turned ON, motors should be in stop condition and the LCD should display
“Speed: 000” at 1st row and 3rd column. When the boot switch is pressed once, the LCD should
display “Speed: 063” and motors should start rotating slowly.
On subsequent press of the boot switch, the speed should be incremented by 63 and the motor
should also rotate faster than before.
Once the speed 252 is reached, the subsequent press of boot switch should start decrementing
the speed by 63 and the motor should rotate slower than before. This continues till the speed 0
is reached, and this cycle should continue as shown in Table 1.
Table 1: Boot switch press and Speed relation
Boot switch press Speed
Initially 0
1st press 63
2nd press 126
3rd press 189
4th press 252
5th press 189
6th press 126
7th press 63
8th press 0
9th press 63

Procedure:
Step-1: Create project named “Experiment-6.atsln” in Atmel Studio.
Step-2: You will notice some pre-written function stubs in included for your assistance
(Experiment-6.c). Write the code to complete the function with the help of function description
and inline comments. Also, some pre-written functions related to LCD are called in main().
These functions are declared and defined in “lcd.h” and “lcd.c” respectively. Some other
functions related to LCD are listed below that can assist you in completing the task:
void lcd_numeric_value(char row, char column, int val, int digits);

// This function prints any integer value or value in a variable as integer on the specified

// location and up to the specified number of digits on LCD. This function calls

// lcd_cursor() function in its definition.

void lcd_string(char row, char column, char *str);

// This function prints the given string on the LCD at the specified (row,column) position

Use these pre-defined functions and write your code to do the following:
1. Display text “Speed: ” starting from the 1st row and 3rd column on LCD.
2. Display the motor’s current speed in 3 digits at 1st row and 10th column on LCD.
Step-3: Check and debug your code by loading the hex file on the robot. Save the project.
Ensure that code performs as expected.
Experiment-6.c
#define F_CPU 14745600

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// LCD Header file included that contains function definitions essential to deal with LCD;
more details can be found in "Read Me" file
#include "lcd.h"
// Declare any global variables if you require here
/*
* Function Name: motion_pin_config
* Input: none
* Output: none
* Logic: Code to initialize desired I/O port using I/O port registers viz. DDRx and PORTx.
* Example Call: motion_pin_config ()
*/
void motion_pin_config (void)
{
DDRA = // Port A Direction pins (PA3-PA0) have to be set as
outputs
PORTA = // Write suitable value in the PORT A register to make
initial values to be "0"
DDRL = // Setting PL3 and PL4 pins as output for PWM generation
PORTL = // Write suitable value in the PORT L register to set
initial value of the Port L pins (PL3, PL4) to logic 1
}

/*
* Function Name: boot_switch_config
* Input: none
* Output: none
* Logic: Code to initialize desired I/O port using IO port registers viz. DDRx and PORTx.
Example Call: boot_switch_config()
*/
void boot_switch_config(void)
{
DDRE = // PE.7 is connected to Boot switch
PORTE = // Write a suitable value to activate pull up resistor for PE.7
only
}

/*
* Function name: port_init
* Input: none
* Output: none
* Logic: Code to initialize desired I/O port using I/O port registers viz. DDRx and PORTx
* Example Call: port_init();
*/

void port_init(void)
{
motion_pin_config();
boot_switch_config();
}

/*
* Function Name: motion_timer5_init
* Input: none
* Output: none
* Logic: Code to initialize the register to generate the PWM using timer 5
viz. TCCR5A, TCCR5B, TCNT5H, TCNT5L, OCR5AL and OCR5BL
* Example Call: motion_timer5_init ()
*/
void motion_timer5_init()
{
TCCR5B = // Stop the timer initially
TCNT5H = // Counter higher 8-bit value to which OCR5xL value is
compared with
TCNT5L = // Counter lower 8-bit value to which OCR5xL value is
compared with
OCR5AL = // Output compare register low value for Left Motor
OCR5BL = // Output compare register low value for Right Motor
TCCR5A = // Write suitable value in this register to override normal
port functionality and to select Fast PWM 8-bit Mode.
TCCR5B = // Write suitable value in this register to set the desired
waveform generation mode and to select a prescalar of 64.
}

// Function for robot velocity control


/*
* Function Name: velocity
* Input: none
* Output: none
* Logic: Function for robot velocity control
* Example Call: velocity (left motor velocity, right motor velocity)
*/
void velocity (unsigned char left_motor, unsigned char right_motor)
{
OCR5AL = (unsigned char)left_motor;
OCR5BL = (unsigned char)right_motor;
}

//Function used for setting motor's direction

/*
* Function Name: forward
* Input: none
* Output: none
* Logic: Code used for setting motor's direction viz. PORTx.
Example Call: forward()
*/
void forward (void)
{
PORTA = // clear the direction pins
PORTA = // set only those pins to rotate both wheels forward
}

/*
* Function Name: stop
* Input: none
* Output: none
* Logic: Code used for setting motor's direction viz.PORTx
Example Call: stop()
*/
void stop (void)
{
PORTA = // clear the direction pins
PORTA = // set only those pins to stop the motors
}

/*
* Function Name: motion_control
* Input: none
* Output: none
* Logic: Code to take input from boot switch press and increment/decrement speed of robot
while displaying it on LCD.
Example Call: motion_control()
*/
void motion_control()
{

/********************************************************************
***

WRITE YOUR CODE HERE. Please write inline comments.

*********************************************************************
***/
}

//Main Function
int main()
{

lcd_port_config(); // function defined in "lcd.h" header file to configure the


LCD pins
lcd_init(); // function defined in "lcd.h" header file to initialize the LCD
motion_pin_config();
boot_switch_config();
motion_timer5_init();

motion_control();
}
ldc.c

#define F_CPU 14745600

#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"

#define RS 0
#define RW 1
#define EN 2
#define lcd_port PORTC
#define sbit(reg,bit) reg |= (1<<bit) // Macro defined for Setting a bit of any
register
#define cbit(reg,bit) reg &= ~(1<<bit) // Macro defined for Clearing a bit of any
register

unsigned int temp;


unsigned int unit;
unsigned int tens;
unsigned int hundred;
unsigned int thousand;
unsigned int million;

/*
* Function Name: lcd_port_config
* Input: None
* Output: None
* Logic: This function configures the LCD port pins as output and sets them to 0 initially
* Example Call: lcd_port_config();
*/
void lcd_port_config(void)
{
DDRC = DDRC | 0xF7; // all LCD pins direction set as output
PORTC = PORTC & 0x08; // all LCD pins set to logic 0 except PC.3 (Buzzer pin)
}

/*
* Function Name: lcd_set_4bit
* Input: None
* Output: None
* Logic: This function configures the LCD to work in 4 bit mode instead of 8 bit mode
* to reduce the number of data lines required to be used
* Example Call: lcd_set_4bit();
*/
void lcd_set_4bit (void)
{
_delay_ms(1);
cbit(lcd_port,RS); // RS=0 --- Command Input
cbit(lcd_port,RW); // RW=0 --- Writing to LCD
lcd_port = 0x30; // Sending 3
sbit(lcd_port,EN); // Set Enable Pin
_delay_ms(5); // Delay
cbit(lcd_port,EN); // Clear Enable Pin

_delay_ms(1);
cbit(lcd_port,RS); // RS=0 --- Command Input
cbit(lcd_port,RW); // RW=0 --- Writing to LCD
lcd_port = 0x30; // Sending 3
sbit(lcd_port,EN); // Set Enable Pin
_delay_ms(5); // Delay
cbit(lcd_port,EN); // Clear Enable Pin

_delay_ms(1);
cbit(lcd_port,RS); // RS=0 --- Command Input
cbit(lcd_port,RW); // RW=0 --- Writing to LCD
lcd_port = 0x30; // Sending 3
sbit(lcd_port,EN); // Set Enable Pin
_delay_ms(5); // Delay
cbit(lcd_port,EN); // Clear Enable Pin

_delay_ms(1);
cbit(lcd_port,RS); // RS=0 --- Command Input
cbit(lcd_port,RW); // RW=0 --- Writing to LCD
lcd_port = 0x20; // Sending 2 to initialize LCD in 4-bit
mode
sbit(lcd_port,EN); // Set Enable Pin
_delay_ms(5); // Delay
cbit(lcd_port,EN); // Clear Enable Pin
}

/*
* Function Name: lcd_wr_command
* Input: cmd => hex value of the command to be given to LCD
* Output: None
* Logic: This function gives specific command values to the LCD to perform necessary
functions
* Example Call: lcd_wr_command(0x80); => to bring cursor at home position
*/
void lcd_wr_command (unsigned char cmd)
{
unsigned char temp;
temp = cmd;
temp = temp & 0xF0;
lcd_port &= 0x0F;
lcd_port |= temp;
cbit(lcd_port,RS);
cbit(lcd_port,RW);
sbit(lcd_port,EN);
_delay_ms(5);
cbit(lcd_port,EN);

cmd = cmd & 0x0F;


cmd = cmd<<4;
lcd_port &= 0x0F;
lcd_port |= cmd;
cbit(lcd_port,RS);
cbit(lcd_port,RW);
sbit(lcd_port,EN);
_delay_ms(5);
cbit(lcd_port,EN);
}

/*
* Function Name: lcd_init
* Input: None
* Output: None
* Logic: This function initializes the LCD
* Example Call: lcd_init();
*/
void lcd_init (void)
{
lcd_set_4bit();
_delay_ms(1);
lcd_wr_command(0x28); // LCD 4-bit mode and 2 lines
lcd_wr_command(0x01); // Clear display screen
lcd_wr_command(0x06); // Entry mode
lcd_wr_command(0x0E); // Display On and Cursor On
lcd_wr_command(0x80); // LCD cursor set to Home position
}

/*
* Function Name: lcd_home
* Input: None
* Output: This function sets the cursor's to home i.e. 1st row, 1st column
* Logic: Passes 0x80 command to LCD using lcd_wr_command
* Example Call: lcd_home();
*/
void lcd_home (void)
{
lcd_wr_command(0x80); // LCD cursor set to Home position
}

/*
* Function Name: lcd_cursor
* Input: row, column => where you want the cursor to be positioned on LCD
* Output: This function sets the cursor to the specified position
* Logic: Position the LCD cursor at position (row, column) by passing
* the required commands to the lcd_wr_command function
* col > 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* 1......... . . . . . . .
* 2......... . . . . . . .
* ^
* row
*
* Example Call: lcd_cursor(2, 3);
*/
void lcd_cursor (char row, char column)
{
switch (row)
{
case 1: lcd_wr_command (0x80 + column - 1); break;
case 2: lcd_wr_command (0xC0 + column - 1); break;
case 3: lcd_wr_command (0x94 + column - 1); break;
case 4: lcd_wr_command (0xD4 + column - 1); break;
default: break;
}
}

/*
* Function Name: lcd_clear
* Input: None
* Output: LCD is cleared
* Logic: This function clears LCD by giving specific command as input to
lcd_wr_command() function
* Example Call: lcd_clear();
*/
void lcd_clear (void)
{
lcd_wr_command(0x01);
}

/*
* Function Name: lcd_wr_char
* Input: row, column => where you want the cursor to be positioned on LCD
* alpha_num_char => alpha-numeric type data to be printed on the LCD at the specified
(row, column) position
* Output: None
* Logic: This function prints an alpha-numeric character at specified (row, column) position
on LCD
* Example Call: lcd_wr_char(1, 4, 'A') => to write character 'A' to the LCD
*/
void lcd_wr_char(char row, char column, char alpha_num_char)
{
lcd_cursor (row, column);

char temp;
temp = alpha_num_char;
temp = (temp & 0xF0);
lcd_port &= 0x0F;
lcd_port |= temp;
sbit(lcd_port,RS);
cbit(lcd_port,RW);
sbit(lcd_port,EN);
_delay_ms(5);
cbit(lcd_port,EN);

alpha_num_char = alpha_num_char & 0x0F;


alpha_num_char = alpha_num_char << 4;
lcd_port &= 0x0F;
lcd_port |= alpha_num_char;
sbit(lcd_port,RS);
cbit(lcd_port,RW);
sbit(lcd_port,EN);
_delay_ms(5);
cbit(lcd_port,EN);
}

/*
* Function Name: lcd_string
* Input: row, column => where you want the cursor to be positioned on LCD
* *str => pointer of the char data type which points to the address of first character of
the string
* Output: This function prints the given string on the LCD at the specified (row, column)
position
* Logic: Positions the cursor and prints each character on LCD in a while loop until EOF is
reached
* Example Call: lcd_string(1, 1, "Hello !");
*/
void lcd_string(char row, char column, char *str)
{
while(*str != '\0')
{
lcd_wr_char(row, column, *str);
str++;
column+=1;
}
}

/* Function Name: lcd_numeric_value


* Input: row, column => where you want the cursor to be positioned on LCD
* val => any integer value or value in a variable as integer
* digits => number of digits of value to display
* Output: This function prints any integer value or value in a variable as integer
* on the specified location and up to the specified number of digits on LCD
* Example Call: lcd_numeric_value(1, 1, -20, 2);
*/
void lcd_numeric_value(char row, char column, int val, int digits)
{
lcd_cursor(row, column);

if (val < 0)
{
val = 0 - val;
lcd_string(row, column, "-");
column+=1;
}

unsigned char flag = 0;

if(row == 0 || column == 0)
{
lcd_home();
}

else
{
lcd_cursor(row, column);
}

if(digits == 5 || flag == 1)
{
million = val/10000+48;
lcd_wr_char(row ,column, million);
column+=1;
flag = 1;
}

if(digits == 4 || flag == 1)
{
temp = val/1000;
thousand = temp%10 + 48;
lcd_wr_char(row, column, thousand);
column+=1;
flag = 1;
}

if(digits == 3 || flag == 1)
{
temp = val/100;
hundred = temp%10 + 48;
lcd_wr_char(row, column, hundred);
column+=1;
flag = 1;
}

if(digits == 2 || flag == 1)
{
temp = val/10;
tens = temp%10 + 48;
lcd_wr_char(row, column, tens);
column+=1;
flag = 1;
}

if(digits == 1 || flag == 1)
{
unit = val%10 + 48;
lcd_wr_char(row, column, unit);
column+=1;
}

if(digits > 5)
{
lcd_wr_char(row, column, 'E');
column+=1;
}
}

You might also like