/* * Copyright (c) 2018 Analog Devices Inc. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #define DELAY_WITH_TRIGGER K_SECONDS(5) #define DELAY_WITHOUT_TRIGGER K_SECONDS(1) #define UCEL_PER_CEL 1000000 #define UCEL_PER_MCEL 1000 #define TEMP_INITIAL_CEL 21 #define TEMP_WINDOW_HALF_UCEL 500000 K_SEM_DEFINE(sem, 0, 1); static const char *now_str(void) { static char buf[16]; /* ...HH:MM:SS.MMM */ uint32_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 void trigger_handler(const struct device *dev, const struct sensor_trigger *trigger) { k_sem_give(&sem); } static int low_ucel; static int high_ucel; static int sensor_set_attribute(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, int value) { struct sensor_value sensor_val; int ret; sensor_val.val1 = value / UCEL_PER_CEL; sensor_val.val2 = value % UCEL_PER_CEL; ret = sensor_attr_set(dev, chan, attr, &sensor_val); if (ret) { printf("sensor_attr_set failed ret %d\n", ret); } return ret; } static bool temp_in_window(const struct sensor_value *val) { int temp_ucel = val->val1 * UCEL_PER_CEL + val->val2; return (temp_ucel >= low_ucel) && (temp_ucel <= high_ucel); } static int sensor_set_window(const struct device *dev, const struct sensor_value *val) { int temp_ucel = val->val1 * UCEL_PER_CEL + val->val2; low_ucel = temp_ucel - TEMP_WINDOW_HALF_UCEL; high_ucel = temp_ucel + TEMP_WINDOW_HALF_UCEL; int rc = sensor_set_attribute(dev, SENSOR_CHAN_AMBIENT_TEMP, SENSOR_ATTR_UPPER_THRESH, high_ucel); if (rc == 0) { sensor_set_attribute(dev, SENSOR_CHAN_AMBIENT_TEMP, SENSOR_ATTR_LOWER_THRESH, low_ucel); } if (rc == 0) { printk("Alert on temp outside [%d, %d] mCel\n", low_ucel / UCEL_PER_MCEL, high_ucel / UCEL_PER_MCEL); } return rc; } static void process(const struct device *dev) { struct sensor_value temp_val; int ret; bool reset_window = false; /* Set update rate to 240 mHz */ sensor_set_attribute(dev, SENSOR_CHAN_AMBIENT_TEMP, SENSOR_ATTR_SAMPLING_FREQUENCY, 240 * 1000); if (IS_ENABLED(CONFIG_ADT7420_TRIGGER)) { struct sensor_trigger trig = { .type = SENSOR_TRIG_THRESHOLD, .chan = SENSOR_CHAN_AMBIENT_TEMP, }; struct sensor_value val = { .val1 = TEMP_INITIAL_CEL, }; ret = sensor_set_window(dev, &val); if (ret == 0) { ret = sensor_trigger_set(dev, &trig, trigger_handler); } if (ret != 0) { printf("Could not set trigger\n"); return; } } while (1) { ret = sensor_sample_fetch(dev); if (ret) { printf("sensor_sample_fetch failed ret %d\n", ret); return; } ret = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp_val); if (ret) { printf("sensor_channel_get failed ret %d\n", ret); return; } if (IS_ENABLED(CONFIG_ADT7420_TRIGGER)) { reset_window |= !temp_in_window(&temp_val); } printf("[%s]: temperature %.6f Cel%s\n", now_str(), sensor_value_to_double(&temp_val), reset_window ? ": NEED RESET" : ""); if (IS_ENABLED(CONFIG_ADT7420_TRIGGER)) { if (reset_window) { ret = sensor_set_window(dev, &temp_val); } if (ret) { printf("Window update failed ret %d\n", ret); return; } printk("Wait for trigger..."); ret = k_sem_take(&sem, DELAY_WITH_TRIGGER); reset_window = (ret == 0); printk("%s\n", reset_window ? "ALERTED!" : "timed-out"); } else { k_sleep(DELAY_WITHOUT_TRIGGER); } } } int main(void) { const struct device *const dev = DEVICE_DT_GET_ONE(adi_adt7420); if (!device_is_ready(dev)) { printk("sensor: device not ready.\n"); return 0; } printf("device is %p, name is %s\n", dev, dev->name); process(dev); return 0; }