MLX90640 and M5Fire/M5Stack



  • Hello,

    I received my MLX90640 thermo cam and used this program to test it:
    https://github.com/dtomyy/M5Stack-MLX90640-Thermal-Camera/blob/master/M5Stack-MLX90640-Thermal-Camera.ino

    I switched the debug level to verbose to see all errors and warnings.
    I got some problems with the SD-card. This was ok because there is no SD-card inside M5Stack.

    09:42:54.222 -> [W][sd_diskio.cpp:137] sdCommand(): no token received
    09:42:54.325 -> [W][sd_diskio.cpp:137] sdCommand(): no token received
    09:42:54.431 -> [W][sd_diskio.cpp:471] ff_sd_initialize(): GO_IDLE_STATE failed
    09:42:54.431 -> [E][sd_diskio.cpp:739] sdcard_mount(): f_mount failed 0x(3)
    09:42:54.431 -> OK
    09:42:54.431 -> M5.begin ok
    09:42:54.431 -> Wire begin ok
    09:42:54.814 -> M5Stack MLX90640 IR Camera
    09:42:55.541 -> Parameter extraction failed
    09:42:55.541 -> Error: Sensor did not ack
    09:42:55.604 -> No ack read
    09:42:55.605 -> No ack read
    09:42:55.605 -> No ack read
    

    The main problem started at this errorline "Parameter extraction failed". The program found the MLX90640 but it didn't read the data from the sensor correct. To comment the ack-check in MLX90640_I2CRead didn't work for me. I read this at https://forums.pimoroni.com/t/mlx90640-no-ack/8662/12
    Can anyone help me?



  • hello
    you need update arduino-esp32 to the newest
    see https://github.com/espressif/arduino-esp32 ,and test it
    the sd card mount in M5.begin()
    if you want init sd card, you can use M5.begin(true, false, true) instead M5.begin(), it will be ok



  • Hello,
    I continued testing and I found two problems:

    • It is necessary to take new arduino library. @heybin: Thanks.
    • Problem with "MLX90640_I2CRead". I changed this in the function:
       /*
        if (Wire.endTransmission(false) != 0) //Do not release bus
        {
          Serial.println("No ack read");
          return (0); //Sensor did not ACK
        }*/
        Wire.endTransmission(false);
    

    Now it worked for me.



  • Hello,
    In the new arduino-esp32 library ,need to pay attention to in new IIC communication:

    • Wire.endTransmission(false) run ok will return 7, not 0


  • Hello heybin,
    thank you for the information of the new return value from "Wire.end".

    Do you know why the second part in "MLX90640_I2CWrite" worked?

    int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data)
    {
      Wire.beginTransmission((uint8_t)_deviceAddress);
      Wire.write(writeAddress >> 8); //MSB
      Wire.write(writeAddress & 0xFF); //LSB
      Wire.write(data >> 8); //MSB
      Wire.write(data & 0xFF); //LSB
      if (Wire.endTransmission() != 0)
      {
        //Sensor did not ACK
        Serial.println("Error: Sensor did not ack");
        return (-1);
      }
    

    I changed "MLX90640_I2CRead" to:

    int MLX90640_I2CRead(uint8_t _deviceAddress, unsigned int startAddress, unsigned int nWordsRead, uint16_t *data)
    {
      //Caller passes number of 'unsigned ints to read', increase this to 'bytes to read'
      uint16_t bytesRemaining = nWordsRead * 2;
      //It doesn't look like sequential read works. Do we need to re-issue the address command each time?
      uint16_t dataSpot = 0; //Start at beginning of array
      //Setup a series of chunked I2C_BUFFER_LENGTH byte reads
      while (bytesRemaining > 0)
      {
        Wire.beginTransmission(_deviceAddress);
        Wire.write(startAddress >> 8); //MSB
        Wire.write(startAddress & 0xFF); //LSB
        if (Wire.endTransmission(false) != 7) //Do not release bus
        {
          Serial.println("No ack read");
          return (0); //Sensor did not ACK
        }
        uint16_t numberOfBytesToRead = bytesRemaining;
    ...
    


  • hello,
    the return mean:

    typedef enum {
        I2C_ERROR_OK=0,
        I2C_ERROR_DEV,
        I2C_ERROR_ACK,
        I2C_ERROR_TIMEOUT,
        I2C_ERROR_BUS,
        I2C_ERROR_BUSY,
        I2C_ERROR_MEMORY,
        I2C_ERROR_CONTINUE,
        I2C_ERROR_NO_BEGIN
    } i2c_err_t;
    
    • when Wire.endTransmission() mean Wire.endTransmission(true), so success return I2C_ERROR_OK
    • Wire.endTransmission(false) success return I2C_ERROR_CONTINUE


  • Hello,

    thank you for the good explanation.