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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
|
@ -8,33 +9,113 @@
|
|||
#include <device.h>
|
||||
#include <drivers/sensor.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)
|
||||
{
|
||||
struct sensor_value co2, voc, voltage, current;
|
||||
while (true) {
|
||||
int rc = do_fetch(dev);
|
||||
|
||||
while (1) {
|
||||
sensor_sample_fetch(dev);
|
||||
sensor_channel_get(dev, SENSOR_CHAN_CO2, &co2);
|
||||
sensor_channel_get(dev, SENSOR_CHAN_VOC, &voc);
|
||||
sensor_channel_get(dev, SENSOR_CHAN_VOLTAGE, &voltage);
|
||||
sensor_channel_get(dev, SENSOR_CHAN_CURRENT, ¤t);
|
||||
|
||||
printk("Co2: %d.%06dppm; VOC: %d.%06dppb\n", co2.val1, co2.val2,
|
||||
voc.val1, voc.val2);
|
||||
printk("Voltage: %d.%06dV; Current: %d.%06dA\n\n", voltage.val1,
|
||||
voltage.val2, current.val1, current.val2);
|
||||
|
||||
k_sleep(K_MSEC(1000));
|
||||
if (rc == 0) {
|
||||
printk("Timed fetch got %d\n", rc);
|
||||
} else if (-EAGAIN == rc) {
|
||||
printk("Timed fetch got stale data\n");
|
||||
} else {
|
||||
printk("Timed fetch failed: %d\n", rc);
|
||||
break;
|
||||
}
|
||||
k_sleep(1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
printk("Failed to get device binding");
|
||||
return;
|
||||
|
@ -42,5 +123,68 @@ void main(void)
|
|||
|
||||
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