CCS811 via ESP32 gives no data


#1

I have tried to get data from a CCS811 in a pure ‘EPS32’ project, but don’t get any data from this sensor. I have double-checked the sensor in an Arduino environment without any problems.

Just to make sure I wasn’t loosing it, I have also tried with a HTS221, a LSM6DSL and a LPS22HB, which all gives me perfect data (I also tried with a LIS3MDL, but have failed so far, but need to check it works in another environment).
I also managed to get data from a LM75B (temperature) and a MLX90614 (IR temperature), but by hacking a function element :wink:

All in pure ‘ESP32’ projects and all over I2C - btw!


#2

Hi,

Are you sure the I2C address is correct? Did you try both 0x5A and 0x5B? When you mention you tested it in Arduino, I assume you are using the Arduino library then?

What form factor is the CCS811 in? Is it the Sparkfun breakout board, or is it on something else?

In the upcoming few months, we will be releasing a tool allowing you to write your own Element Libraries, so feel free to contribute once that’s out!

Sorry for the barrage of questions.

-Nick


#3

Also, if you’re willing to do a little debug, you can call this function:
CCS811_readRegister( CCS811_HW_ID, &val)

That will attempt to grab the hardware ID of the CCS811. That should allow you check whether or not any communication is happening or if something is broken on a fundamental level.

That HW ID is checked on init, and if it doesn’t match, the driver will ignore commands you send it afterwards.


#4

@nick.crast
I am using address 0x5A, I tested the CCS811 in Arduino, where I also got 0x81 (129) value back on 0x20 (HW_ID).
I was not using a library, but coded the Wire (I2C) request directly, just to make sure:

#define CCS811_ADDR 0x5A
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(115200);
}
void loop() {
byte hwID = readRegister(0x20);
Serial.println(hwID);
}
byte readRegister(byte addr){
Wire.beginTransmission(CCS811_ADDR);
Wire.write(addr);
Wire.endTransmission();
Wire.requestFrom(CCS811_ADDR, 1);
return (Wire.read());
}

We got our own form factor, see https://wiki.xinabox.cc/SG33


See the screenshot, which shows the minimum amount of code, just to make sure there is no interference. I also read the temp from another sensor (SW10), again just to make sure the I2C comms actually works.

So, I could get it working in Arduino, but not in Atmosphere IoT:

  1. Should I try another speed (STD Mode, Fast Mode, etc)?
  2. Should I communicate with a release bus, like separate write and read?
  3. Anything else?

Oh, and I couldn’t get CCS811_readRegister( CCS811_HW_ID, &val) to work, some declaration issues, probably just me not understanding the architecture properly.

-Bjarke


#5

That’s odd. One thing you could try is using the raw esp-idf functions to see if you can get it to work that way, then I could see the difference between what you did and what our software is doing.

Looking at the implementation of ATMO_I2C_MasterRead for the ESP32, nothing is jumping out. For your reference:

ATMO_I2C_Status_t ATMO_ESP32_I2C_MasterWrite( ATMO_DriverInstanceData_t *instance, uint16_t slaveAddress, const uint8_t* cmdBytes, uint16_t numCmdBytes, const uint8_t* writeBytes, uint16_t numWriteBytes, uint16_t timeout_ms )
{
	
	if(cmdBytes == NULL && writeBytes == NULL)
	{
		return ATMO_I2C_Status_Success;
	}
	
	i2c_cmd_handle_t cmd = i2c_cmd_link_create();
	i2c_master_start(cmd);
	i2c_master_write_byte(cmd, (slaveAddress << 1) | I2C_MASTER_WRITE, 1);
	
	if(cmdBytes != NULL)
	{
		i2c_master_write(cmd, cmdBytes, numCmdBytes, true);
	}
	
	if(writeBytes != NULL)
	{
		i2c_master_write(cmd, writeBytes, numWriteBytes, true);
	}
	
	i2c_master_stop(cmd);
	i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_PERIOD_MS);
	i2c_cmd_link_delete(cmd);
	
	return ATMO_I2C_Status_Success;
}

ATMO_I2C_Status_t ATMO_ESP32_I2C_MasterRead( ATMO_DriverInstanceData_t *instance, uint16_t slaveAddress, const uint8_t* cmdBytes, uint16_t numCmdBytes, uint8_t* readBytes, uint16_t numReadBytes, uint16_t timeout_ms )
{
	
	ATMO_ESP32_I2C_MasterWrite(instance, slaveAddress, cmdBytes, numCmdBytes, NULL, 0, timeout_ms);
	
	if(readBytes == NULL)
	{
		return ATMO_I2C_Status_Success;
	}

	i2c_cmd_handle_t cmd = i2c_cmd_link_create();
	i2c_master_start(cmd);
	i2c_master_write_byte(cmd, (slaveAddress << 1) | I2C_MASTER_READ, 1);
	
	if(numReadBytes > 1)
	{
        i2c_master_read(cmd, readBytes, numReadBytes - 1, 0);
	}
	
	i2c_master_read_byte(cmd, readBytes + numReadBytes - 1, 1);
	i2c_master_stop(cmd);
	i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000/portTICK_PERIOD_MS);
	i2c_cmd_link_delete(cmd);

	return ATMO_I2C_Status_Success;
}

The only thing that jumps out as odd is the calling of both i2c_master_read and i2c_master_read_byte, but it should be functionally okay.

Unfortunately, I don’t currently have a CCS811 breakout in house, just the one on the RapidIoT Kit, so I won’t be able to dive in until I get one shipped.


#6

Bjarke, did you ever get anywhere with this?

-Nick


#7

@nick.crast, no, I didn’t. I managed to compile your I2C code and also compare directly to the default ESP-IDF code for I2C, but with no luck. I also tried to review the Arduino Wire library, which is vastly different.

In short, your implementation seems spot on, but doesn’t work for the CCS811 combined with the ESP32. I haven’t tried a pure ESP-IDF compilation, which i will pass on to one of my colleagues.

I will come back when I have more info.

Bjarke