Wednesday, May 25, 2011

Long Range Infrared Sensor: GP2Y0A02YK0F

Has it really been over two weeks since I last updated the blag? I for one blame reddit, which has made me far more efficient at wasting time leaving more room for... wasting time.

I've acquired some sensors, motors, and a servo this past week and have been waiting to start plugging them into the Arduino. The servo and motor code seemed straight forward enough so instead I thought I'd first start with one of the cooler looking sensors I bought, the Sharp Long Range Infrared Proximity Sensor -  GP2Y0A02YK0F, courtesy of SparkFun.
I can't be the only one who thinks these look a lot like...
WHOA!
Don't forget your extra wire connectors
The sensors have an odd JST connector, so I'd suggest buying the additional wire adapter (only another $1.50) as well so you don't have to open it up and try to build your own and worry about damaging the sensor. I stripped the ends of the wires and soldered on a single header pin on each for easy wiring.

This long range infrared sensor can calculate the distance from objects up to 150cm away(roughly 5ft). It outputs an analog voltage corresponding to the distance that varies from roughly 2.8V at 15cm to 0.4V at 150cm. This value would be read by the Arduino using the analogRead() function.

Now, while this sensor is quite accurate between the range of 15-150cm (0.5-5ft), it does have two drawbacks:
  • The minimum cutoff for an accurate reading is 15cm, so any reading closer than that will be garbage
  • The voltage output over distance is not linear (more of a power function)

From the Sharp product manual

If your project requires checking for a distance closer than 15cm, there are short and mid-range versions available. If you don't want to sacrifice distance you can always just use more sensors in combination with the long range IR to cover it's "blind spot". Another way to compensate for the minimum distance would be to just place the sensor 6 inches behind the front of your robot...

As for the non-linearity, this just means that we'll have to throw together a nifty little algorithm to convert the sensor's output voltage into distance. Thankfully, Sharp has already taken care of the hard part and provided us with a chart of output values (as seen in the graph above). All we have to do is convert the analog voltages into a 10-bit digital value and determine a best-fit line equation.

Fancy graph drawn up in Excel

By placing the data values into Excel, I got the following graph. The graph most closely resembled a Power function, so the best-fitting line equation was y = 1735 * x ^ (-1.07), with an R^2 value of 0.997. Not bad. You may have noticed that the graph starts at 20 cm instead of 15 cm. I decided to sacrifice an extra 5 cm on the minimum distance in order to have a more accurate algorithm. Since I'll be using the sensor to make sure nothing comes within about 15 cm (6 in) of my robot, this won't be a problem. Also note that the algorithm doesn't take into account the x axis values, so in the equation x = 20 cm would be equivalent to x = 3... just make sure that you take that into consideration if your making an equation this way.

So, what do we do with this equation? Right now it doesn't help us at all since we are reading in y (voltage)   and want to solve for x (distance). We could bust out some scratch paper and a calculator and solve for x, or we could use the All Mighty WolframAlpha.

Is there anything this website can't do? 

So, taking into account the oddities of my graph, our equation to calculate the distance in cm is:
y = 10650.08 * x ^ (-0.935) - 10

For us 'mericans and our imperial units of measurment (10 chains in a furlong?), our algorithm in inches is:
y = 4192.936 * x ^ (-0.935) - 3.937

To use the algorithm in your code, you need to use the pow() function. So, in your Arduino sketch it would look something like this:
inches = 4192.936 * pow(sensorValue,-0.935) - 3.937

In order to test our algorithm, I taped my IR sensor to a tape measure and used a white sheet of printer paper as the test object.

Very rigorous and strict testing standards
 SCIENCE!
I see nothing, nothing!
Here is the code that I wrote up to test the IR sensor:

//  Noah Stahl
//  5/25/2011
//  http://arduinomega.blogspot.com
//  Arduino Mega 2560
//This sketch is used to test the Sharp Long Range Infrared Sensor.
//The sensor output is attached to analog pin 15. Once the distance
//is calculated, it is printed out to the serial monitor.

#define sensorIR 15               //Must be an analog pin
float sensorValue, inches, cm;    //Must be of type float for pow()

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

void loop() {
  sensorValue = analogRead(sensorIR);
  inches = 4192.936 * pow(sensorValue,-0.935) - 3.937;
  //cm = 10650.08 * pow(sensorValue,-0.935) - 10;
  delay(100);
  Serial.print("Inches: ");
  Serial.println(inches);
}


The algorithm works surprisingly well and, without interference, is easily accurate within the inch. The sensor starts at approximately 7.5 inches (19cm) so anything closer than that should be considered garbage data.

The only problem with the sensor is that it is susceptible to noise on the power supply line and needs to be perpendicular to the object for an accurate reading. Being an analog sensor, the output value is going to be dependent on the supply voltage. If you aren't supplying a constant voltage, the numbers are going to fluctuate and if your voltage starts to dip under 5V, you wont get the full 5 ft range. You may need to add an extra 0.1uF cap at the power supply or maybe average every few readings to smooth out the data.

Noise, noise, noise, noise, noise!

If the sensor is not level to the object, your distance is going to be off by a few inches. If you place your sensor on a servo and it's not secured properly, jumbling about (in my case poorly taped to a tape measure), you are going to get random spikes in your data. The sensor is really sensitive, which can be either a good or bad thing depending on your design.

Right now the code doesn't have a cutoff for minimum and maximum distances, but this would be an easy exercise to see if you've been paying any attention. The sensor should be able to read any value inside of roughly 7.5 - 60 inches if you're using this code. Also, if you set your sensor up about 7 inches back from the front of your robot, you can use this code to detect whether an object gets too close without having to worry about the sensor's blind spot. You technically wouldn't need any close ranged sensors if you place it this way to get a basic robot going, but its always good to have more than one sensor to double check your values and in case something manages to sneak in too close. Sensors are the eyes and ears of your robot and you can never have enough eyeballs.

10 comments:

  1. hello:
    i m using the same sensor as u did in ur projects..
    i m making a wall tracking robot.
    can u plz help me out in reducing the noise and unwanted variations in the circuit using passive components,,
    thanx

    ReplyDelete
  2. Sensors are transforming the way engineers think about position sensing

    Distance Sensor

    ReplyDelete
  3. i do my project in eyeblink detection.whether i use this sensor for this project or not

    ReplyDelete
  4. hey man, nice meeting up with you, im having abit of difficulty in coding the gp2y0a710k sensor. any advice. Im not so keen with this microsoft excel method. Really need some help man

    ReplyDelete
  5. Hello, I'm a portuguese studen. I'm working in a project that will use this sensor Sharp.
    I Tried to understand all the steps that you explain, but i'm stoked.

    after put all data on excel, and made the graph, the power function result is y = 1735 * x ^ (-1.07), with an R^2 value of 0.997. like yours,
    The next step it's easy, just put the data on wolframe site and pick the results.
    After this I didn't understand.

    my result is y = 1065.08 * x ^ (-0.935) and you show the same on the photo.

    however you use this y = 10650.08 * x ^ (-0.935) - 10.
    where came the last ten? and Why 10650.08?

    I hope you can help me understand this.

    best regards
    Daniboy

    ReplyDelete
  6. i have use arduino due properly not working .please tell how to write the code

    ReplyDelete
  7. sorry, in this form "//cm = 10650.08 * pow(sensorValue,-0.935) - 10;" what does the "-10" mean?
    And why is it there?
    Thx very much

    ReplyDelete
  8. Most of the time I don’t make comments on any post, but I'd like to say that this content is really helpful. Please share with us more post like this.
    Ultrasonic Level Sensor

    ReplyDelete
  9. hi i have an arduino with ethernetshield and i want to use the sharp sensor to detect if object pass by and count it. do you know how i can do that please?

    ReplyDelete