/************************************************************************************
Written by: Vinod Desai,Sachitanand Malewar NEX Robotics Pvt. Ltd.
Edited by: e-Yantra team www.sureshQ.Blogspot.in
AVR Studio Version 6
Date: 19th October 2012
This experiment demonstrates the application of a simple line follower robot. The
robot follows a white line over a black backround
Concepts covered: ADC, LCD interfacing, motion control based on sensor data
LCD Connections:
LCD Microcontroller Pins
RS --> PC0
RW --> PC1
EN --> PC2
DB7 --> PC7
DB6 --> PC6
DB5 --> PC5
DB4 --> PC4
ADC Connection:
ACD CH. PORT Sensor
0 PF0 Battery Voltage
1 PF1 White line sensor 3
2 PF2 White line sensor 2
3 PF3 White line sensor 1
4 PF4 IR Proximity analog sensor 1*****
5 PF5 IR Proximity analog sensor 2*****
6 PF6 IR Proximity analog sensor 3*****
7 PF7 IR Proximity analog sensor 4*****
8 PK0 IR Proximity analog sensor 5
9 PK1 Sharp IR range sensor 1
10 PK2 Sharp IR range sensor 2
11 PK3 Sharp IR range sensor 3
12 PK4 Sharp IR range sensor 4
13 PK5 Sharp IR range sensor 5
14 PK6 Servo Pod 1
15 PK7 Servo Pod 2
***** For using Analog IR proximity (1, 2, 3 and 4) sensors short the jumper J2.
To use JTAG via expansion slot of the microcontroller socket remove these jumpers.
Motion control Connection:
L-1---->PA0; L-2---->PA1;
R-1---->PA2; R-2---->PA3;
PL3 (OC5A) ----> PWM left; PL4 (OC5B) ----> PWM right;
LCD Display interpretation:
****************************************************************************
*LEFT WL SENSOR CENTER WL SENSOR RIGHT WL SENSOR BLANK *
*BLANK BLANK BLANK BLANK *
****************************************************************************
Note: www.sureshQ.Blogspot.in
1. Make sure that in the configuration options following settings are
done for proper operation of the code
Microcontroller: atmega2560
Frequency: 14745600
Optimization: -O0 (For more information read section: Selecting proper optimization
options below figure 2.22 in the Software Manual)
2. Make sure that you copy the lcd.c file in your folder
3. Distance calculation is for Sharp GP2D12 (10cm-80cm) IR Range sensor
*********************************************************************************/
www.sureshQ.Blogspot.in
/********************************************************************************
********************************************************************************/
#define F_CPU 14745600
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <math.h> //included to support power function
#include "lcd.h"
void port_init();
void timer5_init();
void velocity(unsigned char, unsigned char);
void motors_delay();
unsigned char ADC_Conversion(unsigned char);
unsigned char ADC_Value;
unsigned char flag = 0;
unsigned char Left_white_line = 0;
unsigned char Center_white_line = 0;
unsigned char Right_white_line = 0;
//Function to configure LCD port
void lcd_port_config (void)
{
DDRC = DDRC | 0xF7; //all the LCD pin's direction set as output
PORTC = PORTC & 0x80; // all the LCD pins are set to logic 0 except PORTC 7
}
//ADC pin configuration
void adc_pin_config (void)
{
DDRF = 0x00;
PORTF = 0x00;
DDRK = 0x00;
PORTK = 0x00;
}
//Function to configure ports to enable robot's motion
void motion_pin_config (void)
{
DDRA = DDRA | 0x0F;
PORTA = PORTA & 0xF0;
DDRL = DDRL | 0x18; //Setting PL3 and PL4 pins as output for PWM generation
PORTL = PORTL | 0x18; //PL3 and PL4 pins are for velocity control using PWM.
}
//Function to Initialize PORTS
void port_init()
{
lcd_port_config();
adc_pin_config();
motion_pin_config();
}
// Timer 5 initialized in PWM mode for velocity control
// Prescale:256
// PWM 8bit fast, TOP=0x00FF
// Timer Frequency:225.000Hz
void timer5_init()
{
TCCR5B = 0x00; //Stop
TCNT5H = 0xFF; //Counter higher 8-bit value to which OCR5xH value is compared with
TCNT5L = 0x01; //Counter lower 8-bit value to which OCR5xH value is compared with
OCR5AH = 0x00; //Output compare register high value for Left Motor www.sureshQ.Blogspot.in
OCR5AL = 0xFF; //Output compare register low value for Left Motor
OCR5BH = 0x00; //Output compare register high value for Right Motor
OCR5BL = 0xFF; //Output compare register low value for Right Motor
OCR5CH = 0x00; //Output compare register high value for Motor C1
OCR5CL = 0xFF; //Output compare register low value for Motor C1
TCCR5A = 0xA9; /*{COM5A1=1, COM5A0=0; COM5B1=1, COM5B0=0; COM5C1=1 COM5C0=0}
For Overriding normal port functionality to OCRnA outputs.
{WGM51=0, WGM50=1} Along With WGM52 in TCCR5B for Selecting FAST PWM 8-bit Mode*/
TCCR5B = 0x0B; //WGM12=1; CS12=0, CS11=1, CS10=1 (Prescaler=64)
}
void adc_init()
{
ADCSRA = 0x00;
ADCSRB = 0x00; //MUX5 = 0
ADMUX = 0x20; //Vref=5V external --- ADLAR=1 --- MUX4:0 = 0000
ACSR = 0x80;
ADCSRA = 0x86; //ADEN=1 --- ADIE=1 --- ADPS2:0 = 1 1 0
}
//Function For ADC Conversion
unsigned char ADC_Conversion(unsigned char Ch)
{
unsigned char a;
if(Ch>7)
{
ADCSRB = 0x08;
}
Ch = Ch & 0x07;
ADMUX= 0x20| Ch;
ADCSRA = ADCSRA | 0x40; //Set start conversion bit
while((ADCSRA&0x10)==0); //Wait for conversion to complete www.sureshQ.Blogspot.in
a=ADCH;
ADCSRA = ADCSRA|0x10; //clear ADIF (ADC Interrupt Flag) by writing 1 to it
ADCSRB = 0x00;
return a;
}
//Function To Print Sesor Values At Desired Row And Coloumn Location on LCD
void print_sensor(char row, char coloumn,unsigned char channel)
{
ADC_Value = ADC_Conversion(channel);
lcd_print(row, coloumn, ADC_Value, 3);
}
//Function for velocity control
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
void motion_set (unsigned char Direction)
{
unsigned char PortARestore = 0;
Direction &= 0x0F; // removing upper nibbel for the protection
PortARestore = PORTA; // reading the PORTA original status
PortARestore &= 0xF0; // making lower direction nibbel to 0
PortARestore |= Direction; // adding lower nibbel for forward command and restoring the PORTA status
PORTA = PortARestore; // executing the command www.sureshQ.Blogspot.in
}
void forward (void)
{
motion_set (0x06);
}
void stop (void)
{
motion_set (0x00);
}
void init_devices (void)
{
cli(); //Clears the global interrupts
port_init();
adc_init();
timer5_init();
sei(); //Enables the global interrupts
}
//Main Function
int main()
{
init_devices();
lcd_set_4bit();
lcd_init();
while(1)
{
Left_white_line = ADC_Conversion(3); //Getting data of Left WL Sensor
Center_white_line = ADC_Conversion(2); //Getting data of Center WL Sensor
Right_white_line = ADC_Conversion(1); //Getting data of Right WL Sensor
flag=0;
print_sensor(1,1,3); //Prints value of White Line Sensor1
print_sensor(1,5,2); //Prints Value of White Line Sensor2
print_sensor(1,9,1); //Prints Value of White Line Sensor3
if(Center_white_line<0x10)
{
flag=1;
forward();
velocity(100,100);
}
if((Left_white_line>0x10) && (flag==0))
{
flag=1;
forward();
velocity(130,50);
}
if((Right_white_line>0x10) && (flag==0))
{
flag=1;
forward();
velocity(50,130);
}
if(Center_white_line>0x10 && Left_white_line>0x10 && Right_white_line>0x10)
{
forward();
velocity(0,0);
}
}
}
ATMEL Studio 6.0 Programming :Robot follows a white line over a black backround
Reviewed by Suresh Bojja
on
9/07/2018 09:38:00 PM
Rating: