CCS811 driver added (#479)
This commit is contained in:
parent
2f62c6e9df
commit
61f23d0cf4
11 changed files with 1989 additions and 0 deletions
examples/ccs811
57
examples/ccs811/README.md
Normal file
57
examples/ccs811/README.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
# CCS811 Driver Examples
|
||||
|
||||
These examples demonstrate the usage of the CCS811 driver with only one sensors.
|
||||
|
||||
## Hardware setup
|
||||
|
||||
Most examples use only one CCS811 sensor. Following figure shows the hardware configuration if no interrupt is used.
|
||||
|
||||
```
|
||||
+------------------------+ +--------+
|
||||
| ESP8266 Bus 0 | | CCS811 |
|
||||
| GPIO 5 (SCL) >----> SCL |
|
||||
| GPIO 4 (SDA) ------ SDA |
|
||||
| GND -----> /WAKE |
|
||||
+------------------------+ +--------+
|
||||
```
|
||||
|
||||
If *nINT* interrupt is used to fetch new data, additionally the interrupt pin has to be connected to a GPIO pin.
|
||||
|
||||
```
|
||||
+------------------------+ +--------+
|
||||
| ESP8266 Bus 0 | | CCS811 |
|
||||
| GPIO 5 (SCL) >----> SCL |
|
||||
| GPIO 4 (SDA) ------ SDA |
|
||||
| GPIO 2 <----- /nINT |
|
||||
| GND -----> /WAKE |
|
||||
+------------------------+ +--------+
|
||||
```
|
||||
|
||||
In examples where CCS811 sensor is used in conjunction with a SHT3x sensor, the hardware configuration looks like following:
|
||||
|
||||
```
|
||||
+------------------------+ +--------+
|
||||
| ESP8266 Bus 0 | | CCS811 |
|
||||
| GPIO 5 (SCL) >--+----> SCL |
|
||||
| GPIO 4 (SDA) ---|-+--- SDA |
|
||||
| GND ---|-|--> /WAKE |
|
||||
| | | | +--------+
|
||||
| | | | | SHT3x |
|
||||
| | +----> SCL |
|
||||
| | +--- SDA |
|
||||
+------------------------+ +--------+
|
||||
```
|
||||
|
||||
## Example description
|
||||
|
||||
__*ccs811_one_sensor*__
|
||||
|
||||
Simple example with one CCS811 sensor connected to I2C bus 0. It demonstrates the different approaches to fetch the data. Either the interrupt *nINT* is used when new data are available or exceed defined thresholds or the new data are fetched periodically. Which approach is used is defined by the constants ```INT_DATA_RDY_USED``` and ```INT_THRESHOLD_USED```.
|
||||
|
||||
__*ccs811_plus_sht3x*__
|
||||
|
||||
Simple example with one CCS811 sensor connected to I2C bus 0 and one SHT3x sensor to determine ambient temperature. New data are fetched peridically every 2 seconds.
|
||||
|
||||
__*ccs811_temperature*__
|
||||
|
||||
Simple example with one CCS811 sensor connected to I2C bus 0. It demonstrates how to use CCS811 with an external NTC resistor to determine ambient temperature.
|
4
examples/ccs811/ccs811_one_sensor/Makefile
Normal file
4
examples/ccs811/ccs811_one_sensor/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
PROGRAM=CCS811_One_Sensor
|
||||
EXTRA_COMPONENTS = extras/i2c extras/ccs811
|
||||
include ../../../common.mk
|
||||
|
159
examples/ccs811/ccs811_one_sensor/ccs811_one_sensor.c
Normal file
159
examples/ccs811/ccs811_one_sensor/ccs811_one_sensor.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
/**
|
||||
* Simple example with one sensor connected to I2C bus 0. It demonstrates the
|
||||
* different approaches to fetch the data. Either the interrupt *nINT* is used
|
||||
* whenever new data are available or exceed defined thresholds or the new
|
||||
* data are fetched periodically.
|
||||
*
|
||||
* Harware configuration:
|
||||
*
|
||||
* +------------------------+ +--------+
|
||||
* | ESP8266 Bus 0 | | CCS811 |
|
||||
* | GPIO 5 (SCL) >----> SCL |
|
||||
* | GPIO 4 (SDA) ------ SDA |
|
||||
* | GPIO 2 <----- /nINT |
|
||||
* | GND -----> /WAKE |
|
||||
* +------------------------+ +--------+
|
||||
*/
|
||||
|
||||
// use following constants to define the demo mode
|
||||
// #define INT_DATA_RDY_USED
|
||||
// #define INT_THRESHOLD_USED
|
||||
|
||||
#include "espressif/esp_common.h"
|
||||
#include "esp/uart.h"
|
||||
#include "i2c/i2c.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include <task.h>
|
||||
|
||||
// include CCS811 driver
|
||||
#include "ccs811/ccs811.h"
|
||||
|
||||
// define I2C interfaces at which CCS811 sensors can be connected
|
||||
#define I2C_BUS 0
|
||||
#define I2C_SCL_PIN 5
|
||||
#define I2C_SDA_PIN 4
|
||||
|
||||
// define GPIO for interrupt
|
||||
#define INT_GPIO 2
|
||||
|
||||
static ccs811_sensor_t* sensor;
|
||||
|
||||
#if defined(INT_DATA_RDY_USED) || defined(INT_THRESHOLD_USED)
|
||||
/**
|
||||
* In this example, the interrupt *nINT* is used. It is triggered every time
|
||||
* new data are available (INT_DATA_RDY_USED) or exceed defined thresholds
|
||||
* (INT_THRESHOLD_USED). In this case, the user has to define an interrupt
|
||||
* handler that fetches the data directly or triggers a task, that is waiting
|
||||
* to fetch the data. In this example, a task is defined which suspends itself
|
||||
* in each cycle to wait for fetching the data. The task is resumed by the
|
||||
* the interrupt handler.
|
||||
*/
|
||||
|
||||
TaskHandle_t nINT_task;
|
||||
|
||||
// User task that fetches the sensor values.
|
||||
|
||||
void user_task_interrupt (void *pvParameters)
|
||||
{
|
||||
uint16_t tvoc;
|
||||
uint16_t eco2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// task suspends itself and waits to be resumed by interrupt handler
|
||||
vTaskSuspend (NULL);
|
||||
|
||||
// after resume get the results and do something with them
|
||||
if (ccs811_get_results (sensor, &tvoc, &eco2, 0, 0))
|
||||
printf("%.3f CCS811 Sensor interrupt: TVOC %d ppb, eCO2 %d ppm\n",
|
||||
(double)sdk_system_get_time()*1e-3, tvoc, eco2);
|
||||
}
|
||||
}
|
||||
|
||||
// Interrupt handler which resumes user_task_interrupt on interrupt
|
||||
|
||||
void nINT_handler (uint8_t gpio)
|
||||
{
|
||||
xTaskResumeFromISR (nINT_task);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* In this example, user task fetches the sensor values every seconds.
|
||||
*/
|
||||
|
||||
void user_task_periodic(void *pvParameters)
|
||||
{
|
||||
uint16_t tvoc;
|
||||
uint16_t eco2;
|
||||
|
||||
TickType_t last_wakeup = xTaskGetTickCount();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// get environmental data from another sensor and set them
|
||||
// ccs811_set_environmental_data (sensor, 25.3, 47.8);
|
||||
|
||||
// get the results and do something with them
|
||||
if (ccs811_get_results (sensor, &tvoc, &eco2, 0, 0))
|
||||
printf("%.3f CCS811 Sensor periodic: TVOC %d ppb, eCO2 %d ppm\n",
|
||||
(double)sdk_system_get_time()*1e-3, tvoc, eco2);
|
||||
|
||||
// passive waiting until 1 second is over
|
||||
vTaskDelayUntil(&last_wakeup, 1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
// set UART Parameter
|
||||
uart_set_baud(0, 115200);
|
||||
// give the UART some time to settle
|
||||
sdk_os_delay_us(500);
|
||||
|
||||
/** -- MANDATORY PART -- */
|
||||
|
||||
// init all I2C bus interfaces at which CCS811 sensors are connected
|
||||
i2c_init (I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K);
|
||||
|
||||
// longer clock stretching is required for CCS811
|
||||
i2c_set_clock_stretch (I2C_BUS, CCS811_I2C_CLOCK_STRETCH);
|
||||
|
||||
// init the sensor with slave address CCS811_I2C_ADDRESS_1 connected I2C_BUS.
|
||||
sensor = ccs811_init_sensor (I2C_BUS, CCS811_I2C_ADDRESS_1);
|
||||
|
||||
if (sensor)
|
||||
{
|
||||
#if defined(INT_DATA_RDY_USED) || defined(INT_THRESHOLD_USED)
|
||||
|
||||
// create a task that is resumed by interrupt handler to use the sensor
|
||||
xTaskCreate(user_task_interrupt, "user_task_interrupt", 256, NULL, 2, &nINT_task);
|
||||
|
||||
// activate the interrupt for INT_GPIO and set the interrupt handler
|
||||
gpio_set_interrupt(INT_GPIO, GPIO_INTTYPE_EDGE_NEG, nINT_handler);
|
||||
|
||||
#ifdef INT_DATA_RDY_USED
|
||||
// enable the data ready interrupt
|
||||
ccs811_enable_interrupt (sensor, true);
|
||||
#else
|
||||
// set threshold parameters and enable threshold interrupt mode
|
||||
ccs811_set_eco2_thresholds (sensor, 600, 1100, 40);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// create a periodic task that uses the sensor
|
||||
xTaskCreate(user_task_periodic, "user_task_periodic", 256, NULL, 2, NULL);
|
||||
|
||||
#endif
|
||||
|
||||
// start periodic measurement with one measurement per second
|
||||
ccs811_set_mode (sensor, ccs811_mode_1s);
|
||||
}
|
||||
}
|
||||
|
3
examples/ccs811/ccs811_plus_sht3x/Makefile
Normal file
3
examples/ccs811/ccs811_plus_sht3x/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
PROGRAM=CCS811_Plus_SHT3x
|
||||
EXTRA_COMPONENTS = extras/i2c extras/ccs811 extras/sht3x
|
||||
include ../../../common.mk
|
106
examples/ccs811/ccs811_plus_sht3x/ccs811_plus_sht3x.c
Normal file
106
examples/ccs811/ccs811_plus_sht3x/ccs811_plus_sht3x.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* Simple example with one CCS811 sensor connected to I2C bus 0 and one SHT3x
|
||||
* sensor to determine ambient temperature. New data are fetched peridically.
|
||||
*
|
||||
* Harware configuration:
|
||||
*
|
||||
* +------------------------+ +--------+
|
||||
* | ESP8266 Bus 0 | | CCS811 |
|
||||
* | GPIO 5 (SCL) >--+----> SCL |
|
||||
* | GPIO 4 (SDA) ---|-+--- SDA |
|
||||
* | GND ---|-|--> /WAKE |
|
||||
* | | | | +--------+
|
||||
* | | | | | SHT3x |
|
||||
* | | +----> SCL |
|
||||
* | | +--- SDA |
|
||||
* +------------------------+ +--------+
|
||||
*/
|
||||
|
||||
#include "espressif/esp_common.h"
|
||||
#include "esp/uart.h"
|
||||
#include "i2c/i2c.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include <task.h>
|
||||
|
||||
// include CCS811 driver
|
||||
#include "ccs811/ccs811.h"
|
||||
|
||||
// include SHT3x driver
|
||||
#include "sht3x/sht3x.h"
|
||||
|
||||
// define I2C interfaces at which CCS811 and SHT3x sensors are connected
|
||||
#define I2C_BUS 0
|
||||
#define I2C_SCL_PIN 5
|
||||
#define I2C_SDA_PIN 4
|
||||
|
||||
static ccs811_sensor_t* ccs811; // CCS811 device data structure
|
||||
static sht3x_sensor_t* sht3x; // SHT3x device data structure
|
||||
|
||||
/*
|
||||
* User task that fetches the sensor values every 2 seconds.
|
||||
*/
|
||||
void user_task(void *pvParameters)
|
||||
{
|
||||
uint16_t tvoc;
|
||||
uint16_t eco2;
|
||||
|
||||
float temperature;
|
||||
float humidity;
|
||||
|
||||
// start periodic measurement with 1 measurement per second
|
||||
ccs811_set_mode (ccs811, ccs811_mode_1s);
|
||||
|
||||
// start periodic measurements with 1 measurement per second
|
||||
sht3x_start_measurement (sht3x, sht3x_periodic_1mps, sht3x_high);
|
||||
|
||||
// passive waiting until measurement results are available
|
||||
vTaskDelay (sht3x_get_measurement_duration (sht3x_high));
|
||||
|
||||
TickType_t last_wakeup = xTaskGetTickCount();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// get the results from CCS811 and do something with them
|
||||
if (ccs811_get_results (ccs811, &tvoc, &eco2, 0, 0))
|
||||
printf("%.3f CCS811 Sensor periodic: TVOC %d ppb, eCO2 %d ppm\n",
|
||||
(double)sdk_system_get_time()*1e-3, tvoc, eco2);
|
||||
|
||||
// get the values from SHT3x and do something with them
|
||||
if (sht3x_get_results (sht3x, &temperature, &humidity))
|
||||
{
|
||||
printf("%.3f SHT3x Sensor: %.2f °C, %.2f %%\n",
|
||||
(double)sdk_system_get_time()*1e-3, temperature, humidity);
|
||||
|
||||
// set CCS811 environmental data with values fetched from SHT3x
|
||||
ccs811_set_environmental_data (ccs811, temperature, humidity);
|
||||
}
|
||||
// passive waiting until 2 seconds is over
|
||||
vTaskDelayUntil(&last_wakeup, 2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
// set UART Parameter
|
||||
uart_set_baud(0, 115200);
|
||||
// give the UART some time to settle
|
||||
sdk_os_delay_us(500);
|
||||
|
||||
/** -- MANDATORY PART -- */
|
||||
|
||||
// init all I2C bus interfaces at which CCS811 sensors are connected
|
||||
i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K);
|
||||
|
||||
// longer clock stretching is required for CCS811
|
||||
i2c_set_clock_stretch (I2C_BUS, CCS811_I2C_CLOCK_STRETCH);
|
||||
|
||||
// init the sensors
|
||||
ccs811 = ccs811_init_sensor (I2C_BUS, CCS811_I2C_ADDRESS_1);
|
||||
sht3x = sht3x_init_sensor (I2C_BUS, SHT3x_ADDR_2);
|
||||
|
||||
if (ccs811 && sht3x)
|
||||
// create a task that uses the sensor
|
||||
xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL);
|
||||
}
|
4
examples/ccs811/ccs811_temperature/Makefile
Normal file
4
examples/ccs811/ccs811_temperature/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
PROGRAM=CCS811_Temperature
|
||||
EXTRA_COMPONENTS = extras/i2c extras/ccs811
|
||||
LIBS ?= gcc hal m
|
||||
include ../../../common.mk
|
131
examples/ccs811/ccs811_temperature/ccs811_temperature.c
Normal file
131
examples/ccs811/ccs811_temperature/ccs811_temperature.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/**
|
||||
* Simple example with one sensor connected to I2C bus 0. It demonstrates
|
||||
* how to use CCS811 with an external NTC thermistor to determine ambient
|
||||
* temperature.
|
||||
*
|
||||
* Harware configuration:
|
||||
*
|
||||
* +------------------------+ +--------+
|
||||
* | ESP8266 Bus 0 | | CCS811 |
|
||||
* | GPIO 5 (SCL) >----> SCL |
|
||||
* | GPIO 4 (SDA) ------ SDA |
|
||||
* | GND -----> /WAKE |
|
||||
* +------------------------+ +--------+
|
||||
*/
|
||||
|
||||
#include "espressif/esp_common.h"
|
||||
#include "esp/uart.h"
|
||||
#include "i2c/i2c.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include <task.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// include CCS811 driver
|
||||
#include "ccs811/ccs811.h"
|
||||
|
||||
// define I2C interfaces at which CCS811 sensors can be connected
|
||||
#define I2C_BUS 0
|
||||
#define I2C_SCL_PIN 5
|
||||
#define I2C_SDA_PIN 4
|
||||
|
||||
|
||||
static ccs811_sensor_t* sensor;
|
||||
|
||||
|
||||
/*
|
||||
* In this example, user task fetches the sensor values every seconds.
|
||||
*/
|
||||
|
||||
// parameters of the Adafruit CCS811 Air Quality Sensor Breakout
|
||||
#define CCS811_R_REF 100000
|
||||
#define CCS811_R_NTC 10000
|
||||
#define CCS811_R_NTC_TEMP 25
|
||||
#define CCS811_BCONSTANT 3380
|
||||
|
||||
void user_task_periodic(void *pvParameters)
|
||||
{
|
||||
uint16_t tvoc;
|
||||
uint16_t eco2;
|
||||
|
||||
TickType_t last_wakeup = xTaskGetTickCount();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// get environmental data from another sensor and set them
|
||||
// ccs811_set_environmental_data (sensor, 25.3, 47.8);
|
||||
|
||||
// get the results and do something with them
|
||||
if (ccs811_get_results (sensor, &tvoc, &eco2, 0, 0))
|
||||
printf("%.3f CCS811 Sensor periodic: TVOC %d ppb, eCO2 %d ppm\n",
|
||||
(double)sdk_system_get_time()*1e-3, tvoc, eco2);
|
||||
|
||||
// get NTC resistance
|
||||
uint32_t r_ntc = ccs811_get_ntc_resistance (sensor, CCS811_R_REF);
|
||||
|
||||
// calculation of temperature from application note ams AN000372
|
||||
double ntc_temp;
|
||||
ntc_temp = log((double)r_ntc / CCS811_R_NTC); // 1
|
||||
ntc_temp /= CCS811_BCONSTANT; // 2
|
||||
ntc_temp += 1.0 / (CCS811_R_NTC_TEMP + 273.15); // 3
|
||||
ntc_temp = 1.0 / ntc_temp; // 4
|
||||
ntc_temp -= 273.15; // 5
|
||||
|
||||
printf("%.3f CCS811 Sensor temperature: R_NTC %u Ohm, T %f °C\n",
|
||||
(double)sdk_system_get_time()*1e-3, r_ntc, ntc_temp);
|
||||
|
||||
// passive waiting until 1 second is over
|
||||
vTaskDelayUntil(&last_wakeup, 1100 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
// set UART Parameter
|
||||
uart_set_baud(0, 115200);
|
||||
// give the UART some time to settle
|
||||
sdk_os_delay_us(500);
|
||||
|
||||
/** -- MANDATORY PART -- */
|
||||
|
||||
// init all I2C bus interfaces at which CCS811 sensors are connected
|
||||
i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K);
|
||||
|
||||
// longer clock stretching is required for CCS811
|
||||
i2c_set_clock_stretch (I2C_BUS, CCS811_I2C_CLOCK_STRETCH);
|
||||
|
||||
// init the sensor with slave address CCS811_I2C_ADDRESS_1 connected I2C_BUS.
|
||||
sensor = ccs811_init_sensor (I2C_BUS, CCS811_I2C_ADDRESS_1);
|
||||
|
||||
if (sensor)
|
||||
{
|
||||
#if defined(INT_DATA_RDY_USED) || defined(INT_THRESHOLD_USED)
|
||||
|
||||
// create a task that is resumed by interrupt handler to use the sensor
|
||||
xTaskCreate(user_task_interrupt, "user_task_interrupt", 256, NULL, 2, &nINT_task);
|
||||
|
||||
// set the GPIO and interrupt handler for *nINT* interrupt
|
||||
gpio_set_interrupt(INT_GPIO, GPIO_INTTYPE_EDGE_NEG, nINT_handler);
|
||||
|
||||
#ifdef INT_DATA_RDY_USED
|
||||
// enable the data ready interrupt
|
||||
ccs811_enable_interrupt (sensor, true);
|
||||
#else
|
||||
// set threshold parameters and enable threshold interrupt mode
|
||||
ccs811_set_eco2_thresholds (sensor, 600, 1100, 40);
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// create a periodic task that uses the sensor
|
||||
xTaskCreate(user_task_periodic, "user_task_periodic", 256, NULL, 2, NULL);
|
||||
|
||||
#endif
|
||||
|
||||
// start periodic measurement with one measurement per second
|
||||
ccs811_set_mode (sensor, ccs811_mode_1s);
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue