Arduino lookup table...best way to do this?

Hi,

I want to implement a look-up table of sorts, in order to control two stepper motors (might be servos to start with).

Anyway, I want to be able to pass a parameter to some variable, and then, based on that parameter (for example a voltage reading), return a degree value for say servo one, and a degree value for servo two, to move to a particular location (I guess same could be implemented with steppers....).

My challenge is how to create such a table, and then have it referenced through some function/example sketch....

For example, something like this:

Voltage =1.2 => Servo 1 go to 23Deg,, Servo 2 go to 50 Deg.. Voltagre= 1.5 => Servo 1 goto 30 Deg, Servo2 go to 120 Deg... . . . . .

Table could have have say a 100 or even more such values, depending on memory off course (thinking also to have this table on a flash card)...

Any idea?

Any idea?

Sure…

Minimum and maximum voltage values?

If voltage doesn’t match a table entry, do you want to
(a) Use lower voltage from table?
(b) Use higher voltage from table?
(c) Interpolate?

I’m not sure if this is the best way, but the first thing that comes to mind is to take the value and in a for loop, compare it to the values in an array.
Something like this maybe:

float arrayValues[]={1.25, 2.3, 3.75, 4.22, 5.12};
float measuredValue = 0;
byte x=0;
float y=0;

void setup(){
//setup the motors
}
void loop(){
  measuredValue = analogRead(0);
  for(x=0;x<4;x++){
    y = measuredValue-arrayValues[x];
    if(abs(y)<1)
      break;
  }
  if (x=1){
    //motor A do something
    //motor B do something
  }
 if (x=2){
    //motor A do something
    //motor B do something
  }
   if (x=3){
    //motor A do something
    //motor B do something
  }
   if (x=4){
    //motor A do something
    //motor B do something
  }
}

Some code remarks

measuredValue = analogRead(0);

gives a value between 0 and 1023 and you compare it with values in the 0…5 range. Think you need to add something like

measuredValue = 7.0 * measuredValue / 1023; ??

you can do the comparison directly in the for loop (flips the < to >= ) no need for the extra variable y

for( x = 0; x < 4 && abs(measuredValue - arrayValues) >= 1; x++);

Difference between assignment and comparison
if (x==1) <<<<<< not = but == is the compare


The lookup comparison can be made easier by not putting the middle values in the array but the max values per “state”.
==> you get rid of the abs() function making the code faster and more compact.

  float arrayValues[] = { 2.25, 3.3, 4.75, 5.22, 6.12 };  // I added 1.0 to all the values of the original array
...
  for( x=0; x<4 && measuredValue <=arrayValues[x]; x++);
...

[quote author=Morris Dovey link=topic=103560.msg776658#msg776658 date=1335666501]

Any idea?

Sure...

Minimum and maximum voltage values?

If voltage doesn't match a table entry, do you want to (a) Use lower voltage from table? (b) Use higher voltage from table? (c) Interpolate? [/quote]

If the value does not match exactly, close enough is ok...so I would say interpolate.....

So say i have 100 or more comparisons to do.....and each of the 100 values, needs to move the stepper/servos to some location, i would have to write 100 'if' statements?

Do not get me wrong, I am not lazy, just trying to figure out the best and most effecient way to go about this....i was thinking along the lines of some algorithm that depending on the value we read at some pin (close enough is ok), we do some sort of a process to extract the two values needed to move the motors....so something like pass the value i just read to a function, the function returns the two proper movement commands to the motors which correspond to that value which was passed....

Almost like each time the value is passed, parse say some file stored in flash or eeprom, and stop where this value is close enough to what we need, then return the two stepper values needed to move the motors corresponding to this value...

This file could be tab delimited or some other format, and contain entries which have three values...the first value is what we are trying to match...the second two values are the first stepper and second stepper commands...we then move to the next entry....etc..... This way, we would only need to do this parsing as needed, stopping and matching to the location we need....Offcourse we would need to read this file each time, but a file containing say 100 such formatted entries would not be so large, and could afford the computational time....

We would then also have logic to say that if a match is not found, give the option of storing this new value, along with the two stepper locations to the user....

Not sure i am making any sense.....thoughts?

So say i have 100 or more comparisons to do…and each of the 100 values, needs to move the stepper/servos to some location, i would have to write 100 ‘if’ statements?

that might be possible, but there are two generic solution:

  • arrays => use the index of the found value to set the value of a servo
  • formulas => you might be able to catch the logic in a (simple?) formula so you can calculate the position

array’s example

#define MAXSERVOS 2

float arrayValues[] = { 2.25, 3.3, 4.75, 5.22, 6.12 };  // I added 1.0 to all the values of the original array

byte servoAngle[MAXSERVOS ][5] = {  // 5 angles per servo
 { 0, 45, 90, 135, 180 },
 { 0,10,20,30,40 } };  


...
  // find the value in the array
  for( x=0; x<4 && measuredValue <=arrayValues[x]; x++);

  // use the index to set the servo's
  for (int s=0; s< MAXSERVOS; s++)
  {
     servo[s].set(servoAngle[s][x]);  // note the servos are in an array too!
  }
...

that is in essence all (but you still have to type the whole array

formula example

   measurement = analogRead(0);
  //  set the servo's
  for (int s=0; s< MAXSERVOS; s++)
  {
     servo[s].set(func(s, measurement));   
  }

// the func(int s, float measurement) has to be elaborated, this is just an example.
float func(int s, float measurement) 
{
   float x = (measurement-512)/512.0; // map unto -1 .. 1
   float angle = (asin(x) + s * 30) % 180;
   return angle;
}

Mostly the array option is the easiest…

I think the idea of having multiple values for each entry in the are would work. Then you would start at position 0 in the array and increment it by 3 for the check every time in the for loop, and then use the two values after it when the for loop exits. If there was some kind of formula you could use for the positions though, that would probably be ideal.

I see...so use one array for the value, and then two other arrays for the stepper values, and use a loop to track them....

Any way to do this by parsing a file? I think it would be easier to have such a file populated, and then use some sort of a delimiter, to signify the end of the entry....

When we want to match something, have a loop parse the file, and when it finds the entry we need, parse the next two values, which would signify the values we need to position the servos/steppers...

Have been trying to find examples, but not finding anything meaningful....

Having this file also stored on flash, would save considerable memory by not having to allocate all the space needed for many arrays...

Thank you all for your insightful suggestions!