# Can't get consistent readings from Sharp IR range detector

I'm in the very early stages of trying to build a robot that wanders around and builds up a map of its environment. I'm using an Arduino and I currently have a Sharp 2Y0A21 IR range detector sat on top of a servo so it can take a 180 degree sweep in 10 degree increments.

The trouble is that the voltage readings back from the Sharp IR sensor aren't consistent. If I write an app that simple sends the value it reads from the sensor through the serial port and display it on my laptop, sitting the sensor pointing at an object, the values bounce around.

Watching the values, I can see that it tends to report one value more than the rest, so I wrote a SharpReader class that takes 20 samples and then returns the Mode of these values. This now means I get more consistent values, but not as good as I would like.

I have some code that performs the 180 degree scan and sends the angle and distance down the serial. I then have a python script that receives these values and draws what it sees on screen, ignoring any values at either end of the sensors range. So putting it in front of a box, it should draw a straight line on screen, but it doesn't - the line is crooked and not consistently crooked, which confirms to me that it's the readings that are off, not my code.

I have read in the datasheet that it is advisable to put a capacitor (can't remember the value offhand) in between the GND and PWR lines on the Sharp IR - I tried forcing the legs of the capacitor into the JST connector of the Sharp IR, but it made no difference. I'll try soldering it to the sensor and see if that makes any difference.

Can anyone recommend anything else to try, or am I just expecting too much from the Sharp IR?

I'm also considering buying a second servo and Sharp IR and running two at the same time like a pair of eyes, then trying to take an average of the two values to see if that increases the accuracy.

BTW, I'm a newbie to electronics, my background is in programming.

• I did something similar with photo diodes, and you are on the right track I think. you may also want to check out LMR (letsmakerobots.com) they have lots of good info about your sharp IR. – jsolarski Jan 11 '11 at 11:20
• Exact sensor model please + link to datasheet. – BarsMonster Jan 11 '11 at 12:07
• @Bars - Most all of the Sharp IR sensors have nearly the same datasheets, just different numbers throughout. The lessons learned should be the same. – Kevin Vermeer Jan 11 '11 at 15:31
• @Rick_2047 I've considered blogging about my experiences with the Sharp IR - I might do a post here once I get to the bottom of it. @BarsMonster I'm using the 2Y0A21. – littlecharva Jan 11 '11 at 19:15
• @littlecharva I am not just interested in sharp IR, I am interested in the project as a whole. As I said this is exactly what I had written in my wish list of projects. – Rick_2047 Jan 11 '11 at 20:13

The sensor isn't perfect, if you aim even a really, really good sensor (Better than the, um, 'classic' Sharp IR sensors) at the same spot on the wall and take a few readings, there will be some variation. If you discard some number of least significant bits, it's possible to get the same reading every time, but your readings will be more granular. You should probably keep the maximum precision, and then try to fix errors in software (i.e., change your data so that an almost straight line really is straight).

What sensor are you using, and what range of measurement do you expect? The output of the sensor is very much nonlinear. This graph (from the datasheet) compares the output voltage on a linear scale with the distance:

You'll notice that it looks a lot like the graph of y=1/x, i.e volts=k(1/distance). This can be used to get a decent first approximation, but division on an Arduino is expensive. You'll have better luck calibrating the sensor and storing the voltage/distance pairs in a look-up table (in program memory, of course). This one comes calibrated from the factory such that a measurement at precisely 24cm measures to 24cm +/- 3cm. Unfortunately, they don't give you a way of knowing what the voltage at 24cm should be except by squinting at this graph.

The sensor will have higher precision at certain ranges. Imagine that there is a random variation of, say, +/- 250mV in your readings (Gaussian if you like, but random is easier). It's hopefully a lot smaller than that, but it makes it easy to visualize. The variation means that your readings with this sensor at, say, 50cm or 70cm will vary over 20 or 30cm, but measurements at 15cm should be within a few cm. This sensor is rated for 10-80cm, but you'll get more accurate readings if you only trust it for 10-25cm or so. If you're controlling the robot, you should be able to move to these distances and get the best readings.

The sensor draws current in large bursts and is probably mounted on a fairly long cable. A capacitor will help stabilize the readings. Don't jam it into the JST; solder it to the PCB on the back. It's drawing a lot of current and it's pretty slow, so small capacitances traditionally used for decoupling (0.1uF) probably won't work. I'd use a 10uF 1206 or 1210 ceramic SMD cap in parallel with a 100uF electrolytic. If you find that high frequency noise is still present, add a 0.1uF 1206 on top of the 10uF. Here's a picture of the locations for soldering (original image from Sparkfun):

You could also try adding a small capacitance on the Vo line to smooth the output. You should experiment to see whether or not that helps. I'd keep it below 100pF, starting at around 10pF. This will create a moving average of the readings in hardware. More circuitry (a series resistor) would enhance the effect, post a comment or another question if you want to build a more complex low-pass filter system for this purpose. Note: The Sharp sensor may not handle driving into a large capacitance well, and might balk or break if asked to change the voltage quickly. It's also possible that it's a single-sided output, and might require a resistor to ground to discharge the capacitor if you add more capacitance than is currently present in the parasitics.

Twisting the cables together will help reduce noise coupled on from external sources like 60Hz mains. Keeping them short will also help mitigate noise.

• It's the 2Y0A21 that I'm using, and I built a lookup table rather than use a function. I'm also ignoring values towards the far end of the range. I'm an electronics newb, so don't have a lot of capacitors knocking about; I bought a mixed bag from Maplin, but most of the ceramic ones don't have a value printed on, just some random numbers. I've got some 10uF electrolytic (I think? They look like tiny cans of pop?) caps, so I'll try soldering one of those on, and if it makes no difference I'll try to source some of the other ones you mention. I'll also try twisting the cables together. Thanks! – littlecharva Jan 11 '11 at 19:27
• The ceramic caps in a mixed bag will probably be less than 1uF. Electrolytics and other through-holes aren't as good at filtering high frequency signals as ceramic surface-mount caps, the inductance of the leads starts to make a difference at high frequencies. – Kevin Vermeer Jan 11 '11 at 20:23
• Caps in 600 chars: SMD/SMT/SMC are acronyms for Surface Mount Device/Technology/Component. 1206 is a package ID, just like DIP-8 or TO-220. 1206 is the size of the component-a 1206 cap is approximately 0.12" by 0.06". The first character of the dielectric is the minimum temperature (X<Y<Z; X is best) is the maximum temperature (2<3<...<8, 8 is best), and the last number is the temperature dependence (V is -20/+80, R is +/-15%, there are others). X7R and X5R are good. Derate the voltage by 50-100%, so use a 10V cap on 5V. – Kevin Vermeer Jan 17 '11 at 15:46
• To find it on Farnell, select 'Capacitance>10uF' and 'Capacitor Case Style>1206' to narrow it down to 96 possibilities. Then, select the voltage rating to be 50% to 100% greater than your expected voltage, so pick the 10V rating, and choose X5R and X7R dielectrics for these 15 possibilities. Pick the cheapest in stock one; looks like this £0.099 one: 1650933 is the best right now. – Kevin Vermeer Jan 17 '11 at 15:53
• Note: it looks like they're also available in 0805 for similar (or even lower!) prices, last I checked 10uF at 10V was hard to get in 0805. Guess I'm a little out of date. – Kevin Vermeer Jan 17 '11 at 15:55

Good things to do at this stage:

• Determine where the noise is coming from: this can be done by using the FFT function on a DSO while measuring the signal from another IR sensor (IR LED would work), or using a PC to transform the collected data. There are many sources of IR in our households, often modulated near 38kHz. A analog input antialiasing filter set to less than half of your sample rate (max ~7kHz) may be all that's required, though the sensor may already have one. Note that the micros in the Arduino series can't sample at more than about 15kSps, but 38kHz signals can still sneak through by aliasing, so digital filters wouldn't be at 38kHz but something under 15kHz.

• Ensure you're testing within the device's range (max & min).

The 0A700 has a range of 5.5 meters.

• Calibrate and linearize the sensor. Identical models will read differently, and their output is non-linear. This page describes one way to linearize the data, ending up with something like R = (6787 / (V - 3)) - 4. Another method is to use an 8 to 10-bit lookup table. Linearization won't help with the noise issue, but gives a better idea as to its effect and how much mitigation is actually necessary.

• Eat Oreos, torquing them in half and licking out the white stuff first. Makes for much more successful debugging sessions.

• Good catch on the Oreos, I would have missed that. Basically, with the Sharp sensors, you get what you pay for. I have found that oversampling then averaging is the best approach. If you are trying to generate a map, then you may want to step up to some higher-quality sensors as your budget allows. – mjcarroll Jan 11 '11 at 17:16
• Not sure what you mean about FFT and DSO, I assume something to do with oscilloscopes? I'm definitely within my sensors range, and I opted for the lookup table over the linearization, as my poor maths let me down with the linearize function. I've just ordered a pack of Oreos, so I'll let you know how I get on! – littlecharva Jan 11 '11 at 19:19
• @mjcarroll What other sensors would you recommend, I haven't come across any other than the Sharps. – littlecharva Jan 11 '11 at 19:20
• @littlecharva Aside from the advice given in reemrevnivek's answer, I would say try some of the ultrasonic rangefinders as well. You may find that they work better, depending on the application. If you can afford it, a laser range finder is always a good option (1.1k cost, though). There has also been a lot of cool research into the Microsoft Kinect, but that would exclude a pure-Arduino solution. – mjcarroll Jan 12 '11 at 4:09
• I'd read that the ultrasonics weren't as accurate as the Sharps, which is why I avoided them at first. Laser range finder would be awesome, but out of my budget - although I have read some articles suggesting there might be a <£100 due on the market soon, so I'm keeping me eyes open. – littlecharva Jan 12 '11 at 11:13

These sensors really do need a decent decoupling cap across the supply, and a clean 5V supply, i.e. not the same supply as a servo.

Check your input voltage supply to the sensor. I was powering the sensor from my Mega 2560 (5V) and could not get a clean signal. I am still using the 5V from the Mega 2560 but instead ran it through a simple (\$1.99) voltage regulator from radio shack (quick run to a local store). This greatly cleaned the signal up. To clean it up further I ran the return signal through a low pass filter. I chose the frequency at 1/10 and sized the resistor and cap accordingly.

• Can you give us the part number and the output voltage of the regulator you've added to your circuit? – Ricardo Jan 3 '15 at 16:32