MX003 - Look-up tables

Forum to discuss articles which have been published in Matrix Multimedia's article zone. If you have any comments or questions regarding the articles please post them here.

Moderators: Benj, Mods

Post Reply

Please rate this article out of 5: (1 being the worst and 5 being the best)

1
1
7%
2
2
14%
3
0
No votes
4
1
7%
5
10
71%
 
Total votes: 14

Sean
Valued Contributor
Valued Contributor
Posts: 548
Joined: Tue Jun 26, 2007 11:23 am
Has thanked: 6 times
Been thanked: 44 times
Contact:

MX003 - Look-up tables

Post by Sean »

Article: http://www.matrixmultimedia.com/article.php?a=50

If you have any questions for the author or comments on the article, please post them below.

echase
Posts: 429
Joined: Mon Jun 11, 2007 11:55 am
Has thanked: 49 times
Contact:

Re: Look-up tables

Post by echase »

Having stored the values and recalled them, what the simplest way to use them?

For instance I have a table of values that convert a measured external voltage into a displayed temperature reading. Say its
1.0V = 9C
1.1V =10C
1.2V = 12C
1.3V = 15C
1.4V = 19C

It’s non linear like your sine wave.

So if I measure 1.14V it’s closest to 10C in the table.

So do I need a set of Flowcode IF statements that say:-

IF V>=1.0 T=9 ELSE exit to end
IF V>=1.1 T=10 ELSE exit to end
IF V>=1.2 T=12 ELSE exit to end
etc

When it exits the loops on the second line we display current T of 10C.

Or something like:-

Start at Count =10 where 10 is 1volt
IF Count >= FCV_DATA_VAL = table_name [FCV_INDEX
Count = Count +1
IF Count >= FCV_DATA_VAL = table_name [FCV_INDEX
Etc

That syntax is not correct.

I’d rather do it in Flowcode than C.

Next question is how to do interpolation, as my 1.14C is really closer to 11C and not 10C and I want the output to nearest 1C? One way I guess is to write the intermediate values into the table so it’s got a 1C resolution. The easiest way to do that is to write the table backwards so its:-

9C = 1.0V
10C = 1.1V
11C= 1.15V
12C = 1.2V
Etc

But not sure how to do the IF loops with a backwards table as the ‘count’ of voltage is not linear

echase
Posts: 429
Joined: Mon Jun 11, 2007 11:55 am
Has thanked: 49 times
Contact:

Re: Look-up tables

Post by echase »

Put it another way. Suppose you are measuring a 2Vpp sine wave and want to know the phase angle at any given snapshot to one degree accuracy.

So if you measure 0.5V you know the angle is 30 (or 150) degrees. But if you measure 0.540V the angle is 32.69, rounded to 33 if you want it to 1 degree accuracy. Using the posted lookup table you have to interpolate with software 0.540V*100 between the listed 53 and 54 to derive the 33 degrees. Such interpolation seems difficult tome. I suspect also that the rounding done to the sine (volts) column would make the answer inaccurate on occasions.

Is it simpler to reverse the table so it’s got the sine (volts) in column A listed from 0-100 whereas B contains the angle and C the rounded angle? Not sure whether this rounding makes the answer any more accurate than above method.

Sean
Valued Contributor
Valued Contributor
Posts: 548
Joined: Tue Jun 26, 2007 11:23 am
Has thanked: 6 times
Been thanked: 44 times
Contact:

Re: Look-up tables

Post by Sean »

The example program needed to generate voltages representing constant angular increments. In that case the angle could be used as the index and the values for the DAC could be stored at the corresponding locations. To reverse the process you could read an oscillating voltage using an ADC channel and use the result as the index to an array holding the corresponding, pre-calculated, angle value.
Your applications add another level of complication by requiring the non-linear variable to be repesented in a linear way. Probably the best way to do this would be to use a function of the angle as the array index (equal increments for display purposes), and the corresponding DAC values as the contents. After reading the analogue voltage with an ADC channel, the program would then need to scan the array contents for a matching value, or the first value greater. The current index would then represent the display value. A microcontroller would be able to scan a small array quite quickly. If the array is always scanned in one direction (bottom to top) the values stored in the array can include any rounding offsets. Another array, or simple calculation based on the ADC value, can be used to start the scan at an estimated index, instead of always starting at zero, reducing the number of tests required to find a match.

echase
Posts: 429
Joined: Mon Jun 11, 2007 11:55 am
Has thanked: 49 times
Contact:

Re: Look-up tables

Post by echase »

Not quite sure what you meant by “Data can be accessed in a way that will allow the generation of all the sine, cosine and tangent values, using only simple calculations” but remember that cos x = sine (90 – x) and tan x = sine x/cos x so it’s possible to calculate cos and tan off the one quadrant of sine data.

Sean
Valued Contributor
Valued Contributor
Posts: 548
Joined: Tue Jun 26, 2007 11:23 am
Has thanked: 6 times
Been thanked: 44 times
Contact:

Re: Look-up tables

Post by Sean »

Thanks. That was what I should have written!

An array that contains the first quadrant of sine data when read with the index being incremented from 0 to 90 (index = angle) will represent the first quadrant of a cosine wave when read with the index being decremented from 90 to 0 (index = 90 - angle).

The second quadrant of the sine wave (90 to 180 degrees) requires the array index to be decremented and offset (index = 180 - angle). The cosine wave requires the index to be incremented and offset, and the result to be treated as negative (index = angle - 90: value = -data).

The third quadrant (180 to 270 degrees) has the sinewave index incrementing and offset, and the result negative (index = angle - 180: value = -data). The cosine wave has a decrementing, offset index, and a negative value (index = 270 - angle: value = -data).

Finally, the fourth quadrant (270 to 360 degrees) has the sine wave index decrementing and offset, and the result negative (index = 360 - angle: value = -data). The cosine wave uses an incrementing, offset index, and a positive value (index = angle - 270: value = data).

With the sine and cosine values, the tangent value can be calculated: tan(angle) =sin(angle)/cosine(angle)

Boza
Posts: 2
Joined: Sun Mar 01, 2009 9:40 am
Contact:

Re: Look-up tables

Post by Boza »

Does anbody know, what is wrong in this example?
I tryed to modify example with sinus and display the value at the LCD.
But the result is stil 0. I expexted the values from the table.
Procesor is ATMEGA8.

Image
http://img.54.cz/images/998951-gtable.GIF

Sean
Valued Contributor
Valued Contributor
Posts: 548
Joined: Tue Jun 26, 2007 11:23 am
Has thanked: 6 times
Been thanked: 44 times
Contact:

Re: Look-up tables

Post by Sean »

Hello Boza.
Unfortunately the program memory read operation can not be simulated by Flowcode. It functions correctly when downloaded to the target device, but the use of C code prevents the Flowcode simulator from recognising the data.

If you need access to a table of data for simulation, you could declare an equivalent Flowcode string variable (accessible as an array) and populate it with identical data. Temporarily change the read operation to target the Flowcode string (using the original index calculations) while simulating. Convert back to the program memory option, removing the Flowcode string and its setup values, before downloading to the target.

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times
Contact:

Re: MX003 - Look-up tables

Post by Mantas »

Hello Sean,

Is it allowed to change the variable type from char to double in case you want to store big numbers in the LUT? Egzample:

const char L0i_Ai[]={175347046,3341656,34894,3497,3418,3136,2676,2343,1324,1273,1199,990,902,857,780,753,505,492,357,317,284,271,243,206,205,202,156,132,126,115,103,102,102,99,98,86,85,85,80,79,75,74,74,70,62,61,57,56,56,52,52,51,49,41,41,39,37,37,36,36,33,30,30,25,};
This is as it is writen in the article, but I get an error when I am trying to compile:

SPA_Term_LUT.c:55: warning: large integer implicitly truncated to unsigned type
SPA_Term_LUT.c:57: warning: overflow in implicit constant conversion

But if I change the type of variable to double:

const double L0i_Ai[]={175347046,3341656,34894,3497,3418,3136,2676,2343,1324,1273,1199,990,902,857,780,753,505,492,357,317,284,271,243,206,205,202,156,132,126,115,103,102,102,99,98,86,85,85,80,79,75,74,74,70,62,61,57,56,56,52,52,51,49,41,41,39,37,37,36,36,33,30,30,25,};

then it compiles ok. I am right now away from my ARM developmet board, so I can not test it, so the question is it allowed to make such a convertions in command format?
Science is my true religion.

Sean
Valued Contributor
Valued Contributor
Posts: 548
Joined: Tue Jun 26, 2007 11:23 am
Has thanked: 6 times
Been thanked: 44 times
Contact:

Re: MX003 - Look-up tables

Post by Sean »

Hello,

Yes, it is possible to change the array data type to suit the range of the data values being stored. The Flowcode variables used to handle the data (including the table reader macro return variable) will also need to be changed to match the selected data type.

The C data types that are directly compatible with Flowcode depend on the version of Flowcode being used. In the case of Flowcode for ARM, a 'Float' variable is compatible with a C 'double' variable.

The use of floating point variables introduces the possibility of rounding errors, but some of your example values are too large for the 'int' option.

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times
Contact:

Re: MX003 - Look-up tables

Post by Mantas »

Thank you Sean for such a quick reply. Will make the changes in Retval data type.
Science is my true religion.

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times
Contact:

Re: MX003 - Look-up tables

Post by Mantas »

One more question Sean,

If I have several different LUT's and I would like to get data from one of those LUT's but using one macro. For egzample:

const double L0i_Ai[]={175347046,3341656,34894,3497,3418,3136,2676,2343,1324,1273,1199,990,902,857,780,753,505,492,357,317,284,271,243,206,205,202,156,132,126,115,103,102,102,99,98,86,85,85,80,79,75,74,74,70,62,61,57,56,56,52,52,51,49,41,41,39,37,37,36,36,33,30,30,25};
const double L0i_Bi[]={0,4.6692568,4.6261,2.7441,2.8289,3.6277,4.4181,6.1352,0.7425,2.0371,1.1096,5.233,2.045,3.508,1.179,2.533,4.583,4.205,2.92,5.849,1.899,0.315,0.345,4.806,1.869,2.458,0.833,3.411,1.083,0.645,0.636,0.976,4.267,6.21,0.68,5.98,1.3,3.67,1.81,3.04,1.76,3.5,4.68,0.83,3.98,1.82,2.78,4.39,3.47,0.19,1.33,0.28,0.49,5.37,2.4,6.17,6.04,2.57,1.71,1.78,0.59,0.44,2.74,3.16};
const double L0i_Ci[]={0,6283.07585,12566.1517,5753.3849,3.5231,77713.7715,7860.4194,3930.2097,11506.7698,529.691,1577.3435,5884.927,26.298,398.149,5223.694,5507.553,18849.228,775.523,0.067,11790.629,796.298,10977.079,5486.778,2544.314,5573.143,6069.777,213.299,2942.463,20.775,0.98,4694.003,15720.839,7.114,2146.17,155.42,161000.69,6275.96,71430.7,17260.15,12036.46,5088.63,3154.69,801.82,9437.76,8827.39,7084.9,6286.6,14143.5,6279.55,12139.55,1748.02,5856.48,1194.45,8429.24,19651.05,10447.39,10213.29,1059.38,2352.87,6812.77,17789.85,83996.85,1349.87,4690.48};

As you can see, the table name differs, first is for Ai parameter, second for Bi, and third for Ci. Lets say I have a formula L0i=Ai*cos(Bi+Ci*jme). The is the index from 1 to 64 and I need to make a sum of all those L01:L064 (L0=L01+L02+L03+...+L064). How can I modify the call command to retrieve certain parameter for the formula using C block in the macro?

I was thinking about something like this:
Call macro L0i, insert as macro variable, then
C block inside macro:
FCV_AI = L0i_Ai [FCV_I];
FCV_BI = L0i_Bi [FCV_I];
FCV_CI = L0i_Ai [FCV_I];

This compiles ok when I need to calculate L0i terms, but then I have other terms to calculate, which also have their LUT's const double L1i_Ai[]={...}, L1i_Bi[]={...}, L1i_Bi[]={...}. And I dont want to create more macros for each L0, L1, L2, L3, L4, L5, B0, B1...and so on...
How to make the table name a variable, so I could call on macro and insert the necesary table name and index number to get the required parameter?
See the attached flowcode file.
Attachments
SPA_Term_LUT.fcf_arm
(13.14 KiB) Downloaded 907 times
Science is my true religion.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: MX003 - Look-up tables

Post by Benj »

Hello,

You can normally pass the address of the resource using the ampersand syntax.

function (&L0i_Ai, idx);

And here is the function.

function (char* data, char index)
{
data[index] = ...;
or
... = data[index];
}

I don't think you can use addresses or pointers directly in Flowcode v5 at the moment but we have plans for this.

Sean
Valued Contributor
Valued Contributor
Posts: 548
Joined: Tue Jun 26, 2007 11:23 am
Has thanked: 6 times
Been thanked: 44 times
Contact:

Re: MX003 - Look-up tables

Post by Sean »

Another possibility, if all the individual arrays are the same size and type, might be the use of a single, 2-dimensional array (I am not currently able to test this):

const double L[x][y] = {
{1,2,3,4,.,.,.,.,.},
{.,.,.,.,.,.,.,.,.,.,.,.,.,.},
:
:
:
{.,.,.,.,.,.,.,.,.,.,.,.,.,.}
};

where x is the number of data sets and y is the length of each data set.

The reader macro would need to be modified to accept two index variables (Index1 and Index2). The array could then be accessed with the following C code in the macro.

FCR_RETVAL = LUT[FCL_INDEX_1] [FCL_INDEX_2];

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times
Contact:

Re: MX003 - Look-up tables

Post by Mantas »

I was thinking about 2dimentional arrays, but considering my poor knowladge of C :oops: , I got around this problem like this: see attached file. Its not very elegant, but it should work :mrgreen:
Attachments
SPA_Term_LUT.fcf_arm
(23.97 KiB) Downloaded 870 times
Science is my true religion.

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times
Contact:

Re: MX003 - Look-up tables

Post by Mantas »

Sean wrote:Another possibility, if all the individual arrays are the same size and type, might be the use of a single, 2-dimensional array (I am not currently able to test this):

const double L[x][y] = {
{1,2,3,4,.,.,.,.,.},
{.,.,.,.,.,.,.,.,.,.,.,.,.,.},
:
:
:
{.,.,.,.,.,.,.,.,.,.,.,.,.,.}
};

where x is the number of data sets and y is the length of each data set.

The reader macro would need to be modified to accept two index variables (Index1 and Index2). The array could then be accessed with the following C code in the macro.

FCR_RETVAL = LUT[FCL_INDEX_1] [FCL_INDEX_2];
So as I understand [FCL_INDEX_1] would be the row number, and [FCL_INDEX_2] would be the number of the parameter in thar array?

so to reach number "3" in your egzample i would need to call FCR_RETVAL = L[FCL_X] [FCL_Y], where x=1, y=3?
Science is my true religion.

Sean
Valued Contributor
Valued Contributor
Posts: 548
Joined: Tue Jun 26, 2007 11:23 am
Has thanked: 6 times
Been thanked: 44 times
Contact:

Re: MX003 - Look-up tables

Post by Sean »

Yes, for a 2-dimensional array the parameters can be considered to be:

Array[Row][Column]

Post Reply