Posts Tagged ‘GP2Y0A02’

Arduino + Processing – 3D Sensor Data Visualisation

Arduino 3D scan

So following on from my previous posts about visualising sensor data in Processing, I’m now looking at drawing 3D representations of the data recorded from the Sharp IR sensor – although can be any kind of range finder.

I started by rigging 2 servos, one to pan left to right, the other up to down. The latter is limited to only 60 degrees of movement. I’m going to represent each servo position in a grid to start with, so a grid 180 wide (x) by 60 tall (y). The distance measured from the sensor will form the z index position so how far/ close a point will appear.

The setup is pretty much the same, Arduino records and sends the sensor data to the serial port buffer along with the X and Y position of the servos. Processing then picks this up and populates an array. Now this time I’m using multi-dimensional arrays, that is one array that stores other arrays. I could make just one array of 10800 items (180 * 60) but its far more efficient to make an array of 180 items, each item being another array of 60 items to store the distance measured. So for every 1 degree I move left to right, I record the 60 positions of the up/ down servo and the reading taken.

To visualise this I started drawing squares using the QUAD_STRIP shape to produce a grid layout (image at the top of the post). Of course because I’m actually using polar co-ordinates (degrees) instead of cartesian (x, y) then what the sensor is reading can’t really be translated to a flat grid. Because when it measures something vertical the measurements will all be different and when translated to my flat grid, it would make anything vertical look slanted. Trouble is now we’re trying to view something in 3D space so it doesn’t look all that great – so I’ve added in some animation to rotate the object slightly, looks fine when you zoom in close enough to one section but otherwise it’s just a random shape.

There are 2 ways around this, firstly we can convert our co-ordinates to cartesian. Or we can alter the grid used to display our data, the shape needed is basically a 60 degree arc thats lathed 180 degrees – so it kind of looks like a tyre wall. The radius used to draw our 60 degree arc is calculated by the distance taken from the sensor.

Arduino 3D Sensor Data Parts

SRF05 Ultrasonic range finder or Sharp GP2Y0A02 IR sensor (basically any kind of distance sensor)
Arduino Deumilanove w/ ATMEGA328
Breadboard / Prototyping board
Jumper/ Connector wires
2x Servos (has to need no more than 5v supply)
C shaped Servo brackets (If anyone can make these cheap enough let me know!)

Arduino 3D Plotter Circuit

Using the below posts you should be able to figure out how to wire the sensor and how to use the servos. I use digital pins 9 and 10 for the servos and analog pin 1 for the sensor reading.

Arduino SRF-05 Tutorials
Arduino Servo Tutorials
How to use the Sharp IR range finder

Arduino Sketch

We use the servo libary and a couple of FOR loops to control 2 servos, for every degree panned we tilt the other servo through 60 degrees taking a series of sensor readings for each position and averaging them. We output these values with the X and Y position in degrees to the serial port buffer. At the end of each loop we reset the servo position. If the sensor reading is outside the range of operation of the servo we also handle this.

/*
luckylarry.co.uk
3D Scan Visualisation for Sharp GP2Y0A02 IR range finder
Sends sensor readings for every degree moved by the servo
values sent to serial port to be picked up by Processing
*/
#include             // include the standard servo library
Servo leftRightServo;         // set a variable to map the servo
Servo upDownServo;
int leftRightPos = 0;         // set a variable to store the servo position
int upDownPos = 0;
const int numReadings = 10;   // set a variable for the number of readings to take
int index = 0;                // the index of the current reading
float total = 0;              // the total of all readings must be a float to allow totaling of float values
int average = 0;              // the average
int IRpin = 1;                // analog pin for reading the IR sensor

/* setup the pins, servo and serial port */
void setup() {
  leftRightServo.attach(9);
  upDownServo.attach(10);
  // initialize the serial port:
  Serial.begin(9600);
} 

/* begin rotating the servo and getting sensor values */
void loop() {
 for(leftRightPos = 0; leftRightPos < 180; leftRightPos++)
  {
    leftRightServo.write(leftRightPos);             

  for(upDownPos = 60; upDownPos < 120; upDownPos++)
  {
    upDownServo.write(upDownPos);  

      for (index = 0; index<=numReadings;index++) {            // take x number of readings from the sensor and average them
        float volts = analogRead(IRpin)*0.0048828125;   // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
        float distance = 65*pow(volts, -1.10);          // worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
        total = total + distance;                              // update total
        delayMicroseconds(20);
      }
    average = (int) total/numReadings;                               // create average reading
        if (average < 20) {
         average = 20;
        }
        if (average > 150) {
         average = 150;
        }
        //average = 0 - average;
    if (index >= numReadings)  {                               // reset the counts when at the last item of the array
      index = 0;
      total = 0;
    }       

Serial.print("Y");
Serial.print(upDownPos-60);
Serial.print("X");
Serial.print(leftRightPos);
Serial.print("Z");
Serial.println(average);

  }
    upDownServo.write(60);
  }

    leftRightServo.write(0);              

}

[ad#Google Ad in content]

Processing Sketch

We now listen to the serial port and each time there is an event we take the values and populate an array based on the X and Y values sent from the Arduino code. We add this value on to the existing value and then for each complete mapping we work out the average value – so the longer it runs for the more normalised the results should appear.

Using some basic trigonometry we have a class that makes an arc. Our draw() method calls this arc and translates/ rotates it for each of the 180 degrees. The arc itself is calculated from using the distance reading from the sensor as its radius.

If using a grid instead of this shape then we just say at point X,Y set the Z value instead of worrying about radius’s etc…

/*
luckylarry.co.uk
3D Scan Visualisation for Sharp GP2Y0A02
Maps out an area of what the GP2Y0A02 sees into a 3D view
*/
import processing.serial.*;     // import serial library
Serial myPort;                  // declare a serial port
int x, y, z;                     // variable to store x and y co-ordinates for vertices
int value = 0;                  // value from sensor
int[][][] data = new int[181][61][1];  // create an array to store each new sensor value for each servo position
int count;
int average = 1;
PFont myFont;                   // setup fonts in Processing
int numberOfSegments = 179;
createArc Arc;                  // create an instance of the Arc class
float radius = 150;
float angle = 0;

void setup(){
  size(640, 360, P3D);
  Arc = new createArc();        // assign the Arc classes to an object
  myFont = createFont("verdana", 12);
  textFont(myFont);
  // setup the serial port and buffer
  myPort = new Serial(this, Serial.list()[1], 9600);
  myPort.bufferUntil('\n');

}

void draw(){
  background(255);
  float tempX = 0, tempY = 1, tempZ = 0;
  fill(200);
  lights();
  translate(width/2, 200, 110);
  angle = 180.0 / numberOfSegments;
  rotateY(count * PI/10800);
  for (int j = 0; j < numberOfSegments; j++){
      tempZ = cos(radians(angle))*radius;
      tempX = sin(radians(angle))*radius;
      pushMatrix();
      translate(tempX, tempY, tempZ); // move each instance we create of the arc object to a slightly new position and rotation
      rotateY(radians(angle));
      Arc.create(j);
      popMatrix();
      angle += 180.0/numberOfSegments;
  }

}
// creates an arc object using QUAD_STRIP
class createArc {
// pass values to create method to know which array to load 1 to 180...
  void create(int degree){
    pushMatrix();
    rotateY(radians(135));
    beginShape(QUAD_STRIP);
    for(int a=60; a < 120;a++) {
      float x1 = cos(radians(((90+a))))*(data[degree][a-60][0]/average);
      float y1 = sin(radians(((90+a))))*(data[degree][a-60][0]/average);
      float x2 = cos(radians(((90+a))))*(data[degree+1][a-60][0]/average);
      float y2 = sin(radians(((90+a))))*(data[degree+1][a-60][0]/average);
      vertex(x1,y1,100);
      vertex(x2,y2,105);
    }
    endShape();
    popMatrix();
  }
} 

/* get values from serial port */

void serialEvent (Serial myPort) {
  String xString = myPort.readStringUntil('\n');  // read the serial port until a new line
    if (xString != null) {  // if theres data in between the new lines
    	xString = trim(xString); // get rid of any whitespace just in case
    	String getY = xString.substring(1, xString.indexOf("X")); // get the value of the servo position
        String getX = xString.substring(xString.indexOf("X")+1, xString.indexOf("Z")); // get the value of the sensor reading
        String getZ = xString.substring(xString.indexOf("Z")+1, xString.length()); // get the value of the sensor reading
    	x = Integer.parseInt(getX); // set the values to variables
    	y = Integer.parseInt(getY);
        z = Integer.parseInt(getZ);
        data[x][y][0] += z;
        //println(z); // for debugging
        count++;
        if (count > 10800) {
          count = 0;
          average++;
        }
  }
}

[ad#Google Ad in content]

So here’s a quick screen grab of the 3D object that represents what the sensor sees, looks pretty confusing but if you zoom in and take a small section of it then it’s a bit better. Other than that its just a random shape!

3D-scan02

Arduino + Processing – Make a Radar Screen – Part 3: Visualising the Data from Sharp Infrared Range Finder

Arduino Sharp IR radar

So I had some luck with getting the Sharp Infrared range finder working and I’ve now plugged this on to my servo rig to see if I get better results on my radar styled display.

Check out how to use the Sharp IR range finder here

Few things to bare in mind, whilst the code is pretty much the same there are a few subtle differences. Firstly for better readings the Arduino code has a longer delay – but since we’re not allowing for a sonar ping there’s not much noticeable difference.

Next we’re expecting integer values in the processing code so when sending values to over the serial port we cast them from float to integer.

Because the IR sensor has a different range I’ve altered the display to measure only up to 150cm. And becasue of this range limitation, if there is any value recorded outside of this range then we need to handle it to avoid seeing spikes and the same for any value under 20cm we need to also handle this.

To make the display more readable I keep the same size screen and area (radius of 300) and then multiply the sensor values by 2 to magnify them a bit more.

Other than it, it’s basically the same code as before and when we look at the image comparison now between what the sensor records and what is physically there we see a far better match, in some cases it’s a little to accurate.

Sharp-IR-radar

Arduino sketch

/*
luckylarry.co.uk
Radar Screen Visualisation for Sharp GP2Y0A02 IR range finder
Sends sensor readings for every degree moved by the servo
values sent to serial port to be picked up by Processing
*/
#include             // include the standard servo library
Servo leftRightServo;         // set a variable to map the servo
int leftRightPos = 0;         // set a variable to store the servo position
const int numReadings = 10;   // set a variable for the number of readings to take
int index = 0;                // the index of the current reading
float total = 0;              // the total of all readings must be a float to allow totaling of float values
int average = 0;              // the average
int IRpin = 1;                // analog pin for reading the IR sensor
 
/* setup the pins, servo and serial port */
void setup() { 
  leftRightServo.attach(9);
  // initialize the serial port:
  Serial.begin(9600);
} 
 
/* begin rotating the servo and getting sensor values */
void loop() { 
  for(leftRightPos = 0; leftRightPos < 180; leftRightPos++) {  // going left to right.                                
    leftRightServo.write(leftRightPos);             
      for (index = 0; index<=numReadings;index++) {            // take x number of readings from the sensor and average them
        float volts = analogRead(IRpin)*0.0048828125;          // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
        float distance = 65*pow(volts, -1.10);                 // worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
        total = total + distance;                              // update total
        delay(20);
      }
    average = (int) total/numReadings;                         // create average reading CAST TO INT!! remove the decimal places
 
    if (index >= numReadings)  {                               // reset the counts when at the last item of the array    
      index = 0;           
      total = 0;     
    }
    Serial.print("X");                                         // print leading X to mark the following value as degrees
    Serial.print(leftRightPos);                                // current servo position
    Serial.print("V");                                         // preceeding character to separate values
    Serial.println(average);                                   // average of sensor readings
  }
  /* 
  start going right to left after we got to 180 degrees 
  same code as above
  */
  for(leftRightPos = 180; leftRightPos > 0; leftRightPos--) {  // going right to left                                
    leftRightServo.write(leftRightPos);             
    for (index = 0; index<=numReadings;index++) {
      float volts = analogRead(IRpin)*0.0048828125;            // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
      float distance = 65*pow(volts, -1.10);                   // worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
      total = total + distance;
      delay(20);
    }
    average = (int) total/numReadings;  
    if (index >= numReadings)  {           
      index = 0;           
      total = 0;     
    }
    Serial.print("X");
    Serial.print(leftRightPos);
    Serial.print("V");
    Serial.println(average);
   }  
}

[ad#Google Ad in content]

Processing sketch

/*
luckylarry.co.uk
Radar Screen Visualisation for Sharp GP2Y0A02
Maps out an area of what the GP2Y0A02 sees from a top down view.
Takes and displays 2 readings, one left to right and one right to left.
Displays an average of the 2 readings
Displays motion alert if there is a large difference between the 2 values.
*/
import processing.serial.*;     // import serial library
Serial myPort;                  // declare a serial port
float x, y;                     // variable to store x and y co-ordinates for vertices   
int radius = 350;               // set the radius of objects
int w = 300;                    // set an arbitary width value
int degree = 0;                 // servo position in degrees
int value = 0;                  // value from sensor
int motion = 0;                 // value to store which way the servo is panning
int[] newValue = new int[181];  // create an array to store each new sensor value for each servo position
int[] oldValue = new int[181];  // create an array to store the previous values.
PFont myFont;                   // setup fonts in Processing
int radarDist = 0;              // set value to configure Radar distance labels
int firstRun = 0;               // value to ignore triggering motion on the first 2 servo sweeps

/* create background and serial buffer */
void setup(){
  // setup the background size, colour and font.
  size(750, 450);
  background (0); // 0 = black
  myFont = createFont("verdana", 12);
  textFont(myFont);
  // setup the serial port and buffer
  myPort = new Serial(this, Serial.list()[1], 9600);
  myPort.bufferUntil('\n');
}

/* draw the screen */
void draw(){
  fill(0);                              // set the following shapes to be black
  noStroke();                           // set the following shapes to have no outline
  ellipse(radius, radius, 750, 750);    // draw a circle with a width/ height = 750 with its center position (x and y) set by the radius
  rectMode(CENTER);                     // set the following rectangle to be drawn around its center
  rect(350,402,800,100);                // draw rectangle (x, y, width, height)
  if (degree >= 179) {                  // if at the far right then set motion = 1/ true we're about to go right to left
    motion = 1;                         // this changes the animation to run right to left
  }
  if (degree <= 1) {                    // if servo at 0 degrees then we're about to go left to right
    motion = 0;                         // this sets the animation to run left to right
  }
  /* setup the radar sweep */
  /* 
  We use trigonmetry to create points around a circle.
  So the radius plus the cosine of the servo position converted to radians
  Since radians 0 start at 90 degrees we add 180 to make it start from the left
  Adding +1 (i) each time through the loops to move 1 degree matching the one degree of servo movement
  cos is for the x left to right value and sin calculates the y value
  since its a circle we plot our lines and vertices around the start point for everything will always be the center.
  */
  strokeWeight(7);                      // set the thickness of the lines
  if (motion == 0) {                    // if going left to right
    for (int i = 0; i <= 20; i++) {     // draw 20 lines with fading colour each 1 degree further round than the last
      stroke(0, (10*i), 0);             // set the stroke colour (Red, Green, Blue) base it on the the value of i
      line(radius, radius, radius + cos(radians(degree+(180+i)))*w, radius + sin(radians(degree+(180+i)))*w); // line(start x, start y, end x, end y)
    }
  } else {                              // if going right to left
    for (int i = 20; i >= 0; i--) {     // draw 20 lines with fading colour
      stroke(0,200-(10*i), 0);          // using standard RGB values, each between 0 and 255
      line(radius, radius, radius + cos(radians(degree+(180+i)))*w, radius + sin(radians(degree+(180+i)))*w);
    }
  }
  /* Setup the shapes made from the sensor values */
  noStroke();                           // no outline
  /* first sweep */
  fill(0,50,0);                         // set the fill colour of the shape (Red, Green, Blue)
  beginShape();                         // start drawing shape
    for (int i = 0; i < 180; i++) {     // for each degree in the array
      x = radius + cos(radians((180+i)))*((oldValue[i]*2)); // create x coordinate
      y = radius + sin(radians((180+i)))*((oldValue[i]*2)); // create y coordinate
      vertex(x, y);                     // plot vertices
    }
  endShape();                           // end shape
  /* second sweep */
  fill(0,110,0);
  beginShape();
    for (int i = 0; i < 180; i++) {
      x = radius + cos(radians((180+i)))*(newValue[i]*2);
      y = radius + sin(radians((180+i)))*(newValue[i]*2);
      vertex(x, y);
    }
  endShape();
  /* average */
  fill(0,170,0);
  beginShape();
    for (int i = 0; i < 180; i++) {
      x = radius + cos(radians((180+i)))*(((newValue[i]+oldValue[i])/2)*2); // create average
      y = radius + sin(radians((180+i)))*(((newValue[i]+oldValue[i])/2)*2);
      vertex(x, y);
    }
  endShape();
  /* if after first 2 sweeps, highlight motion with red circle*/
  if (firstRun >= 360) {
    stroke(150,0,0);
    strokeWeight(1);
    noFill();
      for (int i = 0; i < 180; i++) {
        if (oldValue[i] - newValue[i] > 35 || newValue[i] - oldValue[i] > 35) {
          x = radius + cos(radians((180+i)))*(newValue[i]*2);
          y = radius + sin(radians((180+i)))*(newValue[i]*2);
          ellipse(x, y, 10, 10); 
        }
      }
  }
  /* set the radar distance rings and out put their values, 50, 100, 150 etc.. */
  for (int i = 0; i <=6; i++){
    noFill();
    strokeWeight(1);
    stroke(0, 255-(30*i), 0);
    ellipse(radius, radius, (100*i), (100*i)); 
    fill(0, 100, 0);
    noStroke();
    text(Integer.toString(radarDist+25), 380, (305-(radarDist*2)), 50, 50); // change this to measure up to 150cm
    radarDist+=25;
  }
  radarDist = 0;
  /* draw the grid lines on the radar every 30 degrees and write their values 180, 210, 240 etc.. */
  for (int i = 0; i <= 6; i++) {
    strokeWeight(1);
    stroke(0, 55, 0);
    line(radius, radius, radius + cos(radians(180+(30*i)))*w, radius + sin(radians(180+(30*i)))*w);
    fill(0, 55, 0);
    noStroke();
    if (180+(30*i) >= 300) {
      text(Integer.toString(180+(30*i)), (radius+10) + cos(radians(180+(30*i)))*(w+10), (radius+10) + sin(radians(180+(30*i)))*(w+10), 25,50);
    } else {
      text(Integer.toString(180+(30*i)), radius + cos(radians(180+(30*i)))*w, radius + sin(radians(180+(30*i)))*w, 60,40);
    }
  }
  /* Write information text and values. */
  noStroke();
  fill(0);
  rect(350,402,800,100);
  fill(0, 100, 0);
  text("Degrees: "+Integer.toString(degree), 100, 380, 100, 50);         // use Integet.toString to convert numeric to string as text() only outputs strings
  text("Distance: "+Integer.toString(value), 100, 400, 100, 50);         // text(string, x, y, width, height)
  text("Radar screen code at luckylarry.co.uk", 540, 380, 250, 50);
  fill(0);
  rect(70,60,150,100);
  fill(0, 100, 0); 
  text("Screen Key:", 100, 50, 150, 50);
  fill(0,50,0);
  rect(30,53,10,10);
  text("First sweep", 115, 70, 150, 50);
  fill(0,110,0);
  rect(30,73,10,10);
  text("Second sweep", 115, 90, 150, 50);
  fill(0,170,0);
  rect(30,93,10,10);
  text("Average", 115, 110, 150, 50);
  noFill();
  stroke(150,0,0);
  strokeWeight(1);
  ellipse(29, 113, 10, 10); 
  fill(150,0,0);
  text("Motion", 115, 130, 150, 50);
}

/* get values from serial port */
void serialEvent (Serial myPort) {
  String xString = myPort.readStringUntil('\n');  // read the serial port until a new line
    if (xString != null) {  // if theres data in between the new lines
    	xString = trim(xString); // get rid of any whitespace just in case
    	String getX = xString.substring(1, xString.indexOf("V")); // get the value of the servo position
    	String getV = xString.substring(xString.indexOf("V")+1, xString.length()); // get the value of the sensor reading
    	degree = Integer.parseInt(getX); // set the values to variables
    	value = Integer.parseInt(getV);
        /*
        If our values are outside either end of the sensors range then convert them to the max/min for a better display without the spikes
        */
        if (value > 150) {
          value = 150; 
        }
        if (value < 20) {
          value = 20;
        }
    	oldValue[degree] = newValue[degree]; // store the values in the arrays.
    	newValue[degree] = value;  
        /* sets a counter to allow for the first 2 sweeps of the servo */
    	firstRun++;
    	if (firstRun > 360) {
    	  firstRun = 360; // keep the value at 360 
    	}
  }
}

[ad#Google Ad in content]
Part 1: Setting up the Circuit and Outputting Values
Part 2: Visualising the Data

Arduino – Using a Sharp IR Sensor for Distance Calculation

Arduino testing Sharp IR

Well, looks like my sonar sensor (SRF05) is a just a tad inaccurate for precise measurement as I found from my radar screen I made (Arduino Radar Sscreen).

So I’ve got hold of a Sharp GP2Y0A02 series infrared distance sensor. It’ll detect and measure anything within a 20-150cm range and it does this by triangulation from where it emits a beam of IR and from when it receives it – this isn’t too important to understand.

The hardest bit of this is actually just getting a rough distance value out of it. If we look at the data sheet you’ll see a graph of Volts to Distance and the greater the voltage the shorter the distance. So to measure distance we’ll need to measure the voltage change as the distance changes.

To do this I have to use the analog pins on the Arduino board, now first off because we’re connecting/ reading directly from the sensor we need to convert the digital value that the Arduino’s onboard analog to digital converters will give us. Sounds odd? Well when you use the analog pins it converts what ever arbitary analog value supplied to a byte value which is between 0 and 1023 (1024 variations).

Sharp-GP2Y0A02Looking at our graph above from the datasheet, this converted value is of no use to us so we need to convert this value back to the true analog value. How? We take the voltage rating of the power supply and divide by 1024 to give us a value per step. So for instance:

5v/1024 = 0.0048828125

We take this value and multiply by what the sensor sends back to get our voltage reading. The next stage is to work out an equation from the graph on the data sheet to get the theoretical distance from the voltage reading, if we look at the graph between 20 and 150cm you can see that its exponential.

To get our distance on the graph I came up with:

1/Volts * 65

I got 65 by taking the distance on the graph and dividing that by 1/Volts. So now we know what to multiply our voltage results by to get the distance. This is fine if we just had one value to read or if this was a linear graph, in that the change in voltage was always the same amount of distance.

For the exponential change we have to turn our value now into an exponent, a fancy way of saying x to the power of y. So our formula for distance from voltage reading is now something like:

distance = (Volts x)*65.

Since our graph is a decaying exponential the value of x will be a fraction – to write this as a exponent we have to use a minus number e.g. -1. The exponent -1 is the equivalent of the fraction 1/2 which is 0.5 as a decimal.

Now through trial and error I programmed this into my Arduino and changed the exponent until my readings became accurate(ish) I started at -1 and by co-incidence the next value I tried was -1.1 which is 11/10 as a fraction, 0.65 as a decimal and oddly enough 1/100th of my distance ration, 65!

Anyway its not spot on but this seems to work for my sensor, for any other Sharp IR sensor, first work out the distance ratio from the graph and then try changing the exponential until you get accurate results. If anyone can show me the equations for doing this that’d be great as I only did this through trial and error.

In Arduino the code for my equation is:

float volts = analogRead(IRpin)*0.0048828125; ;
float distance = 65*pow(volts, -1.10);

I’m using float for my values as the expected result will not be integer and the pow(number, exponent) function is an Arduino function that lets us raise a specified number by a power/ exponent.

So the only other hassle is wiring up the sensor which has 3 pins from a JST connector (Japan Solderless Terminal). Picture below for mapping the Power (Vcc), GND and Reading (Vo).

Arduino Sharp IR Distance Sensor Circuit

Pretty easy – I’ve got a JST lead plugged it in and removed the casing on the wires to expose them and I’ve just jabbed that into a breadboard. Then i’ve run standard jumper wires from these to the Arduino board.

Sharp-GP2Y0A02-circuit

Sharp Infrared Arduino Sketch

Again, pretty easy, read the analog pin and apply my above logic, printing the value to the serial port.

int IRpin = 1;                                    // analog pin for reading the IR sensor

void setup() {
  Serial.begin(9600);                             // start the serial port
}

void loop() {
  float volts = analogRead(IRpin)*0.0048828125;   // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
  float distance = 65*pow(volts, -1.10);          // worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
  Serial.println(distance);                       // print the distance
  delay(100);                                     // arbitary wait time.
}

[ad#Google Ad in content]

Seems pretty accurate, although there does seem to be spikes but with the same approach to the sonar sensor we can smooth this by taking an average of multiple readings. Next step is to run my radar visualisation on it.

Arduino-testing-Sharp-IR
And just so you can see my screen readings:

Sharp-GP2Y0A02-readings

Pretty much measuring spot on, though of course if you’re closer than 20cm are futher than 150cm then the measurements will be grossly inaccurate as this is out side of the sensors evironment.