Society of Robots - Robot Forum

Software => Software => Topic started by: greasemonkey94 on March 01, 2011, 06:00:12 AM

Title: Sharp Ir always shows 30 cm?
Post by: greasemonkey94 on March 01, 2011, 06:00:12 AM
Hello,

I just recently finished building my robot, it has a sharp IR gp2d12 sensor on a servo for basic obstacle avoidance,
I'm using an arduino uno and l293d motor driver.
It worked beautifully(relatively, remember this is my first bot!!) for a while and then it seemed to detect obstacles all
the time, it never went straight.
It seems to stop working after the unplug the battery, I have 2 power supplies a 12 900mAh NiCd for the motors and
a 9V battery for the arduino (i haven't forgotten common ground, I checked  ;D)

It seems to work fine for sometime and then goes completely haywire, this has happened 3-4 times, each time i reloaded the code :(

Does anyone know whats wrong or what im doing wrong, tell me if you need picks of my setup.

Is this a hardware or software problem??. It gives weird readings like 30cm,14cm etc (i powered the uno thoguht the usb and saw the readings via serial) even when when i tilt it towards the ceiling and there is no object to be seen .



here is the code I'm using



Basically whats its supposed to do is move straight until it finds an object, then it stops and scans 90 degrees to its left and right and then moves in the direction of greatest object distance.



Code: [Select]
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo

int motor_left[] = {2, 3};
int motor_right[] = {7, 6};
int IRpin=0 ;
        
void setup()
{
 myservo.attach(9);// attaches the servo on pin 9 to the servo object
 // Setup motors
 int i;
 for(i = 0; i < 2; i++)
 {
  pinMode(motor_left[i], OUTPUT);
  pinMode(motor_right[i], OUTPUT);  
  }
}
 

void loop()
{
 myservo.write(90);
 delay(250);
 int sharpir=getsharpdata();
 drive_forward();
 
 if(sharpir<20)
 {
  
   servo_scan();
 }
 
}

// --------------------------------------------------------------------------- Drive

void motor_stop()
{
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], LOW);

 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], LOW);
 delay(250);
}

void drive_forward()
{
 digitalWrite(motor_left[0], HIGH);
 digitalWrite(motor_left[1], LOW);

 digitalWrite(motor_right[0], HIGH);
 digitalWrite(motor_right[1], LOW);
}

void drive_backward()
{
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], HIGH);

 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], HIGH);
}

void turn_left()
{
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], HIGH);

 digitalWrite(motor_right[0], HIGH);
 digitalWrite(motor_right[1], LOW);
}

void turn_right()
{
 digitalWrite(motor_left[0], HIGH);
 digitalWrite(motor_left[1], LOW);

 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], HIGH);
}

float getsharpdata()
{
  float val = analogRead(IRpin);
  float distance = (2914 / (val + 5)) - 1;
  delay(50);
  return distance;
  
}


void servo_scan()
{
 motor_stop();
 myservo.write(0);
 delay(1000);
 int left=getsharpdata();
 myservo.write(180);
 delay(1000);    
 int right=getsharpdata();
 
 if(left>right)
 {
  turn_left();
  delay(500);
 }

else
 {
   turn_right();
   delay(500);
 }
 
}


Any and all help appreciated hehehe  ;)

Thanks
Title: Re: Sharp Ir always shows 30 cm?
Post by: rbtying on March 01, 2011, 08:57:40 AM
The sensor itself has a maximum range of 80 cm and a minimum range of 10 cm.  You're using the SharpIR reading code for a 4cm to 30cm; as I remember, the code for the GP12D12 is this:

Code: [Select]
float distance = 5 * 2769 / 2 * value * pow(value, -.9988);

Which could of course be wrong - try it out. 

If you want to see if its a hardware or software problem, look at the voltages coming out of the sensor (voltage = analogRead * 5.0 / 1024.0) and see if they're stable at a certain distance.  If they fluctuate wildly, that could be your problem.  Otherwise, it's probably your code.  You could also try averaging 3 values to get a more normalized response, as well.

In your getsharpir function, you make some strange decisions:

the return value from analogRead(pin) is an int: don't make it a float until you have to, because Arduinos do not have floating point coprocessors

the delay(50) doesn't do anything other than make it slower - remove it.
Title: Re: Sharp Ir always shows 30 cm?
Post by: waltr on March 01, 2011, 08:58:23 AM
You'll need to determine if its the voltage from the IR range finder or if its the processor that is behaving incorrectly. Then if its the processor determine if its a hardware or software issue.

Some testing can be done by replacing the IR range finder with a Pot wired into the processor's ADC. If this seems to work correctly leave the pot on the processor and power the IR range finder as before.

The Sharp IR range finders do draw huge current when its switches on the IR LED and can cause havoc with the processor. Search these forums for several discussions about this problem and solutions.
Title: Re: Sharp Ir always shows 30 cm?
Post by: greasemonkey94 on March 01, 2011, 09:21:13 AM
thanks waltr and rbtyping,
rbtyping, i tried your code, but all i got was 6922 :(,
I dont think its a problem with the calcluation because it worked fine just a few days ago and I
havent changed anything in the code,
i used delay(50) because i thought that it could take readings only ever 30 ms, am i wrong??
Title: Re: Sharp Ir always shows 30 cm?
Post by: greasemonkey94 on March 03, 2011, 08:05:25 AM
Hmm I think theres a prblem in the code,
I modified my code and now im taking the average of 5 readings and
using just raw a2d data instead of converting it into Centimeters.

heres the code
Code: [Select]
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo

int motor_left[] = {2, 3};
int motor_right[] = {7, 6};
int IRpin=0 ;
int avgdistance=0;
int val[5];
       
void setup()
{
 myservo.attach(9);// attaches the servo on pin 9 to the servo object
 pinMode(0, INPUT);
 // Setup motors
 int i;
 for(i = 0; i < 2; i++)
 {
  pinMode(motor_left[i], OUTPUT);
  pinMode(motor_right[i], OUTPUT); 
  }
}
 

void loop()
{
 myservo.write(90);
 delay(250);
 int sharpir=getsharpdata();
 drive_forward();
 
 if(sharpir>330)
 {
 
   servo_scan();
 }
 
}

// --------------------------------------------------------------------------- Drive

void motor_stop()
{
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], LOW);

 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], LOW);
 delay(250);
}

void drive_forward()
{
 digitalWrite(motor_left[0], HIGH);
 digitalWrite(motor_left[1], LOW);

 digitalWrite(motor_right[0], HIGH);
 digitalWrite(motor_right[1], LOW);
}

void drive_backward()
{
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], HIGH);

 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], HIGH);
}

void turn_left()
{
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], HIGH);

 digitalWrite(motor_right[0], HIGH);
 digitalWrite(motor_right[1], LOW);
}

void turn_right()
{
 digitalWrite(motor_left[0], HIGH);
 digitalWrite(motor_left[1], LOW);

 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], HIGH);
}

float getsharpdata()
{
  for(int i=0;i<5;i++)
  {
   val[i] = analogRead(IRpin);
   // Calculate linear slope of reading (thanks, Acroname!):
   avgdistance+=val[i];
   delay(10);
  }
   avgdistance=avgdistance/5;
   return avgdistance;
}


void servo_scan()
{
 motor_stop();
 myservo.write(0);
 delay(1000);
 int left=getsharpdata();
 myservo.write(180);
 delay(1000);   
 int right=getsharpdata();
 
 if(left>right)
 {
  turn_left();
  delay(500);
 }

else
 {
   turn_right();
   delay(500);
 }
 
}

It seems to work ok for now,
Here is a crappy video of it in action

http://www.societyofrobots.com/robotforum/index.php?topic=13397.0 (http://www.societyofrobots.com/robotforum/index.php?topic=13397.0)