Author Topic: AVR C: Line following program: sensors HELP!  (Read 11142 times)

0 Members and 1 Guest are viewing this topic.

Offline RoboDoc2008Topic starter

  • Beginner
  • *
  • Posts: 2
  • Helpful? 0
AVR C: Line following program: sensors HELP!
« on: February 12, 2009, 07:11:09 PM »
I trying program a robot that will follow a black line on the ground using a combination of three sensors (left, middle and right)

When The middle sensor is on, then the robot will go forward.
When the left sensor is on or the middle sensor is also on, then the robot will go left.
when the right sensor is on or the middle sensor is also on, then the robot will go right.
For any other combination the robot will reverse.

This is a sample of the program in 'C' for my 'line following' robot.
  :-\
// Robot CAR_bot program


//includes
#include<avr/io.h>
#define      F_CPU   1000000UL   //define how fast processor is
#include   <util/delay.h>

//defines
#define   left_sensor      PD0      // Left sensor
#define   middle_sensor   PD1      // Middle sensor
#define   right_sensor   PD2      // Right sensor   

#define   left_rear      PC3      //Left rear sensor
#define   middle_rear      PC4      //Middle rear sensor

#define   right_rear      PC5      //Right rear sensor

#define   sensor_port      PORTD
#define   sensor_pin      PIND
#define   sensor_ddr      DDRD

#define range         110         //Range of about 25cm
#define rear_port      PORTC
#define rear_pin      PINC

#define      Motor_L1      PD7      //Rear motor 1
#define      Motor_L2      PD6      //Rear motor 2

#define      Motor_R1      PD5      //Front Solanoid 1
#define      Motor_R2      PD4      //Front Solanoid 2



//variables
uint8_t   servodir;   //Servo direction


int forward()
   {
   PORTD&=~(_BV(Motor_L1));                        //turn Off PD6
   PORTD|=_BV(Motor_L2)|_BV(Motor_R2)|_BV(Motor_R1);      //turn On PD7, PD4  and PD5
   return 0;
   }

int reverse()
   {
   PORTD&=~(_BV(Motor_L2));                        //turn Off PD7
   PORTD|=_BV(Motor_L1)|_BV(Motor_R1)|_BV(Motor_R2);      //turn On PD6, PD5 and PD4
   return 0;
   }

int for_left()
   {
   PORTD&=~(_BV(Motor_L1)|_BV(Motor_R2));      //turn Off PD7 and PD4
   PORTD|=_BV(Motor_L2)|_BV(Motor_R1);      //turn On PD6 and PD5
   return 0;
   }

int for_right()
   {
   PORTD&=~(_BV(Motor_L1)|_BV(Motor_R1));      //turn Off PD7 and PD5
   PORTD|=_BV(Motor_L2)|_BV(Motor_R2);      //turn On PD6 and PD4
   return 0;
   }

int rev_left()
   {
   PORTD&=~(_BV(Motor_L2)|_BV(Motor_R2));      //turn Off PD6 and PD4
   PORTD|=_BV(Motor_L1)|_BV(Motor_R1);      //turn On PD7 and PD5
   return 0;
   }

int rev_right()
   {
   PORTD&=~(_BV(Motor_L2)|_BV(Motor_R1));      //turn Off PD6 and PD5
   PORTD|=_BV(Motor_L1)|_BV(Motor_R2);      //turn On PD7 and PD4
   return 0;
   }

int pause()
   {
   PORTD&=~(_BV(Motor_L1)|_BV(Motor_R1)|_BV(Motor_L2)|_BV(Motor_R2));      //turn Off all
   //delay
      _delay_ms (100);
   //continue forward
      forward();
   //delay
   //   _delay_ms (1000);
   return 0;
   }


int enemy_spotted()
   {
   // Enemy is in range?
   if(ADCH>range) //Object is within range
      {
      //time  to attack!!
      switch (servodir)
         {
         case 0:   
            //turn left
            for_left();
            //delay
            _delay_ms (950);
            //forward
            forward();
            break;
         case 1:
         case 3:   //Assume that 1 or 3 is ?
            //forward
            forward();

            break;
         case 2:   //Assume that 2 is right
            //Enemy to right

            //turn right
            for_right();
            //delay
            _delay_ms (950);
            //forward
            forward();
            break;
         }
      }
   return 0;
   }

int main()
   {
   //Setup ADC
      //Config adc; enable, free running, /8 prescaler
      ADCSRA=1<<ADEN|1<<ADFR|1<<ADPS1|1<<ADPS0;
      //use internal ref, left adjust, adc channel
      ADMUX=1<<REFS1|1<<REFS0|1<<ADLAR;
      //Start conversion
      ADCSRA|=1<<ADSC;

   //Setup servo
   //config timer 1. 20ms, fast pwm, OC1B
      ICR1=20000;
      OCR1B=1500;
      TCCR1A=1<<COM1B1|0<<COM1B0|1<<WGM11|0<<WGM10;
      TCCR1B=1<<WGM13|1<<WGM12|0<<CS12|0<<CS11|1<<CS10;

   // ***** Setup Ports and sensors
   DDRB|=1<<PB2;   //Servo
   DDRD|=_BV(PD7)|_BV(PD6)|_BV(PD5)|_BV(PD4);   //motor
   DDRC=0;
   PORTD|=_BV(PD1)|_BV(PD2)|_BV(PD0);   //front sensors
   PORTC|=_BV(PC3)|_BV(PC4)|_BV(PC5);   //Rear sensors
   
   // ***** Insert code here to move forward
   while(1)
      {
      // Where is the black line?
         
   //   if(sensor_pin&(_BV(left_sensor)|_BV(middle_sensor)|_BV(right_sensor)))
   //   if(sensor_pin&(_BV(PD0)|_BV(PD1)|_BV(PD2)))
   //      {
   //      forward();
   //      }

      if(sensor_pin&(_BV(middle_sensor)))
         {
         forward();
         }
      else if(sensor_pin&(_BV(left_sensor)))
         {
         for_left();
         }
      else if(sensor_pin&(_BV(right_sensor)))
         {
         for_right();
         }      
      else
         {      
         reverse();
         }
   




      servodir++;      // increment srvodir
      servodir&=0x03;   //mask off uneede bits
         switch (servodir&0x03) //Move servo to postion based on servodir
            {
            case 0:
               //Servo left
               OCR1B=1100; //1ms Pulse width   (need to test values and change)
               break;
            case 1:
            case 3:
               //Servo forward
               OCR1B=1600; //1.5ms Pulse width (need to test values and change)
               break;
            case 2:
               //Servo right
               OCR1B=2300; //2ms Pulse width (need to test values and change)      
               break;
            }
            //delay
            _delay_ms (300);
            
         }
      }


This is the code that I think i am have trouble with.  :-\
Should I use a Case structure instead? ???

   
while(1)
      {
      // Where is the black line?
         
   //   if(sensor_pin&(_BV(left_sensor)|_BV(middle_sensor)|_BV(right_sensor)))
   //   if(sensor_pin&(_BV(PD0)|_BV(PD1)|_BV(PD2)))
   //      {
   //      forward();
   //      }

      if(sensor_pin&(_BV(middle_sensor)))
         {
         forward();
         }
      else if(sensor_pin&(_BV(left_sensor)))
         {
         for_left();
         }
      else if(sensor_pin&(_BV(right_sensor)))
         {
         for_right();
         }      
      else
         {      
         reverse();
         }

Any, suggestions or Idea's would be Great! Thanks!  :)

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,165
  • Helpful? 111
    • Webbot stuff
Re: AVR C: Line following program: sensors HELP!
« Reply #1 on: February 12, 2009, 07:51:37 PM »
No a case statement tends to be used when you are using one value to 'jump' to the correct code for that value - whereas your 'else if's are each testing for a different thing.

You dont say what problem you've got.

I presume that you've tested out all the routines to move in a given direction individually by just having a 'main' that simply calls them. So basically break it down to see if the problem is in the 'driving' code, or in the 'sensor' code, or in the steering decision code.

Also what processor are you using coz I see you are using PWM and the output pins of PWM vary from one AVR to another
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: AVR C: Line following program: sensors HELP!
« Reply #2 on: February 15, 2009, 02:42:28 AM »
RoboDoc2008, as Webbot said, you need to tell us what isn't working for us to help you fix it :P

Also . . .
Quote
For any other combination the robot will reverse.
This won't work. It'll cause what is called 'infinite oscillation' . . . and will make your robot look like it is doing inappropriate things to the line :P

Typically its better to not have any reverse at all and hope that your bot never goes off the line. But if you still require reverse, put a timer on it, or have it turn as it reverses.

 


data_list