GithubHelp home page GithubHelp logo

maarten-pennings / ccs811 Goto Github PK

View Code? Open in Web Editor NEW
163.0 14.0 46.0 1.74 MB

Arduino library for the CCS811 gas sensor for monitoring indoor air quality.

License: MIT License

C++ 100.00%
gas-sensor arduino-library arduino i2c driver ccs811 iaq tvoc

ccs811's Introduction

CCS811

Arduino library for the CCS811 digital gas sensor for monitoring indoor air quality from ScioSense.

There is a Spanish guide.

Introduction

This project is an Arduino library. It implements a driver for the CCS811. This chip is a indoor air quality sensor module with an I2C interface.

This library includes a CCS811 driver and some examples. When starting, use the example ccs811basic. It is the most simple one, but it helps in getting the wiring correct: the I2C wires, the ADDR select pin and the nWAKE pin. There is also a full fledged example: it reads environmental data from ENS210, writes that to the CCS811, reads the gas data from the CCS811, and then uploads that to ThingSpeak.

If you have an old CCS811, you might want to update its firmware. This library contains an example for that too: ccs811flash.

The rest of this page tells how to get started on the software (install library) and hardware (wiring).

Links

The CCS811 is made by ScioSense formerly ams.

Software

This section gives a quick overview of how to install this library and compile one of its examples (ccs811basic). The end of this file shows an actual run of that example.

Prerequisites

It is assumed that

  • The Arduino IDE has been installed. If not, refer to "Install the Arduino Desktop IDE" on the Arduino site.
  • The Arduino library directory is at its default location. For me, Maarten, that is C:\Users\maarten\Documents\Arduino\libraries.

Installation

Installation steps

  • Visit the project page for the Arduino CCS811 library.
  • Click the green button Clone or download on the right side.
  • From the pop-up choose Download ZIP.
  • In Arduino IDE, select Sketch > Include Library > Manage Libraries ... and browse to the just downloaded ZIP file.
  • When the IDE is ready this README.md should be located at e.g. C:\Users\maarten\Documents\Arduino\libraries\CCS811\README.md.

Build an example

To build an example sketch (just building, for running it we need to wire it, and that is the next step):

  • (Re)start Arduino.
  • Open File > Example > Examples from Custom Libraries > CCS811 > ccs811basic.
  • Make sure Tools > Board lists the correct board.
  • Select Sketch > Verify/Compile.

Hardware

This library has been tested with

Note that the CCS811 requires a supply voltage of 1.8V .. 3.6V. So, 3.3V is ok, but do not use a 5V board. The Nano has a "3v3 out" pin, but that's only a power out pin, the micro drives the I2C lines on 5V. This poses a risk to the CCS811. Also note that the minimum supply voltage of the CCS811 is 1.8V and should not drop below this value for reliable device operation.

Most micro controllers seem to have built-in pull-ups for I2C. However, those pull-ups are typically activated by Wire.begin(). Therefore, between power-up (or reset) and Wire.begin(), the I2C lines might not be high. This might cause unwanted behavior on the slaves. It is recommended to add 10k pull-ups on both SDA and SCL.

Wiring

The CCS811 has several pins:

  • VDD must be connected to 3V3 of the micro.
  • GND must be connected to GND of the micro.
  • SDA must be connected to SDA of the micro (and maybe a pull-up, but the below micros have that internally).
  • SCL must be connected to SCL of the micro (and maybe a pull-up, but the below micros have that internally).
  • nWAKE can either be tied to GND, in which case the CCS811 is always awake (using more power). Alternatively nWAKE can be tied to a GPIO pin of the micro, the CCS library will then use this pin to wake-up the micro when needed. In the former case pass -1 to the constructor CCS811 ccs811(-1), in the latter case, pass the pin number, e.g. CCS811 ccs811(D3).
  • nINT can be left dangling, interrupts are not used by the library.
  • nRESET can be left dangling, it is not used by the library (the library employs a software reset).
  • When ADDR is connected to GND, the CCS811 has slave address 0x5A (constant CCS811_SLAVEADDR_0). When ADDR is connected to VDD, the CCS811 has slave address 0x5B (constant CCS811_SLAVEADDR_1). If your board has an ADDR pin, then likely it has a pull-up, so leaving it dangling selects 0x5B. If your board has no ADDR pin, then likely it has the pin tied to GND, selecting 0x5A. The ccs811.begin() uses the address passed in the constructor, but if the other address does work, it prints this on Serial.

ESP8266

For the NodeMCU (ESP8266), connect as follows (I did not use pull-ups, presumably they are inside the MCU). The SDA and SCL could be mapped to other pins, but these are the default in the Arduino wire library.

CCS811 ESP8266
VDD 3V3
GND GND
SDA D2
SCL D1
nWAKE D3 or GND

wiring ESP8266 NodeMCU

Unfortunately, the CCS811 uses clock stretching, and the I2C sw library in the ESP8266 (up to version 2.4.2) can not handle this in all cases, therefore this library add waits (see set_i2cdelay() in ccs811.h).

However, the real solution is to fix the clock stretch problem in the ESP8266 core libraries. I have submitted an issue for that, which is included in core library version 2.5.0. I submitted and another issue, which is not yet released. My suggested do-it-yourself solution is described here

It seems that in Release 2.6.0 (released Nov 9, 2019) includes my I2C fix so ESP8266 can be used with CCS811 without problems.

Pro Mini

For the Pro Mini (do not use a 5V board), connect as follows (I did not use pull-ups, presumably they are inside the MCU).

CCS811 Pro mini
VDD VCC
GND GND
SDA A4
SCL A5
nWAKE D3 or GND

wiring pro mini

Arduino Nano

The Nano runs on 5V and it also drives its I2C lines at 5V. Yes, it has a 3V3 pin, but that is just a "power out" pin. Driving the CCS811 with a Nano did work for me (I forgot to check the datasheets), but is out of spec for the CCS811:

The CCS811 datasheet specifies that logic high is at most 1.0 x VDD (i.e. 3v3), connecting the CCS811 to the I2C pins of the Nano (at 5V) is thus a risk for the CCS811.

For the Arduino Nano, connect as follows (I did not use pull-ups, presumably they are inside the MCU).

CCS811 Nano
VDD 3V3
GND GND
SDA A4
SCL A5
nWAKE D3 or GND

wiring nano

ESP32

For the ES32, connect as follows (I did not use pull-ups, presumably they are inside the MCU). The SDA and SCL could be mapped to other pins, but these are the default in the Arduino wire library.

CCS811 ESP32
VDD 3V3
GND GND
SDA 21
SCL 22
nWAKE 23 or GND

wiring ESP32

The ESP32 has, unlike its predecessor ESP8266, an I2C interface in hardware. However, the Arduino library version 1.0.0 has a bug: it does not support repeated start conditions. However, this seems to be fixed in release 1.0.1, so use that.

CCS811

Connect the official CCS811 module, which also has an ENS210, as follows

wiring CCS811

An alternative is a CCS811-only board (without and ENS210). Wire it as follows

Wiring CCS811

Run an example

To build, flash and run an example sketch

  • (Re)start Arduino.

  • Open File > Example > Examples from Custom Libraries > CCS811 > ccs811basic.

  • Make sure Tools > Board lists the correct board.

  • Select Sketch > Upload.

  • Select Tools > Serial Monitor.

  • Enjoy the output, which should be like this for ccs811basic:

    setup: Starting CCS811 basic demo
    setup: ccs811 lib  version: 10
    setup: hardware    version: 12
    setup: bootloader  version: 1000
    setup: application version: 2000
    CCS811: waiting for (new) data
    CCS811: waiting for (new) data
    CCS811: waiting for (new) data
    CCS811: waiting for (new) data
    CCS811: eco2=400 ppm  etvoc=0 ppb  
    CCS811: eco2=405 ppm  etvoc=0 ppb  
    CCS811: eco2=405 ppm  etvoc=0 ppb  
    CCS811: eco2=407 ppm  etvoc=1 ppb  
    CCS811: eco2=405 ppm  etvoc=0 ppb  
    CCS811: eco2=400 ppm  etvoc=0 ppb  
    CCS811: eco2=400 ppm  etvoc=0 ppb  
    CCS811: eco2=405 ppm  etvoc=0 ppb  
    CCS811: eco2=405 ppm  etvoc=0 ppb  
    CCS811: eco2=405 ppm  etvoc=0 ppb
    
  • It is normal that early measurements do not provide data yet; the internal gas library needs some data points to startup.

  • At the time of developing this github project, application version: 2000 is available on the ams website. You might still have version 1100. To flash version 2000, you need the CCS811 eval kit. As an alternative, you could try my flash example - at your own risk.

Error flags overview

The read function returns a 16-bit "concatenation" of the 8 bit ERROR_ID and the 8 bit STATUS. If there is an error, you can use the CCS811_ERRSTAT_XXX macros to find the offending bit flag. Alternatively, the errstat_str() method prints a character per flag, uppercase when set. The example applications do that.

Normally you should either see CCS811_ERRSTAT_OK or CCS811_ERRSTAT_OK_NODATA.

Find an overview below.

ERROR_ID   STATUS
76543210 76543210

--vhxmrw f--ad-ie                          - Shows all (existing) flags in the down state (cleared)
--vhxmrw F--Ad-ie CCS811_ERRSTAT_OK_NODATA - No errors (e), app valid (A), and running (F), no data yet (d)          
--vhxmrw F--AD-ie CCS811_ERRSTAT_OK        - No errors (e), app valid (A), and running (F), data available (D)
--VHXMRW F--AD-IE                          - Shows all (existing) flags in the up state (set)

|||||||| ||||||||
|||||||| |||||||E: CCS811_ERRSTAT_ERROR    - There is an error, the ERROR_ID register (0xE0) contains the error source
|||||||| ||||||I: CCS811_ERRSTAT_I2CFAIL   - Bit flag added by software (so not in datasheet): I2C transaction error       
|||||||| |||||-: Reserved
|||||||| ||||D: CCS811_ERRSTAT_DATA_READY  - A new data sample is ready in ALG_RESULT_DATA     
|||||||| |||A: CCS811_ERRSTAT_APP_VALID    - Valid application firmware loaded    
|||||||| ||-: app verify (boot mode only)
|||||||| |-: app erase (boot mode only)
|||||||| F: CCS811_ERRSTAT_FW_MODE         - Firmware is in application mode (not boot mode) 
||||||||
|||||||W: CCS811_ERRSTAT_WRITE_REG_INVALID - The CCS811 received an I²C write request but with invalid register address ID
||||||R: CCS811_ERRSTAT_READ_REG_INVALID   - The CCS811 received an I²C read request to a register addres that is invalid
|||||M: CCS811_ERRSTAT_MEASMODE_INVALID    - The CCS811 received an I²C request to write an unsupported mode to MEAS_MODE
||||X: CCS811_ERRSTAT_MAX_RESISTANCE       - The sensor resistance measurement has reached or exceeded the maximum range
|||H: CCS811_ERRSTAT_HEATER_FAULT          - The heater current in the CCS811 is not in range
||V: CCS811_ERRSTAT_HEATER_SUPPLY          - The heater voltage is not being applied correctly
|-: Reserved
-: Reserved                          

(end of doc)

ccs811's People

Contributors

erguro1973 avatar fcar12 avatar luytendries avatar maarten-pennings avatar per1234 avatar piecol avatar stigtsp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ccs811's Issues

Error Code - More questions...

Hello Maarten,
First, many thanks for your code, this is really appreciated.
I'm not able to get any value out of my CCS811.
First I upgraded the application to 2.0 using your code. It work without any problem.
Here is what I'm getting:

setup: Starting CCS811 basic demo
setup: ccs811 lib version: 10
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 2000
CCS811: waiting for (new) data
CCS811: errstat=2091=--VhxmrwF--Ad-iE
CCS811: errstat=2091=--VhxmrwF--Ad-iE
CCS811: errstat=2891=--VhXmrwF--Ad-iE
CCS811: errstat=2899=--VhXmrwF--AD-iE
CCS811: errstat=2899=--VhXmrwF--AD-iE
CCS811: errstat=2899=--VhXmrwF--AD-iE
CCS811: errstat=2899=--VhXmrwF--AD-iE

I updated to the latest ESP8266 Library.
I'm using a China D1 Mini
Supply is maybe a little low 3.27 since i'm powering with the USB.
Wake pin is tie to GND.

Waiting for your feedback
David

sensor missbehaviour

It is not directly related to this library itself, but maybe the right sport to discuss this:

setup: hardware    version: 12
setup: bootloader  version: 1000
setup: application version: 2000
[...]
148:	Temp: 29.51°C	Humidity: 23.67% RH	Pressure: 1001.30hPa	eCO2: 1726 ppm 	eTVOC: 366 ppb 	
148:	Temp: 29.75°C	Humidity: 24.82% RH	Pressure: 1001.30hPa	eCO2: 1625 ppm 	eTVOC: 268 ppb 	
baseline for this sensor: 0xEBB0
148:	Temp: 29.88°C	Humidity: 26.04% RH	Pressure: 1001.29hPa	eCO2: 1621 ppm 	eTVOC: 265 ppb 	
149:	Temp: 30.03°C	Humidity: 24.51% RH	Pressure: 1001.22hPa	eCO2: 1692 ppm 	eTVOC: 330 ppb 	
149:	Temp: 30.04°C	Humidity: 24.36% RH	Pressure: 1001.32hPa	eCO2: 1702 ppm 	eTVOC: 341 ppb 	
149:	Temp: 29.79°C	Humidity: 24.80% RH	Pressure: 1001.28hPa	eCO2: 782 ppm 	eTVOC: 57 ppb 	
149:	Temp: 30.04°C	Humidity: 23.65% RH	Pressure: 1001.32hPa	eCO2: 570 ppm 	eTVOC: 25 ppb 	
149:	Temp: 29.65°C	Humidity: 25.73% RH	Pressure: 1001.29hPa	eCO2: 423 ppm 	eTVOC: 3 ppb 	
149:	Temp: 29.66°C	Humidity: 24.65% RH	Pressure: 1001.22hPa	eCO2: 403 ppm 	eTVOC: 0 ppb 	
149:	Temp: 29.69°C	Humidity: 25.42% RH	Pressure: 1001.23hPa	eCO2: 405 ppm 	eTVOC: 0 ppb 	
149:	Temp: 29.65°C	Humidity: 23.97% RH	Pressure: 1001.22hPa	eCO2: 415 ppm 	eTVOC: 2 ppb 	
149:	Temp: 29.70°C	Humidity: 23.55% RH	Pressure: 1001.26hPa	eCO2: 402 ppm 	eTVOC: 0 ppb 	
149:	Temp: 29.47°C	Humidity: 23.88% RH	Pressure: 1001.30hPa	eCO2: 401 ppm 	eTVOC: 0 ppb 	
150:	Temp: 29.31°C	Humidity: 23.96% RH	Pressure: 1001.21hPa	eCO2: 403 ppm 	eTVOC: 0 ppb 	
150:	Temp: 28.56°C	Humidity: 24.77% RH	Pressure: 1001.23hPa	eCO2: 408 ppm 	eTVOC: 1 ppb 	
150:	Temp: 28.93°C	Humidity: 24.37% RH	Pressure: 1001.27hPa	eCO2: 412 ppm 	eTVOC: 1 ppb 	
150:	Temp: 28.56°C	Humidity: 24.88% RH	Pressure: 1001.25hPa	eCO2: 409 ppm 	eTVOC: 1 ppb 	
150:	Temp: 28.32°C	Humidity: 25.19% RH	Pressure: 1001.30hPa	CCS811: errstat=899=--vhXmrwF--AD-iE
150:	Temp: 28.70°C	Humidity: 25.07% RH	Pressure: 1001.18hPa	CCS811: errstat=899=--vhXmrwF--AD-iE
150:	Temp: 28.63°C	Humidity: 25.25% RH	Pressure: 1001.18hPa	eCO2: 466 ppm 	eTVOC: 9 ppb 	
baseline for this sensor: 0x9DAD
150:	Temp: 28.76°C	Humidity: 25.17% RH	Pressure: 1001.27hPa	CCS811: errstat=899=--vhXmrwF--AD-iE
150:	Temp: 28.68°C	Humidity: 30.86% RH	Pressure: 1001.32hPa	eCO2: 514 ppm 	eTVOC: 25 ppb 	
150:	Temp: 28.38°C	Humidity: 32.08% RH	Pressure: 1001.28hPa	eCO2: 1961 ppm 	eTVOC: 756 ppb 	
151:	Temp: 27.83°C	Humidity: 32.73% RH	Pressure: 1001.28hPa	eCO2: 2866 ppm 	eTVOC: 2566 ppb 	
151:	Temp: 27.45°C	Humidity: 33.58% RH	Pressure: 1001.31hPa	eCO2: 3702 ppm 	eTVOC: 4359 ppb 
151:	Temp: 27.07°C	Humidity: 34.13% RH	Pressure: 1001.28hPa	eCO2: 4463 ppm 	eTVOC: 5976 ppb 	
151:	Temp: 26.83°C	Humidity: 34.89% RH	Pressure: 1001.30hPa	eCO2: 5092 ppm 	eTVOC: 7319 ppb 	
151:	Temp: 26.56°C	Humidity: 35.67% RH	Pressure: 1001.24hPa	eCO2: 5750 ppm 	eTVOC: 8736 ppb 	
151:	Temp: 26.37°C	Humidity: 36.19% RH	Pressure: 1001.26hPa	eCO2: 6383 ppm 	eTVOC: 10079 ppb 	
151:	Temp: 26.20°C	Humidity: 36.54% RH	Pressure: 1001.21hPa	eCO2: 6940 ppm 	eTVOC: 11271 ppb 	
151:	Temp: 26.09°C	Humidity: 36.84% RH	Pressure: 1001.26hPa	eCO2: 7859 ppm 	eTVOC: 13267 ppb 	
151:	Temp: 25.99°C	Humidity: 36.72% RH	Pressure: 1001.26hPa	eCO2: 8421 ppm 	eTVOC: 14433 ppb 	

I put the sensor out of the window to get the baseline. The measurement is done every second but the values get summed up for a minute. First of all, there occurs some errors because of maximum resistance was reached. After this errors the sensors was placed inside. The absolute values are far beyond useful.
The sensor itself is burned-in (at least for a week) and this specific print-out was done after three hours running.

Chinese NodeMCU and CCS811

I use chinese clones. Like this: https://www.aliexpress.com/item/CJMCU-811-CCS811-Carbon-Monoxide-CO-VOCs-Air-Quality-Numerical-Gas-Sensors/32762314271.html
And this library is in trouble to read data:

Starting CCS811 basic demo
init: hardware version: 12
init: bootloader version: 1000
init: application version: 1100
CCS811: errstat=0=--vhxmrwf--ad-ie
CCS811: errstat=0=--vhxmrwf--ad-ie
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: waiting for (new) data

When i wait 5 min i get some data:

CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: I2C error
CCS811: eco2=459 ppm etvoc=8 ppb
CCS811: waiting for (new) data
CCS811: waiting for (new) data

Sensor works when i use Adafruit ccs811 library. But there are other problems ...

Measurements not realistic

Hi Maarten,

First of all thanks for sharing this CCS811 info! I'm running your css811basic sketch on a Nano, WAKE connected to ground. The CO2 values in the serial monitor are not very realistic, mostly around 475 ppm while my Netatmo module in the same room reports about 1000 ppm.

Info from sketch:
setup: Starting CCS811 basic demo
setup: ccs811 lib version: 10
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 1100

The sensor is brand new and came from China (see image). Do I need more patient for a burn-in or do you have other suggestions?

Best regards,

Hans.

d6b66492-8ae9-4f77-8285-8a867a5d1b8d

CCS811 & Deep Sleep

Greetings,

So I've been doing some experimenting with using the CCS811 with a deep sleep functionality and have been getting some odd results. Perhaps someone also has some experience and can help me out. So the code looks something like this:

const SleepTimer = 15 //in min
void setup(){
esp_sleep_wakeup_cause_t wakeup_reason;
  wakeup_reason = esp_sleep_get_wakeup_cause();

switch (wakeup_reason)
  {
  case ESP_SLEEP_WAKEUP_UNDEFINED:
     ccs811.begin();
  break;

   case ESP_SLEEP_WAKEUP_TIMER:
      uint16_t eco2, etvoc, errstat, raw;

      ccs811.read(&eco2, &etvoc, &errstat, &raw);
      Serial.println(eco2);
      Serial.println(etvoc);
   break;
   };

   esp_sleep_enable_timer_wakeup(SleepTimer * 1000000LL);
   delay(100);
   esp_deep_sleep_start();
}

While this works and I get readings every 15 min and they even seem to be quite accurate for the first hour or two. The problem is that after that first hour the VOC steadily increases resulting in an increased eCO2. I have several CCS811 sensors so I've compared the deep sleep version with one that runs in the loop and there is odd behaviour going on while it's asleep.

I have several theories, including that while the sensor is not being read it slowly builds VOC in the sensor resulting in increased readings, but I have no way to verify this. If anyone has any ideas, it would be much appreciated!

Also hex.py

I tried to dump Version 2-0-1 as my sensor is older.

I get:

File "hex.py", line 32
if( n%16==0 ): print( " ", end="" )
^
SyntaxError: invalid syntax

Thanks for helping.
Maybe you could offer a dump of 2-0-1?
I already flashed 2-0-0 with your great tool. Should I just let it be? But my sensor is already burned in.

ESP8266 Thing

I'm using ESP8266 Thing with CCS811 and I considering I/O # I made these changes to make the code run.

#define D1 14
#define D2 2
#define D3 5

But I'm getting this error. I have already tried connecting WAKE to GND and 5.

Starting CCS811 simple demo
ccs811: begin: reset failed
init: CCS811 begin FAILED
init: CCS811 versions FAILED
init: CCS811 start FAILED
CCS811: eco2=65535 ppm, etvoc=65535 ppb, errstat=3F9B=--VHXMRWF--AD-IE=ERROR|OLD, raw6=63 uA, raw10=1023 ADC

Reflashed Adafruit CCS811 and lost access to thermistor

The reflash of an Adafruit CCS811 to 2.0.0.0 went well. No worries there. The little chip now reports being at version 2.0.0 from version 1. However to my surprise I can no longer see the onboard thermistor. I do not have a copy of the old binary so I can not go back (not that I want to). Should I use a different binary for on-board thermistor support?

Very high eCO2 values

Hey! thanks a lot for the library, this is awesome. I saw the other thread with a similar question but my problem is slightly different:
image

It looks like an inverse burn :P haha for first days seemed to work on an acceptable range, but now the values are crazy high. Do I really need the humedity and temperature reference?

I am using your example for ThingSpeak directly, no other modifications to the ESP8266.

Seek help from CCS811

setup: Starting CCS811 basic demo
setup: ccs811 lib version: 10
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 2000

#Who knows if it's firmware or software
#Problem specification
When errstat: 2201! It is difficult to wake up THE CCS811, when the measurement results are incorrect

errstat: 2201
CCS811_ERRSTAT_OK: 152
CCS811: eco2=400 ppm etvoc=0 ppb CCS811: errstat=899=--vhXmrwF--AD-iE
errstat: 2201
CCS811_ERRSTAT_OK: 152
CCS811: eco2=400 ppm etvoc=0 ppb CCS811: errstat=899=--vhXmrwF--AD-iE
errstat: 2201
CCS811_ERRSTAT_OK: 152

#Normal execution:
errstat: 152
CCS811_ERRSTAT_OK: 152
CCS811: eco2=462 ppm etvoc=9 ppb CCS811: eco2=462 ppm etvoc=9 ppb
errstat: 152
CCS811_ERRSTAT_OK: 152
CCS811: eco2=454 ppm etvoc=8 ppb CCS811: eco2=454 ppm etvoc=8 ppb
errstat: 152
CCS811_ERRSTAT_OK: 152

#CCS811 firmware 1.0.0 is also a problem with the above

setup: Starting CCS811 basic demo
setup: ccs811 lib version: 10
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 1000
errstat: 144
CCS811_ERRSTAT_OK: 152
CCS811: eco2=4096 ppm etvoc=0 ppb CCS811: waiting for (new) data
errstat: 144
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: waiting for (new) data
errstat: 152
CCS811_ERRSTAT_OK: 152
CCS811: eco2=0 ppm etvoc=0 ppb CCS811: eco2=0 ppm etvoc=0 ppb
errstat: 152
CCS811_ERRSTAT_OK: 152
CCS811: eco2=0 ppm etvoc=0 ppb CCS811: eco2=0 ppm etvoc=0 ppb
errstat: 153
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: errstat=99=--vhxmrwF--AD-iE
errstat: 153
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: errstat=99=--vhxmrwF--AD-iE
errstat: 153
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: errstat=99=--vhxmrwF--AD-iE
errstat: 153
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: errstat=99=--vhxmrwF--AD-iE
errstat: 153
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: errstat=99=--vhxmrwF--AD-iE
errstat: 153
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: errstat=99=--vhxmrwF--AD-iE
errstat: 153
CCS811_ERRSTAT_OK: 152
CCS811: eco2=24713 ppm etvoc=65087 ppb CCS811: errstat=99=--vhxmrwF--AD-iE

somehow broken

load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0d

Starting CCS811 flasher
setup: library     version: 10
setup: hardware    version: 12
setup: bootloader  version: FFFFFFFF
setup: application version: FFFFFFFF
setup: starting flash of 'CCS811_SW000246_1-00.bin' in 5 seconds

ccs811: ping ok
ccs811: reset ok
ccs811: status (reset1) 10 ok
ccs811: app-erase ok
ccs811: status (app-erase) 40 ok
ccs811: writing 5120 ................................................................ 4608
ccs811: writing 4608 ................................................................ 4096
ccs811: writing 4096 ................................................................ 3584
ccs811: writing 3584 ................................................................ 3072
ccs811: writing 3072 ................................................................ 2560
ccs811: writing 2560 ................................................................ 2048
ccs811: writing 2048 ................................................................ 1536
ccs811: writing 1536 ................................................................ 1024
ccs811: writing 1024 ................................................................ 512
ccs811: writing 512 ................................................................ 0
ccs811: app-verify ok
ccs811: status (app-verify) 30 ok
ccs811: reset2 ok
ccs811: status (reset2) 10 ok

loop: ended ...
loop: ended ...


load 0x4010f000, len 1384, room 16 
tail 8
c&⸮]⸮⸮⸮⸮D⸮b1.⸮⸮⸮e
Starting CCS811 flasher
setup: library     version: 10
ccs811: Not in boot mode, or no valid app: 20
setup: CCS811 begin FAILED
setup: hardware    version: 12
setup: bootloader  version: 1000
setup: application version: 2000
init: already has 2.0.0
loop: ended ...
loop: ended ...


setup: Starting CCS811 basic demo
setup: ccs811 lib  version: 10
Scanning...
I2C device found at address 0x5A  !
done

ccs811: Not in boot mode, or no valid app: 20
setup: CCS811 begin FAILED
setup: hardware    version: 12
setup: bootloader  version: 1000
setup: application version: 2000
CCS811: I2C error
CCS811: I2C error
CCS811: I2C error

I put a I2C Scan after using Wire.begin(), the device is there and up, I2C should be working.
I'm currently on the master branch for esp8266 (commit a9e89500e16e1e9f07a3a4eec9370982e7b6b3cf) and using for this firmware flash a wemos D1 mini board.

Any suggestion?

Error code

I am getting this error code randomly between good readings. If it starts generating errors they keep coming. I am clock stretching on an ESP32 with a generic Chinese CS811 (ver. 2 firmware)

errstat=899=--vhXmrwF--AD-iE

How do I translate this? I can probably track this down on my own if I know what's going on. Interestingly, the first reading after setup is always good.

Problem with CCS811 version

Problem with CCS811 version
With the 2.0.0 version of the firmware, the sensitivity of the sense detection becomes very low
Who knows why

CCS811 on NodeMCU v3

I'm using NodeMCU v3 and CCS811's chinese copy (CJMCU).

I'm trying to run the basic program, to check if the sensor reads some data.
At first I was receiving messages like this:

Starting CCS811 basic demo
init: hardware version: 12
init: bootloader version: 1000
init: application version: 1100
errstat=10=--vhxmrwf--Ad-ie
errstat=10=--vhxmrwf--Ad-ie
errstat=10=--vhxmrwf--Ad-ie

and it kept going like this indefinitely.
After I did a hard reset using the RST pin, I started receiving these messages:

image

and, again, it waits indefinitely and reads no data.

I've tried using Adafruit's library here, these were the results:

image

If it had failed to start, I would've been prompted with another message. Instead, it starts, but it fails to read data.

Also, I've checked everything with an i2c scanner and the sensor is recognized with its correct address. I've also used your library to check the i2c bus and everything works normally.

Do you have any suggestions? What does errstat= 10 mean? (I couldn't find anything on the web).

Chinese module, I2C error

Hi,

I found the firmware section in datasheet and was wondering if I already had the last one. So I founded your library.

But unfortunately like https://github.com/maarten-pennings/CCS811/issues/6 and https://github.com/maarten-pennings/CCS811/issues/7 I can't get your library working.

I can successfully use adafruit or sparkfun library ones. I don't touch wiring, just upload your code, and get this "I2C error":

setup: Starting CCS811 basic demo
setup: ccs811 lib  version: 10
ccs811: ping failed (VDD/GND connected? SDA/SCL connected?)
setup: CCS811 begin FAILED
setup: hardware    version: FFFFFFFF
setup: bootloader  version: FFFFFFFF
setup: application version: FFFFFFFF
setup: CCS811 start FAILED
CCS811: I2C error
CCS811: I2C error
CCS811: I2C error
CCS811: I2C error

I tried with and without setting I2C SDA/SCL pins (21,22)
I tried with and without ccs811.set_i2cdelay(50);
I tried with and without an WAK pin (17 / -1)
I tried with an without an I2C address set (0x5A)

I am on a ESP32 with a Chinese CSS811 module like https://raw.githubusercontent.com/maarten-pennings/CCS811/master/wire-ccs811only.jpg
I don't add resistors for pull-up.

Oh and something weird: after flashing your library, if I flash again the adafruit one that was working for me just before, I had to do some reset of the chip first or it won't be recognized.

Sorry for my poor English, hope this information help.

constructor not working

Hi.

I see the idea you had with your constructor using default values. On the other hand, if you use CCS811() as a constructor call, this will call the default constructor, because it is still there and fits better than the constructor you created.

So just a hint, that it might not work the intended way...

  public: // Main interface
    CCS811() {
		CCS811(-1,CCS811_SLAVADDR_0);
	}
    CCS811(int nwake=-1, int slaveaddr=CCS811_SLAVADDR_0);       

Sleep mode

Hi! Thanks a lot for the library, it's working fine with ESP32, but i have a problem when i try to use it with sleep mode.

My code is:

`#include <Wire.h> // I2C library
#include "ccs811.h" // CCS811 library

#define uS_TO_S_FACTOR 1000000 // Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 60 // Time ESP32 will go to sleep (in seconds) 1 minute

CCS811 ccs811(23);

void setup() {
Serial.begin(115200);
Wire.begin();

// Enable CCS811
ccs811.set_i2cdelay(50); // Needed for ESP8266 because it doesn't handle I2C clock stretch correctly
bool ok= ccs811.begin();
if( !ok ) Serial.println("setup: CCS811 begin FAILED");

// Start measuring
ok= ccs811.start(CCS811_MODE_1SEC);
if( !ok ) Serial.println("setup: CCS811 start FAILED");

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
}

void loop() {
// Read
uint16_t eco2, etvoc, errstat, raw;
ccs811.read(&eco2,&etvoc,&errstat,&raw);

// Print measurement results based on status
if( errstat==CCS811_ERRSTAT_OK ) {
Serial.print("CCS811: ");
Serial.print("eco2="); Serial.print(eco2); Serial.print(" ppm ");
Serial.print("etvoc="); Serial.print(etvoc); Serial.print(" ppb ");
Serial.println();
} else if( errstat==CCS811_ERRSTAT_OK_NODATA ) {
Serial.println("CCS811: waiting for (new) data");
} else if( errstat & CCS811_ERRSTAT_I2CFAIL ) {
Serial.println("CCS811: I2C error");
} else {
Serial.print("CCS811: errstat="); Serial.print(errstat,HEX);
Serial.print("="); Serial.println( ccs811.errstat_str(errstat) );
}

// go to sleep for 1 minute
Serial.println("Going to sleep now");
delay(1000);
Serial.flush();
// delay(60000);
esp_deep_sleep_start();
}`

And the result is continuously: "CCS811: waiting for (new) data"

If i use delay(60000) without sleep, it's all ok.

Could you please help me?

CCS811 bricked???

Hello Maarten,
I have a CCS811 with old firmware and tried to flash it... that failed.. it was firmware 1.1
And when I run the flasher again it is like you showed a version FD...
Used a Arduino Autonomo and it say's it starts th eflashing procedure but after 15 minutes it still is not ready...

Any idea to get this working again???
Have the nWake pin connected to GND I am not sure if that's a problem??

Best regards,
Jody

CJMCU-811 successful flash

Hi Maarten how are you man ?
I just successful flashed my CJMCU-811 using an WEMOS D1

Thank you so much man

ccs811: begin: HW_ID read failed

Something went wrong... but i don't know why. If I'm using the Ardafruit CCS811 lib, the sensor is working.

My Code mods
CCS811 ccs811(-1, 0x5A); // nWAKE on D3
ccs811.set_i2cdelay(0); // Needed for ESP8266 because it doesn't handle I2C clock stretch correctly

My Hardware

  • CCS811 is like your picture "wire-ccs811only.jpg"
  • WEMOS LOLIN32 (ESP32)

Serial ouput:
Starting CCS811 flasher
ccs811: begin: HW_ID read failed
init: CCS811 begin FAILED
init: hardware version: FFFFFFFF
init: bootloader version: FFFFFFFF
init: application version: FFFFFFFF
init: comment-out this code line if you want to flash
loop: ended ...

Esp32 Deepsleep confusion

Hey,

Had a couple questions, I want to deep sleep with the esp32 for about 20minutes. How would this work with this sensor? Do I just set the mode to the 60second one and then just go to sleep and not put the sensor to sleep? And then when the esp32 Wakes up it will be able to get the data? How would I restore the settings? A detailed explanation would really help! Thank you.

hex.py file with python3

Hello!!!
If someboby need to modifiy hex.py file for its python version, I had to do this modification for my python3.4 version to make it work.
Hope it will be helpful for someone.

hex.py.zip

Version 1100 wrong ERROR_ID read?

I had an issue with my cjmcu-811 on firmware 1100. It kept throwing the following at startup:

setup: Starting CCS811 basic demo
setup: ccs811 lib  version: 10
setup: hardware    version: 12
setup: bootloader  version: 1000
setup: application version: 1100
CCS811: waiting for (new) data
CCS811: errstat=91=--vhxmrwF--Ad-iE
CCS811: errstat=99=--vhxmrwF--AD-iE
CCS811: errstat=99=--vhxmrwF--AD-iE
.
.
.

This seemed odd because it meant it was in application mode (good), application firmware loaded (good), data ready (good), and some error in the ERROR_ID... but none of the other flags were being thrown even though it thinks there's an error in ERROR_ID?

So I took out the debugger and found this code block:

    if( _appversion<0x2000 ) {
      ok= i2cread(CCS811_STATUS,1,&stat); // CCS811 with pre 2.0.0 firmware has wrong STATUS in CCS811_ALG_RESULT_DATA
      if( ok && stat==CCS811_ERRSTAT_OK ) ok= i2cread(CCS811_ALG_RESULT_DATA,8,buf); else buf[5]=0;
      buf[4]= stat; // Update STATUS field with correct STATUS
    } else {
      ok = i2cread(CCS811_ALG_RESULT_DATA,8,buf);
    }

The important part is the third line. If i2cread() passed and stat==CCS811_ERRSTAT_OK, then read the whole CCS811_ALG_RESULT_DATA into buff. Otherwise... just zero out the ERROR_ID part of buff at buf[5]? Why?

My issue ended up being a poorly soldered zero-ohm resistor between pins 4 and 5 on the CCS811 package. These are the PWM and Sense pins which need a connection for sensing the Heater current. Since these were not connected the board was throwing a CCS811_ERRSTAT_HEATER_SUPPLY error in ERROR_ID but I was never getting these flags printed for me. Correct me if I'm wrong, but it seems as if your code doesn't read the ERROR_ID byte unless there are no errors reported by status? If there's an error in status, it doesn't read anything into buff.

A second note, this whole workaround for v1100 is supposedly because the status register from i2cread(CCS811_ALG_RESULT_DATA,8,buf); reads incorrectly in firmware v1100. However, my status register seemed to read fine on firmware v1100 from CCS811_ALG_RESULT_DATA.

WAK pin

Hi, this is not really an issue, but I don't know of another to communicate about this library.

I've been playing both with this library and the sparkfun CCS811 library and I'm trying to build a CCS811 sensor with environmental (temperature / humidity) compensation. With the Sparkfun library, a CCS811 and a BME280, I've had trouble because of I2C problems (I think). With the CCS811 and the BME280 on the same I2C bus I have problems communicating with both devices (on different i2c addresses obviously), unless I manually switch the WAKE pin.

I think this library is taking a very smart approach to specifying the WAKE pin in the constructor of the driver.

How to clear calibration

I am running a generic CCS811 board (latest firmware) with a DHT22 on an ESP32 WEMOS board (probably counterfeit).

All is more or less well except that I have strange behavior from time to time similar to what is reported by others. eVOC and ECO2 will inexplicably climb after 15 hours or so of operation. Readings will suddenly revert to the startup values of 400/0 for no apparent reason.

When it is working as expected it well work well for many hours. Based on no clear evidence whatsoever I suspect that self calibration may be going awry.

Is there a way to do a "factory reset"? In other words clear all calibration memory and start over. I would like to "factory reset" and leave it outside in good air for 24 hours or more and see what happens.

Perhaps re-flashing the firmware would do the trick but I suspect that there is a smarter way,

Thanks,

Bill

hex.py

python hex.py CCS811_FW_App_v2-0-1.bin > CCS811_FW_App_v2-0-1.h
File "", line 1
python hex.py CCS811_FW_App_v2-0-1.bin > CCS811_FW_App_v2-0-1.h
^
SyntaxError: invalid syntax

CCS811 does not play nice with ArduinoECCX08 and ArduinoMqttClient libraries

On Arduino MKR WiFi 1010, I'm unable to properly initialise and/or use the CCS811 in conjunction with both of the ArduinoECCX08 and ArduinoMqttClient libraries. The basic example runs fine, so I can safely exclude any hardware issues. When I comment out everything that has to do with the ECCX08 and the MqttClient, my code runs fine, however when either of these libraries come into play, the CCS fails to initialize and start, resulting in weird readings like: 54263 and 65503... Could it be an issue with i2c communication? I have the WAKE pin wired to ground... would it make sense to let the Arduino manage it? Any recommendations as to how can I start unraveling this? Thank you, I appreciate your time and effort!

Here's the serial output of what I'm currently getting:

Attempting to connect to SSID: CentralPerk
You're connected to the network

Attempting to MQTT broker: xxx.xxxxxxxxx.xxxxxx.amazonaws.com
.
You're connected to the MQTT broker

ccs811: ping failed (VDD/GND connected? SDA/SCL connected?)
setup: CCS811 begin FAILED
setup: hardware version: FFFFFFFF
setup: bootloader version: FFFFFFFF
setup: application version: FFFFFFFF
setup: CCS811 start FAILED
Publishing new sensor readings:
{"temperature":22.7,"humidity":49,"feelsLike":22.3,"co2":54263,"tvoc":65503}

Here's my setup() code:

void setup() {
  Serial.begin(115200);
  while (!Serial);

  // Enable I2C
  Wire.begin();

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);

  // Set the ECCX08 slot to use for the private key
  // and the accompanying public certificate for it
  sslClient.setEccSlot(0, certificate);

  // Crypto Element Setup
  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  // Connect to WiFi
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }

  // Connect to MQTT Broker
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(broker);
  Serial.println(" ");

  while (!mqttClient.connect(broker, 8883)) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  mqttClient.subscribe("arduino/incoming");

  // Set the message callback, this function is
  // called when the MQTTClient receives a message
  mqttClient.onMessage(onMessageReceived);

  // Enable CCS811
  // Needed for ESP8266 because it doesn't handle I2C clock stretch correctly
  // ccs811.set_i2cdelay(50);
  bool ok = ccs811.begin();
  if(!ok) Serial.println("setup: CCS811 begin FAILED");

  // Print CCS811 versions
  Serial.print("setup: hardware    version: "); Serial.println(ccs811.hardware_version(),HEX);
  Serial.print("setup: bootloader  version: "); Serial.println(ccs811.bootloader_version(),HEX);
  Serial.print("setup: application version: "); Serial.println(ccs811.application_version(),HEX);

  // Start measuring
  ok = ccs811.start(CCS811_MODE_1SEC);
  if(!ok) Serial.println("setup: CCS811 start FAILED");

  // DHT Setup
  dht.begin();

  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);

}

And loop:

void loop() {

  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // poll for new MQTT messages and send keep alives
  mqttClient.poll();

  // check for changes and publish a message if values have changed
  if (millis() - lastMillis > 10000) {
    lastMillis = millis();
    updateSensorReadings();
  }

  // read the state of the pushbutton value:
  reading = digitalRead(buttonPin);
   if (reading != lastButtonState) {
      lastDebounceTime = millis();
      lastButtonState = reading;
   }

   if ((millis() - lastDebounceTime) > debounceDelay) {
       if (buttonState != lastButtonState) {
           buttonState = lastButtonState;
           if (buttonState == HIGH) {
                 ledState = !ledState;
                 digitalWrite(ledPin, ledState);
           }
       }
   }

}

The only part in loop that has anything to do with the CCS811 is simply calling this function:

void updateSensorReadings() {
  h = dht.readHumidity();
  t = dht.readTemperature();
  f = round(dht.computeHeatIndex(t, h, false) * 10.0) / 10.0;

  ccs811.read(&co2, &tvoc, NULL, NULL);

  if (h != prevH || t != prevT || f != prevF || co2 != prevCo2 || tvoc != prevTvoc) {
    prevH = h;
    prevT = t;
    prevF = f;
    prevCo2 = co2;
    prevTvoc = prevTvoc;
    publishMessage(t, h, f, co2, tvoc);
  } else {
    Serial.println("Sensor readings unchanged");
  };

  delay(50);

}

How To: use multiple CJMCU-8110

Hi, I am rather new in programming and wonder how to compact the code I wrote for using a flexible number of CJMCU-8110 connected to my NodeMCU.
In the attached test code below I have 2 connected, but in the near future I want to expand to 3 or 4 and would like to drive that by a variable (f.i. int SensorNumber = 2) instead of duplicating the code for each sensor.

Who can guide me to a solution?

#include <Arduino.h>
#include <Wire.h>    // I2C library
#include "ccs811.h"  // CCS811 library
#include "ClosedCube_HDC1080.h"

CCS811 ccs811_1;
CCS811 ccs811_2;

ClosedCube_HDC1080 HDC1080_1;
ClosedCube_HDC1080 HDC1080_2;

int SDApin;
int SCLpin = D1;

HDC1080_SerialNumber sernum;
char format[12];
bool vBootphase = true;
uint16_t eco2, etvoc, errstat, raw;

void setup() {Serial.begin(115200); while(!Serial){;}}

void loop() 
{
  if (vBootphase == true)
  {
    // Channel 1: Setup
    SDApin = D2;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.println("");
    Serial.println("*** CCS1 ***");
    Serial.print("CCS :");
    ccs811_1.set_i2cdelay(50);
    ccs811_1.begin();
    delay(500);
    ccs811_1.start(CCS811_MODE_1SEC);
    delay(1000);
    Serial.print("setup: hardware    version: "); Serial.println(ccs811_1.hardware_version(),HEX);
    Serial.print("setup: bootloader  version: "); Serial.println(ccs811_1.bootloader_version(),HEX);
    Serial.print("setup: application version: "); Serial.println(ccs811_1.application_version(),HEX);
    // HDC1080
    HDC1080_1.begin(0x40);
    Serial.print("Manufacturer ID=0x");
    Serial.println(HDC1080_1.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments
    Serial.print("Device ID=0x");
    Serial.println(HDC1080_1.readDeviceId(), HEX); // 0x1050 ID of the device
    Serial.print("Device Serial Number=");
  	sernum = HDC1080_1.readSerialNumber();
  	sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast);
  	Serial.println(format);

    // Channel 2: Setup
    SDApin = D6;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.println("*** CCS2 ***");
    // Print CCS811 versions
    Serial.print("CCS2 :");
    ccs811_2.set_i2cdelay(50);
    ccs811_2.begin();
    delay(500);
    ccs811_2.start(CCS811_MODE_1SEC);
    delay(1000);
    Serial.print("setup: hardware    version: "); Serial.println(ccs811_2.hardware_version(),HEX);
    Serial.print("setup: bootloader  version: "); Serial.println(ccs811_2.bootloader_version(),HEX);
    Serial.print("setup: application version: "); Serial.println(ccs811_2.application_version(),HEX);
    // HDC1080
    HDC1080_2.begin(0x40);
    Serial.print("Manufacturer ID=0x");
    Serial.println(HDC1080_2.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments
    Serial.print("Device ID=0x");
    Serial.println(HDC1080_2.readDeviceId(), HEX); // 0x1050 ID of the device
    Serial.print("Device Serial Number=");
    sernum = HDC1080_2.readSerialNumber();
  	sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast);
  	Serial.println(format);

    vBootphase = false;
  }
  else
  {
    // Channel 1
    SDApin = D2;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.print("\nSensor connected on: ");
    Serial.print("SDA - ");Serial.print(SDApin); Serial.print(" | SCL - ");Serial.print(SCLpin);
    Serial.print("\n");
    ccs811_1.read(&eco2,&etvoc,&errstat,&raw);
    delay(500);
    Serial.print("ErrStat: ");Serial.print(errstat);Serial.print(" | ");Serial.println(ccs811_1.errstat_str(errstat));
    if(!errstat==CCS811_ERRSTAT_OK) 
    {
      Serial.print("CCS811-1: ");
      Serial.println("Failed to read from sensor");
      ccs811_1.begin();
      delay(500);
      ccs811_1.start(CCS811_MODE_1SEC);
    }
    else
    { 
      Serial.print("CCS811-1: ");
      Serial.print("eco2=");    Serial.print(eco2);     Serial.print(" ppm | ");
      Serial.print("etvoc=");   Serial.print(etvoc);    Serial.print(" ppb");
      Serial.print("\n");
    }
    // ** HDC1080 **
    Serial.print("T="); Serial.print(HDC1080_1.readTemperature()); Serial.print("C");
    Serial.print(", RH="); Serial.print(HDC1080_1.readHumidity()); Serial.println("%");

    // Channel 2
    SDApin = D6;
    Wire.begin(SDApin, SCLpin);
    delay(500);
    // ** CCS811 **
    Serial.print("Sensor connected on: ");
    Serial.print("SDA - ");Serial.print(SDApin); Serial.print(" | SCL - ");Serial.print(SCLpin);
    Serial.print("\n");
    ccs811_2.read(&eco2,&etvoc,&errstat,&raw);
    delay(500);
    Serial.print("ErrStat: ");Serial.print(errstat);Serial.print(" | ");Serial.println(ccs811_2.errstat_str(errstat));
    if(errstat!=CCS811_ERRSTAT_OK) 
    {
      Serial.print("CCS811-2: ");
      Serial.println("Failed to read from sensor");
      ccs811_1.begin();
      delay(500);
      ccs811_2.start(CCS811_MODE_1SEC);
    }
    else
    { 
      Serial.print("CCS811-2: ");
      Serial.print("eco2=");    Serial.print(eco2);     Serial.print(" ppm | ");
      Serial.print("etvoc=");   Serial.print(etvoc);    Serial.print(" ppb");
      Serial.print("\n");
    }
    // ** HDC1080 **
    Serial.print("T="); Serial.print(HDC1080_1.readTemperature()); Serial.print("C");
    Serial.print(", RH="); Serial.print(HDC1080_1.readHumidity()); Serial.println("%");
   
    delay(10000);
  }
}

20200514_PostedCode.txt

CJMCU-8118 ; 3 degrees over and 5% humity bellow.

Hello Marteen , pleased to contact you.

We've been fighing for weeks to get an accurate temp/humity/CO2/TVOC measurements from a CJMCU-8118, using ESP-IDF.

Best results have been 2ºC over , and 5% less humity than measured with 3 other instruments.

If I use modes 0x10 or 0x40 on the CCS811 , it seems the heater (all time on) is affecting the measurement on the HDC1080. (2-3ºC over , 5-7%Hum below)

If I use mode 0x20 or 0x30 in CCS811 , HDC1080 temperature and humidity give good valuea but I'm unable to get correct measurements from the CSS811. (allways same wrong value , or 0x400, 0)..

If we use the INT pin , in order to get the value from the sensor when it's ready you think this will fix the issue?

We are using a self delevolped application written entirely in ESP-IDF.

On other hand, our sensor hardware version is 1.2 and app version is 1.1 when we try to upgrade to app version 2.00 or 2.01 we can not get any measurements again.

Do you think which is the minimum hardware version we need to upgrade app to 2.x?

Thank you in advance and congrats for your great work .-

CCSbasic log :

18:48:38.027 -> setup: Starting CCS811 basic demo
18:48:38.027 -> setup: ccs811 lib version: 10
18:48:38.027 -> setup: hardware version: 12
18:48:38.027 -> setup: bootloader version: 1000
18:48:38.027 -> setup: application version: 1100
18:48:38.027 -> CCS811: waiting for (new) data
18:48:39.022 -> CCS811: waiting for (new) data
18:48:40.016 -> CCS811: eco2=0 ppm etvoc=0 ppb
18:48:41.044 -> CCS811: eco2=0 ppm etvoc=0 ppb
18:48:42.039 -> CCS811: eco2=0 ppm etvoc=0 ppb
18:48:43.033 -> CCS811: eco2=400 ppm etvoc=0 ppb
18:48:44.028 -> CCS811: eco2=405 ppm etvoc=0 ppb
18:48:45.056 -> CCS811: eco2=405 ppm etvoc=0 ppb
18:48:46.050 -> CCS811: eco2=400 ppm etvoc=0 ppb
18:48:47.045 -> CCS811: eco2=400 ppm etvoc=0 ppb
18:48:48.039 -> CCS811: eco2=400 ppm etvoc=0 ppb
18:48:49.034 -> CCS811: eco2=400 ppm etvoc=0 ppb

AIDomotics app log :

I (602) AIDOM-SENSOR System Log: ..::AIDomotics::.. - T,H,CO2,TVOC Sensor
I (612) AIDOM-SENSOR System Log: Developed by: Santiago Moncada, Ruben Montferrer, Andres Prieto
I (622) AIDOM-SENSOR System Log: Coded For: UPC University and the whole world
I (622) AIDOM-SENSOR System Log: WARRANTY: This software have NOT any warranty
I (632) AIDOM-SENSOR System Log: Executing POST...
Turning on the R LED
Turning off the R LED
Turning on the G LED
Turning off the G LED
Turning on the B LED
Turning off the B LED
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- 5a -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
I (1072) AIDOM-SENSOR System Log: POST Completed...
I (1072) AIDOM-SENSOR System Log: COLD START DETECTED ...
I (1082) AIDOM-SENSOR System Log: LED_EVENT_RECEIVED
I (1082) AIDOM-SENSOR System Log: LED REQUEST = 12
I (1092) LED CONTROL: LED ACTIVE STATUS IS: 12
I (1122) 802.11: ESP_WIFI_MODE_STA
I (1132) wifi: wifi driver task: 3ffc4c18, prio:23, stack:3584, core=0
I (1132) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (1132) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
Task List :
ipc1 R 24 564 3 1
main_loop R 24 2492 14 0
main R 1 404 5 0
IDLE1 R 0 1116 7 1
IDLE0 R 0 1088 6 0
button_handler B 10 1616 13 0
led_active B 10 520 15 -1
Tmr Svc B 1 1596 8 0
esp_timer B 22 3640 1 0
aidom_events_ta B 10 2160 12 1
ipc0 B 24 572 2 0
I (1162) wifi: wifi firmware version: a44d1c6
I (1182) wifi: config NVS flash: enabled
I (1192) wifi: config nano formating: disabled
I (1192) wifi: Init dynamic tx buffer num: 32
I (1202) wifi: Init data frame dynamic rx buffer num: 32
I (1202) wifi: Init management frame dynamic rx buffer num: 32
I (1212) wifi: Init management short buffer num: 32
I (1212) wifi: Init static rx buffer size: 1600
I (1212) wifi: Init static rx buffer num: 10
I (1222) wifi: Init dynamic rx buffer num: 32
I (1312) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0
I (1312) wifi: mode : sta (a4:cf:12:32:f7:8c)
I (1322) 802.11: wifi_init_sta finished.
I (1322) 802.11: connect to ap SSID:AIDOMGW51 password: XXXXX
I (1322) AIDOM SENSING: ENPOWERING SENSORS ....
I (1432) AIDOM SENSING: CONFIGURING SENSORS ...
I (1442) wifi: new:<11,0>, old:<1,0>, ap:<255,255>, sta:<11,0>, prof:1
I (1442) wifi: state: init -> auth (b0)
I (1442) wifi: state: auth -> assoc (0)
I (1452) wifi: state: assoc -> run (10)
Current Sensor Status :W (1452) AIDOM SENSING: ESP_OK
0x10 0x00
I (1472) wifi: connected with AIDOMGW51, aid = 3, channel 11, BW20, bssid = 00:e0:4c:2b:3e:00, security type: 3, phy: bgn, rssi: -51
Current measuring mode :W (1472) AIDOM SENSING: ESP_OK
0x20
I (1472) AIDOM SENSING: WARMING SENSORS ...
I (1482) wifi: pm start, type: 1

I (1482) wifi: AP's beacon interval = 102400 us, DTIM period = 1
I (1532) AIDOM SENSING: READING MEASUREMENTS ...
I (1652) AIDOM SENSING: T/H/Co2/TVOC : 28.10Cº, 49.27, 477ppms, 11ppms
I (3122) esp_netif_handlers: sta ip: 10.254.254.12, mask: 255.255.255.0, gw: 10.254.254.1
I (3122) power_save: got ip: 10.254.254.12
JSON len = 79
JSON Payload ={"temperature":28.0987548828125,"humidity":49.273681640625,"co2":477,"tvoc":11}
I (4322) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
I (4332) MQTTS_FUNCTIONS: Other event id:7
I (4342) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
I (4352) MQTTS_FUNCTIONS: MQTT_EVENT_CONNECTED
I (5332) MQTTS_FUNCTIONS: MQTT Topic : dt/device/a4:cf:12:32:f7:8c/sensor
I (5332) MQTTS_FUNCTIONS: MQTT Data : {"temperature":28.0987548828125,"humidity":49.273681640625,"co2":477,"tvoc":11}
I (5332) MQTTS_FUNCTIONS: Publishing data...
I (5342) MQTTS_FUNCTIONS: Sent publish successful, msg_id=31063
I (5342) AIDOM-SENSOR System Log: LED_EVENT_RECEIVED
I (5352) MQTTS_FUNCTIONS: MQTT_EVENT_PUBLISHED, msg_id=31063
I (5352) AIDOM-SENSOR System Log: LED REQUEST = 33
I (5412) LED CONTROL: LED ACTIVE STATUS IS: 33
I (5842) AIDOM-SENSOR System Log: LED_EVENT_RECEIVED
I (5842) AIDOM-SENSOR System Log: LED REQUEST = 0
I (5902) LED CONTROL: LED ACTIVE STATUS IS: 0
I (5942) AIDOM-SENSOR System Log: Enabling timer wakeup, 60 seconds
I (5962) AIDOM-SENSOR System Log: Entering deep sleep....
I (5962) wifi: state: run -> init (0)
I (5962) wifi: pm stop, total sleep time: 3127797 us / 4475512 us

I (5962) wifi: new:<11,0>, old:<11,0>, ap:<255,255>, sta:<11,0>, prof:1
E (5972) wifi: esp_wifi_connect 1148 wifi not start
I (5982) wifi: flush txq
I (5982) wifi: stop sw txq
I (5982) wifi: lmac stop hw txq

Done

Santiago .-

Having a simple questions about the CCS811 function when it comes to modes

@maarten-pennings

I apologize if this questions have been asked before, but afterchecking around i did not find any info about this in the other posts.

So we are using the CCS811 in a indoor sensor device, CCS811 is running the latest 2.0.1 version of the firmware.
When running it in constantly in Mode 3 it seems to behave quite well, after the initial burn in the readings seems to make sense. TVOC = 240 with minor fluxuations and eCO2 = in the 1600-1800...cant recal the excat value now.

Since the device is battery driven we tried to save some power by doing the following:

1: Let device run for 30min in mode 3 so that readings are stable, documentation says 20min
After 30min we take a reading, then it goes back to Idle Mode, but doing this we see some odd behavior

If we use this 30min interval were we switch from 30min runtime and back to idle, the reading shows tvoc = 0 and eCo2 = 400
And its basically stuck there, meaning values dont move at all unless we beath on it or leave a open pen next to the sensor, then we get a spike. I know we have good air quality in the office, but its not that great:)

Are we doing it wrong or is there another way to do this, or should we just forget about this and just let it run in mode 3 the entire time ?

Any ideas and suggestions would be highly appritiated

Best regards
SC Naimy

nWake issue

Hi @maarten-pennings, thanks for this library, it is very helpful. I am having trouble getting nWAKE to work. Do you have any suggestions to troubleshoot?

I can get ccs811basic working fine as long as I have nWake directly connected to GND. The wiring is correct and matches the README.md for ESP8266. Whenever I wire D3 to nWake and use ccs811(D3), I get: ccs811: ping failed (VDD/GND connected? SDA/SCL connected?). I am using Wemos D1 mini with CJMCU-811. I also tried using D4 pin instead of D3, and also tried flashing from 1.1 to 2.0, but still see the same error.

Downgrade to CCS811 Old Firmware v1.0.0

Hi guys!
I've modified my chinesse CSS811 board and soldered a 10k SMD NTC and a 10k SMD Resitor (R3 and R4 in original schematic) in orther to get Temperature readings.
The fact was that I had this board updated to firmware version 2.0.1 and it wasn't impossible to get temperature readings with this firmware.

So after a lot of searching Internet, I've found the old firmware to get temperature readings.
And of course downgraded it with success.

Here you have that firmware.
ccs811_fw_app_1v0p0.bin.zip

Hope it will serve to somebody.

borken CJMU-8118 ?

I am trying to run your demo for CJMU-8118 on Chinese clone of Arduino Nano with old bootloader.
I checked that i2c works with monitor.
When I plug CJMU-8118 in it is not detected.
I do not use pull ups.
Could you suggest smth ?

eco2=0 ppm, etvoc=0 ppb

Hi,

on ESP8266 I get always the same results of eco2=0 ppm and etvoc=0 ppb. The output looks like this:
CCS811: eco2=0 ppm, etvoc=0 ppb, errstat=90=--vhxmrwF--Ad-ie=ERROR|OLD, raw6=10 uA, raw10=407 ADC. The raw10 varies a little bit but stays in a range between 400 and 420. What could cause this behavior?

Reliability of measurements

From yesterday, every 10 minutes I take measurements (NodeMCU + CCS811). In the code I have delay (300000);. I send measurements to my InfluxDB database. I visualize them using Grafan. Here are my measurements from the last 24 hours.

zrzut ekranu 2018-12-16 o 14 06 51

  • A few minutes after midnight I restarted the NodeMCU, because the measurements seemed too high. After the reboot they dropped significantly.
  • It is strange that at night, with the windows and doors closed, there has been no increase in CO2 levels. I have poor ventilation in the flat, so it should be significant.
  • TVOC and CO2 levels seem to be strongly related. Which is rather strange.

Does CCS811 require any additional calibration? Do I only have such strange measurements?

Wire.xxxx in library

Hi,
how to use the lib with an ESP32 (as sample) with two I2C interfaces?

Because of using the predefined Wire functions it is not possible to redefine the interface.

bool CCS811::i2cwrite(int regaddr, int count, const uint8_t * buf) {
Wire.beginTransmission(_slaveaddr);              // START, SLAVEADDR
Wire.write(regaddr); // Register address

Using following code (as sample) - it will not work:

TwoWire I2Cone = TwoWire(0);
TwoWire I2Ctwo = TwoWire(1);
...
I2Cone.begin(SDA1,SCL1,400000); // SDA pin 21, SCL pin 22 
I2Ctwo.begin(SDA2,SCL2,400000); // SDA pin 5, SCL pin 4 builtin OLED
...

As sample in CCS811Core was realized better:

CCS811Core::status CCS811Core::beginCore(TwoWire &wirePort)
{
	CCS811Core::status returnError = SENSOR_SUCCESS;
	
	_i2cPort = &wirePort; //Pull in user's choice of I2C hardware

	//Wire.begin(); //See issue 13 https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library/issues/13
...

Maybe you could adapt it?

Thanks!

begin() required before flash() ?

trying to set up startup in a loop so if flash gets disrupted, etc, then we'll try again.
In the flash ino example begin() is called before and again after flashing. this makes for an awkward loop.

Question: can flash() be run without begin() first?
i.e.
init();
do
{
if (application_version() < 0x2000)
{
flash();
}
begin();
} while (errorHappened);

Pain with capitalization and Wires

It started out easy: downloaded your lib as zip and installed in the uecide IDE for use with my ESP32. Basic example ran fine, even the flash could be done without any problems (so I now have app 0x2000). Great. Was not possible with the Arduino and Sparkfun libs.

But then I wanted to integrate the lib into my big sketch. The ESP32 supports two separate I2C connections, which Wire supports by default as Wire and Wire1 (can be named differently if desired). And my CCS811 has to be on Wire1. Not a major problem; all I had to do was to rename each occurrence of Wire in your lib to Wire1.

As I didn't want to modify the lib at its default place, I created a local copy, private to just my sketch. This is easily done under uecide. But there is a catch: uecide wants the same capitalization of folder, filenames and includes, while you have a mix of big cap in the folder, and small caps elsewhere.

So, now I have renamed everything to big cap, renamed the Wire to Wire1, and it is running! Please, don't upgrade!

But when you do, my wishlist is:

  • support both Wire options on the ESP32
  • be strictly consistent on your lib naming
  • expose the chip ID (like getCCS811ID). I am using so many chips, I'd prefer to just call a function instead of figuring it out from the lib code.

Now I am puzzled with the huge variation of the Css811 data, and I saw a lengthy discussion elsewhere on this site. But one question: there is some "raw" calculation in your basic script. Is that explained somewhere in the datasheet, or did you figure this out yourself? How is that related to the co2 and tvoc data? Is that even explained, or hidden in the firmware?

Self over-heating

Hello,
first I have to say Thank you for your library, its works perfect :)
This is not a issue, it's something like warning for others!

Im using CCS811 on small board with BMP280 and Si7021, all together on I2C, works good but there is a problem with overheating of CCS811 which affect other sensors. Supply voltage is 3.2V.

CCS811 on Mode 1 (CCS811_MODE_1SEC) produces a lot of heat, sensor surface temperature is approx 40°C (around temperature is like 24°C). BMP280 is like 10mm left and it's useless for reading surrounding temperature. His value is around 2..3°C above the ambient. It's also affecting Si7021 and his humidity values...

After switching CCS811 to Mode 3 (CCS811_MODE_60SEC) it's much better. CCS811 surface temperature is approx 26°C during idle and 30°C when measuring (for like 1 second). But it's still about 2°C above the ambient.

I will make more measuring later after modify supply voltage to 2.0V. I hope that that will help reduce warming.

Place CCS811 as far as possible from temperature sensors if you require measurement accuracy!

set_envdata() t & h format?

I've been making a bit of a sensor matrix and have included the CCS811 along with a slew of other environmental sensors. After a couple revisions and different libraries, I've found yours to the most robust for testing my hardware. While I'm getting consistent readings from the sensor now, I'm looking more at calibrating the results and so look to set the environmental information via the set_envdata(). I've tried just feeding in the float values from the SHT31 and BMP280 that I have onboard but the readings I get back are very skewed (~6500ppm). Have been trying to see If this is a burn-in issue but I think more likely its a formatting issue between what the set_envdat() needs.

Does it work with just any float or does there need to be some additional calculations or rounding in order to feed the values into the functions?

Thanks :)

Hey Maarten,

I just wanted to thank you for this library. Now after I flashed my chip to the 2.1.0 version it gives quite nice results. As I'm currently learning rust I rewrote this library in rust with some minor changes. Also not everything is covered but the main functionality like reading data, setting baseline and environmental data and flashing the chip is supported and works. It was easy for me because of your work. That's why I just wanted to say thank you :)

If you want to have a look at my rust library check out https://crates.io/crates/ccs811

SetBaseline bounds

Hello,
I played around with the set_baseline.
I don't know if this can be really considered as an issue but I wanted to share on it as it seems that the baseline if a very important parameter.
Unfortunately it seems that there's ranges where the baseline works, ranges where it does not.

When setting the baseline manually, the maximum value is 3327, the lower value is 173.
When inputing -1, the baseline is 65535, which is the maximum value of the uint16_t C type, minus ( 65536 -1). So the maximum baseline in minus working value, is -83 (Baseline = 65536-83 = 65453 ).

Other numbers gives what seems to be an "automatic" baseline.
Oh you thought there was only top minus and upper bounds?

It also work between :
~11000 to ~14000 and
~21500 to ~24500 and
32173 to 35071 and,
~43000 to ~46300 and,
~54000 to ~56500 and,
~64500 to 65535.

CCS811 firmware demoted to version 1.1.0

CCS811 firmware demoted to version 1.1.0

CCS811 firmware demoted to version 1.1.0
Who knows how to downgrade from 2.0.0 to 1.1.0! No firmware version 1.1.0 was found in the warehouse

CCS811: I2C error

Hi,

I am following the basic example from your library and running it on this NodeMCU with this CCS811.

I have made the 2 edits in the Arduino15\packages\esp8266\hardware\esp8266\2.4.2\cores\esp8266.

But I am getting the error: CCS811: I2C error. This is my first complex project (I've only done LED ones before) with NodeMCU, so I not sure how to solved it.

I don't know if it matters but this is the errstat:

errstat=  16283
ccs811.errstat_str(errstat)=  1073675076

I looked at this link , and I replaced SDA and SCL with shorter cable (10 cm instead of 30cm), twisting SCL with GND and SDA with VCC, using 10k pull-ups resistor on both SDA and SCL (I didn't know how to do it, so I followed what is done on this circuit, I hope this is how it should be done), but I am still getting the same error and errstat code.

Here is my circuit (I followed you color code for the wire):
nodemcu
sensor

I am powering the NoceMCU via a USB charger (not a computer)

Thanks a lot for your help!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.