Strange Error when assigning global Variable from array

Hi all,

I have a function that acts as a lookup table, input is resistance, output is temperature. For debug purposes, I wanted to output an array value (defined globally) to a global variable, but the compiler gets upset.

I found a workaround, but it does not make sense to me.

Here’s the original that does not work - please keep in mind that within the function I am using local and global vars.

#define NUM_PTS 46

double temp = 0.0;
double temp_N = 0.0;
double temp_D = 0.0;
double temp_1 = 0.0;
double temp_2 = 0.0;

const double sensor_resCur[NUM_PTS] = {169.2,185.3,193.3,201.2,220.9,240.3,259.4,278.3,296.4,314.9,333.3,351.5,369.7,387.7,405.6,423.3,441,458.5,475.9,493.2,510.4,527.5,544.4,561.2,577.9,594.5,610.9,627.3,643.2,659.1,674.8,690.4,705.8,721.1,736.2,751.1,765.9,780.5,795,809.4,823.5,837.6,851.4,865.2,878.7,892.1};
const double sensor_tempCur[NUM_PTS] = {-40,-20,-10,0,25,50,75,100,125,150,175,200,225,250,275,300,325,350,375,400,425,450,475,500,525,550,575,600,625,650,675,700,725,750,775,800,825,850,875,900,925,950,975,1000,1025,1050};


long search(double input_R, int breakPts)
{
  double ratio = 0.0;
  double temp_degC = 0.0;
  double num = 0.0;
  double den = 0.0;
  double val = 0.0;
  int i = 0;
  long outputVal = 0;

  for(i=0;i<(breakPts-1);i++)
  {
    if((input_R >= sensor_resCur[i]) && (input_R < sensor_resCur[i+1]))
    {
      val = sensor_resCur[i];
      num = input_R - val;

      temp_1 = input_R;
      temp_2 = sensor_resCur[i];
      den = (double)sensor_resCur[i+1] - sensor_resCur[i];
      ratio = num / den;
      
      temp_degC = sensor_tempCur[i] + ((sensor_tempCur[i+1] - sensor_tempCur[i]) * ratio);
      temp = ratio;
      temp_N = num;
      temp_D = den;
    }
    if(input_R < sensor_resCur[0])
    {
      temp_degC = sensor_tempCur[0];
    }
    if(input_R >= sensor_resCur[breakPts-1])
    {
      temp_degC = sensor_tempCur[breakPts-1];
    }   
  }
  
  outputVal = (long)temp_degC;
  
  return outputVal;
}

The Compiler freaks out here:

temp_2 = sensor_resCur[i];

I get the error:

Arduino: 1.8.5 (Windows 7), Board: "Arduino/Genuino Uno"

C:\ArduinoDiag\Projects\TempSensor\TempSensor.ino: In function 'search.constprop':

TempSensor:190: error: unable to find a register to spill in class 'POINTER_REGS'

 }

 ^

TempSensor:190: error: this is the insn:

(insn 47 46 49 3 (set (reg:SF 62 [ D.2153 ])

        (mem:SF (post_inc:HI (reg:HI 78 [ ivtmp.13 ])) [2 MEM[base: _56, offset: 0B]+0 S4 A8])) C:\ArduinoDiag\Projects\TempSensor\TempSensor.ino:162 100 {*movsf}

     (expr_list:REG_INC (reg:HI 78 [ ivtmp.13 ])

        (nil)))

C:\ArduinoDiag\Projects\TempSensor\TempSensor.ino:190: confused by earlier errors, bailing out

lto-wrapper: C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-gcc returned 1 exit status

c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.9.2/../../../../avr/bin/ld.exe: error: lto-wrapper failed

collect2.exe: error: ld returned 1 exit status

exit status 1
unable to find a register to spill in class 'POINTER_REGS'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Notice that the local variable val does not have problems.

Now when assign the local to the global, I get the same error (excess code removed):

for(i=0;i<(breakPts-1);i++)
  {
    if((input_R >= sensor_resCur[i]) && (input_R < sensor_resCur[i+1]))
    {
      val = sensor_resCur[i];
      num = input_R - val;

      temp_1 = input_R;
      temp_2 = val;

    }

The strange part is, I get the code to work when I add an arbitrary arithmetic operation to the local variable (excess code removed):

 for(i=0;i<(breakPts-1);i++)
  {
    if((input_R >= sensor_resCur[i]) && (input_R < sensor_resCur[i+1]))
    {
      val = sensor_resCur[i];
      num = input_R - val;
      val = val + 0;
      temp_1 = input_R;
      temp_2 = val;

    }

The code above shows no errors, and when I output temp_2 on the serial monitor, it is displaying the expected value.

Any ideas?

Thanks!!

Any ideas?

Yes. Post ALL of your code. The "unable to find a register to spill" almost always indicates some kind of memory issue.

Hi PaulS,

I will have to review/sanitize my overall code to make sure nothing is posted that shouldn't be posted.

I have simplified the problem a bit here...

This doesn't work:

temp_2 = sensor_resCur[i];

but this does work:

temp_2 = sensor_resCur[i] + 0;

Thanks

Here’s the full Code:

#define NUM_PTS 46

//Analog Input Pins
const byte pinIn_Sensor = 0;

//Digital Output Pins
const byte pinOut_LED = 13;

long Sensor_ADC;
long Sensor_mV;
double Sensor_ohms;
long Sensor_degC;
const double RPU_ohms = 2000;
const double Vref_mV = 5000;
const double Sensor_ohms_OC = 1000000.0;

const double sensor_resCur[NUM_PTS] = {169.2,185.3,193.3,201.2,220.9,240.3,259.4,278.3,296.4,314.9,333.3,351.5,369.7,387.7,405.6,423.3,441,458.5,475.9,493.2,510.4,527.5,544.4,561.2,577.9,594.5,610.9,627.3,643.2,659.1,674.8,690.4,705.8,721.1,736.2,751.1,765.9,780.5,795,809.4,823.5,837.6,851.4,865.2,878.7,892.1};
const double sensor_tempCur[NUM_PTS] = {-40,-20,-10,0,25,50,75,100,125,150,175,200,225,250,275,300,325,350,375,400,425,450,475,500,525,550,575,600,625,650,675,700,725,750,775,800,825,850,875,900,925,950,975,1000,1025,1050};


unsigned long t1,t2,t3;
const unsigned long sampleTime_ms = 50;
const unsigned long TxTime_ms = 5000;

double temp = 0.0;
double temp_N = 0.0;
double temp_D = 0.0;
double temp_1 = 0.0;
double temp_2 = 0.0;

///////////////////////////////////////////////////////////////////
void setup()
{
  pinMode(pinOut_LED,OUTPUT);
  digitalWrite(pinOut_LED,HIGH);

  Serial.begin(9600);
  delay(100); 
  
  t1 = millis();
  t2 = t1;
  t3 = t1;
}

///////////////////////////////////////////////////////////////////
void loop()
{
  t1 = millis();
  if(((t1-t2) > sampleTime_ms) or (t2 > t1))
  {
    //Here we sample our analog inputs at pre-prescribed times
    getInputs();
    t2 = t1;
  }


  if(((t1-t3) > TxTime_ms) or (t3 > t1))
  {
    //Here we send out debug data on Serial bus
    Serial.print("t: ");
    Serial.println(t1);  
    Serial.print("mV: ");
    Serial.println(Sensor_mV);
    Serial.print("Ohms: ");
    Serial.println(Sensor_ohms);
    Serial.print("degC: ");
    Serial.println(Sensor_degC);
    Serial.print("Ratio: ");
    Serial.println(temp);
    Serial.print("Num: ");
    Serial.println(temp_N);
    Serial.print("Den: ");
    Serial.println(temp_D);
    Serial.print("temp_1: ");
    Serial.println(temp_1);
    Serial.print("temp_2: ");
    Serial.println(temp_2);
    Serial.println();
    t3 = t1;
  }    
}

///////////////////////////////////////////////////////////////////
int getInputs()
{
  Sensor_ADC = analogRead(pinIn_Sensor);

  //Debug start
  Sensor_ADC = 512;
  //Debug End
  
  Sensor_mV = (Sensor_ADC * 5000) / 1023;

  if(Sensor_mV < Vref_mV)
  {
    Sensor_ohms = RPU_ohms / (((double)Vref_mV /  Sensor_mV) - 1);
  }
  else
  {
    Sensor_ohms = Sensor_ohms_OC;
  }  
 
  Sensor_degC = search(Sensor_ohms,NUM_PTS);
}

///////////////////////////////////////////////////////////////////
long search(double input_R, int breakPts)
{
  double ratio = 0.0;
  double temp_degC = 0.0;
  double num = 0.0;
  double den = 0.0;
  int i = 0;
  long outputVal = 0;

  for(i=0;i<(breakPts-1);i++)
  {
    if((input_R >= sensor_resCur[i]) && (input_R < sensor_resCur[i+1]))
    {
      num = input_R - sensor_resCur[i];
      den = sensor_resCur[i+1] - sensor_resCur[i];
      ratio = num / den;
      
      temp_degC = sensor_tempCur[i] + ((sensor_tempCur[i+1] - sensor_tempCur[i]) * ratio);
      
      //Debugging Vars Start
      temp_1 = input_R;
      temp_2 = sensor_resCur[i] + 0;
      temp = ratio;
      temp_N = num;
      temp_D = den;
      //Debugging Vars End

    }
    if(input_R < sensor_resCur[0])
    {
      temp_degC = sensor_tempCur[0];
    }
    if(input_R >= sensor_resCur[breakPts-1])
    {
      temp_degC = sensor_tempCur[breakPts-1];
    }   
  }
  
  outputVal = (long)temp_degC;
  
  return outputVal;
}

Other than your ‘int getInputs()’ function not returning a value as you promised the compiler it would, your code from Reply #3 compiles fine for me for an Uno using Arduino 1.8.5.

That is a compiler optimizer bug. I've seen it myself. Using a different version of the compiler will likely make it go away. Often, just making some inane change somewhere else in the code will make it go away as well. I would expect it to be fixed in the latest release, as I first came across it over a year ago.

Regards,
Ray L.

Thank you Ray, PaulS, & gfvalvo!