Offline
Jr. Member
Karma: 1
Posts: 86
|
 |
« on: January 23, 2012, 01:03:18 am » |
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
Tesla Member
Karma: 71
Posts: 6827
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #1 on: January 23, 2012, 08:14:38 am » |
You have an array of (in your case) 10 values and use the sensor value to index into that array. 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. 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
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 86
|
 |
« Reply #2 on: January 23, 2012, 09:49:29 am » |
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
Faraday Member
Karma: 27
Posts: 5081
Where's the beer?
|
 |
« Reply #3 on: January 23, 2012, 10:55:47 am » |
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
|
|
|
|
|
Manchester (England England)
Offline
Brattain Member
Karma: 277
Posts: 25506
Solder is electric glue
|
 |
« Reply #4 on: January 23, 2012, 10:56:26 am » |
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 value = table[6]; Will return the sixth value in your array. Or if your reading was in a variable called "reading" then 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
Jr. Member
Karma: 1
Posts: 86
|
 |
« Reply #5 on: January 23, 2012, 10:15:57 pm » |
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
Faraday Member
Karma: 31
Posts: 2930
I only know some basic electricity....
|
 |
« Reply #6 on: January 23, 2012, 10:41:25 pm » |
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 at Learning in the Main Site and at the Playground
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 86
|
 |
« Reply #7 on: January 23, 2012, 11:55:51 pm » |
Thank you Now I understand the function. Do you have a code example with explanation?
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6388
-
|
 |
« Reply #8 on: January 24, 2012, 01:41:33 pm » |
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
|
|
|
|
|
Pittsburgh, PA, USA
Offline
Faraday Member
Karma: 31
Posts: 2930
I only know some basic electricity....
|
 |
« Reply #9 on: January 24, 2012, 03:06:15 pm » |
How does that work out for a non-linear table of say, sine values 0 - pi/2?
|
|
|
|
|
Logged
|
Examples can be found at Learning in the Main Site and at the Playground
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6388
-
|
 |
« Reply #10 on: January 24, 2012, 04:44:01 pm » |
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
|
|
|
|
|
Pittsburgh, PA, USA
Offline
Faraday Member
Karma: 31
Posts: 2930
I only know some basic electricity....
|
 |
« Reply #11 on: January 24, 2012, 07:22:13 pm » |
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 at Learning in the Main Site and at the Playground
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6388
-
|
 |
« Reply #12 on: January 24, 2012, 08:19:00 pm » |
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
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 86
|
 |
« Reply #13 on: January 25, 2012, 12:10:13 am » |
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
Brattain Member
Karma: 277
Posts: 25506
Solder is electric glue
|
 |
« Reply #14 on: January 25, 2012, 04:57:07 am » |
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
|
|
|
|
|
|