calculating real position w/ linear potentiometer


I have a 170mm touch sensor that sends 0-5V into Arduino, giving me a range of 0-1023 from the ADC. I have a stack of 64 LEDs next to the sensor, ~170mm tall. I divide the 0-1023 value by 16 to determine which LED to turn on adjacent to the sensor. It sort of works except in the middle of the sensor...

It is more accurate at the ends, e.g. my finger on the bottom of the sensor lights the bottom LED, but as I move up towards the middle of the sensor the LED begins to lag behind. As I approach the top of the sensor it "catches up" and then is accurate again near the top.

So I think I need to add a curve into the calculation to compensate for this non-linear difference between the physical position on the sensor and the value of the LED to light up.

I'm sure there's some handy function to do this but my math isn't so great. Any help appreciated!

Its difficult to suggest a math function to correct the error without knowing the nature of the nonlinearity. A different approach for compensating for the nonlinearity is to use an array to look up which led to light

Declare an array of 64 values byte values[64]; The input from the touch sensor (divided by 16) will index into the array to get the value indicating which led to light.

You can calibrate the array using a couple of buttons, one to increase value and one to decrease. If you touch a spot that has the wrong led lit, hit the appropriate button until the correct LED is lit. Or you could simply hard code the values and tweek by trial and error

Typed this in rush because I have log off for tonight, I hope that all makes sense.

That is a good approach, actaully my firmware is full of all kinds of array processing to flip values and so on. I thought I was cheating. ;)

I guess I imagined there would be a formula that would let me plot a line against a curve to find the right ratio. For instance I can do it for the lower LEDs by multiplying the value times 1.2 of itself, but then it's off again close top the middle and goes too high towards the top. So it's like I need to multiply by a variable that starts out with the value 1.0, then 1.1, then 1.2, then 1.3, then 1.2 then 1.1 then 1.0 - or something like that.

I suppose I can stick those in an array, too... It just FEELS like there should be a more elegant way. Where's that calculus book...?

There is a almost certainly a curve that will correct the error, but you need to know what the error is for a range number of data points (how many points depends on the nature of the errors). You could plot the error values in something like excel, invert the sign of the error values and then use excel's curve fitting function to get a formula that you could implement. OF, if you post the raw error valueshere then perhaps someone could suggest the appropriate formula.

But I it's probably not worth the trouble if you have the RAM available to do the lookup. And no, its not cheating. Avoiding floating point math through the use of lookup tables has been a time honoured method if designing efficient embedded solutions.

Avoiding floating point math through the use of lookup tables has been a time honoured method of designing efficient embedded solutions.


It's funny, I keep finding this out as I proceed thru my project. Since I am self-taught, I assume there's a "right" way to do something that I just don't know about. As I bumble along, I just do whatever works. I love it when something I think of as "cheating" or a "shortcut" turns out to be the "right" way to do something. Cool.

Probably the easiest solution is too use some of the data logging examples to write out the value of the resistor when it’s in each of the locations that you want and then use an if then else if then construct like this:

if a<val1 then
led = 1;
else if a<val2 then
led = 2;
else if a<val3 then

This will use about the same amount of memory and it’s very easy to modify.