samples: sensor: ccs811: update for new capabilities
Use nrf52_pca20020 and nrf51_ble400 to demonstrate the new functionality of the CCS811 driver. Signed-off-by: Peter A. Bigot <pab@pabigot.com>
This commit is contained in:
parent
ff7269013e
commit
45f9efe02f
5 changed files with 334 additions and 18 deletions
52
samples/sensor/ccs811/Kconfig
Normal file
52
samples/sensor/ccs811/Kconfig
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Peter Bigot Consulting, LLC
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
mainmenu "CCS811 sample application"
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "CCS811 Trigger On"
|
||||||
|
default APP_TRIGGER_ON_DATAREADY
|
||||||
|
depends on CCS811_TRIGGER
|
||||||
|
help
|
||||||
|
Select the type of trigger to use
|
||||||
|
|
||||||
|
config APP_TRIGGER_ON_DATAREADY
|
||||||
|
bool "Trigger on data ready"
|
||||||
|
|
||||||
|
config APP_TRIGGER_ON_THRESHOLD
|
||||||
|
bool "Trigger on eCO2 threshold crossing"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config APP_CO2_MEDIUM_PPM
|
||||||
|
int "Threshold of eCO2 between low and medium"
|
||||||
|
default 1500
|
||||||
|
depends on APP_TRIGGER_ON_THRESHOLD
|
||||||
|
|
||||||
|
config APP_CO2_HIGH_PPM
|
||||||
|
int "Threshold of eCO2 between medium and high"
|
||||||
|
default 2500
|
||||||
|
depends on APP_TRIGGER_ON_THRESHOLD
|
||||||
|
|
||||||
|
config APP_MONITOR_BASELINE
|
||||||
|
bool "Display BASELINE register value for each sample"
|
||||||
|
default y
|
||||||
|
|
||||||
|
config APP_USE_ENVDATA
|
||||||
|
bool "Program CCS811 with fixed environmental parameters"
|
||||||
|
default n
|
||||||
|
|
||||||
|
config APP_ENV_TEMPERATURE
|
||||||
|
int "Environment temperature for CCS811, Cel"
|
||||||
|
default 25
|
||||||
|
depends on APP_USE_ENVDATA
|
||||||
|
|
||||||
|
config APP_ENV_HUMIDITY
|
||||||
|
int "Environment humidity for CCS811, %RH"
|
||||||
|
default 50
|
||||||
|
depends on APP_USE_ENVDATA
|
||||||
|
|
||||||
|
source "Kconfig.zephyr"
|
87
samples/sensor/ccs811/README.rst
Normal file
87
samples/sensor/ccs811/README.rst
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
.. _ccs811:
|
||||||
|
|
||||||
|
CCS811 Indoor Air Quality Sensor
|
||||||
|
################################
|
||||||
|
|
||||||
|
Overview
|
||||||
|
********
|
||||||
|
|
||||||
|
The CCS811 digital gas sensor detects volatile organic compounds (VOCs)
|
||||||
|
for indoor air quality measurements. VOCs are often categorized as
|
||||||
|
pollutants and/or sensory irritants and can come from a variety of
|
||||||
|
sources such as construction materials (paint and carpet), machines
|
||||||
|
(copiers and processors), and even people (breathing and smoking). It
|
||||||
|
estimates carbon dioxide (CO2) levels where the main source of VOCs is
|
||||||
|
human presence.
|
||||||
|
|
||||||
|
Building and Running
|
||||||
|
********************
|
||||||
|
|
||||||
|
Building and Running on nrf52_pca20020
|
||||||
|
======================================
|
||||||
|
|
||||||
|
.. zephyr-app-commands::
|
||||||
|
:zephyr-app: samples/sensor/ccs811
|
||||||
|
:board: nrf52_pca20020
|
||||||
|
:goals: build flash
|
||||||
|
:compact:
|
||||||
|
|
||||||
|
|
||||||
|
Sample Output
|
||||||
|
=============
|
||||||
|
|
||||||
|
The sample output below is from a `Nordic Thingy:52
|
||||||
|
<https://www.nordicsemi.com/Software-and-tools/Prototyping-platforms/Nordic-Thingy-52>`_
|
||||||
|
(nrf52_pca20020) that includes this sensor (and others).
|
||||||
|
After a soft reset, there is a 5-second startup period
|
||||||
|
where readings are unstable, and then we can see steady
|
||||||
|
reported measurements of about 400 ppm eC02 and 0 ppb eTVOC.
|
||||||
|
|
||||||
|
.. code-block::console
|
||||||
|
|
||||||
|
*** Booting Zephyr OS build zephyr-v2.1.0-310-g32a3e9907bab ***
|
||||||
|
device is 0x20001088, name is CCS811
|
||||||
|
HW 12; FW Boot 1000 App 1100 ; mode 10
|
||||||
|
|
||||||
|
[0:00:00.046]: CCS811: 65021 ppm eCO2; 65021 ppb eTVOC
|
||||||
|
Voltage: 0.000000V; Current: 0.000000A
|
||||||
|
BASELINE fff4
|
||||||
|
Timed fetch got 0
|
||||||
|
|
||||||
|
[0:00:01.059]: CCS811: 65021 ppm eCO2; 65021 ppb eTVOC
|
||||||
|
Voltage: 0.000000V; Current: 0.000000A
|
||||||
|
BASELINE fff4
|
||||||
|
Timed fetch got 0
|
||||||
|
Timed fetch got stale data
|
||||||
|
Timed fetch got stale data
|
||||||
|
Timed fetch got stale data
|
||||||
|
|
||||||
|
[0:00:05.084]: CCS811: 400 ppm eCO2; 0 ppb eTVOC
|
||||||
|
Voltage: 0.677040V; Current: 0.000014A
|
||||||
|
BASELINE 8384
|
||||||
|
Timed fetch got 0
|
||||||
|
|
||||||
|
[0:00:06.096]: CCS811: 405 ppm eCO2; 0 ppb eTVOC
|
||||||
|
Voltage: 0.675428V; Current: 0.000014A
|
||||||
|
BASELINE 8384
|
||||||
|
Timed fetch got 0
|
||||||
|
|
||||||
|
[0:00:07.108]: CCS811: 400 ppm eCO2; 0 ppb eTVOC
|
||||||
|
Voltage: 0.677040V; Current: 0.000014A
|
||||||
|
BASELINE 8384
|
||||||
|
Timed fetch got 0
|
||||||
|
|
||||||
|
[0:00:08.121]: CCS811: 400 ppm eCO2; 0 ppb eTVOC
|
||||||
|
Voltage: 0.677040V; Current: 0.000014A
|
||||||
|
BASELINE 8384
|
||||||
|
Timed fetch got 0
|
||||||
|
|
||||||
|
[0:00:09.133]: CCS811: 400 ppm eCO2; 0 ppb eTVOC
|
||||||
|
Voltage: 0.677040V; Current: 0.000014A
|
||||||
|
BASELINE 8384
|
||||||
|
Timed fetch got 0
|
||||||
|
|
||||||
|
[0:00:10.145]: CCS811: 400 ppm eCO2; 0 ppb eTVOC
|
||||||
|
Voltage: 0.677040V; Current: 0.000014A
|
||||||
|
BASELINE 8384
|
||||||
|
Timed fetch got 0
|
12
samples/sensor/ccs811/boards/nrf51_ble400.conf
Normal file
12
samples/sensor/ccs811/boards/nrf51_ble400.conf
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Peter Bigot Consulting, LLC
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
CONFIG_STDOUT_CONSOLE=y
|
||||||
|
CONFIG_SENSOR=y
|
||||||
|
CONFIG_CCS811=y
|
||||||
|
#CONFIG_CCS811_DRIVE_MODE_2=y
|
||||||
|
#CONFIG_CCS811_TRIGGER_GLOBAL_THREAD=y
|
||||||
|
#CONFIG_CCS811_TRIGGER_OWN_THREAD=y
|
21
samples/sensor/ccs811/boards/nrf51_ble400.overlay
Normal file
21
samples/sensor/ccs811/boards/nrf51_ble400.overlay
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Peter Bigot Consulting, LLC
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
&i2c0 {
|
||||||
|
status = "okay";
|
||||||
|
sda-pin = <0>;
|
||||||
|
scl-pin = <1>;
|
||||||
|
|
||||||
|
/* Sparkfun Environment Combo uses second I2C address */
|
||||||
|
ccs811: ccs811@5b {
|
||||||
|
compatible = "ams,ccs811";
|
||||||
|
reg = <0x5b>;
|
||||||
|
label = "CCS811";
|
||||||
|
irq-gpios = <&gpio0 2 GPIO_INT_ACTIVE_LOW>;
|
||||||
|
wake-gpios = <&gpio0 5 GPIO_INT_ACTIVE_LOW>;
|
||||||
|
reset-gpios = <&gpio0 6 GPIO_INT_ACTIVE_LOW>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2018 Peter Bigot Consulting, LLC
|
||||||
* Copyright (c) 2018 Linaro Ltd.
|
* Copyright (c) 2018 Linaro Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
@ -8,33 +9,113 @@
|
||||||
#include <device.h>
|
#include <device.h>
|
||||||
#include <drivers/sensor.h>
|
#include <drivers/sensor.h>
|
||||||
#include <sys/printk.h>
|
#include <sys/printk.h>
|
||||||
|
#include <drivers/sensor/ccs811.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static bool app_fw_2;
|
||||||
|
|
||||||
|
static const char *now_str(void)
|
||||||
|
{
|
||||||
|
static char buf[16]; /* ...HH:MM:SS.MMM */
|
||||||
|
u32_t now = k_uptime_get_32();
|
||||||
|
unsigned int ms = now % MSEC_PER_SEC;
|
||||||
|
unsigned int s;
|
||||||
|
unsigned int min;
|
||||||
|
unsigned int h;
|
||||||
|
|
||||||
|
now /= MSEC_PER_SEC;
|
||||||
|
s = now % 60U;
|
||||||
|
now /= 60U;
|
||||||
|
min = now % 60U;
|
||||||
|
now /= 60U;
|
||||||
|
h = now;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u",
|
||||||
|
h, min, s, ms);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_fetch(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sensor_value co2, tvoc, voltage, current;
|
||||||
|
int rc = 0;
|
||||||
|
int baseline = -1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_MONITOR_BASELINE
|
||||||
|
rc = ccs811_baseline_fetch(dev);
|
||||||
|
if (rc >= 0) {
|
||||||
|
baseline = rc;
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = sensor_sample_fetch(dev);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
const struct ccs811_result_type *rp = ccs811_result(dev);
|
||||||
|
|
||||||
|
sensor_channel_get(dev, SENSOR_CHAN_CO2, &co2);
|
||||||
|
sensor_channel_get(dev, SENSOR_CHAN_VOC, &tvoc);
|
||||||
|
sensor_channel_get(dev, SENSOR_CHAN_VOLTAGE, &voltage);
|
||||||
|
sensor_channel_get(dev, SENSOR_CHAN_CURRENT, ¤t);
|
||||||
|
printk("\n[%s]: CCS811: %u ppm eCO2; %u ppb eTVOC\n",
|
||||||
|
now_str(), co2.val1, tvoc.val1);
|
||||||
|
printk("Voltage: %d.%06dV; Current: %d.%06dA\n", voltage.val1,
|
||||||
|
voltage.val2, current.val1, current.val2);
|
||||||
|
#ifdef CONFIG_APP_MONITOR_BASELINE
|
||||||
|
printk("BASELINE %04x\n", baseline);
|
||||||
|
#endif
|
||||||
|
if (app_fw_2 && !(rp->status & CCS811_STATUS_DATA_READY)) {
|
||||||
|
printk("STALE DATA\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rp->status & CCS811_STATUS_ERROR) {
|
||||||
|
printk("ERROR: %02x\n", rp->error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_CCS811_TRIGGER_NONE
|
||||||
|
|
||||||
|
static void trigger_handler(struct device *dev, struct sensor_trigger *trig)
|
||||||
|
{
|
||||||
|
int rc = do_fetch(dev);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
printk("Triggered fetch got %d\n", rc);
|
||||||
|
} else if (-EAGAIN == rc) {
|
||||||
|
printk("Triggered fetch got stale data\n");
|
||||||
|
} else {
|
||||||
|
printk("Triggered fetch failed: %d\n", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !CONFIG_CCS811_TRIGGER_NONE */
|
||||||
|
|
||||||
static void do_main(struct device *dev)
|
static void do_main(struct device *dev)
|
||||||
{
|
{
|
||||||
struct sensor_value co2, voc, voltage, current;
|
while (true) {
|
||||||
|
int rc = do_fetch(dev);
|
||||||
|
|
||||||
while (1) {
|
if (rc == 0) {
|
||||||
sensor_sample_fetch(dev);
|
printk("Timed fetch got %d\n", rc);
|
||||||
sensor_channel_get(dev, SENSOR_CHAN_CO2, &co2);
|
} else if (-EAGAIN == rc) {
|
||||||
sensor_channel_get(dev, SENSOR_CHAN_VOC, &voc);
|
printk("Timed fetch got stale data\n");
|
||||||
sensor_channel_get(dev, SENSOR_CHAN_VOLTAGE, &voltage);
|
} else {
|
||||||
sensor_channel_get(dev, SENSOR_CHAN_CURRENT, ¤t);
|
printk("Timed fetch failed: %d\n", rc);
|
||||||
|
break;
|
||||||
printk("Co2: %d.%06dppm; VOC: %d.%06dppb\n", co2.val1, co2.val2,
|
}
|
||||||
voc.val1, voc.val2);
|
k_sleep(1000);
|
||||||
printk("Voltage: %d.%06dV; Current: %d.%06dA\n\n", voltage.val1,
|
|
||||||
voltage.val2, current.val1, current.val2);
|
|
||||||
|
|
||||||
k_sleep(K_MSEC(1000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev = device_get_binding(DT_INST_0_AMS_CCS811_LABEL);
|
||||||
|
struct ccs811_configver_type cfgver;
|
||||||
|
int rc;
|
||||||
|
|
||||||
dev = device_get_binding(DT_INST_0_AMS_CCS811_LABEL);
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
printk("Failed to get device binding");
|
printk("Failed to get device binding");
|
||||||
return;
|
return;
|
||||||
|
@ -42,5 +123,68 @@ void main(void)
|
||||||
|
|
||||||
printk("device is %p, name is %s\n", dev, dev->config->name);
|
printk("device is %p, name is %s\n", dev, dev->config->name);
|
||||||
|
|
||||||
do_main(dev);
|
rc = ccs811_configver_fetch(dev, &cfgver);
|
||||||
|
if (rc == 0) {
|
||||||
|
printk("HW %02x; FW Boot %04x App %04x ; mode %02x\n",
|
||||||
|
cfgver.hw_version, cfgver.fw_boot_version,
|
||||||
|
cfgver.fw_app_version, cfgver.mode);
|
||||||
|
app_fw_2 = (cfgver.fw_app_version >> 8) > 0x11;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_USE_ENVDATA
|
||||||
|
struct sensor_value temp = { CONFIG_APP_ENV_TEMPERATURE };
|
||||||
|
struct sensor_value humidity = { CONFIG_APP_ENV_HUMIDITY };
|
||||||
|
|
||||||
|
rc = ccs811_envdata_update(dev, &temp, &humidity);
|
||||||
|
printk("ENV_DATA set for %d Cel, %d %%RH got %d\n",
|
||||||
|
temp.val1, humidity.val1, rc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CCS811_TRIGGER
|
||||||
|
struct sensor_trigger trig = { 0 };
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_TRIGGER_ON_THRESHOLD
|
||||||
|
printk("Triggering on threshold:\n");
|
||||||
|
if (rc == 0) {
|
||||||
|
struct sensor_value thr = {
|
||||||
|
.val1 = CONFIG_APP_CO2_MEDIUM_PPM,
|
||||||
|
};
|
||||||
|
rc = sensor_attr_set(dev, SENSOR_CHAN_CO2,
|
||||||
|
SENSOR_ATTR_LOWER_THRESH,
|
||||||
|
&thr);
|
||||||
|
printk("L/M threshold to %d got %d\n", thr.val1, rc);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
struct sensor_value thr = {
|
||||||
|
.val1 = CONFIG_APP_CO2_HIGH_PPM,
|
||||||
|
};
|
||||||
|
rc = sensor_attr_set(dev, SENSOR_CHAN_CO2,
|
||||||
|
SENSOR_ATTR_UPPER_THRESH,
|
||||||
|
&thr);
|
||||||
|
printk("M/H threshold to %d got %d\n", thr.val1, rc);
|
||||||
|
}
|
||||||
|
trig.type = SENSOR_TRIG_THRESHOLD;
|
||||||
|
trig.chan = SENSOR_CHAN_CO2;
|
||||||
|
#elif defined(CONFIG_APP_TRIGGER_ON_DATAREADY)
|
||||||
|
printk("Triggering on data ready\n");
|
||||||
|
trig.type = SENSOR_TRIG_DATA_READY;
|
||||||
|
trig.chan = SENSOR_CHAN_ALL;
|
||||||
|
#else
|
||||||
|
#error Unhandled trigger on
|
||||||
|
#endif
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = sensor_trigger_set(dev, &trig, trigger_handler);
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
#ifdef CONFIG_APP_TRIGGER_ON_DATAREADY
|
||||||
|
while (true) {
|
||||||
|
k_sleep(K_FOREVER);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
printk("Trigger installation got: %d\n", rc);
|
||||||
|
#endif /* CONFIG_CCS811_TRIGGER */
|
||||||
|
if (rc == 0) {
|
||||||
|
do_main(dev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue