ATMEL Studio 6.0 Programming :Robot follows a white line over a black backround


/************************************************************************************
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);
}

}
}

0 comments: