Pages: [1]   Go Down
Author Topic: More efficient way to code?  (Read 524 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 6
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
      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:

Code:
#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?
Logged

Offline Offline
God Member
*****
Karma: 17
Posts: 752
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Phoenix, Arizona USA
Offline Offline
Faraday Member
**
Karma: 40
Posts: 5570
Where's the beer?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

smiley
Logged

I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

New Jersey
Online Online
Faraday Member
**
Karma: 67
Posts: 3679
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Wellington, New Zealand
Offline Offline
Sr. Member
****
Karma: 1
Posts: 404
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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: http://arduino.cc/en/Reference/PROGMEM

E.g. something like this:
Code:
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()
{
}
Logged


Pages: [1]   Go Up
Jump to: