Pages: [1] 2   Go Down
Author Topic: Non-linear interpolation table help needed  (Read 1213 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 2
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am a newbie and struggling to understand tables and the code to use them. I have about 10 sample analog values from 600 to 990 that represent different distances from the sensor. Problem is it is not linear.
Can someone give me a simple explanation of how a table works and the code to implement it?
I just want to write the distance out to the monitor.

I have looked at some recipes that implement tables but I am confused.

Thanks in advance
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8458
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You have an array of (in your case) 10 values and use the sensor value to index into that array.

Code:
int table [10] = {1,2,4,7,10,15,20,27,35,45}; // example non-linear values

sensor_linearized_val = table[sensor_val];

Actually that changes linear to non-linear but the principle is the same.

Quote
10 sample analog values from 600 to 990
Do you get the same 10 values or 10 ranges of values? That would be different.

______
Rob
« Last Edit: January 23, 2012, 08:19:09 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Full Member
***
Karma: 2
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry I was not clear. The 10 values are hust arbitrary measurements of anakog input A1 at a few different distances from the sensor. It is not linear in that a 1cm distance change does not produce a linear change in sensor output v. I tried to follow the recipe for "Measuring distance accurately" im the arduino cookbook but I am confused.
So the measured values are not equidistant but break up the log curve into smaller chunks. I want the code to substitute any read analog value into a real distance.
I am just unclear on how the actual table functions and how it determines a value to be returned.

I guess I could write 100 code lines tonsay if the value is >x but <y then distance = 1cm etc but it seems the table should do this much easier.
Logged

Phoenix, Arizona USA
Offline Offline
Faraday Member
**
Karma: 36
Posts: 5519
Where's the beer?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry I was not clear. The 10 values are hust arbitrary measurements of anakog input A1 at a few different distances from the sensor. It is not linear in that a 1cm distance change does not produce a linear change in sensor output v. I tried to follow the recipe for "Measuring distance accurately" im the arduino cookbook but I am confused.
So the measured values are not equidistant but break up the log curve into smaller chunks. I want the code to substitute any read analog value into a real distance.
I am just unclear on how the actual table functions and how it determines a value to be returned.

I guess I could write 100 code lines tonsay if the value is >x but <y then distance = 1cm etc but it seems the table should do this much easier.


You've been given the basics by Graynomad on converting a linear value (1-10) into a non-linear value from a table; you should be able to figure out the inverse. Just realize that this could take up a lot of memory (and you might have to do some interpolation to figure out "in-between" values or such).

What would take less memory than a table would be to figure out what your non-linear curve is (ie - graph it), then fit an equation to match it (as close as possible); unless the curve is really complex (and from a distance sensor, it shouldn't be), the equation should be fairly simple. Or, you could make your table smaller, and use interpolation along with curve fitting to potentially speed things up (while keeping the table size small).
Logged

I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 513
Posts: 31529
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I am just unclear on how the actual table functions and how it determines a value to be returned.
It functions by using an array to fetch values given to it in the form of an array index.
So if you the array table, as shown above and have a reading of 6 then
Code:
value = table[6];
Will return the sixth value in your array. Or if your reading was in a variable called "reading" then
Code:
value = table[reading];
Would give you the appropriate value in your array.

Note here you have to have one array element for every reading you are going to get, so for an analogue input you would require an array with 1024 values in it. This is too big most of the time so there are tricks to reduce this. However you just want a restricted range of reading from 600 to 990, that is just 390 elements in your array. So you take your reading and subtract 600 from it to get the array element to use.

Even that may be too big an array, in which case you break it up into ranges and do an linear interpolation between the readings.

 
Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That is exactly what I intend. I am breaking the curve into 10 ranges and need to interpolate the values. So if the value is example 800, the range above is 830 (10cm) and below is 790 (7.2cm), then the interpolation should return 8.5 cm ( just example).
This is the explanation given in the Arduino Cookbook forthe recipe "measuring distance more accurately".
But I am lost as to how it works.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4024
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you ever interpolated tabled values by hand before? Like a sine table?

Basically your table would have an entry (array element) for each unit of range, possibly 1 per foot or meter. and you would compare your analog input to each entry in turn until you found the first entry bigger than your input. If the first bigger than your input is the first entry (array[0]) then you're out of range as would be the case where your input is bigger than the last entry but in between you can interpolate.

Say your input reads 780 (call it R) and there are table values 740 (call it L) and 800 (call it H).

The percentage of the range between L and H that R falls on is ((100 x (R - L)) / (H - L)). If you want to get 3 places then multiply by 1000 to get 10ths of a percent, etc. Then you have distance corresponding to L plus percentage times 1 unit for your interpolated answer. Just take care about your units if you use integers or use floating-point since exactness isn't really any issue. With FP fastest processing shouldn't be either, it's your choice.

Logged

Examples can be found in your IDE.

Offline Offline
Full Member
***
Karma: 2
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you
Now I understand the function. Do you have a code example with explanation?
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11195
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would suggest a slightly different approach.

Use DIV and MOD operations to convert your input value into an array index, and a remainder.

Use the array index to look up two adjacent values in the array. Use the remainder to interpolate between these two values.

The result of the interpolation is your answer.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4024
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How does that work out for a non-linear table of say, sine values 0 - pi/2?
Logged

Examples can be found in your IDE.

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11195
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How does that work out for a non-linear table of say, sine values 0 - pi/2?


The problem is to calculate an output value which is related in a non-linear but monotonic way to the input value. In this case the input is the signal amplitude and the output is the corresponding range.

The two approaches we've described are similar and both work in the same situations, but in the scheme I'm proposing the interpolation points are equally space in the input domain, and in the other they aren't. Since they're equally spaced, the interpolation points can be calculated (by a simple div) rather than needing to be found by a search through the array. This also simplifies the interpolation since the distance between the two interpolation points is also known.

Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4024
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So for a sine table with values of 0.0 to 1.0 I might have 11 array elements where each holds the angle corresponding to sine = 0, .1, .2, ... 1.0 rather than array elements for angles with values = sine of those. More of an arcsine table.

Logged

Examples can be found in your IDE.

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11195
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So for a sine table with values of 0.0 to 1.0 I might have 11 array elements where each holds the angle corresponding to sine = 0, .1, .2, ... 1.0 rather than array elements for angles with values = sine of those. More of an arcsine table.

I haven't fully understood your example. Are you starting with an angle and trying to estimate its sine, or starting with a sine and trying to estimate the angle?
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Full Member
***
Karma: 2
Posts: 104
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you give a code example of the DIV MOD  method?
I am struggling to understand how to reference the correct range and how the MOD gets you closer to the correct value.
I guess my main battle is that my analog voltage increases as my distance decreases so its inversed as well as non linear.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 513
Posts: 31529
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Can you give a code example of the DIV MOD  method?
If you actually try and write it yourself you will learn a lot more. Programming is just doing stuff one step at a time.
If you get stuck post what you have and people will help, but don't do this helpless "can someone post an example" business all the time.
Logged

Pages: [1] 2   Go Up
Jump to: