Function to find index in 2D array based on sensor values

Status
Not open for further replies.

frankzappa

Well-known member
Hello!

I need to write a program that can find the right indexes in a 2D array based off of sensor values and have no clue how to best solve this in an effecient way.

Basically I have two variables that I calculate from sensor values. They range from -1200 to 1200. I need the variables to represent two indexes in a 2D array. Every increment of 50 is one index so -1100, -1050, -1000, -950..... 950, 1000, 1050, 1100 need to represent indexes 0, 1, 2, 3.... 41, 42, 43, 44 for example. The array is 45x45 in size.

If the two variables are for instance: 903 and 323 I want the program to find the closest matching indexes so in this case the indexes that correspond to 900 and 300. I then need to read the value in that array location.

Here is a pictorial representation of the array with some random values inside that I want to read based on the sensor values.

https://www.dropbox.com/s/5n5mf2bkhb7sftj/sheet.jpg?dl=0

Any ideas how I might do this?

I'm thinking either I need to compare the sensor value with two index values for instance to find which one is bigger/smaller or just average the values within a range of 50 and then write another function to find the index that matches with that value.

Any suggestions?
 
Does this work? You might need to finetune it to your needs...

Code:
void setup()
{
    while(!Serial);

    for (int value = -1200; value <= 1200; value++)
    {
        unsigned index = map(value,-1200, 1200, 0, 44);
        Serial.printf("%d -> %u\n", value, index);
    }
}

void loop ()
{
}

here a cutout of the output
Code:
...
-4 -> 22
-3 -> 22
-2 -> 22
-1 -> 22
0 -> 22
1 -> 22
2 -> 22
3 -> 22
4 -> 22
5 -> 22
6 -> 22
7 -> 22
8 -> 22
9 -> 22
10 -> 22
11 -> 22
12 -> 22
13 -> 22
14 -> 22
15 -> 22
16 -> 22
17 -> 22
18 -> 22
19 -> 22
20 -> 22
21 -> 22
22 -> 22
23 -> 22
24 -> 22
25 -> 22
26 -> 22
27 -> 22
28 -> 23
29 -> 23
30 -> 23
31 -> 23
32 -> 23
33 -> 23
34 -> 23
35 -> 23
36 -> 23
...
 
If the two variables are for instance: 903 and 323 I want the program to find the closest matching indexes so in this case the indexes that correspond to 900 and 300.

Try this:
903/50 is 18.06 then (cast)/store it into an integer then it will be 18. 18 then multiply by 50 gives you 900.

323/50 == (int)6.46 x 50 == 300
 
Does this work? You might need to finetune it to your needs...
Was not expecting replies this fast.

Hmm... that may work. I will try. Thanks.
Will have to see how fast it is, I don't know what's inside the map function.

Try this:
903/50 is 18.06 then (cast)/store it into an integer then it will be 18. 18 then multiply by 50 gives you 900.

323/50 == (int)6.46 x 50 == 300

Thanks for the suggestion. This will work but not produce very accurate results. It will discard the value. If it's 349 it will still be 300 in stead of 350.
 
Both the suggestions produced the same result. It discards the value. However clearly this is the way to go. I can use floats in stead and then make a function that rounds the result to the closest integer value.

Thanks guys.
 
Here is the solution, this produces accurate results:

Code:
void setup()
{
    

  
}

void loop ()
{

float value = -24.0f;
    
        float index = map(value,-1100.0f, 1100.0f, 0.0f, 44.0f);
        int indexRound = (index + 0.5f);
        Serial.println(indexRound);
        delay(1000);
    
  
}

This seems to work.

Here I was going to write this huge function with a bunch of nested if statements and whatnot. I can not believe it would be this simple. Thanks guys.
 
there are other ways to round up or down, you want rounding to closest integer?

i think you solved your issue above?
 
there are other ways to round up or down, you want rounding to closest integer?

i think you solved your issue above?

Yes I used your method but with floats and added 0.5 before converting to int. This works as it should. It rounds it to the correct value.
 
Since we are discussing map functions: is there a way to map a variable non linearly? For instance if a variable goes from 0-1023 make it 0-1023 but a logarithmic response.
 
If speed isn't an issue, I agree with a curve fit. For high speed, I use table look-ups with interpolation. I could dig out that optimized code.
 
Yes. But I think you will find it difficult to figure out. Tell me more about your application and I'll make an example. 1D or 2D? What are the axis values and values in the table?
 
Yes. But I think you will find it difficult to figure out. Tell me more about your application and I'll make an example. 1D or 2D? What are the axis values and values in the table?

I have a sensor that I peak track. I get values from about 1006.0f to about 2500.0f. I want to make that range logarithmic so it converts from 1006 to 2500 to 1-127 but the lower/mid values rise faster than the upper range.
 
> values from about 1006.0f to about 2500.0f to 1-127

I call this a 1D byte table. You should post the full table that you want to use - typically with more values in any non-linear portions.

My code was written for speed and limited memory, so it only takes a int16_t as input. Is multiplying the inputs by 10 and then truncating to an integer accurate enough? If not, re-writing for your simple case isn't hard. It's just find the two closest input values and then interpolate between the two corresponding data values.
 
Last edited:
> values from about 1006.0f to about 2500.0f to 1-127

I call this a 1D byte table. You should post the full table that you want to use - typically with more values in any non-linear portions.

My code was written for speed and limited memory, so it only takes a int16_t as input. Is multiplying the inputs by 10 and then truncating to an integer accurate enough? If not, re-writing for your simple case isn't hard. It's just find the two closest input values and then interpolate between the two corresponding data values.

I'm not sure what you mean by table. The log thing is unrelated to the original question of sensor values to indexes of a 2D array.

I need to convert 1006 - 2500 from linear to logarithmic response in the range of 1006-2500. Then I can use the map function to convert to 1-127. Doesn't have to be super accurate.

I'm not sure if this makes any sense.

I'm reading the sensor in realtime so not storing it in a buffer.
 
Posting 10 examples of input and expected output would be enough.

Here is a int16_t table lookup that compiles and works in the Arduino environment. But in your case, a formula may be a better choice.
 

Attachments

  • Table_Lookup.zip
    5.5 KB · Views: 53
Status
Not open for further replies.
Back
Top