100% found this document useful (2 votes)
434 views16 pages

Code For Fruit Plucking Robot Using ATMEGA2560

This document contains C code for initializing and controlling a microcontroller-based robot. It includes functions for initializing ports, timers, sensors and actuators. There are also functions for robot motion like moving forward, backward, rotating and reading sensor values. Interrupt service routines are used to track the position of encoders on each wheel.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
434 views16 pages

Code For Fruit Plucking Robot Using ATMEGA2560

This document contains C code for initializing and controlling a microcontroller-based robot. It includes functions for initializing ports, timers, sensors and actuators. There are also functions for robot motion like moving forward, backward, rotating and reading sensor values. Interrupt service routines are used to track the position of encoders on each wheel.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 16

#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 void void void port_init(); timer5_init(); velocity(unsigned char, unsigned char); motors_delay();

volatile unsigned long int ShaftCountLeft = 0; //to keep track of left position encoder volatile unsigned long int ShaftCountRight = 0; //to keep track of right positio n encoder volatile unsigned int Degrees; //to accept angle in degrees for turning unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned char sharp, distance, adc_reading; int value; char ADC_Conversion(unsigned char); char ADC_Value; char flag = 0; char Left_white_line = 0; char Center_white_line = 0; char Right_white_line = 0;

//Configure PORTB 5 pin for servo motor 1 operation void servo1_pin_config (void) { DDRB = DDRB | 0x20; //making PORTB 5 pin output PORTB = PORTB | 0x20; //setting PORTB 5 pin to logic 1 } //Configure PORTB 6 pin for servo motor 2 operation void servo2_pin_config (void) { DDRB = DDRB | 0x40; //making PORTB 6 pin output PORTB = PORTB | 0x40; //setting PORTB 6 pin to logic 1 } // This Function calculates the actual distance in millimeters(mm) from the inpu t // analog value of Sharp Sensor. unsigned int Sharp_GP2D12_estimation(unsigned char adc_reading) { float distance; unsigned int distanceInt; distance = (int)(10.00*(2799.6*(1.00/(pow(adc_reading,1.1546))))); //distance=270/sharp; distanceInt = (int)distance; if(distanceInt>800) { distanceInt=800; } return distanceInt; }

void left_encoder_pin_config (void) { DDRE = DDRE & 0xEF; //Set the direction of the PORTE 4 pin as input PORTE = PORTE | 0x10; //Enable internal pull-up for PORTE 4 pin } //Function to configure INT5 (PORTE 5) pin as input for the right position encod er void right_encoder_pin_config (void) { DDRE = DDRE & 0xDF; //Set the direction of the PORTE 4 pin as input PORTE = PORTE | 0x20; //Enable internal pull-up for PORTE 4 pin } //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(); buzzer_pin_config(); servo1_pin_config(); //Configure PORTB 5 pin for servo motor 1 operatio n servo2_pin_config(); //Configure PORTB 6 pin for servo motor 2 operatio n left_encoder_pin_config(); //left encoder pin config right_encoder_pin_config(); //right encoder pin config } void left_position_encoder_interrupt_init (void) //Interrupt 4 enable { cli(); //Clears the global interrupt

EICRB = EICRB | 0x02; // INT4 is set to trigger with falling edge EIMSK = EIMSK | 0x10; // Enable Interrupt INT4 for left position encoder sei(); // Enables the global interrupt } void right_position_encoder_interrupt_init (void) //Interrupt 5 enable { cli(); //Clears the global interrupt EICRB = EICRB | 0x08; // INT5 is set to trigger with falling edge EIMSK = EIMSK | 0x20; // Enable Interrupt INT5 for right position encode r sei(); // Enables the global interrupt } //ISR for right position encoder ISR(INT5_vect) { ShaftCountRight++; //increment right shaft position count } //ISR for left position encoder ISR(INT4_vect) { ShaftCountLeft++; //increment left shaft position count }

// 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 co mpared with TCNT5L = 0x01; //Counter lower 8-bit value to which OCR5xH value is com pared with OCR5AH = 0x00; //Output compare register high value for Left Motor 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 COM5 C0=0} For Overriding normal port functionali ty 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) } //TIMER1 initialization in 10 bit fast PWM mode //prescale:256 // WGM: 7) PWM 10bit fast, TOP=0x03FF // actual value: 52.25Hz

void timer1_init(void) { TCCR1B = 0x00; //stop TCNT1H = 0xFC; //Counter high value to which OCR1xH value is to be compared wit h TCNT1L = 0x01; //Counter low value to which OCR1xH value is to be compared with OCR1AH = 0x03; //Output compare Register high value for servo 1 OCR1AL = 0xFF; //Output Compare Register low Value For servo 1 OCR1BH = 0x03; //Output compare Register high value for servo 2 OCR1BL = 0xFF; //Output Compare Register low Value For servo 2 OCR1CH = 0x03; //Output compare Register high value for servo 3 OCR1CL = 0xFF; //Output Compare Register low Value For servo 3 ICR1H = 0x03; ICR1L = 0xFF; TCCR1A = 0xAB; /*{COM1A1=1, COM1A0=0; COM1B1=1, COM1B0=0; COM1C1=1 COM1C0=0} For Overriding normal port functionality to OCRnA outputs. {WGM11=1, WGM10=1} Along With WGM12 in TCCR1B for Selecting FAST PWM Mode*/ TCCR1C = 0x00; TCCR1B = 0x0C; //WGM12=1; CS12=1, CS11=0, CS10=0 (Prescaler=256) } void adc_init() { ADCSRA = 0x00; ADCSRB = 0x00; ADMUX = 0x20; ACSR = 0x80; ADCSRA = 0x86; }

//MUX5 = 0 //Vref=5V external --- ADLAR=1 --- MUX4:0 = 0000 //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 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 resto ring the PORTA status PORTA = PortARestore; // executing the command } void forward (void) { motion_set (0x06); } void stop (void) { motion_set (0x00); } void back (void) //both wheels backward { motion_set(0x09); } void left (void) //Left wheel backward, Right wheel forward { motion_set(0x05); } void right (void) //Left wheel forward, Right wheel backward { motion_set(0x0A); } void init_devices (void) { cli(); //Clears the global interrupts port_init(); adc_init(); timer5_init(); timer1_init(); left_position_encoder_interrupt_init(); right_position_encoder_interrupt_init(); sei(); //Enables the global interrupts } void soft_left (void) //Left wheel stationary, Right wheel forward { motion_set(0x04); }

void soft_right (void) //Left wheel forward, Right wheel is stationary { motion_set(0x02); } void angle_rotate(unsigned int Degrees) { float ReqdShaftCount = 0; unsigned long int ReqdShaftCountInt = 0; ReqdShaftCount = (float) Degrees/ 4.090; // division by resolution to ge t shaft count ReqdShaftCountInt = (unsigned int) ReqdShaftCount; ShaftCountRight = 0; ShaftCountLeft = 0; while (1) { if((ShaftCountRight >= ReqdShaftCountInt) | (ShaftCountLeft >= R eqdShaftCountInt)) break; } stop(); //Stop robot } //Function used for moving robot forward by specified distance void linear_distance_mm(unsigned int DistanceInMM) { float ReqdShaftCount = 0; unsigned long int ReqdShaftCountInt = 0; ReqdShaftCount = DistanceInMM / 5.338; // division by resolution to get shaft count ReqdShaftCountInt = (unsigned long int) ReqdShaftCount; ShaftCountRight = 0; while(1) { if(ShaftCountRight > ReqdShaftCountInt) { break; } } stop(); //Stop robot } void right_degrees(unsigned int Degrees) { // 88 pulses for 360 degrees rotation 4.090 degrees per count right(); //Turn right angle_rotate(Degrees); } void left_degrees(unsigned int Degrees) { // 88 pulses for 360 degrees rotation 4.090 degrees per count left(); //Turn left

angle_rotate(Degrees); } void soft_left_degrees(unsigned int Degrees) { // 176 pulses for 360 degrees rotation 2.045 degrees per count soft_left(); //Turn soft left Degrees=Degrees*2; angle_rotate(Degrees); } void soft_right_degrees(unsigned int Degrees) { // 176 pulses for 360 degrees rotation 2.045 degrees per count soft_right(); //Turn soft right Degrees=Degrees*2; angle_rotate(Degrees); } void forward_mm(unsigned int DistanceInMM) { forward(); linear_distance_mm(DistanceInMM); } void back_mm(unsigned int DistanceInMM) { back(); linear_distance_mm(DistanceInMM); } void buzzer_pin_config (void) { DDRC = DDRC | 0x08; PORTC = PORTC & 0xF7; uzzer }

//Setting PORTC 3 as output //Setting PORTC 3 logic low to turnoff b

void buzzer_on (void) { unsigned char port_restore = 0; port_restore = PINC; port_restore = port_restore | 0x08; PORTC = port_restore; } void buzzer_off (void) { unsigned char port_restore = 0; port_restore = PINC; port_restore = port_restore & 0xF7; PORTC = port_restore; } //Function to rotate Servo 1 by a specified angle in the multiples of 1.86 degre es void servo_1(unsigned char degrees) { float PositionPanServo = 0;

PositionPanServo = ((float)degrees / 1.86) + 35.0; OCR1AH = 0x00; OCR1AL = (unsigned char) PositionPanServo; } //Function to rotate Servo 2 by a specified angle in the multiples of 1.86 degre es void servo_2(unsigned char degrees) { float PositionTiltServo = 0; PositionTiltServo = ((float)degrees / 1.86) + 35.0; OCR1BH = 0x00; OCR1BL = (unsigned char) PositionTiltServo; } //servo_free functions unlocks the servo motors from the any angle //and make them free by giving 100% duty cycle at the PWM. This function can be used to //reduce the power consumption of the motor if it is holding load against the gr avity. void servo_1_free (void) //makes servo 1 free rotating { OCR1AH = 0x03; OCR1AL = 0xFF; //Servo 1 off } void servo_2_free (void) //makes servo 2 free rotating { OCR1BH = 0x03; OCR1BL = 0xFF; //Servo 2 off } void revlinefol(void) { Left_white_line = ADC_Conversion(3); L Sensor Center_white_line = ADC_Conversion(2); //Getting data of Center WL Sensor Right_white_line = ADC_Conversion(1); WL Sensor flag=0; unsigned char n; print_sensor(1,1,3); print_sensor(1,5,2); print_sensor(1,9,1); //Prints value of White Line Sensor1 //Prints Value of White Line Sensor2 //Prints Value of White Line Sensor3 //Getting data of Right //Getting data of Left W

if(Center_white_line>0x50) {_delay_ms(20); stop(); flag=1; back(); velocity(190,190); _delay_ms(100);

stop(); _delay_ms(300); Left_white_line = ADC_Conversion(3); g data of Left WL Sensor g data of Center WL Sensor Right_white_line = ADC_Conversion(1); g data of Right WL Sensor }

//Gettin

Center_white_line = ADC_Conversion(2); //Gettin //Gettin

if((Left_white_line>Right_white_line) && (flag==0)) { flag=1; stop(); _delay_ms(50); back(); velocity(205,180); _delay_ms(300); stop(); _delay_ms(300); } if((Right_white_line>Left_white_line) && (flag==0)) { flag=1; stop(); _delay_ms(50); back(); velocity(180,205); _delay_ms(300); stop(); _delay_ms(300); } if(Center_white_line<0x0A && Left_white_line<0x0A && Rig ht_white_line<0x0A) { Left_white_line = ADC_Conversion(3); g data of Left WL Sensor Center_white_line = ADC_Conversion(2); //Gettin g data of Center WL Sensor Right_white_line = ADC_Conversion(1); g data of Right WL Sensor _delay_ms(2000); forward(); velocity(0,0); } } void linefol(void) { unsigned int flag=0; Left_white_line = ADC_Conversion(3); //Getting data of Left WL Sensor Center_white_line = ADC_Conversion(2); //Getting data of Center WL Sens //Gettin //Gettin

or Right_white_line = ADC_Conversion(1); r //Getting data of Right WL Senso

print_sensor(1,1,3); print_sensor(1,5,2); print_sensor(1,9,1);

//Prints value of White Line Sensor1 //Prints Value of White Line Sensor2 //Prints Value of White Line Sensor3

if(Center_white_line>0x0A) { flag=1; forward(); velocity(190,190); } if((Left_white_line>0x0A) && (flag==0)) { flag=1; stop(); _delay_ms(100); 3forward(); velocity(170,210); } if((Right_white_line>0x0A) && (flag==0)) { flag=1; stop(); _delay_ms(100); forward(); velocity(210,170); } if(Center_white_line<0x0A && Left_white_line<0x0A && Right_white_line<0x 0A) { _delay_ms(2000); forward(); velocity(0,0); } } void m_forward(void) { do { linefol(); _delay_ms(50); stop(); _delay_ms(10); sharp = ADC_Conversion(11); //Stores the Analog value of front sharp connected to ADC channel 11 into variab le "sharp" value = Sharp_GP2D12_estimation(sharp); _delay_ms(50); } while (value>140);

_delay_ms(30); stop(); } void m_reverse(void) {do { back(); _delay_ms(50); stop(); sharp = ADC_Conversion(11); //Stores the Analog value of front sharp connected to ADC channel 11 into variab le "sharp" value = Sharp_GP2D12_estimation(sharp); _delay_ms(50); } while (value<160); _delay_ms(30); stop(); } void fruit_pluck(int m) { servo_1(20); _delay_ms(30);

m=m+6; servo_2(m); _delay_ms(30); m_forward(); _delay_ms(500); for(int j=50;j<160;j++) {j=j+2; servo_1(j); _delay_ms(30); } _delay_ms(100); m_reverse(); back_mm(30); for(int j=(m-15);j>20;j--) {j=j-3; servo_2(j); _delay_ms(30); } for(int j=160;j>20;j--) { j=j-2; servo_1(j);

_delay_ms(30); } _delay_ms(500); forward_mm(30); } void fruit_sense(void) { float dis; int n; _delay_ms(50); for(int p=0;p<20;p++) { linefol(); _delay_ms(100); stop(); _delay_ms(10); } stop(); right_degrees(87); for(int p=0;p<16;p++) { linefol(); _delay_ms(100); stop(); _delay_ms(10); } _delay_ms(100); stop(); _delay_ms(200);

/*do { 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 if(Left_white_line>0x0A) {left(); _delay_ms(50); stop(); } if(Right_white_line>0x0A) { right(); _delay_ms(50); stop(); }

Left_white_line = ADC_Conversion(3); f Left WL Sensor f Center WL Sensor Right_white_line = ADC_Conversion(1); f Right WL Sensor _delay_ms(50); }while(Center_white_line<90); _delay_ms(50);

//Getting data o

Center_white_line = ADC_Conversion(2); //Getting data o //Getting data o

sharp = ADC_Conversion(11); //Stores the Analog value of front sharp connected to ADC channel 11 into variab le "sharp" value = Sharp_GP2D12_estimation(sharp); dis=value;*/ do { revlinefol(); _delay_ms(100); stop(); _delay_ms(50); sharp = ADC_Conversion(11); //Stores the Analog value of front sharp connected to ADC channel 11 into variab le "sharp" value = Sharp_GP2D12_estimation(sharp); _delay_ms(50); } while (value<160 || value>750); for(int a=130;a<185;a++) {a=a+2; servo_2(a); _delay_ms(500); sharp = ADC_Conversion(12); //Stores the Analog value of front sharp connected to ADC channel 11 into variab le "sharp" value = Sharp_GP2D12_estimation(sharp); if (value <145 || value >750) {fruit_pluck(a); } _delay_ms(10); } do { linefol(); _delay_ms(50); stop(); _delay_ms(50); sharp = ADC_Conversion(11); //Stores the Analog value of front sharp connected to ADC channel 11 into variab le "sharp" value = Sharp_GP2D12_estimation(sharp);

_delay_ms(50); } while (value>170); } //Main Function int main() { unsigned int i; init_devices(); lcd_set_4bit(); lcd_init(); int k,j; servo_1(20); servo_1_free(); servo_2(20); forward(); velocity(195,195); _delay_ms(400); while(1) { linefol(); Left_white_line = ADC_Conversion(3); L Sensor Center_white_line = ADC_Conversion(2); //Getting data of Center WL Sensor Right_white_line = ADC_Conversion(1); WL Sensor //Getting data of Right //Getting data of Left W

print_sensor(1,1,3); print_sensor(1,5,2); print_sensor(1,9,1);

//Prints value of White Line Sensor1 //Prints Value of White Line Sensor2 //Prints Value of White Line Sensor3

if(Center_white_line>0x0f && (Right_white_line> 0x0f || Left_whi te_line> 0x0f)) goto down; } down: soft_right_degrees(90); stop(); _delay_ms(50); forward(); velocity(195,195); _delay_ms(400); while(1) { linefol(); Left_white_line = ADC_Conversion(3); //Getting data of Left W

L Sensor Center_white_line = ADC_Conversion(2); //Getting data of Center WL Sensor Right_white_line = ADC_Conversion(1); WL Sensor //Getting data of Right

print_sensor(1,1,3); print_sensor(1,5,2); print_sensor(1,9,1);

//Prints value of White Line Sensor1 //Prints Value of White Line Sensor2 //Prints Value of White Line Sensor3

if(Center_white_line>0x0f && (Right_white_line> 0x0f || Left_whi te_line> 0x0f)) goto down1; }

down1:right_degrees(180); stop(); _delay_ms(50); i=1; j=0; while(1) { Left_white_line = ADC_Conversion(3); L Sensor Center_white_line = ADC_Conversion(2); //Getting data of Center WL Sensor Right_white_line = ADC_Conversion(1); WL Sensor //Getting data of Right //Getting data of Left W

print_sensor(1,1,3); print_sensor(1,5,2); print_sensor(1,9,1);

//Prints value of White Line Sensor1 //Prints Value of White Line Sensor2 //Prints Value of White Line Sensor3

if(Center_white_line>0x0f && (Right_white_line> 0x0f || Left_whi te_line> 0x0f)) { if (i==4) { stop(); soft_right_degrees(90); stop(); _delay_ms(60000); i=1; k++;

} else { stop(); _delay_ms(1000); fruit_sense(); left_degrees(87); _delay_ms(500); servo_1(20); servo_1_free(); servo_2(20); /*j=2500; abc:linefol(); j--; if(j!=0) goto abc;*/ i+=1; j++; if(j==12) goto last; forward(); velocity(220,220); _delay_ms(300); } } else { linefol(); } } last:soft_left_degrees(90); forward(); velocity(190,190); _delay_ms(2000); right_degrees(180); buzzer_on(); _delay_ms(5000); buzzer_off(); }

You might also like