Does the Qwiic MLX90614 module support I2C fast mode?

I am able to read the temperature fine with the standard I2C speed. However, I need to log other sensors on the bus at 25Hz which requires me to use Fast Mode on the I2C bus (Wire.setClock(400000):wink:

When I do this, I no longer am able to communicate with the MLX90614 sensor.

Is it possible to use this sensor in I2C Fast Mode?

The MLX90614 supports between 10Khz and 100Khz.

25Hz is not the same as setting Wire to 400KHZ. Which sensor is that ?

Iā€™m using this product: Qwiic IR Thermometer - MLX90614 (https://www.sparkfun.com/products/17522)

I am trying to build a data logger that samples: GPS, IMU and IR Temp at 25Hz.

When I switch the I2C bus to FastMode (myWire.setClock(400000)), the GPS and IMU data is great but I lose the IR Temp.

When I switch the I2C bus to Normal Mode (myWire.setClock(100000)), I get all 3 sensors; however, the GPS sensor drops out 2 or 3 times per second. (There is a comment in the GPS example code that says FastMode is needed when sampling higher rates.)

https://www.sparkfun.com/products/15712 (SparkFun GPS Breakout - NEO-M9N, U.FL (Qwiic))

Here is my code:

#include <Wire.h> //Needed for I2C
#define myWire Wire // Connect using the Wire1 port. Change this if required

//=========
//GPS
//=========
#include <SparkFun_u-blox_GNSS_v3.h> //http://librarymanager/All#SparkFun_u-blox_GNSS_v3
SFE_UBLOX_GNSS myGPS;

//==============
// ICM
//==============
#include "ICM_20948.h" // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU
ICM_20948_I2C myICM; // Create an ICM_20948_I2C object

//===================
// MLX90614 - IR Temp
//===================
#include <SparkFunMLX90614.h> //Click here to get the library: http://librarymanager/All#Qwiic_IR_Thermometer by SparkFun
IRTherm therm; // Create an IRTherm object to interact with throughout

void setup()
{
  Serial.begin(115200);
  delay(1000); 

  Serial.println("Starting Data Logger...");

  myWire.begin(); // Start I2C

  //Init IR Sensor
  while (!therm.begin() ){ // Initialize thermal IR sensor
    Serial.println(" IR thermometer did not acknowledge! ");
    delay(1000);
  }
  therm.setUnit(TEMP_F); // Set the library's units to Farenheit

  //Init GPS
  while (myGPS.begin() == false) //Connect to the u-blox module using our custom port and address
  {
    Serial.println(F("u-blox GNSS not detected. Retrying..."));
    delay (1000);
  }

  myGPS.setI2COutput(COM_TYPE_UBX); // Turn on both UBX and NMEA sentences on I2C. (Turn off RTCM and SPARTN)
  myGPS.setNavigationFrequency(25);
  myGPS.setHighPrecisionMode(true);
  myGPS.setAutoPVT(true);
  myGPS.saveConfiguration();
  
  //Init ICM
  bool initialized = false;
  while (!initialized)
  {
    myICM.begin();
    if (myICM.status != ICM_20948_Stat_Ok)
    {
      Serial.println("ICM: Trying again...");
      delay(500);
    }
    else
    {
      initialized = true;
    }
  }
  myWire.setClock(100000); 
}

unsigned long previousMillis = 0; 
const long interval = 40;  // interval at which to blink (milliseconds) - 40 = 25Hz

void loop()
{
  unsigned long currentMillis = millis();
  String output = "";
  String temp;

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    //Log GPS
    if (myGPS.getPVT() == true)
    {
      output =  String(myGPS.getYear()) + "-" + 
                _padLeftZeroes(String(myGPS.getMonth()), 2) + "-" + 
                _padLeftZeroes(String(myGPS.getDay()), 2) + " " +
                _padLeftZeroes(String(myGPS.getHour()), 2) + ":" + 
                _padLeftZeroes(String(myGPS.getMinute()), 2) + ":" + 
                _padLeftZeroes(String(myGPS.getSecond()), 2) + "." + 
                _padLeftZeroes(String(myGPS.getMillisecond()), 3);
                
      output = output + ",";
      output = output + String(myGPS.getLatitude() / 10000000);
      output = output + ",";
      output = output + String(myGPS.getLongitude() / 10000000);
      output = output + ",";
      output = output + String(myGPS.getAltitudeMSL() / 304.8);
    }
    else {
      output = ",,,";
    }

    //Log ICM
    myICM.getAGMT();
    output = output + ",";
    output = output + String(myICM.accX()) + ",";
    output = output + String(myICM.accY()) + ",";
    output = output + String(myICM.accZ()) + ",";

    output = output + String(myICM.gyrX()) + ",";
    output = output + String(myICM.gyrY()) + ",";
    output = output + String(myICM.gyrZ()) + ",";

    output = output + String(myICM.magX()) + ",";
    output = output + String(myICM.magY()) + ",";
    output = output + String(myICM.magZ()) + ",";

    //Log IR Temp
    if (therm.read()) // On success, read() will return 1, on fail 0.
    {
      // Use the object() and ambient() functions to grab the object and ambient
      // temperatures.
      // They'll be floats, calculated out to the unit you set with setUnit().
      output = output + String(therm.object(), 2) + ",";
      output = output + String(therm.ambient(), 2);
    }
    else {
      output = output + ",";
    }
    Serial.println(output);
  }
}

String _padLeftZeroes(String in, int len) {
  while (in.length() < len) {
    in = "0" + in;
  }
  return in;
}

Thanks understand now.

Which processor board do you use ? Maybe a second Wire channel can be enabled ?

As testā€¦ set the Wire speed to 100Khz before any interaction (init / reading etc) with the MLX and reset to to 400Khz ? Maybe combine this with reading the MLX every X-seconds instead of 25HZ. An object temperature does not change THAT fast !

The MLX90614 data sheet does not seem to specify a maximum data output rate, but it does give a factory default ā€œsettling timeā€ for the digital filter, which ranges from 0.1 seconds to 1.33 seconds, depending on which model you have).

Perhaps you can get around that, but if not, 10 Hz is the fastest sensible readout frequency.

paulvha:
Which processor board do you use ? Maybe a second Wire channel can be enabled ?

Teensy MicroMod board

Having worked on the Teensy before, I know it uses a different library approach than all the other boards. Much of the definitions is in different files and spread all over the place, where most boards use the variant-folder approach. So you have to deepdive to find out.

The Teensy Micromod seems to have 4 (!) Wire instances.

           Teensy pin      MicroMod         naming
                           connector
Wire   
    SDA       18            12              I2C-SDA
    SCL       19            14              I2C-SCL
Wire1
    SDA       25            51              I2C-SDA1
    SCL       24            53              I2C-SCL1
Wire2
    SDA       17            22              TX2
    SCL       16            20              RX2
Wire3
    SDA       41            42              G1/BUS1
    SCL       40            40              G0/BUS0

Depending on the Micromod carrier board you have, you may be able to select another Wire instance and set a different speed.