Gen 3 Device Support for Repeated Start I2C Requests?

Can gen 3 particle products (specifically Boron) support I2C repeated start?

I’m working with the Melexis MLX90614 5V infrared temperature sensor and a Boron LTE for a contactless temperature station. However it appears that for proper operation the sensor requires I2C repeated-start communication.

It does not appear that I2C repeated-start works natively, but I’m wondering: Can I2C repeated start functionality be added using a library?
If not, could I2C be extended via future updates to the particle Device OS?

For example, I was able to get the MLX90614 example sketch working properly on an arduino uno board by using 10KΩ pull up resistors on the SCL and SDA lines using the Adafruit_MLX90614 library.

However when using the same circuit connected to a Boron device along with examples from any of the following MLX90614 libraries:

  1. Adafruit_MLX90614 - This library demo just returns the max reading values:
    “Ambient = 1037.55C Object = 1037.55C
    Ambient = 1899.59F Object = 1899.59F”

  2. SparkfunMLX90614 - This library’s therm.begin() call always fails, returning a 0.

To me it appears that the I2C repeated start condition is the cause. All of the posts I’ve seen on the particle community forums which relate to the MLX90614 and their related particle cloud libraries were using the photon devices but I cannot get this working on a Boron or Argon device.

If anyone has experience using I2C repeated start sensors on gen 3 devices, any help with that process or any examples would be greatly appreciated. :slightly_smiling_face:

References:
Datasheet for the MLX90614
Arduino Uno Example that worked

Can you put the sensor in 400khz I2C mode?

I had to do that for a battery management chip that required repeated start under the SmBus standard.

Thanks for the suggestion.

I couldn’t find any information on the datasheet related to I2C clock speed. I did enable the 400Khz mode, but saw no change in operation.

Included this line before mlx.begin() which then calls Wire.begin()

// set the I2C clock speed to 400Khz
Wire.setSpeed(CLOCK_SPEED_400KHZ);

Adafruit_MLX90614 mlxtest.ino

/***************************************************
  This is a library example for the MLX90614 Temp Sensor

  Designed specifically to work with the MLX90614 sensors in the
  adafruit shop
  ----> https://www.adafruit.com/products/1748
  ----> https://www.adafruit.com/products/1749

  These sensors use I2C to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Adafruit_MLX90614.h>
#include <Wire.h>

Adafruit_MLX90614 mlx = Adafruit_MLX90614();

void setup() {
  Serial.begin(9600);

  Serial.println("Adafruit MLX90614 test");
  Serial.println("Set clock speed");
  Wire.setSpeed(CLOCK_SPEED_400KHZ);

  mlx.begin();
}

void loop() {
  Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempC());
  Serial.print("*C\tObject = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C");
  Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempF());
  Serial.print("*F\tObject = "); Serial.print(mlx.readObjectTempF()); Serial.println("*F");

  Serial.println("Start Delay");
  delay(10000);
}

Sample output:

Adafruit MLX90614 test
Set clock speed
Ambient = 1037.55*C     Object = 1037.55*C
Ambient = 1899.59*F     Object = 1899.59*F
Start Delay
Ambient = 1037.55*C     Object = 1037.55*C
Ambient = 1899.59*F     Object = 1899.59*F
Start Delay
Ambient = 1037.55*C     Object = 1037.55*C
Ambient = 1899.59*F     Object = 1899.59*F
Start Delay

When attempting to use the SparkfunMLX90614, the overall result is similar. Obviously, it’s a different library, but therm.read() returns false. Are you aware of any tools available to debug the I2C communication at a lower level?

Looking deeper into the library, these are the two functions doing most of the communication work:

// Adafruit_MLX90614
float Adafruit_MLX90614::readTemp(uint8_t reg) {
  float temp;

  temp = read16(reg);
  temp *= .02;
  temp  -= 273.15;
  return temp;
}

/*********************************************************************/

uint16_t Adafruit_MLX90614::read16(uint8_t a) {
  uint16_t ret;

  Wire.beginTransmission(_addr); // start transmission to device
  Wire.write(a); // sends register address to read from
  Wire.endTransmission(false); // end transmission

  Wire.requestFrom(_addr, (uint8_t)3);// send data n-bytes read
  ret = Wire.read(); // receive DATA
  ret |= Wire.read() << 8; // receive DATA

  uint8_t pec = Wire.read();

  return ret;
}

For now, I will create the project with this library locally so I can insert debug statements in the library, specifically trying to see the data that is pass to and from the Wire statements. Any other suggestions would be appreciated.

I didn’t enable 400Hz I2C on the Argon but only on the battery chip.