Use nrf52_pca20020 and nrf51_ble400 to demonstrate the new functionality of the CCS811 driver. Signed-off-by: Peter A. Bigot <pab@pabigot.com>
191 lines
4.4 KiB
C
191 lines
4.4 KiB
C
/*
|
|
* Copyright (c) 2018 Peter Bigot Consulting, LLC
|
|
* Copyright (c) 2018 Linaro Ltd.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr.h>
|
|
#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)
|
|
{
|
|
while (true) {
|
|
int rc = do_fetch(dev);
|
|
|
|
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 = device_get_binding(DT_INST_0_AMS_CCS811_LABEL);
|
|
struct ccs811_configver_type cfgver;
|
|
int rc;
|
|
|
|
if (!dev) {
|
|
printk("Failed to get device binding");
|
|
return;
|
|
}
|
|
|
|
printk("device is %p, name is %s\n", dev, dev->config->name);
|
|
|
|
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);
|
|
}
|
|
}
|