Go Down

Topic: Problems passing an array to a function for 2d interpolation (Read 6556 times) previous topic - next topic

rgb32

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.

Code: [Select]

// 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);
      }
}


nickgammon

Code: [Select]
      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:

Code: [Select]
zvalues[xpos,ypos]
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon

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

Code: [Select]
  tpsout = multimap2d(4000, 50, rpmaxis, tpsaxis, (int *) tpso);
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

rgb32

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

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

nickgammon

This compiles and might be better:

Code: [Select]
// 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);
      }
}
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

rgb32


This compiles and might be better:

Code: [Select]
// 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

PaulS

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 art of getting good answers lies in asking good questions.

rgb32

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

robtillaart

Interesting variation of multimap. I added a link to this discussion on the multimap page - http://playground.arduino.cc//Main/MultiMap -
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

JimboZA

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.
Johannesburg hams call me: ZS6JMB on Highveld rep 145.7875 (-600 & 88.5 tone)
Dr Perry Cox: "Help me to help you, help me to help you...."
Your answer may already be here: https://forum.arduino.cc/index.php?topic=384198.0

JimboZA

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.
Johannesburg hams call me: ZS6JMB on Highveld rep 145.7875 (-600 & 88.5 tone)
Dr Perry Cox: "Help me to help you, help me to help you...."
Your answer may already be here: https://forum.arduino.cc/index.php?topic=384198.0

issadjay

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


PaulS

Code: [Select]
  float x_sun[] = { 1};  // 11
A one element array is useless.

Code: [Select]
  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?
The art of getting good answers lies in asking good questions.

KeithRB

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

Go Up