ESP-IDF驱动程序/i2c.h读取CCS811寄存器的数据不起作用
我想从CCS811空气传感器寄存器中读取数据时遇到一些麻烦,例如,我想从CSS811_Programming_Guide中重新创建一个示例,该示例正在从下面显示的硬件ID寄存器中读取:
这样做是为了使用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, ¤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;
}
上传代码和监视输出后,我得到了一些错误的数据:
在任务空气传感器中的应用
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
嗨,你能尝试这样的事情吗?
你看到区别了吗?
Hi can you try something like this?
Do you see the difference?