Skip to content

[I2C] MLX90614 temp sensor not working over ESP32 I2C interface #2408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
marquesn opened this issue Jan 30, 2019 · 24 comments
Closed

[I2C] MLX90614 temp sensor not working over ESP32 I2C interface #2408

marquesn opened this issue Jan 30, 2019 · 24 comments
Labels
Status: Stale Issue is stale stage (outdated/stuck)

Comments

@marquesn
Copy link

Hardware:

Board: ESP-WROOM-32 (ESP32_DevKitc_V4)
Core Installation version: 1.0.1
IDE name: Arduino IDE
Flash Frequency: 80Mhz
PSRAM enabled: No
Upload Speed: 921600
Computer OS: Windows 10

Description:

I have been trying to get a MLX90614 IR temperature sensor to work with the ESP32 - this sensor makes use of the I2C interface. However, the values are always reported back as 1037 C and 1899F.

I have been using pins 22 and 21 for SCL and SDA, and have tried supplying the sensor with both 3.3V and 5V. I have also connected 4.7K pull-up resistors to the SDA and SCL lines (also tried 2K7, 10K, and with no pull-ups).

I am using the "Adafruit_MLX90614" library, and have also tried to use the Sparkfun MLX90614 (although Sparkfun is giving me a compiling error when trying to compile for the ESP32). I have also tried to connect another MLX90614 to the ESP32 on the off chance that one of them might've just been broken, but the results were the same.

I have also seen similar issues to this as in:
#1694
#2089
#1962

Based on the solutions provided in the links shown above, I also tried to update the latest version of the arduino-esp32 using the arduino boards manager to version 1.0.1.

Sketch:

#include <Wire.h>
#include <Adafruit_MLX90614.h>
 
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
 
void setup()
{
  Serial.begin(9600);
  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();
  delay(1000);
}
@marquesn
Copy link
Author

marquesn commented Feb 1, 2019

I've been struggling with this issue for almost a week now and have tried all I2C and Wire files from the latest version of this repo. Would very much appreciate some feedback on this....

@stickbreaker
Copy link
Contributor

@marquesn I don't have access to MLX90614 so I can't directly test it.

I looked at the adafruit library, it is very simple and does not test for any error codes / i2c failure codes.

I recommend you add debug code to your copy of the library and see what errors are being returned by i2c(Wire).

Change every Wire.endTransmission() into:

uint_8 err = Wire.endTransmission();
if(err != 0) {
  Serial.printf("fail %d(%s)/n",err, Wire.getErrorText(err));
}

// after each requestFrom() add
if(Wire.lastError() !=0 ){
Serial.printf("fail %d(%s)/n",err, Wire.getErrorText(err));
}

See what is actually happening.

Chuck.

@marquesn
Copy link
Author

marquesn commented Feb 1, 2019

@stickbreaker Many thanks for having a look at this!

I've inserted that piece of code into the Adafruit library and I got the following in the serial output window:

ɭշ⸮⸮8⸮"/-n^.p⸮�⸮⸮5Q⸮N⸮⸮⸮[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
fail 2(ACK)/nfail 2(ACK)/n1037.55*C
Ambient = fail 2(ACK)/nfail 2(ACK)/n1899.59*F	Object = fail 2(ACK)/nfail 2(ACK)/n1899.59*F

Ambient = fail 2(ACK)/nfail 2(ACK)/n1037.55*C	Object = fail 2(ACK)/nfail 2(ACK)/n1037.55*C
Ambient = fail 2(ACK)/nfail 2(ACK)/n1899.59*F	Object = fail 2(ACK)/nfail 2(ACK)/n1899.59*F

@marquesn
Copy link
Author

marquesn commented Feb 1, 2019

There was only one

Wire.endTransmission(false);

But if instead of:

uint8_t err = Wire.endTransmission();

I change it to:

uint8_t err = Wire.endTransmission(false);

I get the following:

⸮⸮⸮⸮⸮⸮8⸮⸮2⸮⸮Շ⸮⸮i�Q⸮qm⸮555ԡx⸮⸮⸮⸮⸮⸮⸮⸮[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
=Ambient = fail 0(OK)/n1037.55*C	Object = fail 0(OK)/n1037.55*C
Ambient = fail 0(OK)/n1899.59*F	Object = fail 0(OK)/n1899.59*F

Ambient = fail 0(OK)/n1037.55*C	Object = fail 0(OK)/n1037.55*C
Ambient = fail 0(OK)/n1899.59*F	Object = fail 0(OK)/n1899.59*F

@stickbreaker
Copy link
Contributor

@marquesn ok, that is telling you the I2C communication succeeded.
now you need to look at the data it received.
Write out the raw data byte from the sensor.

 // where it receives data with Wire.read(), print the raw byte out
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
  uint8_t err =  Wire.endTransmission(false); // end transmission
  if(err !=0){
    Serial.printf("Selecting sensor register failed =%d(%s)\n",err, Wire.getErrorText(err)));
  }
  uint8_t count =Wire.requestFrom(_addr, (uint8_t)3);// send data n-bytes read
  If(count != 3){
    Serial.printf("Receiving sensor data failed, expected 3 bytes received %d.\n Wire() error =%d(%s)\n",
     count,Wire.lastError(),Wire.getErrorText(Wire.lastError()));
  }
  uint8_t raw = Wire.read();
  Serial.printf(" first byte = 0x%02x",raw);
  ret = raw; // receive DATA
  raw = Wire.read();
   Serial.printf(" Second Byte = 0x%02x\n",raw);
  ret |= raw << 8; // receive DATA

  uint8_t pec = Wire.read();
  Serial.printf(" pec=0x%02x\n", pec);
  return ret;
}

Chuck.

@marquesn
Copy link
Author

marquesn commented Feb 1, 2019

@marquesn ok, that is telling you the I2C communication succeeded.
now you need to look at the data it received.
Write out the raw data byte from the sensor.

 // where it receives data with Wire.read(), print the raw byte out
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
  uint8_t err =  Wire.endTransmission(false); // end transmission
  if(err !=0){
    Serial.printf("Selecting sensor register failed =%d(%s)\n",err, Wire.getErrorText(err)));
  }
  uint8_t count =Wire.requestFrom(_addr, (uint8_t)3);// send data n-bytes read
  If(count != 3){
    Serial.printf("Receiving sensor data failed, expected 3 bytes received %d.\n Wire() error =%d(%s)\n",
     count,Wire.lastError(),Wire.getErrorText(Wire.lastError()));
  }
  uint8_t raw = Wire.read();
  Serial.printf(" first byte = 0x%02x",raw);
  ret = raw; // receive DATA
  raw = Wire.read();
   Serial.printf(" Second Byte = 0x%02x\n",raw);
  ret |= raw << 8; // receive DATA

  uint8_t pec = Wire.read();
  Serial.printf(" pec=0x%02x\n", pec);
  return ret;
}

Chuck.

Thanks Chuck. This code gives me the following:

[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1037.55*C
Ambient = Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1899.59*F	Object = Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1899.59*F

But changing:

uint8_t err =  Wire.endTransmission(false); // end transmission

to:

uint8_t err =  Wire.endTransmission(); // end transmission

gives me:

[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
1037.55*C	Object = Selecting sensor register failed =2(ACK)
Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1037.55*C
Ambient = Selecting sensor register failed =2(ACK)
Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1899.59*F	Object = Selecting sensor register failed =2(ACK)
Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1899.59*F

Seems like the "false" keyword in wire.endtransmission() prints out another line - "Ambient = Selecting sensor register failed =2(ACK)". Besides that, everything else seems the same.

@stickbreaker
Copy link
Contributor

The Error 2, ACK is telling you the sensor did not respond when the ESP32 sent out it's request.. Since it did not respond, no data was received. the 0xff is the response from Wire.read() when no data is available.

The code that produces this:

=Ambient = fail 0(OK)/n1037.55*C	Object = fail 0(OK)/n1037.55*C
Ambient = fail 0(OK)/n1899.59*F	Object = fail 0(OK)/n1899.59*F

Ambient = fail 0(OK)/n1037.55*C	Object = fail 0(OK)/n1037.55*C
Ambient = fail 0(OK)/n1899.59*F	Object = fail 0(OK)/n1899.59*F

the (ok) shows that the device can answer.

does your circuit had 3.3k pullups on SCL and SDA?

Once you can get no errors reported by Wire() then we can see what the data conversion problems are.

Chuck.

@marquesn
Copy link
Author

marquesn commented Feb 1, 2019

I see... I have 4.7K pull-ups on the SCL and SDA lines.

I believe I had tried other resistor values as well, but I will try again when I get back to the office, and I'll report back here with the results.

Once again, thanks for the clarifications @stickbreaker

@AbaloneIron
Copy link

@marquesn I am having the same problem and due to a lack of time and/or tenacity am awaiting with bated breath.

Thanks

@marquesn
Copy link
Author

marquesn commented Feb 4, 2019

@stickbreaker I have just tried this with the 3.3K pull-ups but the result is the same:

[V][esp32-hal-i2c.c:1483] i2cInit(): num=0 sda=21 scl=22 freq=0
[V][esp32-hal-i2c.c:1677] i2cSetFrequency(): freq=100000Hz
[V][esp32-hal-i2c.c:1692] i2cSetFrequency(): cpu Freq=240Mhz, i2c Freq=100000Hz
[V][esp32-hal-i2c.c:1698] i2cSetFrequency(): Fifo delta=1
Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1037.55*C
Ambient = Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1899.59*F	Object = Receiving sensor data failed, expected 3 bytes received 0.
 Wire() error =2(ACK)
 first byte = 0xff Second Byte = 0xff
 pec=0xff
1899.59*F

Also just tried it with the other MLX sensor that I have, as well as with another ESP32 of the same model, and the results were the same.

Just in case I may be doing something wrong with with the debug code in the Adafruit library, here is a pastebin link of my Adafruit_MLX90614.cpp library after substituting in the debug code that you provided:

https://pastebin.com/WBr8Bihy

@marquesn
Copy link
Author

marquesn commented Feb 6, 2019

Does anyone else have any other ideas regarding this issue?

@asetyde
Copy link

asetyde commented Feb 6, 2019

I've same problem with SHT21 value is not correct, probably all is linked to cpu/i2c relationship I think, this part of code is changed, test if, as I, with previous releases work

@elasly
Copy link

elasly commented Feb 13, 2019

I am having the exact same issue with the same versions of libraries, Any one figured the reason behind this or how to solve it. Thanks in advance

@martinlaurentfr
Copy link

martinlaurentfr commented Apr 15, 2019

As i m a noob, I've been spending days and days to find a solution on this.
It seems defaut frequency of this thing is not the right one, when i specified it, the probleme disepeared

i2c = machine.I2C(scl=machine.Pin(sdaPin), sda=machine.Pin(sclPin),freq=100000)

All other sensor worked on the i2c bus on the same time, without this freq specification, but Mlx didn't

Didn' t used the Adafruit librarys but hope it can help

@stale
Copy link

stale bot commented Aug 1, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Aug 1, 2019
@stale
Copy link

stale bot commented Aug 15, 2019

This stale issue has been automatically closed. Thank you for your contributions.

@nae9
Copy link

nae9 commented Apr 3, 2020

I set i2c speed to 50000 and mlx start answer fine!!!

@SpoturDeal
Copy link

I have changed line 25 in Adafruit_mlx90614.h

to

#define MLX90614_I2CADDR 0x0E

The original address was 0x5A
No i am reading proper values

Ambient = 27.65*C       Object = 26.83*C
Ambient = 81.77*F       Object = 80.29*F

@francisreader
Copy link

I set i2c speed to 50000 and mlx start answer fine!!!
The other suggestions did not work for me, but when I changed from the default (50kHz) to 100kHz now getting reliable comms.

@nae9
Copy link

nae9 commented Jul 4, 2020

I set i2c speed to 50000 and mlx start answer fine!!!
The other suggestions did not work for me, but when I changed from the default (50kHz) to 100kHz now getting reliable comms.

In my files default was 100k :)

@crizgem
Copy link

crizgem commented Jul 23, 2020

I also had this problem, I tried to find out what was going on. I found that the adafruit library has the wrong address of the sensor. So i checked the available i2C adreess using i2C master library (https://github.com/rambo/I2C).
Here the code.

`#include <I2C.h>

void setup() {
// put your setup code here, to run once:
I2c.begin();
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
I2c.scan();
delay(1000);
}`

I got this:

i2c_adrees

I changed the devide I2C address, in Adafruit_MLX90614 library
Inkedlib_LI

Now, I get the proper values. After this, the 0x5A address magically started working. ¬¬
temp

@martinberlin
Copy link

For me it worked lowering frequency and setting right PIN modes:

  pinMode(22, OUTPUT);       // Clock goes from master to peripherical  
  pinMode(21, INPUT_PULLUP); // Data should be internally pulled up (or 4.7K pullup to 3.3v)
  Wire.begin(21,22,10000); 

@isarafx
Copy link

isarafx commented Nov 26, 2020

I try fixing by change i2c address or change wire frequency but still not work
but when I change from 3.3v from my esp32 to 5v arduino nano
It worked fine now(even I change back to old 3.3v)
hope this help :)
ps.btw in case you're using external source to power the module don't forget to connect gnd to esp32 like me!

@devin180
Copy link

devin180 commented Jan 6, 2022

I am using an Ardunio Uno board and having similar issues. Trying to run the Adafruit MLX90614 test file but serial monitor just spits out "ambient = " and goes no further. Tried running the I2C master file noted in the comments above but not sure if I did it right. Anyone else have this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Stale Issue is stale stage (outdated/stuck)
Projects
None yet
Development

No branches or pull requests