| /* |
| * 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_msleep(1000); |
| } |
| } |
| |
| void main(void) |
| { |
| struct device *dev = device_get_binding(DT_LABEL(DT_INST(0, ams_ccs811))); |
| 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->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); |
| } |
| } |