Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 22 of 22

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

  1. #1
    Senior Member
    Join Date
    Jan 2020
    Posts
    129

    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. #2
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,167
    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. #3
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,451
    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. #4
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by luni View Post
    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.

    Quote Originally Posted by tonton81 View Post
    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. #5
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    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. #6
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    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. #7
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,451
    there are other ways to round up or down, you want rounding to closest integer?

    i think you solved your issue above?

  8. #8
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by tonton81 View Post
    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. #9
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Also I had to limit the output to between 0 and 44. The map function went over and under the range.

  10. #10
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,451
    Code:
    constrain(map(value,-1100.0f, 1100.0f, 0.0f, 44.0f), 0.0f, 44.0f)

  11. #11
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by tonton81 View Post
    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. #12
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    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. #13
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,762
    Quote Originally Posted by frankzappa View Post
    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. #14
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    648
    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. #15
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by jonr View Post
    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. #16
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    648
    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. #17
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by jonr View Post
    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. #18
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    648
    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. #19
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by jonr View Post
    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.

  20. #20
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    648
    > 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 by jonr; 09-24-2020 at 02:03 PM.

  21. #21
    Senior Member
    Join Date
    Jan 2020
    Posts
    129
    Quote Originally Posted by jonr View Post
    > 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.

  22. #22
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    648
    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.
    Attached Files Attached Files

Posting Permissions

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