More efficient way to code?

I am looking for a more efficient way to code. In particular what I have is a need to map a value, but the table is non linear so to do this I would need to use multiple map functions. An example is below.

      if (MiliAmps <= 1200)
      {
        LvlGal = 10000; 
      }
      else if (MiliAmps <= 1560)
      {
        LvlGal = 475; 
      }
      else if (MiliAmps <= 4380)
      {
        LvlGal = map(MiliAmps, 1560, 4380, 475, 170);
      }
      else if (MiliAmps <= 5116)
      {
        LvlGal = map(MiliAmps, 4380, 5116, 170, 105);
      }
      else if (MiliAmps <= 6164)
      {
        LvlGal = map(MiliAmps, 5116, 6164, 105, 50);
      }
      else if (MiliAmps <= 7820)
      {
        LvlGal = map(MiliAmps, 6164, 7820, 50, 1);
      }
      else
      {
        LvlGal = 1;
      }

This works but this is one table that I may use. I currently have 16 tables like this or bigger and I am getting close to filling up the UNO. I am only using 2 tables at a time and I know which ones to use by checking dip switch settings when the arguing boots.

I was hoping to save space and have more efficient code by using an array and a for loop. like below:

#define NUMREADINGSLVL 48  // Level array max size 
int LvlTbl[NUMREADINGSLVL];               // Level Array
int LvlEnt=0;                             // # of entries in LVL table

  for (int i = 0; i < NUMREADINGSLVL; i++)
    LvlTbl[i] = 0;                      // initialize all the readings to 0
    switch(DipTotal){
  case 0:
    LvlTbl[0]=1200;   LvlTbl[1]=475;
    LvlTbl[2]=1560;   LvlTbl[3]=475;
    LvlTbl[4]=4380;   LvlTbl[5]=170;
    LvlTbl[6]=5116;   LvlTbl[7]=105;
    LvlTbl[8]=6164;   LvlTbl[9]=50;
    LvlTbl[10]=7820;  LvlTbl[11]=1;
    LvlTbl[12]=9000;  LvlTbl[13]=1;
    LvlTbl[14]=9000;  LvlTbl[15]=1;
    LvlEnt=14; 
   
    break;
  default:
  
    LvlTbl[0]=1200;   LvlTbl[1]=475;
    LvlTbl[2]=1560;   LvlTbl[3]=475;
    LvlTbl[4]=8000;   LvlTbl[5]=170;
    LvlTbl[6]=9000;   LvlTbl[7]=1;
    LvlTbl[8]=9000;   LvlTbl[9]=1;
    LvlEnt=14; 
      }  

      if (MiliAmps <= 1200)
      {
        LvlGal = 10000; 
      }
      else
      {
        for (int i=0; i< (LvlEnt/2)-2; i++){
          if (MiliAmps <= LvlTbl[i*2]){
            LvlGal = map(MiliAmps, LvlTbl[(i*2)+2], LvlTbl[i*2], LvlTbl[i*2+1], LvlTbl[i*2+3]);
            break;
          }
        }
      }

But as I add the data inside for the different cases to build the tables the program fills the chips flash just as fast as if I did it the first way.

Is there a way to make this work to have a table or multiple tables of data that the only uses a smaller portion of memory to hold the values in and then loads the values selected into the map function, or something like that, to save on the flash that would be needed?

You could use EEPROM if it will fit, but that's going to fill up fast. The other option would be to put it all on an SD card.

You could look for a mathematical model of that so that you don't need so many ifs and values. Put the points into Excel and graph them and see if it can fit a curve.

Delta_G:
Put the points into Excel and graph them and see if it can fit a curve.

This is the answer.

It's not the easiest answer, but it is the answer you need, Tomasreabe.

Google "non-linear curve fitting" - the maths/algorithms behind this ranges from somewhat "trivial" to decidedly "non-trivial"...

Good luck.

:slight_smile:

Would the multimap function help? http://arduino.cc/playground/Main/MultiMap

16 tables of 48 ints is 1536 bytes. That's not really a lot of flash space. Did you mean that you were filling up the RAM rather than flash?

You can load your tables into flash using the progmem attribute: PROGMEM - Arduino Reference

E.g. something like this:

struct {
    int fromLow;
    int fromHigh;
    int toLow;
    int toHigh;
} mymap[] PROGMEM = {
   { 0, 1200, 10000, 10000 },
   { 1201, 1560, 475, 475 },
   { 1561, 4380, 475, 170 },
   { 4381, 5116, 170, 105 },
   { 5117, 6164, 105,  50 },
   { 6165, 7280,  50,   1 }
};

int getLvlGal(int MilliAmps) 
{
    int LvlGal = 1;
    for (int ind=0; ind<(sizeof(mymap)/sizeof(mymap[1])); ind++) {
        if (MilliAmps < (int)pgm_read_word(&mymap[ind].fromHigh)) {
	    LvlGal = map(MilliAmps,
			pgm_read_word(&mymap[ind].fromLow),
			pgm_read_word(&mymap[ind].fromHigh),
			pgm_read_word(&mymap[ind].toLow),
			pgm_read_word(&mymap[ind].toHigh));
	    break;
	}
    }

    return LvlGal;
}

void setup()
{
    Serial.begin(115200);
    Serial.println("Started");
    int MilliAmps = 3001;

    Serial.print(MilliAmps);
    Serial.print("ma -> ");
    Serial.println(getLvlGal(MilliAmps));
}

void loop()
{
}