SparkFun Forums 

Where electronics enthusiasts find answers.

Hardware or product specific questions are best asked here.
User avatar
By leandro_jesus_eng
#229602
I changed the OpenLog_Artemis_V10-v20 firmware to use the Qwiic IR Thermometer - MLX90614 sensor.
I made two different implementations, one uses the SparkFunMLX90614.h library and the other implementation uses the Adafruit_MLX90614.h library. In both implementations I have the same problem, when reading the I2C data the values ​​I get are always at a high level. I believe I will have to use a logic level converter. I tested it with Arduino Uno and had no problem. Does anyone have any ideas?
#229605
Hi,

The standard OpenLog Artemis firmware does not support the MLX90614. To add it, you would need to follow all of the steps here:
https://github.com/sparkfun/OpenLog_Art ... SENSORS.md

Once you have done that, I believe it should work. But I do not have an MLX90614 to test it.

If you are trying to use the MLX90614 library on its own, without using the OLA firmware, then the main thing you will need to do is to enable power for the Qwiic interface. You will need to include:

The Qwiic port and pin definitions:
https://github.com/sparkfun/OpenLog_Art ... o#L77-L113

beginQwiic():
https://github.com/sparkfun/OpenLog_Art ... g.ino#L164
https://github.com/sparkfun/OpenLog_Art ... #L491-L497

and the Qwiic power functions:
https://github.com/sparkfun/OpenLog_Art ... #L450-L467

When you call the therm.begin, you will need to use the format:
therm.begin(MLX90614_DEFAULT_ADDRESS, qwiic);

Best wishes,
Paul
User avatar
By leandro_jesus_eng
#229606
paulvha wrote: Fri Nov 12, 2021 2:42 am instead of including in openlog firmware, try to load example2 with the standard library to the openlog board. So what happens...
Thank you so much for replying quickly.

I ran example 2.
The first error is a compilation error in the SparkFunMLX90614.h library because PIN_WIRE_SDA and PIN_WIRE_SCL have not been set. I solved it.

The second error I get the message "asdasd". This is because the ports used for i2c communication by default are different in Artemis. In Artemis the qwiic communication needs to be energized before starting the communication.

The conclusion I come to is that the SparkFunMLX90614.h library and examples need a lot of changes to make it work in Artemis.

I think I'd better spend my time solving this issue within the OpenLogArtemis firmware.

Thank you very much for your considerations.
User avatar
By leandro_jesus_eng
#229608
PaulZC wrote: Fri Nov 12, 2021 2:46 am Hi,

The standard OpenLog Artemis firmware does not support the MLX90614. To add it, you would need to follow all of the steps here:
https://github.com/sparkfun/OpenLog_Art ... SENSORS.md

Once you have done that, I believe it should work. But I do not have an MLX90614 to test it.

If you are trying to use the MLX90614 library on its own, without using the OLA firmware, then the main thing you will need to do is to enable power for the Qwiic interface. You will need to include:

The Qwiic port and pin definitions:
https://github.com/sparkfun/OpenLog_Art ... o#L77-L113

beginQwiic():
https://github.com/sparkfun/OpenLog_Art ... g.ino#L164
https://github.com/sparkfun/OpenLog_Art ... #L491-L497

and the Qwiic power functions:
https://github.com/sparkfun/OpenLog_Art ... #L450-L467

When you call the therm.begin, you will need to use the format:
therm.begin(MLX90614_DEFAULT_ADDRESS, qwiic);

Best wishes,
Paul
Hi Paul,

I was really fan of the work you guys did with OpenLogArtemis. Congratulations.

Thank you very much for the tips. I will try to use the sensor outside the OpenLogArtemis firmware.

But my object is to change the firmware and integrate this sensor. I followed all the recommendations described in ADDING_SENSORS.md.

When I'm done I'll post the changes for you to review.

To work!
#229615
Understand the extra work this takes.

Just out of interest I have connected an MLX90615 that I have around. It has similar specifications to the MLX90614 but not completely the same and different register addresses. BUT they are part of the same family and design. Their interface is very much the same.

Now the fun part.. compiled and connected to an Arduino UNO gives good results (around 21 C), compiling the same sketch but now for an Artemis ATP gives me 1037C... What ? Actually checking with a logic analyzer (or you can include print statements in readreg) shows that the ATP is constant receiving 0xffff

Checked the 3v3, in both cases that is 3.25V. So it is not the power supply.

Then looked with a logic analyzer. The time between writing the register address and starting reading from that address on the UNO takes 16.2us, the time on the ATP takes 98.7us. SAME CODE !!

So what ? one could think.. well according to the datasheet of the MLX90615 :
Code: Select all
Timeout H is the maximum time for which it is allowed for SCL to be high during communication. After
this time MLX90615 will reset its communication block assuming that the bus is idle (according to the SMBus
specification) - not more than 52µs
This means that the MLX90615 with the ATP is now reset and sending incorrect data.

For an MLX90614 the timeout H is 50us (according to the datasheet).

I suspect this is the reason why you get high results. I also suspect this is because of Mbed overhead, which is part of V2. When creating SoftwareSerial for V2 I run into similar microsecond issues.

I will try to spend more time analyzing in the coming days.
User avatar
By leandro_jesus_eng
#229616
I made changes to Example2 that comes with the library to try to make it work in Artemis.
I get the same message: "Qwiic IR thermometer did not acknowledge! Freezing!"
Code: Select all

#include <Wire.h> // I2C library, required for MLX90614
#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

// OLA Specifics:
//Setup Qwiic Port
#include <Wire.h>
const byte PIN_QWIIC_SCL = 8;
const byte PIN_QWIIC_SDA = 9;
TwoWire qwiic(PIN_QWIIC_SDA,PIN_QWIIC_SCL); //Will use pads 8/9

//Define the pin functions
//Depends on hardware version. This can be found as a marking on the PCB.
//x04 was the SparkX 'black' version.
//v10 was the first red version.
#define HARDWARE_VERSION_MAJOR 1
#define HARDWARE_VERSION_MINOR 0

#if(HARDWARE_VERSION_MAJOR == 0 && HARDWARE_VERSION_MINOR == 4)
const byte PIN_MICROSD_CHIP_SELECT = 10;
const byte PIN_IMU_POWER = 22;
#elif(HARDWARE_VERSION_MAJOR == 1 && HARDWARE_VERSION_MINOR == 0)
const byte PIN_MICROSD_CHIP_SELECT = 23;
const byte PIN_IMU_POWER = 27;
const byte PIN_PWR_LED = 29;
const byte PIN_VREG_ENABLE = 25;
const byte PIN_VIN_MONITOR = 34; // VIN/3 (1M/2M - will require a correction factor)
#endif

const byte PIN_POWER_LOSS = 3;
const byte PIN_MICROSD_POWER = 15;
const byte PIN_QWIIC_POWER = 18;
const byte PIN_STAT_LED = 19;
const byte PIN_IMU_INT = 37;
const byte PIN_IMU_CHIP_SELECT = 44;
const byte PIN_STOP_LOGGING = 32;
const byte BREAKOUT_PIN_32 = 32;
const byte BREAKOUT_PIN_TX = 12;
const byte BREAKOUT_PIN_RX = 13;
const byte BREAKOUT_PIN_11 = 11;


void setup() 
{
  Serial.begin(115200); // Initialize Serial to log output
  
  //Wire.begin(); //Joing I2C bus
  beginQwiic(); // Turn the qwiic power on as early as possible
  
  if (therm.begin(MLX90614_DEFAULT_ADDRESS, qwiic) == false){ // Initialize thermal IR sensor
    Serial.println("Qwiic IR thermometer did not acknowledge! Freezing!");
    while(1);
  }
  Serial.println("Qwiic IR Thermometer did acknowledge.");
  
  therm.setUnit(TEMP_F); // Set the library's units to Farenheit
                         // Alternatively, TEMP_F can be replaced with TEMP_C for Celsius or
                         // TEMP_K for Kelvin.
  
  pinMode(LED_BUILTIN, OUTPUT); // LED pin as output
}

void loop() 
{
  digitalWrite(LED_BUILTIN, HIGH);
    
  // Call therm.read() to read object and ambient temperatures from the sensor.
  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().
    Serial.print("Object: " + String(therm.object(), 2));
    Serial.println("F");
    Serial.print("Ambient: " + String(therm.ambient(), 2));
    Serial.println("F");
    Serial.println();
  }
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}



void beginQwiic()
{
  pinMode(PIN_QWIIC_POWER, OUTPUT);
  qwiicPowerOn();
  qwiic.begin();
  setQwiicPullups(0); //Just to make it really clear what pull-ups are being used, set pullups here.
}

void setQwiicPullups(uint32_t i2cBusPullUps)
{
  //Change SCL and SDA pull-ups manually using pin_config
  am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM1_SCL;
  am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM1_SDA;

  if (i2cBusPullUps == 0)
  {
    sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // No pull-ups
    sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
  }
  else if (i2cBusPullUps == 1)
  {
    sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K; // Use 1K5 pull-ups
    sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K;
  }
  else if (i2cBusPullUps == 6)
  {
    sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_6K; // Use 6K pull-ups
    sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_6K;
  }
  else if (i2cBusPullUps == 12)
  {
    sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_12K; // Use 12K pull-ups
    sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_12K;
  }
  else
  {
    sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_24K; // Use 24K pull-ups
    sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_24K;
  }

  pin_config(PinName(PIN_QWIIC_SCL), sclPinCfg);
  pin_config(PinName(PIN_QWIIC_SDA), sdaPinCfg);
}

void qwiicPowerOn()
{
  pinMode(PIN_QWIIC_POWER, OUTPUT);
#if(HARDWARE_VERSION_MAJOR == 0)
  digitalWrite(PIN_QWIIC_POWER, LOW);
#else
  digitalWrite(PIN_QWIIC_POWER, HIGH);
#endif
}

void qwiicPowerOff()
{
  pinMode(PIN_QWIIC_POWER, OUTPUT);
#if(HARDWARE_VERSION_MAJOR == 0)
  digitalWrite(PIN_QWIIC_POWER, HIGH);
#else
  digitalWrite(PIN_QWIIC_POWER, LOW);
#endif
}
User avatar
By leandro_jesus_eng
#229618
paulvha wrote: Fri Nov 12, 2021 10:59 am Understand the extra work this takes.

Just out of interest I have connected an MLX90615 that I have around. It has similar specifications to the MLX90614 but not completely the same and different register addresses. BUT they are part of the same family and design. Their interface is very much the same.

Now the fun part.. compiled and connected to an Arduino UNO gives good results (around 21 C), compiling the same sketch but now for an Artemis ATP gives me 1037C... What ? Actually checking with a logic analyzer (or you can include print statements in readreg) shows that the ATP is constant receiving 0xffff

Checked the 3v3, in both cases that is 3.25V. So it is not the power supply.

Then looked with a logic analyzer. The time between writing the register address and starting reading from that address on the UNO takes 16.2us, the time on the ATP takes 98.7us. SAME CODE !!

So what ? one could think.. well according to the datasheet of the MLX90615 :
Code: Select all
Timeout H is the maximum time for which it is allowed for SCL to be high during communication. After
this time MLX90615 will reset its communication block assuming that the bus is idle (according to the SMBus
specification) - not more than 52µs
This means that the MLX90615 with the ATP is now reset and sending incorrect data.

For an MLX90614 the timeout H is 50us (according to the datasheet).

I suspect this is the reason why you get high results. I also suspect this is because of Mbed overhead, which is part of V2. When creating SoftwareSerial for V2 I run into similar microsecond issues.

I will try to spend more time analyzing in the coming days.
Hi, you got to the same stage as me and diagnosed that the return value was always 0xffff. I think I was happy, maybe I'm not so lost.

Great datasheet analysis! I didn't know about this timeout.

Unfortunately, the problem is bigger than my knowledge of the field so far. I don't know how to go about solving this problem.
#229619
This is something that needs to be solved with the V2 library. Nothing you can do on the driver/application level. The I2C on the Artemis is having a couple of challenges, this is just adding to the list. If Openlog on V1 is still available try using that MBED is only part of V2 and brings new features BUT also a lot of overhead.
#229638
I have tested on Apollo3 library V1.2.1. It provides good results, but the timing is very critical as there is 49.1us between requesting a register address content and starting to read. (as a reminder there 50us is the maximum according to the datasheet) So it looks that V2 is adding about 40us. More work to analyze and find a potential solution to reduce the time.
#229709
I have done a deep dive on the I2C for Apollo3 to understand what is going on and how that relates to the SMBUS specifications as the MLX90614 / MLX 90615 has adopted that. Attached is a detailed document but in short the conclusions :
  • The Apollo3 V1.x library can be compatible with SMBUS 2.0 specifications starting at 200Khz. Of course your device needs to support that.
  • The Apollo3 v2.x library is NOT compatible with the SMBUS 2.0 specifications given the 50us boundary. As such MLX-9061x will not work with V2 over I2C.
Will now try to see whether it can be interfaced using PWM
You do not have the required permissions to view the files attached to this post.
#229892
A took some time, but I was able to set the MLX90614 in PWM mode and read it on the Apollo3 ATP board, either running V1.x or V2.x library. The attached zip file has sketches and descriptions on how to switch between SMBUS and PWM mode (and back again if you like) and a sketch to read in PWM mode (e.g. on an ATP).
You do not have the required permissions to view the files attached to this post.
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum