melexis / mlx90640-library

MLX90640 library functions
Apache License 2.0
238 stars 187 forks source link

MLX90640 Eval Board I2C #86

Open calvinfoo opened 3 years ago

calvinfoo commented 3 years ago

Hi,

I am trying to use the VDD, GND and SCL, SDA pins on the Melexis evaluation board for ML90640.

VCC=3.3V GND =GND SCL & SDA with pull up 3.3k resisters But I can't seems to get any address with I2C scanner on ESP32. (I tried with VL53L0X and can get I2C address).

Anyone manage to get this working?

karelv commented 3 years ago

At first I would add a decoupling capacitor on VDD/GND. Also in this driver the I2C functions still need an implementation.

You might compare your MLX90640_I2C_Driver.c with this content:

/**
 * @copyright (C) 2017 Melexis N.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include "MLX90640_I2C_Driver.h"

#include "esp_log.h"
#include "driver/i2c.h"
#define ACK_CHECK_EN 0x1                        /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0                       /*!< I2C master will not check ack from slave */
#define ACK_VAL I2C_MASTER_ACK                             /*!< I2C ack value */
#define NACK_VAL I2C_MASTER_NACK                            /*!< I2C nack value */

    // I2C_MASTER_ACK = 0x0,        /*!< I2C ack for each byte read */
    // I2C_MASTER_NACK = 0x1,       !< I2C nack for each byte read
    // I2C_MASTER_LAST_NACK = 0x2,   /*!< I2C nack for the last byte*/

// #define _I2C_NUMBER(num) I2C_NUM_##num
// #define I2C_NUMBER(num) _I2C_NUMBER(num)

i2c_port_t g_i2c_num = I2C_NUM_0;

void MLX90640_I2CInit()
{
  // send 8 clock pulses and a STOP condition.
  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  i2c_master_write_byte(cmd, (0x7F << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
  i2c_master_stop(cmd);
  i2c_master_cmd_begin(g_i2c_num, cmd, 1000 / portTICK_RATE_MS);
  i2c_cmd_link_delete(cmd);
}

int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data)
{

  if (nMemAddressRead == 0) return 0;

  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  i2c_master_start(cmd);
  i2c_master_write_byte(cmd, (slaveAddr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
  i2c_master_write_byte(cmd, startAddress >> 8, ACK_CHECK_EN);
  i2c_master_write_byte(cmd, startAddress, ACK_CHECK_EN);

  i2c_master_start(cmd); // repeated start
  i2c_master_write_byte(cmd, (slaveAddr << 1) | I2C_MASTER_READ, ACK_CHECK_EN);

  uint8_t *data_rd = (uint8_t *)data;

  uint16_t bytes2Read = nMemAddressRead * 2;

  i2c_master_read(cmd, data_rd, bytes2Read - 1, ACK_VAL);
  i2c_master_read_byte(cmd, data_rd + bytes2Read - 1, NACK_VAL);
  i2c_master_stop(cmd);
  esp_err_t ret = i2c_master_cmd_begin(g_i2c_num, cmd, 3000 / portTICK_RATE_MS); // 3 sec timeout
  i2c_cmd_link_delete(cmd);
  // ESP_LOGE("MLX90640-I2C-Driver", "ret = %d (%d, %d, %d, %d, %d)", ret, ESP_OK, ESP_ERR_INVALID_ARG, ESP_FAIL, ESP_ERR_INVALID_STATE, ESP_ERR_TIMEOUT);

  if (ret == ESP_OK)
  {
    for (uint16_t i=0; i<nMemAddressRead; i++)
    { // swap low & high byte!
      data[i] = (data[i]>>8) | (data[i]<<8);
    }
  }

  return ret != ESP_OK;
}

void MLX90640_I2CFreqSet(int freq)
{
  ESP_LOGE("MLX90640-I2C-Driver", "set I2C master SCL frequency directly in i2c master functions!!!");
}

int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data)
{
  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  i2c_master_start(cmd);
  i2c_master_write_byte(cmd, (slaveAddr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
  i2c_master_write_byte(cmd, writeAddress >> 8, ACK_CHECK_EN);
  i2c_master_write_byte(cmd, writeAddress, ACK_CHECK_EN);
  i2c_master_write_byte(cmd, data >> 8, ACK_CHECK_EN);
  i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
  i2c_master_stop(cmd);
  esp_err_t ret = i2c_master_cmd_begin(g_i2c_num, cmd, 1000 / portTICK_RATE_MS);
  i2c_cmd_link_delete(cmd);
  if (ret == ESP_OK)
  {
    return 0;
  }

  uint16_t dataCheck;
  MLX90640_I2CRead(slaveAddr, writeAddress, 1, &dataCheck);
  if (dataCheck != data)
  {
    return -2;
  }
  return -1;
}