Problems passing an array to a function for 2d interpolation

Hi. I've been trying to write a sketch to interpolate between points from a table. The stumbling block at the moment is a compiling problem where error message " cannot convert 'int ()[10]' to 'int' for argument '5' to 'int multimap2d(int, int, int*, int*, int*)' " you'll see that this relates to an array being passed to function "multimap2d".

I'm running an Uno 3

Can anyone advise a fix to get this running?

Although the numbers in the array are all the same (by column) at this point this is for ease of generating a starting point. Every point could be unique. Likewise the tpsaxis and rpmaxis do need necessarily have regular spacing.

// 2d interpolation


void setup() {
  Serial.begin(9600);
}

void loop() {

  int tpsaxis[] = { 0, 5, 10, 50, 60, 80, 90, 95, 97, 100,};  // 10
  int rpmaxis[]  = {1000,2000,3000,4000,5000,7000,8000,10000,12000,13500}; // 10
  int tpso[10][10] = {
      100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
      97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
      97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
      97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
      40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // [ 9 x 9 ] matrix
  
  int tpsout; 
  
  tpsout = multimap2d(4000, 50, rpmaxis, tpsaxis, tpso);

Serial.println(tpsout);
  
}


int multimap2d(int xval, int yval, int* xaxis, int* yaxis, int* zvalues)
{
  byte xpos = 1;
  byte xi = 0;
  byte ypos = 1;
  byte yi = 0;
  
// deal with special cases first
  if (xval <= xaxis[0])
    {
    xpos = 0 ;
    xi=0 ; // then no interpolation is required. 
    }
  else if (xval >= xaxis[9]) 
    {
    xpos = 9;
    xi=0;  // then no interpolation is required. 
    }
  else 
    {
//search right interval
  //  uint8_t pos = 1; // have already established that we're not at xaxis[0] use xpos=1
  while(xval > xaxis[xpos]) xpos++; // search until xpos found
  // this will handle all exact "points" in the xaxis array
      if (xval == xaxis[xpos])
      {
      xi=0; // no interpolation is required in x.
      }
      else
      {
      xi=1; // If above doesn't solve then interpolation is required using xpos and xpos-1
      }
    }
// do the same for yaxis

// deal with special cases first
  if (yval <= yaxis[0])
    {
    ypos = 0;
    yi=0; // then no interpolation is required. 
    } 
  else if (yval >= yaxis[9])
    {
    ypos = 9;
    yi=0 ;// then no interpolation is required. 
    }
  else
    {
    //search right interval
  // have already established that we're not at yaxis[0] use ypos = 1
    while(yval > yaxis[ypos]) ypos++; // search until ypos found
      // this will handle all exact "points" in the _in array
      if (yval == yaxis[ypos])
        {
        yi=0; // no interpolation is required in y.
        }
      else
        {
        yi=1; // If above doesn't solve then interpolation is required using ypos and ypos-1
        }
     }

// case 1. There is an exact point in the table
    if(xi==0 && yi==0) return zvalues[xpos,ypos];
// case 2. Interpolate in x only. i.e. yval corresponds to bounds or a breakpoint
    if(xi==1 && yi==0) 
      {
      return map(xval, xaxis[xpos-1], xaxis[xpos], zvalues[xpos-1,ypos], zvalues[xpos,ypos]);
      }
// case 3.
    if(xi==0 && yi==1) 
      {
      return map(yval, yaxis[ypos-1],yaxis[ypos], zvalues[xpos,ypos-1], zvalues[xpos,ypos]);
      }
//case 4. Interpolate both. x first
    // if(xi==1 & yi==1) 
    else
      {
      int _high = map(xval, xaxis[xpos-1],xaxis[xpos], zvalues[xpos-1,ypos], zvalues[xpos,ypos]);
      int _low = map(xval, xaxis[xpos-1],xaxis[xpos], zvalues[xpos-1,ypos-1], zvalues[xpos,ypos-1]);
      return map(yval, yaxis[ypos-1],yaxis[ypos],_low,_high);
      }
}
      int _high = map(xval, xaxis[xpos-1],xaxis[xpos], zvalues[xpos-1,ypos], zvalues[xpos,ypos]);

This isn't the right way to index into a 2-dimensional array:

zvalues[xpos,ypos]

This makes it compile, but I doubt it will do what you expect because of my earlier comment:

  tpsout = multimap2d(4000, 50, rpmaxis, tpsaxis, (int *) tpso);

Nice one. that bit is now fixed....

seems I have matlab in my head......

This compiles and might be better:

// 2d interpolation

void setup() {
  Serial.begin(9600);
}

void loop() {

  int tpsaxis[] = { 0, 5, 10, 50, 60, 80, 90, 95, 97, 100,};  // 10
  int rpmaxis[]  = {1000,2000,3000,4000,5000,7000,8000,10000,12000,13500}; // 10
  int tpso[10][10] = {
      100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
      97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
      97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
      97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
      40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // [ 9 x 9 ] matrix
  
  int tpsout; 
  
  tpsout = multimap2d(4000, 50, rpmaxis, tpsaxis, tpso);

Serial.println(tpsout);
  
}


int multimap2d(int xval, int yval, int* xaxis, int* yaxis, int zvalues [10] [10] )
{
  byte xpos = 1;
  byte xi = 0;
  byte ypos = 1;
  byte yi = 0;
  
// deal with special cases first
  if (xval <= xaxis[0])
    {
    xpos = 0 ;
    xi=0 ; // then no interpolation is required. 
    }
  else if (xval >= xaxis[9]) 
    {
    xpos = 9;
    xi=0;  // then no interpolation is required. 
    }
  else 
    {
//search right interval
  //  uint8_t pos = 1; // have already established that we're not at xaxis[0] use xpos=1
  while(xval > xaxis[xpos]) xpos++; // search until xpos found
  // this will handle all exact "points" in the xaxis array
      if (xval == xaxis[xpos])
      {
      xi=0; // no interpolation is required in x.
      }
      else
      {
      xi=1; // If above doesn't solve then interpolation is required using xpos and xpos-1
      }
    }
// do the same for yaxis

// deal with special cases first
  if (yval <= yaxis[0])
    {
    ypos = 0;
    yi=0; // then no interpolation is required. 
    } 
  else if (yval >= yaxis[9])
    {
    ypos = 9;
    yi=0 ;// then no interpolation is required. 
    }
  else
    {
    //search right interval
  // have already established that we're not at yaxis[0] use ypos = 1
    while(yval > yaxis[ypos]) ypos++; // search until ypos found
      // this will handle all exact "points" in the _in array
      if (yval == yaxis[ypos])
        {
        yi=0; // no interpolation is required in y.
        }
      else
        {
        yi=1; // If above doesn't solve then interpolation is required using ypos and ypos-1
        }
     }

// case 1. There is an exact point in the table
    if(xi==0 && yi==0) return zvalues[xpos] [ypos];
// case 2. Interpolate in x only. i.e. yval corresponds to bounds or a breakpoint
    if(xi==1 && yi==0) 
      {
      return map(xval, xaxis[xpos-1], xaxis[xpos], zvalues[xpos-1] [ypos], zvalues[xpos] [ypos]);
      }
// case 3.
    if(xi==0 && yi==1) 
      {
      return map(yval, yaxis[ypos-1],yaxis[ypos], zvalues[xpos] [ypos-1], zvalues[xpos] [ypos]);
      }
//case 4. Interpolate both. x first
    // if(xi==1 & yi==1) 
    else
      {
      int _high = map(xval, xaxis[xpos-1],xaxis[xpos], zvalues[xpos-1] [ypos], zvalues[xpos] [ypos]);
      int _low = map(xval, xaxis[xpos-1],xaxis[xpos], zvalues[xpos-1] [ypos-1], zvalues[xpos] [ypos-1]);
      return map(yval, yaxis[ypos-1],yaxis[ypos],_low,_high);
      }
}

It does :). Need to try it on the Uno now. Thankyou very much Nick

Why are you storing 10 rows and 10 columns of data in your 9 x 9 array? Does that comment really add anything useful? Or even correct?

Why are the arrays declared in loop()? Are you planning on changing them?

Why is tpso, containing byte sized values, an int array?

Why are the arrays not const?

The answer to all these is that the base function I copied and turned into multimap2d was setup like this. I will make all the changes you outlined + tpsaxis...

Interesting variation of multimap. I added a link to this discussion on the multimap page - Arduino Playground - HomePage -

Hmmm, this is probably what I need to look up the comfort level given the temperature and humidity, where the comfort level is just Red, Blue, Yellow or Green as here.

And indeed it proves easy enough. One wrinkle is that I think I have my values typed in back-asswards or confusing the axes, since I'm not getting the right values out: probably reading say cell (3,4) when I should be at (4,3). But I daresay I'll figure that out.

Next step is an RGB led to produce the colour.

I am doing the same task with a larger array. can anyone tell me why I am not getting the result from from serial monitor. my code is given below
Do I have to use the Flash memory to complete this task. If so how do i retrieve data from Flash memory

sketch_jun09b.ino (10.5 KB)

  float x_sun[] = { 1};  // 11

A one element array is useless.

  float y_voltage[]  = {
}; // 501
  float current[1][501] = {
}; // [ 1 x 501 ] matrix

These 2 arrays are taking up 4008 bytes of SRAM. Do you have that much SRAM?

and a "1x501" matrix makes no sense in C, more MATLAB speak.