High precision, short range distance sensor

Hi all,

I'm looking for a component but I don't even know if it exists :slight_smile:
Well actually, it should be a non contact distance sensor, but the range and precision are critical.

First the precision. It should be at least 0.5mm. Higher precision would be better.

Then the range. Schematically it looks like this:

The object travels max 20mm (maybe 25mm)
The sensor distance isn't to critical, could also be 30-60mm

Wait... I might have found something:

Sharp GP2Y0A41SK0F Analog Distance Sensor

So, let's say I make the sensor distance 60mm
60mm: 2 Volts
40mm: 2.75 Volts

0.75V/20mm > 0.0375 V/mm > 0.01875 V/0.5mm

Would it be possible to detect voltage so precisely on an arduino ?
Maybe using an AD converter ?

But I'd love to hear any other suggestions too.

Thanks

Distancesensor_reqs02.jpg

Would it be possible to detect voltage so precisely on an arduino

The Arduino has a built in 10 bit A/D converter so with a 5V reference you get each step representing a voltage of 4.88mV.
However, as you do not get over 3V3 on that sensor if you wired the 3V3 output to the Vref input this comes down to each step representing 3.22mV.

Depending on how reflective your target is it might work but occasionally these sensors throw a rough reading although you can normally take that out with software.

Thanks for the tip :slight_smile:

I got a potmeter and tested with the example sketch for analog read.

So by using Vref=3.3 it would be more accurate, right ? Not sure yet how to calculate a distance from this but I'll figure that out later.

First a question about my test.

I used one of these:

Now if i look at the readings:
1.5347
1.4565
1.5152
1.4858
1.4858
1.4809
1.4809
1.4809
1.4809
1.4956
1.4712
1.3978

1.5152 - 1.3978 = 0.1174 difference

If this fluctuation is going to happen on the sensor I might as wel give up now :slight_smile:
Or could the fluctuation be in the contacts, wires, breadboard ?

Or is this what you mean by "a rough reading" that has to taken out by software ?

Thanks

EDIT:

I replaced the potmeter with two identical resitors, the readings are better now

2.4926686
2.4926686
2.4926686
2.4926686
2.4926686
2.4926686
2.4926686
2.4926686
2.4877810
2.4926686
2.4926686
2.4926686
2.4926686
2.4926686
2.4926686

but that 2.4877810 pops up once in a while, 76 times in 1905 readings to be exact

How often are you sampling? The Sharps only have a sampling rate of like 50ms or something, so if you're doing very fast sampling you're getting 'repeat' reads which are basically useless (not confirming a value). Also, each time you read you're likely to get an "off" reading or 2 (perhaps your 2.48?), which then settles for the remainder of the sample time - you discard that in software, unless you want to get really fancy with serious noise-cancelling capacitors etc.

If you're serious about accuracy, you could get multiple sensors, array them to avoid interfering reflection, and again deal with that in software for averaging, etc.

Again, if you're really serious about accuracy, and cost is less of a factor, sparkfun has a relatively new LIDAR unit.

I don't have the sensor yet, I was testing the AD conversion on my arduino using a potmeter and then two resistors. Just to see how it worked an what the reading were.

I ordered the sharp sensor and hope to be testing it end of the week. And about the sampling time, the datasheet of this sensor shows this time chart:

Doesn't that mean the sampling time is 20ms ?

And the LIDAR looks fancy and expensive but:
Accuracy: +/- 0.025m

Sorry, 20ms; so 50 readings per second at best. For many purposes that's more than enough. For some it's definitely not (I've done the math as to how far dogs can travel in 20ms :P). Again, you're likely best to just read it 200 times per second, and filter out garbage.

LIDAR's an option, yes. And much more accurate than you need. Again, sampling rate might matter, but you haven't told us your application.

Also, there's a ton of ultrasonic rangefinders on the market which could work.

So by using Vref=3.3 it would be more accurate, right ? Not sure yet how to calculate a distance from this but I'll figure that out later.

First convert the AD measurement to voltage and then to distance

float voltage = analogRead(A0) * 3.3V/1023;

distance = func(voltage);

what you also can do is to make a multimap lookup which is quite fast for non linear interpolation.

Would it be possible to detect voltage so precisely on an arduino ?

A more important question is does the Sharp generate voltages that precisely? There is no mention of how precise it is in the spec.
However, the datasheet does have some interesting numbers. Under "Electro-optical Characteristics" the voltage generated (by a Kodak white target) at 30cm can vary from a minimum of 0.25V to a maximum of 0.55V. The difference between the voltages generated at 30cm and at 4cm can vary from 1.95V to 2.55V. If you really do want an accuracy of 0.5mm you are going to have to spend a lot of time calibrating the specific ones that you buy because without measuring them, you won't know where they lie within those specified limits.

Pete

dirtyharry2:
...
LIDAR's an option, yes. And much more accurate than you need. Again, sampling rate might matter, but you haven't told us your application.

Also, there's a ton of ultrasonic rangefinders on the market which could work.

Thanks, but what you say about accuracy puzzles me a bit :slight_smile:
I would like to achieve : 0.5 millimeters or better.
The LIDAR does 2.5 centimeters so 25 millimeters.
That's a factor 50x difference.

About the application: I would like to use the measured distance as feedback for a positioning system.

robtillaart:
First convert the AD measurement to voltage and then to distance

float voltage = analogRead(A0) * 3.3V/1023;
...

what you also can do is to make a multimap lookup which is quite fast for non linear interpolation.
...

Nice work and thanks for the tip, this will be very useful I think

el_supremo:
A more important question is does the Sharp generate voltages that precisely? There is no mention of how precise it is in the spec.
...

Yes I am a little worried about that too. Above the graph in the datasheet: "Example of output distance characteristics"
Calibrating one sensor is ok for now. Calibrating a batch.. I'll start a new topic when i get to that point :slight_smile:

Two additional questions:

  • I can put a reflector sticker or paint onto the object, would that increase the accuracy ?

  • It is suggested to use 3.3V for Vref, is that because 3.3V is a common voltage ? Or could I use 3V ?
    3.3/1023 = 0.003225
    3.0/1023 = 0.002932

Thanks for all your input :slight_smile:

  • It is suggested to use 3.3V for Vref, is that because 3.3V is a common voltage ? Or could I use 3V ?
    3.3/1023 = 0.003225
    3.0/1023 = 0.002932

You could use any voltage between 0 and 5V however the Arduino can supply 3.3V directly from its board.
Note that the peak of the graph is just above 3.0V. So 3.3V is a bit on the safe side when you going to calibrate your sensor.

You could use any voltage between 0 and 5V

Not quite, anything between 1.1V to 5V

robtillaart:
...the Arduino can supply 3.3V directly from its board.
Note that the peak of the graph is just above 3.0V. So 3.3V is a bit on the safe side when you going to calibrate your sensor.

Ok thanks, so if the arduino provides a clean 3.3000V as Vref, without additional components I'll go with that :slight_smile:

* mrExplore Currently trying to find the 3.3V pin on his Arduino Micro - 5V 16MHz - (ATmega32u4)
Or would I need an Arduino Pro Micro 3.3V 8MHz ?

[edit]
Whut ? the "/me" tag actually works on this forum :slight_smile:
[/edit]

It's there on the Micro, right next to the AREF pin, in fact....

Is this the 3.3V ref pin ?

No it is the 3V3 pin, you have to connect it to the Vref pin and then set the board to use the external reframe with a software command. If you try and simply read the analogue input with it attached and without issuing the command you will damage your board.

I can put a reflector sticker or paint onto the object, would that increase the accuracy ?

I don't think it affects the accuracy but it means that you would have to calibrate the sensors using the same colour as is on the objects you are detecting. Note that the graph on page 4 shows a difference between the voltage generated by Kodak white and Kodak gray at the same distance above 16cm. You mention in your first post a distance of around 6cm so it may not be an issue, but worth a quick check beforehand to save grief afterwards.

Pete

mrExplore:
Ok thanks, so if the arduino provides a clean 3.3000V as Vref, without additional components I'll go with that :slight_smile:

You won't get 3.3000V accuracy from an arduino regulator. More like 3.3V +/- 33mV @ 25C. (And note the 25C - it will also vary with temperature.) From the datasheet: "On chip trimming allows the regulator to reach a very tight output voltage tolerance, within ± 1% at 25°C."
The actual datasheet:-

Another consideration is that even if the sensor has the accuracy that you want, it's very likely to vary with temperature too. Also, ambient light levels will make some difference.
Your 0.5mm accuracy at 60mm, (0.8%), goes right out the window when you take these things into consideration. You'd possibly need to control both ambient light and temperature to have much chance of the results that you're after.
Of course, I could be completely wrong, but these are the points that immediately came to mind as I read through the thread.

@Steve - do not confuse accuracy with stability. Any inaccuracy will be calibrated out.

This sensor gives you the accuracy that is needed but not the long range you require :-
ldc1000nhrt/converter-inductance-digital
But maybe you could use two or more to increase the range. For example one on the other side measuring the distance from the stop.

Here is a link to an eval board if you don't fancy soldering the chip.
ldc1000-inductive-sensing-eval board

Grumpy_Mike:
@Steve - do not confuse accuracy with stability. Any inaccuracy will be calibrated out.

Yeah, I thought about that shortly after I posted, (the +-1%, that is). In this respect I was mostly addressing MrExplore's statement about 3.3000V.

The variation with temperature could also be cancelled, with care. I was thinking about just the sensor that was linked and an Arduino without additional temperature compensation circuitry.
(I didn't spend much time pondering and just posted my immediate impressions.)

An inductive sensor would be a much better way to go if, as you say, the required range was shorter.
Pity it needs to be non-contact. Digital calipers are cheap. :smiley:

Grumpy_Mike:
No it is the 3V3 pin, you have to connect it to the Vref pin and then set the board to use the external reframe with a software command. If you try and simply read the analogue input with it attached and without issuing the command you will damage your board.

Got that figured out now. Connected the pins marked "3V" and "RF" and used :
analogReference(EXTERNAL); // use AREF for reference voltage

And about the 3.3000V, should have just typed 3.3V to avoid confusion, sowwy.

But I thought, hey, lets do a test on the 3.3V pin. First curious about the voltage, then curious about whether a component connected to the arduino would have any influence.

So here is what I did on my arduino mega 2560:

  • connected the 3.3v pin directly to A0
  • connected a led
  • turn on the led, take X readings, calculate and display average
  • turn off the led, take X readings, calculate and display average

The code I used is this:

//--------------------------------------------------
//  This code can be used to test the 3.3V Vref
//  
//  Tested here is the influence of a connected led that is switched on and off
//  - The led is turned ON, a number of readings (intSamples) is done
//  - The avarage of the readings is calculated and displayed 
//
//  - The led is turned OFF, a number of readings (intSamples) is done
//  - The avarage of the readings is calculated and displayed 
//
//  - Format of one line is semicolon seperated: LED ON;3.3366;LED OFF;3.3255
//  - Copy the data into a text file, import that text file into excel and calculate the grand total :)


//Number of samples
int intSamples = 500;

//Float that is used to calculate average
float fltTotal;


void setup() {
  Serial.begin(9600);
  //Pin number to which the led is connected
  pinMode(52, OUTPUT);
  digitalWrite(52, LOW);
}

void loop() {

  //turn on the led
  digitalWrite(52, HIGH);
  Serial.print("LED ON;");

  //set the total of all readings to 0
  fltTotal = 0;

  for (int i = 0; i < intSamples; i++) {
    // read the input on analog pin 0:
    int sensorValue = analogRead(A0);
    // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    float voltage = sensorValue * (5.0 / 1024.0);
    //add the sampled voltage to the total of all readings
    fltTotal = fltTotal + voltage;
  }

  //After reading and adding samples calculate average and print with 4 decimals
  Serial.print(fltTotal / intSamples, 4);

  digitalWrite(52, LOW);
  Serial.print(";LED OFF;");
  
  fltTotal = 0;

  for (int i = 0; i < intSamples; i++) {
    int sensorValue = analogRead(A0);
    float voltage = sensorValue * (5.0 / 1024.0);
    fltTotal = fltTotal + voltage;
  }

  Serial.println(fltTotal / intSamples, 4);

}

After running the code for a few seconds and calculating the average of 80x500 samples the result is:
Average voltage on 3.3v pin

  • with led ON : 3.3372
  • with led OFF: 3.3264

So I guess it might be better to get an external 3.3V reference. For anyone interested, I found a nice pdf with info on voltage reference, attached below.

I hope to get the sensor in the mail tomorrow. First I'll need a program running and then I'll do some testing on behaviour, temparature and ambient light.

Voltage Reference Info.pdf (276 KB)