This chip works fine on my hardware using the arduino library in an arduino project.
In my esp-idf driver i am encountering large delays between i2c transactions which is preventing the driver from working.
Since the code works in arduino, which is based on esp-idf, there is no problem with my hardware, and no problem with esp-idf itself.
So I would appreciate help with what I am doing wrong.
- ESP-IDF v4.2-dev-1660-g7d7521367-dirty
- ESP32-WROVER-B on custom PCB
- 10k pullups on I2C Bus
Screenshot from datasheet showing transaction I am trying to achieve
(Note I am aware the datasheet shows a sequential start for the read command rather than two transactions, I have tried it both ways with the same results but am doing it this way because this is how the arduino lib seems to do it)
Output of my esp-idf code showing large delays
Output of arduino code showing normal timing
Code: Select all
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include <driver/i2c.h>
#define I2C_SCL_IO 22 //19 /*!< gpio number for I2C master clock */
#define I2C_SDA_IO 21 //18 /*!< gpio number for I2C master data */
#define I2C_FREQ_HZ 100000 /*!< I2C master clock frequency */
#define I2C_PORT_NUM I2C_NUM_1 /*!< I2C port number for master dev */
#define I2C_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
#define I2C_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
#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 BQ27441_I2C_ADDRESS 0x55
static const char* TAG = "I2C Test";
static esp_err_t i2c_master_init(void)
{
i2c_config_t conf = {};
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = (gpio_num_t)I2C_SDA_IO;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = (gpio_num_t)I2C_SCL_IO;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = I2C_FREQ_HZ;
i2c_param_config(I2C_PORT_NUM, &conf);
return i2c_driver_install(I2C_PORT_NUM, conf.mode, I2C_RX_BUF_DISABLE, I2C_TX_BUF_DISABLE, 0);
}
void i2cWriteTwoBytes(uint8_t subAddress, uint8_t byte0, uint8_t byte1)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (BQ27441_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
i2c_master_write_byte(cmd, subAddress, ACK_CHECK_EN);
i2c_master_write_byte(cmd, byte0, ACK_CHECK_EN);
i2c_master_write_byte(cmd, byte1, ACK_CHECK_EN);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_PORT_NUM, cmd, 100 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
}
// Write a single byte to
void i2cWriteByte(uint8_t byte)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (BQ27441_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
i2c_master_write_byte(cmd, byte, ACK_CHECK_EN);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_PORT_NUM, cmd, 100 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
}
// Read a specified number of bytes over I2C at a given subAddress
bool i2cReadBytes(uint8_t * dest, uint8_t count)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (BQ27441_I2C_ADDRESS << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
if (count > 1) {
i2c_master_read(cmd, dest, count - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, dest + count - 1, I2C_MASTER_NACK);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_PORT_NUM, cmd, 100 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret == ESP_OK)
return true;
else
return false;
}
static void task_fuel_gauge(void *args)
{
// Attempt to get the device type
uint8_t devType[2];
i2cWriteTwoBytes(0x00,0x01,0x00);
i2cWriteByte(0x00);
i2cReadBytes(devType,2);
while(true)
{
vTaskDelay(500/portTICK_PERIOD_MS);
}
}
void app_main(void)
{
ESP_LOGI(TAG,"MAIN ENTRY");
i2c_master_init();
xTaskCreate(task_fuel_gauge, "fuel_gauge", 2048, (void* ) 0, 20, NULL);
}