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)
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.
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.