Forum Rule: Always post complete source code & details to reproduce any issue!

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

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

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/5n5mf2bkhb...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?

2. 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
...```

3. 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

4. Originally Posted by luni
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.

Originally Posted by tonton81
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.

5. 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.

6. 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.

7. there are other ways to round up or down, you want rounding to closest integer?

i think you solved your issue above?

8. Originally Posted by tonton81
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.

9. Also I had to limit the output to between 0 and 44. The map function went over and under the range.

10. Code:
`constrain(map(value,-1100.0f, 1100.0f, 0.0f, 44.0f), 0.0f, 44.0f)`

11. Originally Posted by tonton81
Code:
`constrain(map(value,-1100.0f, 1100.0f, 0.0f, 44.0f), 0.0f, 44.0f)`
Ah, yes that is cleaner than what I did, thanks 😊

12. 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.

13. Originally Posted by frankzappa
is there a way to map a variable non linearly?
With the map() function, no. It's always linear.

But you certainly can create your own non-linear mapping using equations and functions like logf() or expf(). Some math required...

14. 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.

15. Originally Posted by jonr
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.
Aha, yes pleaase

16. Some code for 1D and 2D table lookups is here. You pass it either an X value or X&Y values and it returns an interpolated table value. It was designed so that the tables could be edited by external software.

https://gitlab.com/our-sci/reflectan...ob/master/src/

17. Originally Posted by jonr
Some code for 1D and 2D table lookups is here. You pass it either an X value or X&Y values and it returns an interpolated table value. It was designed so that the tables could be edited by external software.

https://gitlab.com/our-sci/reflectan...ob/master/src/
Thanks, much appreciated. I'm guessing it's the ones called table_lookup_JZ.

18. 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?

19. Originally Posted by jonr
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.

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.

21. Originally Posted by jonr

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.

22. 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.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•