ESP-IDF驱动程序/i2c.h读取CCS811寄存器的数据不起作用

发布于 2025-01-30 14:22:52 字数 8303 浏览 4 评论 0原文

我想从CCS811空气传感器寄存器中读取数据时遇到一些麻烦,例如,我想从CSS811_Programming_Guide中重新创建一个示例,该示例正在从下面显示的硬件ID寄存器中读取:

css811_programming_guide 的示例

这样做是为了使用ESP-IDF驱动程序/I2C:

#include "task_air_sensor.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include "driver/i2c.h"

static const char *TAG = "i2c-simple-example";

// defines for master
#define I2C_MASTER_SCL_IO           2                      /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO           1                      /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          4000                     /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS       1000

#define WRITE_BIT I2C_MASTER_WRITE  /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ    /*!< I2C master read */
#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 0x0                 /*!< I2C ack value */
#define NACK_VAL 0x1                /*!< I2C nack value */

// defines for ccs_811
#define STATUS_REG                  0x00
#define MEAS_MODE_REG               0x01
#define ALG_RESULT_DATA             0x02
#define ENV_DATA                    0x05
#define NTC_REG                     0x06
#define THRESHOLDS                  0x10
#define BASELINE                    0x11
#define HW_ID_REG                   0x20
#define ERROR_ID_REG                0xE0
#define APP_START_REG               0xF4
#define SW_RESET                    0xFF
#define CCS_811_ADDRESS             0x5B
#define CCS_811_WHO_AM_I            0x81
#define GPIO_WAKE                   0x5
#define DRIVE_MODE_IDLE             0x0             /*!< Drive mode */
#define DRIVE_MODE_1SEC             0x10            /*!< Drive mode */
#define DRIVE_MODE_10SEC            0x20            /*!< Drive mode */
#define DRIVE_MODE_60SEC            0x30            /*!< Drive mode */
#define INTERRUPT_DRIVEN            0x8
#define THRESHOLDS_ENABLED          0x4

#define ERROR_NOT_A_CCS811          -1

typedef struct 
{
    uint16_t eco2;
    uint16_t tvoc;
    uint8_t status;
    uint8_t error_id;
    uint16_t raw_data;
} ccs811_measurement_t;

ccs811_measurement_t current_data;

static esp_err_t i2c_master_init(void);
static esp_err_t i2c_sensor_init(void);
static esp_err_t i2c_get_sensor_data(void);

uint8_t i2c_buff[8];
bool wake_gpio_enabled = true;

void task_air_sensor(void *pvParameter)
{
    printf("Start of Task Air Sensor\n");

    ESP_ERROR_CHECK(i2c_master_init());
    ESP_LOGI(TAG, "I2C Master initialized successfully");

    // ESP_ERROR_CHECK(i2c_sensor_init());
    // ESP_LOGI(TAG, "I2C Sensor initialized successfully");

    

    while(1)
    {
        printf("App in Task Air Sensor\n");

        i2c_sensor_init();
        i2c_get_sensor_data();
        printf("status register = %d\n", current_data.status);
        vTaskDelay(30 / portTICK_PERIOD_MS);
    }
    vTaskDelete(NULL);
}

/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    i2c_port_t i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

/**
 * @brief test code to operate on CCS811 air quality sensor
 *
 * 1. set drive mode in Measure Mode Register
 * _________________________________________________________________
 * | start | slave_addr + wr_bit + ack | write 1 byte + ack  | stop |
 * --------|---------------------------|---------------------|------|
 * 2. wait more than 24 ms
 * 3. read data
 * ______________________________________________________________________________________
 * | start | slave_addr + rd_bit + ack | read 1 byte + ack  | read 1 byte + nack | stop |
 * --------|---------------------------|--------------------|--------------------|------|
 */
static esp_err_t i2c_sensor_init(void)
{
    i2c_port_t i2c_num = I2C_MASTER_NUM;
    esp_err_t ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();

    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MEAS_MODE_REG, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, DRIVE_MODE_1SEC, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during setting drive mode.\n");
        return ret;
    }
    vTaskDelay(30 / portTICK_PERIOD_MS);

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, HW_ID_REG, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during writing to HAW_ID_REG.\n");
        return ret;
    }

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | READ_BIT, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, &i2c_buff[0], NACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    if(i2c_buff[0] != CCS_811_WHO_AM_I)
    {
        printf("i2c_buff[0] = %d \n", i2c_buff[0]);
        ESP_LOGI(TAG,"Error during reading from HW_ID_REG.\n");
        return ERROR_NOT_A_CCS811;
    }
    return ret;
}

static esp_err_t i2c_get_sensor_data(void)
{
    i2c_port_t i2c_num = I2C_MASTER_NUM;
    esp_err_t ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, STATUS_REG, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during writing to STATUS_REG.\n");
        return ret;
    }

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | READ_BIT, ACK_VAL);
    i2c_master_read_byte(cmd, &current_data.status, NACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during reading from STATUS_REG.\n");
        return ret;
    }

    return ret;
}

上传代码和监视输出后,我得到了一些错误的数据:

在任务空气传感器中的应用
i2c_buff [0] = 3
i2c-simple-示例:从hw_id_reg。
阅读过程中的错误 状态寄存器= 3

但是,当我使用Logic Analyzer监视I2C总线时,我会得到我期望的正确数据。

logic Analyzer 阅读I2C总线 (地址与有意的编程指南中的地址不同)

是否有人知道为什么在函数static ESP_ERR_T I2C_SENSOR_INIT(void)中以下条件的条件已满?

  if(i2c_buff [0]!= ccs_811_who_am_i)
{
    printf(“ i2c_buff [0] =%d \ n”,i2c_buff [0]);
    ESP_LOGI(标签,“从HW_ID_REG。\ n”阅读过程中的错误);
    返回error_not_a_ccs811;
}
 

根据分析仪的数据,应等于0x81(ccs_811_who_am_i),而不是3:/

I have some troubles with reading data from ccs811 air sensors registers for example I want to recreate an example from css811_Programming_Guide which is reading from the hardware ID register presented below:

example from css811_Programming_Guide

To do so I am using esp-idf driver/i2c:

#include "task_air_sensor.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"
#include "driver/i2c.h"

static const char *TAG = "i2c-simple-example";

// defines for master
#define I2C_MASTER_SCL_IO           2                      /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO           1                      /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          4000                     /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS       1000

#define WRITE_BIT I2C_MASTER_WRITE  /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ    /*!< I2C master read */
#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 0x0                 /*!< I2C ack value */
#define NACK_VAL 0x1                /*!< I2C nack value */

// defines for ccs_811
#define STATUS_REG                  0x00
#define MEAS_MODE_REG               0x01
#define ALG_RESULT_DATA             0x02
#define ENV_DATA                    0x05
#define NTC_REG                     0x06
#define THRESHOLDS                  0x10
#define BASELINE                    0x11
#define HW_ID_REG                   0x20
#define ERROR_ID_REG                0xE0
#define APP_START_REG               0xF4
#define SW_RESET                    0xFF
#define CCS_811_ADDRESS             0x5B
#define CCS_811_WHO_AM_I            0x81
#define GPIO_WAKE                   0x5
#define DRIVE_MODE_IDLE             0x0             /*!< Drive mode */
#define DRIVE_MODE_1SEC             0x10            /*!< Drive mode */
#define DRIVE_MODE_10SEC            0x20            /*!< Drive mode */
#define DRIVE_MODE_60SEC            0x30            /*!< Drive mode */
#define INTERRUPT_DRIVEN            0x8
#define THRESHOLDS_ENABLED          0x4

#define ERROR_NOT_A_CCS811          -1

typedef struct 
{
    uint16_t eco2;
    uint16_t tvoc;
    uint8_t status;
    uint8_t error_id;
    uint16_t raw_data;
} ccs811_measurement_t;

ccs811_measurement_t current_data;

static esp_err_t i2c_master_init(void);
static esp_err_t i2c_sensor_init(void);
static esp_err_t i2c_get_sensor_data(void);

uint8_t i2c_buff[8];
bool wake_gpio_enabled = true;

void task_air_sensor(void *pvParameter)
{
    printf("Start of Task Air Sensor\n");

    ESP_ERROR_CHECK(i2c_master_init());
    ESP_LOGI(TAG, "I2C Master initialized successfully");

    // ESP_ERROR_CHECK(i2c_sensor_init());
    // ESP_LOGI(TAG, "I2C Sensor initialized successfully");

    

    while(1)
    {
        printf("App in Task Air Sensor\n");

        i2c_sensor_init();
        i2c_get_sensor_data();
        printf("status register = %d\n", current_data.status);
        vTaskDelay(30 / portTICK_PERIOD_MS);
    }
    vTaskDelete(NULL);
}

/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    i2c_port_t i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

/**
 * @brief test code to operate on CCS811 air quality sensor
 *
 * 1. set drive mode in Measure Mode Register
 * _________________________________________________________________
 * | start | slave_addr + wr_bit + ack | write 1 byte + ack  | stop |
 * --------|---------------------------|---------------------|------|
 * 2. wait more than 24 ms
 * 3. read data
 * ______________________________________________________________________________________
 * | start | slave_addr + rd_bit + ack | read 1 byte + ack  | read 1 byte + nack | stop |
 * --------|---------------------------|--------------------|--------------------|------|
 */
static esp_err_t i2c_sensor_init(void)
{
    i2c_port_t i2c_num = I2C_MASTER_NUM;
    esp_err_t ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();

    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, MEAS_MODE_REG, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, DRIVE_MODE_1SEC, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during setting drive mode.\n");
        return ret;
    }
    vTaskDelay(30 / portTICK_PERIOD_MS);

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, HW_ID_REG, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during writing to HAW_ID_REG.\n");
        return ret;
    }

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | READ_BIT, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, &i2c_buff[0], NACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);

    if(i2c_buff[0] != CCS_811_WHO_AM_I)
    {
        printf("i2c_buff[0] = %d \n", i2c_buff[0]);
        ESP_LOGI(TAG,"Error during reading from HW_ID_REG.\n");
        return ERROR_NOT_A_CCS811;
    }
    return ret;
}

static esp_err_t i2c_get_sensor_data(void)
{
    i2c_port_t i2c_num = I2C_MASTER_NUM;
    esp_err_t ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, STATUS_REG, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during writing to STATUS_REG.\n");
        return ret;
    }

    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, CCS_811_ADDRESS << 1 | READ_BIT, ACK_VAL);
    i2c_master_read_byte(cmd, ¤t_data.status, NACK_VAL);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) 
    {
        ESP_LOGI(TAG,"Error during reading from STATUS_REG.\n");
        return ret;
    }

    return ret;
}

After uploading the code and monitoring outputs I get some incorrect data:

App in Task Air Sensor
i2c_buff[0] = 3
i2c-simple-example: Error during reading from HW_ID_REG.
status register = 3

However when I'm monitoring i2c bus with logic analyzer I get the correct data that I was expecting.

reading i2c bus by logic analyzer
(address is different than the one in Programming Guide intentionally)

Is anyone know why below condition in function static esp_err_t i2c_sensor_init(void) is fullfiled?

if(i2c_buff[0] != CCS_811_WHO_AM_I)
{
    printf("i2c_buff[0] = %d \n", i2c_buff[0]);
    ESP_LOGI(TAG,"Error during reading from HW_ID_REG.\n");
    return ERROR_NOT_A_CCS811;
}

According to data from analyzer it should be equal to 0x81 (CCS_811_WHO_AM_I) rather than 3 :/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

于我来说 2025-02-06 14:22:52

嗨,你能尝试这样的事情吗?

i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (I2C_SCD41 << 1) | I2C_MASTER_WRITE, 1);
i2c_master_write(cmd, &data[0],2,1);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (I2C_SCD41 << 1) | I2C_MASTER_READ, 1);
i2c_master_read(cmd,&data[0],8,I2C_MASTER_ACK);
i2c_master_read_byte(cmd, &data[8], I2C_MASTER_NACK);
i2c_master_stop(cmd);
status = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
if (status != 0) ESP_LOGE("I2C","%d:%s",status,esp_err_to_name(status));
i2c_cmd_link_delete(cmd);

你看到区别了吗?

Hi can you try something like this?

i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (I2C_SCD41 << 1) | I2C_MASTER_WRITE, 1);
i2c_master_write(cmd, &data[0],2,1);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (I2C_SCD41 << 1) | I2C_MASTER_READ, 1);
i2c_master_read(cmd,&data[0],8,I2C_MASTER_ACK);
i2c_master_read_byte(cmd, &data[8], I2C_MASTER_NACK);
i2c_master_stop(cmd);
status = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
if (status != 0) ESP_LOGE("I2C","%d:%s",status,esp_err_to_name(status));
i2c_cmd_link_delete(cmd);

Do you see the difference?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文