arduino + processing + sharp IR = periodic output?

Hey everyone, I set up a sharp IR sensor to send a distance through the serial port to processing, which then graphs the result. However, it looks like a sine wave or something, see pic below. Here’s the arduino code:

int pin = 0; // sharp IR sensor
float reading;
int pin1 = 5; // potentiometer for time delay
float reading2 = 0;
int i;

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

void loop(){
  //I take five delayed readings and average them
  for(i = 0; i < 5; i++){
  reading = analogRead(pin);
  reading = (243.46 *  (1 / reading));
  reading2 = reading2 + reading;
  delay(2);
}  
  Serial.println(100 * (reading2 / 5));
  reading2 = 0;
  delay(analogRead(pin1));
}

and the processing code:

 import processing.serial.*;
 
 Serial myPort;        
 int xPos = 1;        
 
 void setup () {

 size(400, 300);        
 
 println(Serial.list());
 
 myPort = new Serial(this, Serial.list()[0], 9600);
 myPort.bufferUntil('\n');
 
 background(0);
 }
 void draw () {
 // everything happens in the serialEvent()
 }
 
 void serialEvent (Serial myPort) {
 String inString = myPort.readStringUntil('\n');
 
 if (inString != null) {
 inString = trim(inString);
 float inByte = float(inString);
 inByte = map(inByte, 60, 85, 0, height); 
 // maps reading to window, zoomed for detail
 
 // draw the line:
 stroke(200,25,50);
 line(xPos, height, xPos, height - inByte);
 
 // at the edge of the screen, go back to the beginning:
 if (xPos >= width) {
 xPos = 0;
 background(0);
 }
 else {
 // increment the horizontal position:
  xPos++;
 }
 }
 }

and the screenshot (hopefully, I don’t think I’ve ever successfully posted a picture):

anyone know why it looks sawtooth-y?

Inspired by this? http://luckylarry.co.uk/arduino-projects/arduino-using-a-sharp-ir-sensor-for-distance-calculation/

...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.

Ah, I thought of that. I'm using a different model, but I made sure that the wall was well within the datasheet's range. A note I forgot to say above: Nothing was moving when I measured this. The sensor was stationary on the table and pointing straight at a wall, which was obviously stationary as well. I don't really mind the spikiness, but I'm just curious as to why it appears to be so uniform and periodic.

Looks like 50 or 60 Hz mains pick up beating with the sample period. What impedance are you feeding into the analogue port? Have you tried a 0.1uF capacitor across the analogue input?

I'm just sending it straight in with no cap. I'm not worried about it or anything and I realize it's easy to fix, but I was just curious about why it happens. I notice that the max height per cycle changes, if I set the delay to be 60 Hz would I see it become uniform? Also, why would it be picking that up? I'm running the arduino off of the usb port and the whole setup is several feet away from the wall and away from the floor as well. The sensor is pointed at a wooden shelf-y thing that does not have any electricity running through it. The only explanation I can think of is that it's coming from the computer, which seems like it's bad...

if I set the delay to be 60 Hz would I see it become uniform?

No because it would not be exactly the same frequency as the mains it would drift or beat as I said.

why would it be picking that up?

It matters not where you are unless you take specific steps to screen from it there is mains everywhere. To remove mains pickup you would have to be an a ferrite lined chamber like you do RF emissions testing in.

If you have a scope just touch the probe and see how much you pick up.

hiya,

I’m using a sharp GP2Y0A02YK0F…they are noisey

this seems to worsen when on a robot platform and with other peripherals. 20mV ripple supply ripple will affect longer range readings by 20cm or more…a sensor switching such as a light reflecting odometer P5587 will affect the readings too as it switches on off …

I filter the ADC input values, using averaging or Standard deviation software filters discarding anything too high or low. I use 20 readings as the sharp samples at 40KHz if I remember properly not a worry. For averaging discarding >< 15% seems to be ok.

The averaging filter works better when the robot is moving, the SD method has a bit of lag so it works better when the robot is stationary.

I’ve been usig 5cm volt/range tables but not accurate enough, tried best fit lines not happy (v) /(1/r) etc not much better than the range table, I’m now trying a curve solution which is really showing much better accuracy.

My maths is school boy ish, so fitting a curve etc beyond me, so

I’ve got the plot data and submitted to zunzun.com using the “Marc Plante’s Custom Quadratic With Linear Decay And Offset” , that’s in 2D polynomials, Theres a submission of text data and some options

Data is prepared x for vin and range cm as y ( I’m not going to even try and transpose the formula)

I used a DVM is get the readings and then checked the ADC values, DVM is much easier for this method. ADC noisey but through the filter compares well with the DVM and not far off the datasheet.

zunzun.com returns a report with a formula and the values for a really good curve fit. I used “scilab” a matlab type engine to check data and curve fit which showed some glitches in the data, corrected resubmit and got this back

y = ( (-b + (b2 - 4 a (c - x))0.5) / 2 / a ) / (d * x) + Offset
Fitting target of sum of squared absolute error = 1.0087491765917592E+02
a = -1.9035009792227321E-10
b = 2.2117131291348640E-04
c = 4.9075752602887955E-02
d = -3.7454750379930721E+00
Offset = 1.2109501295599825E+03

Hope this heklps someone!

Dave

range_value is actually the vin or “x”

arduino code is something like this,

if ( range_value >= 0.35 && range_value < 2.4 ) {

float a = -1.9035009792227321E-10;
float b = 2.2117131291348640E-04;
float c = 4.9075752602887955E-02;
float d = -3.7454750379930721E+00;
float offset = 1.2109501295599825E+03;
float x = ( float ) range_value;
float y = 0;

y = ( ( -b + sqrt(sq(b) - 4 * a * (c-x) ) ) /2 / a ) / ( d * x ) + offset ;
range = double (y);
if (range > 150) { range = 150 };

The range finder is pretty accurate now, I’m using a seed meg and the code fits well into my resource budget.

I would not use my values there are abit off the data sheet ideal, use your own as a small change to the data seems to cause some radical changes to the values for abcd and offset values.

Seem to be getting close to -+ 1 cm from ideal surfaces measurements in near to medium range and accpetable out 130 ± 2cm as the scan passes a surface the responses map very well with the angle and distance the object is to the robot.

Idealising is not going to help if the surfaces are not nice ones but it does seem to help with the bigger problems…

Dave