Random errors on reading four TMP117 QWIIC sensors

Hello,

We are prototyping a product using 4 (four) SparkFun High Precision Temperature Sensors - TMP117 (Qwiic) on the same I2C port. Their addresses are configured correctly and most of the time they work fine, except for some ‘spikes’ in the read values.

We have not changed the pull-up resistors on any of the boards. Can you please indicate what should we try in order to avoid these erroneous random indications?

Other details of our configuration:

  • Arduino IDE ver 1.8.13

  • SparkFun_TMP117.h library

  • MCU board: Sodaq SARA SFF (processor Atmel SAMD21)

Is it only one sensor giving these spikes? (red?) - if so, it may be a defective board (head over here https://www.sparkfun.com/returns to get a replacement)

If not, please share the code being used.

Sometimes only one sensor gives out spikes (not necessarily the red one), other times all the 4 sensors’ values jump high or low with some un-natural values, not necessarily all in the same direction (i.e. some spikes are ‘upwards’, some are ‘downwards’).

Please find below the code we are using to get the measured values from the sensors.

Thank you,

Darius

= = = = = = = = = = = = = = =

TMP117 sensor1, sensor2, sensor3, sensor4;

bool isValid1 = false, isValid2 = false, isValid3 = false, isValid4 = false;

bool hasTemp1 = false, hasTemp2 = false, hasTemp3 = false, hasTemp4 = false;

long msTMP117Start = 0;

uint16_t msTMP117TIMEOUT = 2500;

int val_null = -99;

// sensor address

uint8_t ADDR1 = 0x48, ADDR2 = 0x49, ADDR3 = 0x4A, ADDR4 = 0x4B;

/* --------- INIT the sensors ------------------- */

void initTMP117(){

// 1. Check if the sensor will correctly self-identify with the proper Device ID/Address

beginSensors(1); beginSensors(2); beginSensors(3); beginSensors(4);

// 2. oneShotmeasurement, average = 1, cycle bit = 1 (125ms)

if (isValid1) {setOneshotMode(sensor1); sensor1.setConversionAverageMode(1); sensor1.setConversionCycleBit(1);}

if (isValid2) {setOneshotMode(sensor2); sensor2.setConversionAverageMode(1); sensor2.setConversionCycleBit(1);}

if (isValid3) {setOneshotMode(sensor3); sensor3.setConversionAverageMode(1); sensor3.setConversionCycleBit(1);}

if (isValid4) {setOneshotMode(sensor4); sensor4.setConversionAverageMode(1); sensor4.setConversionCycleBit(1);}

}

bool beginSensors(uint8_t idSensor) {

if (idSensor == 1) {

isValid1 = sensor1.begin(ADDR1, Wire);

if (isValid1) {DEBUG_STREAM.println(“I found 0x48 sensor”);}

else {DEBUG_STREAM.println(“Failed to setup sensor 0x48.”);}

return isValid1;

} else if (idSensor == 2) {

isValid2 = sensor2.begin(ADDR2, Wire);

if (isValid2) {DEBUG_STREAM.println(“I found 0x49 sensor”);}

else {DEBUG_STREAM.println(“Failed to setup sensor 0x49.”);}

return isValid2;

} else if (idSensor == 3) {

isValid3 = sensor3.begin(ADDR3, Wire);

if (isValid3) {DEBUG_STREAM.println(“I found 0x4A sensor”);}

else {DEBUG_STREAM.println(“Failed to setup sensor 0x4A.”);}

return isValid3;

} else {

isValid4 = sensor4.begin(ADDR4, Wire);

if (isValid4) {DEBUG_STREAM.println(“I found 0x4B sensor”);}

else {DEBUG_STREAM.println(“Failed to setup sensor 0x4B.”);}

return isValid4;

}

}

bool setOneshotMode(TMP117 sensor) {

sensor.setOneShotMode();

if (sensor.getConversionMode() == 3 ) { return true;}

return false;

}

/* --------- STATES MACHINE FOR TMP117 VALUES READINGS ------------------- */

int ReadTemperatures(int sens_status) {

// *** (STATE == 0) GENERAL INIT *************************************

if (sens_status == 0 ){

delayMicroseconds (5000);

hasTemp1 = false; hasTemp2 = false; hasTemp3 = false; hasTemp4 = false;

tmp117.T1 = val_null; tmp117.T2 = val_null; tmp117.T3 = val_null; tmp117.T4 = val_null;

sens_status = 1;

// *** (STATE == 1) INIT SENSOR 1 *******************************

} else if (sens_status == 1) {

sens_status = init_temp_sensor (sensor1, 1, sens_status);

// *** (STATE == 2) READ SENSOR 1 *******************************

} else if (sens_status == 2) {

sens_status = read_temp_sensor(sensor1, 1, sens_status, hasTemp1);

// *** (STATE == 3) INIT SENSOR 2 *******************************

} else if (sens_status == 3) {

sens_status = init_temp_sensor (sensor2, 2, sens_status);

// *** (STATE == 4) READ SENSOR 2 *******************************

} else if (sens_status == 4) {

sens_status = read_temp_sensor(sensor2, 2, sens_status, hasTemp2);

// *** (STATE == 5) INIT SENSOR 3 *******************************

} else if (sens_status == 5) {

sens_status = init_temp_sensor (sensor3, 3, sens_status);

// *** (STATE == 6) READ SENSOR 3 *******************************

} else if (sens_status == 6) {

sens_status = read_temp_sensor(sensor3, 3, sens_status, hasTemp3);

// *** (STATE == 7) INIT SENSOR 4 *******************************

} else if (sens_status == 7) {

sens_status = init_temp_sensor (sensor4, 4, sens_status);

// *** (STATE == 8) READ SENSOR 4 *******************************

} else if (sens_status == 8) {

sens_status = read_temp_sensor(sensor4, 4, sens_status, hasTemp4);

// *** (STATE == 9) DISPLAY DATA ********************

} else if (sens_status == 9) {

displayTMP117("TMP117 values ", tmp117);

sens_status = 0;

delay(60000);

}

return sens_status;

}

uint8_t init_temp_sensor (TMP117& _sensor, uint8_t _idSensor, int _status) {

bool result = false;

msTMP117Start = millis(); // used for timeout

result = beginSensors(_idSensor); // init temperature sensor

if(!result) {return (_status + 2);} // sensor not valid (not found) → no reading

result = setOneshotMode(_sensor); // set ONE SHOT MODE

if (!result) {

DEBUG_STREAM.print(F("Error setting one shot mode, for sensor "));

DEBUG_STREAM.println(_idSensor);

}

delayMicroseconds (150000); // wait for temperature to be ready

return (_status + 1); // next state

}

uint8_t read_temp_sensor(TMP117& _sensor, uint8_t _idSensor, int _status, bool& _hasTemp) {

if (!_hasTemp) {_hasTemp = readTemp(_sensor, _idSensor);}

if (_hasTemp) {

return (_status + 1); // it’s OK → next state

} else if ((millis() - msTMP117Start) > msTMP117TIMEOUT) {

if (!_hasTemp) {

DEBUG_STREAM.print(F("For TMP117 sensor "));

DEBUG_STREAM.print(_idSensor); DEBUG_STREAM.println(F(“, timeout occured!”));

}

return (_status + 1); // timeout → next state

}

return _status;

}

bool readTemp(TMP117& sensor, byte id) {

// read and save value from sensor

float tempC = val_null;

if (sensor.dataReady() == true) {

tempC = sensor.readTempC();

if (tempC != val_null) {

if (id == 1) {tmp117.T1 = tempC;}

else if (id == 2) {tmp117.T2 = tempC;}

else if (id == 3) {tmp117.T3 = tempC;}

else if (id == 4) {tmp117.T4 = tempC;}

return true;

}

}

return false;

}

void printTMP117settings(){

DEBUG_STREAM.println(F(" "));

printTMP117settings(sensor1, isValid1); // display setttings for sensor 1

printTMP117settings(sensor2, isValid2); // display setttings for sensor 2

printTMP117settings(sensor3, isValid3); // display setttings for sensor 3

printTMP117settings(sensor4, isValid4); // display setttings for sensor 4

}

void printTMP117settings(TMP117 sensor, bool isValid) {

if (isValid) {

DEBUG_STREAM.print(F("Sensor "));

DEBUG_STREAM.print(sensor.getAddress(), HEX);

DEBUG_STREAM.print(F(", mode "));

DEBUG_STREAM.print(sensor.getConversionMode());

DEBUG_STREAM.print(F(", average "));

DEBUG_STREAM.print(sensor.getConversionAverageMode());

DEBUG_STREAM.print(F(", cycle bit "));

DEBUG_STREAM.print(sensor.getConversionCycleBit());

DEBUG_STREAM.print(F(", offset "));

DEBUG_STREAM.println(sensor.getTemperatureOffset());

} else {

DEBUG_STREAM.print(F("Sensor "));

DEBUG_STREAM.print(sensor.getAddress(), HEX);

DEBUG_STREAM.println(F(“, mode /, average /, cycle bit /, offset /”));

}

}

void displayTMP117(const char header[25], TMP117Data tmpSOIL) {

byte decimal = 7;

DEBUG_STREAM.print(F(“\r\n”)); DEBUG_STREAM.println(F(header));

DEBUG_STREAM.print(F("TEMP 1 = "));

DEBUG_STREAM.print(tmpSOIL.T1, decimal);

DEBUG_STREAM.print(F(", TEMP 2 = "));

DEBUG_STREAM.print(tmpSOIL.T2, decimal);

DEBUG_STREAM.print(F(", TEMP 3 = "));

DEBUG_STREAM.print(tmpSOIL.T3, decimal);

DEBUG_STREAM.print(F(", TEMP 4 = "));

DEBUG_STREAM.println(tmpSOIL.T4, decimal);

}

The hookup guide https://learn.sparkfun.com/tutorials/qw … 1615791300 mentions a couple things that might be helpful here

“Note: For accurate readings, make sure to avoid heavy bypass traffic on the I2C bus and use the highest available communication speed. That is, try to not add too many I2C devices talking on the same bus or stretch your clock signal.” - please share a diagram of your wiring setup, and how the sensors are arranged on the i2c bus - if you have more i2c ports available, you may experience fewer anomalies by spreading traffic over them

"Pull-Up Resistors

The board also includes jumpers to disable the pull-up resistors on the I2C bus line. If you are using a few I2C devices on the same bus that already have pull-up resistors on their respective boards, you may want to cut the jumpers to disconnect. This is for special use cases when daisy chaining about 7x I2C devices on the same bus. Keep in mind that you will want to avoid heavy bypass traffic on the I2C bus if you are trying to take accurate readings." - even though you are using 4, this might be an issue?

Not sure what the cause might be, but a quick solution would be to check to see if the new reading is significantly different than the previous readings. If it is, assume you received a bad read and take another.

Thanks a lot, @TS-Russel and @TS-Chris. We are already reading twice and, if the values are different, reading again twice (as the third read would not necessarily provide the ‘true’ value.

Did you notice something bad in our code?

Sincerely,

Darius

I did not notice anything obvious…Perhaps try TS-Chris’ suggestion and add-in a running average variable that tosses out readings that are >5 degreees from the last one?

Thanks again, Russell. We thought about applying some signal processing to filter out the spikes, but are still trying to find and eliminate the root cause. We shall try first to find out whether this behaviour will disappear when leaving just one set of resistors, on one of the four boards.

Hello,

I hereby confirm that removing the pullup resistors on three of the four SparkFun High Precision Temperature Sensors - TMP117 (Qwiic) has solved the problem :slight_smile: . Spikes did not appear anymore.

Thanks for your support,

Best Regards,

Darius

Good to hear, and thanks for sharing!