Best range finder

I am trying to get a proximity sensor for my robot with a range of roughly 20-80 cm. I have tried using the Maxbotix ultrasonic sensors and not surprisingly it picked up everything in a wide arc making it not very useful. I have also tried using the sharp 10-80 cm IR range finder, but as the distance increases the resolution really drops and after 45cm readings are all over the place.

I have tried several different programs that people have posted on the web for the Sharp IR sensor with the same outcome for them all. For the Maxbotix I used the Ping program in Arduino Examples.

Does anyone know of a good sensor to accomplish this task for under $50. Is there another brand of IR sensors that some one has had a good experience with?

This strange, I thought IR sensor was specifically design for accurate close distance measurements. Is it possible , that sensor picking up electrical EMI from your motors?
What is reflective surface bouncing light back? Post your code.

It works great the first 45cm then slowly loses accuracy. Here are some of the sample codes that I have tried

#include <DistanceGP2Y0A21YK.h>

DistanceGP2Y0A21YK Dist;
int distance;

void setup()
{
  Serial.begin(9600);
  Dist.begin(A0);
}

void loop()
{
  distance = Dist.getDistanceCentimeter();
  Serial.print("\nDistance in centimers: ");
  Serial.print(distance);  
  delay(500); //make it readable
}
int i;
int val;
int redpin=0;
void setup() {
    pinMode(redpin,OUTPUT);
    Serial.begin(9600);
}
void loop() {
    i=analogRead(redpin);
    val=(6762/(i-9))-4;
    Serial.println(val);
}

I have also just tried reading the raw analog values that come out using a ruler, but as the distance stays fixed the value will go from 250 to 230 to 255 and all over.

Also I have used white and black cards to test these distances. The power supply is always 5V.

tip 1) I wrote MultiMap as a generic solution for non-linear functions like the distance function - Arduino Playground - MultiMap -
You can tune the tables based upon the measurements of a specific sensor.

tip 2) make 16 readings of the analog value and average them

tip 3) add a capacitor between the analog pin and GND to stabilize the reading

delay(500); //make it readable

I like this comment :slight_smile: ("keep it readable" ?)

More serious, have a look at the blink without delay how to prevent the use of delay() in your code.

It looks to me like rounding error. Have you tried 6762 / 27 = 250 , than next value 6762 / 28 = 241, nothing in between - integer math. I'd suggest follow tip #2, averaging results over 16 gives 2 additional bits of resolution 10bit ADC becomes 12-bit.
Two options:

  1. sum up 16 variables but do NOT divide by 16, better scale up 6762 x 16 = 108 192
    val=(108192UL/( sum_i_16 - 9)) - 4;
    Serial.println(val);

You, probably will have to adjust 9 and 4 coefficient as well, do you math in Excell or LIbreOffice.

  1. sum up 16 results of analog reading, but keep results of division as "float"
     val=(6762.0/( average16_float-9))-4;
    Serial.println(val);