help with a lookup table

I’m trying to get a lookup table working.

I have a 0-5v variable input which I want to use to lookup a value in a lookup table.
I’ve found small bits of code on various forums but can’t seem to get it working.

i’ve attached my code (which doesn’t work). I’m very new to this and just cant seem to get my head round this problem.

Thanks

analog_voltage_lookup.ino (1.99 KB)

int[] theArray = {
    1, 0.0001,

Did you mean “float”?

// have a 10k pot connected to A0. sensorValue reads as 0-1023 bytes
  int sensorValue = analogRead(A0);
  // convert sensorValue value into voltage
  float voltage = sensorValue * (5.0 / 1024);
 for (int i = 0; i < (sizeof (theArray) / sizeof (theArray [0])) - 2; i += 2)

i’m not sure

I was following the example given here

they have it as int not float.

these are the errors im getting when trying to compile.

analog_voltage_lookup.ino: In function ‘void loop()’:
analog_voltage_lookup:24: error: expected unqualified-id before ‘[’ token
analog_voltage_lookup:75: error: ‘theArray’ was not declared in this scope
analog_voltage_lookup:76: error: ‘A’ was not declared in this scope
analog_voltage_lookup:77: error: ‘newVal’ was not declared in this scope
analog_voltage_lookup:90: error: ‘newVal’ was not declared in this scope

they have it as int not float.

But "they"probably weren't interested in floating point values.

  float theArray []= {

Looking at it again, you'd be better with an array of mixed int/float records, using the raw ADC reading as an integer to perform the range lookup, IMO.

ok I see what you mean about the float now.

would you be able to elaborate on how I can get this working?

Thanks

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

void setup() {
  
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

}


void loop() {
  // have a 10k pot connected to A0. sensorValue reads as 0-1023
  int sensorValue = analogRead(A0);
  // convert sensorValue value into voltage
  float voltage = sensorValue * (5.0 / 1024);
  
  // The look up table. first numbers are voltage, second numbers are what I want to lookup and display.
  float theArray []= {
    1, 0.0001,
    1.025, 0.000231,
    1.05, 0.000621,
    1.1, 0.00136,
    1.2, 0.00297,
    1.3, 0.00461,
    1.4, 0.00651,
    1.5, 0.0102,
    1.6, 0.0147,
    1.7, 0.0191,
    1.8, 0.0295,
    1.9, 0.0416,
    2, 0.0561,
    2.1, 0.072,
    2.2, 0.0894,
    2.3, 0.113,
    2.4, 0.145,
    2.5, 0.176,
    2.6, 0.222,
    2.7, 0.316,
    2.8, 0.413,
    2.9, 0.54,
    3, 0.682,
    3.1, 0.841,
    3.2, 1.06,
    3.3, 1.33,
    3.4, 1.6,
    3.5, 1.87,
    3.6, 2.26,
    3.7, 2.75,
    3.8, 3.24,
    3.9, 3.73,
    4, 4.39,
    4.1, 5.29,
    4.2, 6.27,
    4.3, 7.63,
    4.4, 9.39,
    4.5, 12.7,
    4.6, 16.7,
    4.7, 22.4,
    4.75, 28.8,
    4.8, 35.3,
    4.85, 44.8,
    4.9, 66.5,
    4.95, 141,
    4.975, 616,
    5, 1000};
   
   float newVal;
   //Code I found on forums which i hope can use the lookup table somehow
    for (int i = 0; i < (sizeof (theArray) / sizeof(theArray[0]))-2; i += 2) {
        if ( (voltage >= theArray[i])  &&  (voltage < theArray[i+2]) ) {
          newVal = theArray[i+1] - ((theArray[i+1] - theArray[i+3]) * (  ( (float) voltage - theArray[i] ) / (theArray[i+2] - theArray[i] ) ) );
        break;
    }
}
  
  //Outputs the various values onto my display (below works fine)
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print(voltage);
  display.println("v");
  display.print(sensorValue);
  display.println(" bytes");
  display.println(newVal);
  display.display();
  display.clearDisplay();

}

Compiled, but untested.

thanks for that. running that does not give desired results. although no error appears, no value appears on the display and the 10k pot does nothing to affect values

Time to add some debug prints and find out what's happening.

changing the array to int rather than float (i realise this is probably wrong) allows the code to run and display a value on the display.

this value however does not match what it should be in the lookup table.

up to 3v, display reads 0.00 3v - 4v, display reads same as voltage 4v - 5v, display reads 600-1000

does that give any clues as to what's going on?

does that give any clues as to what's going on?

Yes, all those values with fractional parts are being truncated to their integer values by declaring the array to be of type "int". (an "int" can't hold a fractional part)

do you have any idea why it wouldn't work when set to float? the display just flashes

RobUK: do you have any idea why it wouldn't work when set to float? the display just flashes

Would you please show the complete "lookup table" that you want to use?

Is it this table as visible in some code posted by AWOL:

// The look up table. first numbers are voltage, second numbers are what I want to lookup and display.
  float theArray []= {
    1, 0.0001,
    1.025, 0.000231,
    1.05, 0.000621,
    1.1, 0.00136,
    1.2, 0.00297,
    1.3, 0.00461,
    1.4, 0.00651,
    1.5, 0.0102,
    1.6, 0.0147,
    1.7, 0.0191,
    1.8, 0.0295,
    1.9, 0.0416,
    2, 0.0561,
    2.1, 0.072,
    2.2, 0.0894,
    2.3, 0.113,
    2.4, 0.145,
    2.5, 0.176,
    2.6, 0.222,
    2.7, 0.316,
    2.8, 0.413,
    2.9, 0.54,
    3, 0.682,
    3.1, 0.841,
    3.2, 1.06,
    3.3, 1.33,
    3.4, 1.6,
    3.5, 1.87,
    3.6, 2.26,
    3.7, 2.75,
    3.8, 3.24,
    3.9, 3.73,
    4, 4.39,
    4.1, 5.29,
    4.2, 6.27,
    4.3, 7.63,
    4.4, 9.39,
    4.5, 12.7,
    4.6, 16.7,
    4.7, 22.4,
    4.75, 28.8,
    4.8, 35.3,
    4.85, 44.8,
    4.9, 66.5,
    4.95, 141,
    4.975, 616,
    5, 1000};

Things could be coded much easier, if the first value had equal difference from value to value, but in that table in some rare cases the difference between values is not 0.1V but 0.05V or 0.025V.

So is this your actual table? Or is your actual table simpler with equal voltage differences between data points?

That is my lookup table the values are strange I know.

It's a vacuum gauge and the output voltage relates to pressure in mbar.

RobUK:
That is my lookup table the values are strange I know.

It’s a vacuum gauge and the output voltage relates to pressure in mbar.

OK, in that case I have nothing ready for copy-and-paste and will have to write some lines of code.

I suppose, in case of voltage<1.0 the table value has to be 0.0 and (I don’t know if it can happen) in case of voltage>5.0 the table value is the last value in the table?

Or would you like to have some special error values if the input value is <1.0V or >5.0V?

Less than 1v would be considered "under range" and over 5v "over range". Would be nice if the display could show those words.

Thanks a lot

RobUK:
Less than 1v would be considered “under range” and over 5v “over range”. Would be nice if the display could show those words.

Here is a code for float-to-float interpolation from a table.

I included an example program that simulates input voltages in the range 0.980 … 5.019 Volt and shows how to handle “under range” and “over range” text messages.

// code for thread http://forum.arduino.cc/index.php?topic=297755.0
// The look up table. First numbers are voltage, second numbers are what I want to lookup and display.
  struct interpolate_t {float voltage; float pressure;};
  interpolate_t pressureTable []= {
    {1, 0.0001},
    {1.025, 0.000231},
    {1.05, 0.000621},
    {1.1, 0.00136},
    {1.2, 0.00297},
    {1.3, 0.00461},
    {1.4, 0.00651},
    {1.5, 0.0102},
    {1.6, 0.0147},
    {1.7, 0.0191},
    {1.8, 0.0295},
    {1.9, 0.0416},
    {2, 0.0561},
    {2.1, 0.072},
    {2.2, 0.0894},
    {2.3, 0.113},
    {2.4, 0.145},
    {2.5, 0.176},
    {2.6, 0.222},
    {2.7, 0.316},
    {2.8, 0.413},
    {2.9, 0.54},
    {3, 0.682},
    {3.1, 0.841},
    {3.2, 1.06},
    {3.3, 1.33},
    {3.4, 1.6},
    {3.5, 1.87},
    {3.6, 2.26},
    {3.7, 2.75},
    {3.8, 3.24},
    {3.9, 3.73},
    {4, 4.39},
    {4.1, 5.29},
    {4.2, 6.27},
    {4.3, 7.63},
    {4.4, 9.39},
    {4.5, 12.7},
    {4.6, 16.7},
    {4.7, 22.4},
    {4.75, 28.8},
    {4.8, 35.3},
    {4.85, 44.8},
    {4.9, 66.5},
    {4.95, 141},
    {4.975, 616},
    {5, 1000},
  };

#define TABLEENTRIES sizeof(pressureTable)/sizeof(pressureTable[0])
#define UNDERRANGEVALUE 0.0
#define OVERRANGEVALUE 10000.0

float interpolate_f2f(float inValue)
{
  if (inValue<pressureTable[0].voltage) return UNDERRANGEVALUE;
  if (inValue> pressureTable[TABLEENTRIES-1].voltage) return OVERRANGEVALUE;
  int i;
  for (i=1;i<TABLEENTRIES;i++)
  {
    if ( pressureTable[i].voltage>inValue) break;
  }
  if (i>TABLEENTRIES-1) i=TABLEENTRIES-1;
  return pressureTable[i-1].pressure + (pressureTable[i].pressure-pressureTable[i-1].pressure) * (inValue-pressureTable[i-1].voltage) / (pressureTable[i].voltage-pressureTable[i-1].voltage);
}



void setup() {
  Serial.begin(9600);
  for (int i=980;i<5020;i++)   // simulate input in millivolts
  {
    float voltage=i/1000.0;
    float pressure= interpolate_f2f(voltage);
    Serial.print(voltage,3);
    Serial.print('\t');
    if (pressure==UNDERRANGEVALUE)
      Serial.println("under range");
    else if (pressure==OVERRANGEVALUE)
      Serial.println("over range");
    else
      Serial.println(pressure,6);  
  }
}

void loop() {
}

If you need to save RAM, you would have to put the table into PROGMEM instead RAM.

Edit: Fixed calculation (first version was wrong)

that worked really well, thanks. I have it working and out putting to my display. really appreciate your help

all I need now is to convert the pressure readings to exponent format and display that too any tips?

RobUK: all I need now is to convert the pressure readings to exponent format and display that too any tips?

Here is a slightly changed output logic:

    if (pressure==UNDERRANGEVALUE)
      Serial.println(F("under range"));
    else if (pressure==OVERRANGEVALUE)
      Serial.println(F("over range ")); // same width as the 'under range message'
    else
    {
      char pressureE[12];
      dtostre(pressure, pressureE, 4, 0); // scientific format with 4 digits
      Serial.print(' '); // format to the same width as the 'under range' message
      Serial.println(pressureE);  
    }

Changes: - using F-macro for string constants saves RAM - using scientific formatted output to display value - formatting value same width as the longest message You can use this with an LCD text display, output string is then always same length when displaying error message or formatted value.

excellent! That worked brilliantly and is far simpler than other examples i've seen.

Thanks for everything.

RobUK: excellent! That worked brilliantly and is far simpler than other examples i've seen.

There are always four ways of programming things on an Arduino board:

The right way, the wrong way, the usual way, and my way.

If things are done my way, we'll get along... (I'm just kidding and spoofing a movie quote.) ;)

And keep in mind: The posted version of the code keeps the whole table in RAM memory all the time. You could preserve a considerable amount of RAM for other things in your program, if you'd put the table into PROGMEM and read only at most 4 float values from PROGMEM into RAM when needed for the actual calculation.