QTR calibration values from EEPROM

I am working on saving QTRA calibration values to EEPROM so calibration doesn’t have to happen on every power up, and more importantly so the function can continue if there is a crash/restart.

When calibration is run, the values get saved to EEPROM-

void set_sensor()                                    //Calibrate the reflectance sensors  Add LED indication that calibration is happening
{
  delay(500);
 
  for (int i = 0; i < 200; i++)  // make the calibration take about 5 seconds
  {
    qtra.calibrate();       // reads all sensors 10 times at 2500 us per read (i.e. ~25 ms per call)
  }

  // print the calibration minimum values measured when emitters were on
  Serial.begin(9600);
  Serial.print("Minimum Values: ");
  for (int i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtra.calibratedMinimumOn[i]);
    EEPROM.writeInt(i*2,qtra.calibratedMinimumOn[i]);     //Write the minimum values into EEPROM. Each takes 2 slots, 0-1,2-3,4-5,6-7
    Serial.print(' ');
  }
  Serial.println();
  Serial.print("Maximum Values: ");
  
  // print the calibration maximum values measured when emitters were on
  for (int i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtra.calibratedMaximumOn[i]);
  EEPROM.writeInt((i*2)+10,qtra.calibratedMaximumOn[i]);     //Write the minimum values into EEPROM. Each takes 2 slots, 10-11,12-13,14-15,16-17
    Serial.print(' ');
  }
  Serial.println();
  Serial.println();
  delay(1000);
}

During setup I have a call to a function that will read the EEPROM into a pair of int arrays-

void restore_sensor(){
  
    for (int i = 0; i < NUM_SENSORS; i++)
  {minimum_from_EEPROM[i] = EEPROM.readInt(i*2);
  }

  for (int i = 0; i < NUM_SENSORS; i++)
  {maximum_from_EEPROM[i] = EEPROM.readInt((i*2)+10);
 
}

This all works so far, and I can bring those arrays over to the QTRSensors.cpp tab with

extern int minimum_from_EEPROM[4];
extern int maximum_from_EEPROM[4];

From here I don’t know how to get the values in the array transferred into calibratedMinimumOn[i] and calibratedMaximumOn[i] in such a way that they will be used by the readCalibrated function. It needs to start out with the EEPROM values, but change to what ever values get determined by a subsequent calibration.

Since I don’t use the calibration reset, I tried changing it so that instead of resetting them to 0, it would reset the calibration to the EEPROM values.

// Resets the calibration.
void QTRSensors::resetCalibration( )     //This has been changed to reset the calibration to the values that were stored in EEPROM
{
	unsigned char i;
	for(i=0;i<_numSensors;i++)
	{
		calibratedMinimumOn[i] = minimum_from_EEPROM[i];
		calibratedMaximumOn[i] = maximum_from_EEPROM[i];
	}
}

Then I called it in Setup()

restore_sensor();                //Read sensor calibration values out of EEPROM into minimum_from_EEPROM and maximum_from_EEPROM arrays
qtra.resetCalibration();          //Run reset function from QTRA library, but instead of setting the value to 0, set to the values in the above arrays.

This didn’t work, and in the Serial Monitor I had what looked like an error about an overflow. What can I do to get the values from my minimum_from_EEPROM[4]; and maximum_from_EEPROM[4]; arrays into the library for use with QTRA?

Is this all I need to do, in the Setup()?

restore_sensor();                //Read sensor calibration values out of EEPROM into minimum_from_EEPROM and maximum_from_EEPROM arrays
qtra.calibratedMinimumOn[0] = minimum_from_EEPROM[0];
qtra.calibratedMinimumOn[1] = minimum_from_EEPROM[1];
qtra.calibratedMinimumOn[2] = minimum_from_EEPROM[2];
qtra.calibratedMinimumOn[3] = minimum_from_EEPROM[3];

qtra.calibratedMaximumOn[0] = maximum_from_EEPROM[0];
qtra.calibratedMaximumOn[1] = maximum_from_EEPROM[1];
qtra.calibratedMaximumOn[2] = maximum_from_EEPROM[2];
qtra.calibratedMaximumOn[3] = maximum_from_EEPROM[3];

I know I can use a For loop, but sometimes I like to see it spelled out…

Hi.

I suspect that your error is being caused because the calibratedMinimumOn[i] and calibratedMaximumOn[i] arrays never get allocated in the program you have that reads from EEPROM and sets those values. The description of the calibrate method in the QTR Reflectance Sensors section of the Pololu AVR Library Command Reference states that:

That guide is meant for use with our AVR libraries, rather than our Arduino library for these sensors, but they both handle the pointers the same way.

Could you try adding a call to the calibrate method before trying to write the stored maximum and minimum? If that does not work, could you try verifying that your methods to write and read EEPROM are working as you expect independently from the QTR sensor code?

-Claire

I’m using a QTR-8A, Mega2560 and EEPROMex http://thijs.elenbaas.net/2012/07/extended-eeprom-library-for-arduino/ for eeprom layer. I had the same problem, it drove me nuts for three days, until I’ve found Claire’s answer :slight_smile:

It was a mistery, why a save to eprom, followed by a restore from eprom, worked perfectly, but a restore without saving first, did not. If anyone interested, my program looks like:

  1. calling qtra.calibrate()for n times
  2. save values with a call like EEPROM.writeBlock<unsigned int>(addrCalibratedMinimumOn, qtra.calibratedMinimumOn, 8);

For restoring back the saved values,
3. one single call to qtra.calibrate() , then
4. restore the array using EEPROM.readBlock<unsigned int>(addrCalibratedMinimumOn, qtra.calibratedMinimumOn, 8);

In case you are using saved calibration data, just comment steps 1 and 2.

Regards,
Ciprian

Hi, Ciprian.

I am glad that you found this thread helpful. Thanks for posting the commands that worked for you.

-Claire

I just want to say thank you for the example you provided. It helped me write my own version of the code here: