From 250939c5797de64d2bff641070b66752a926cba4 Mon Sep 17 00:00:00 2001 From: Peter Sjodin Date: Fri, 25 Aug 2017 10:11:31 +0200 Subject: [PATCH] Make duty-cycling runtime configurable with timers for sample period and warmup time --- dev/pms5003/pms5003.c | 102 +++++++++++++++++++++++++++++++----------- dev/pms5003/pms5003.h | 20 +++++---- 2 files changed, 89 insertions(+), 33 deletions(-) diff --git a/dev/pms5003/pms5003.c b/dev/pms5003/pms5003.c index 70ae74f6c..79c01e2f0 100644 --- a/dev/pms5003/pms5003.c +++ b/dev/pms5003/pms5003.c @@ -69,8 +69,6 @@ static uint32_t invalid_frames, valid_frames; /* Sensor configured on? */ static uint8_t configured_on = 0; -/* When sensor entered current power save mode, in clock_seconds()*/ -static unsigned long when_mode; /* Last readings of sensor data */ static uint16_t PM1, PM2_5, PM10; @@ -91,6 +89,11 @@ static uint8_t rxbuf_data[PMS_BUFSIZE]; static int uart_input_byte(unsigned char); #endif /* PMS_SERIAL_UART */ +static struct pms_config { + unsigned sample_period; /* Time between samples (sec) */ + unsigned warmup_interval; /* Warmup time (sec) */ +} pms_config; + /*---------------------------------------------------------------------------*/ #if PMS_SERIAL_UART PROCESS(pms5003_uart_process, "PMS5003/UART dust sensor process"); @@ -105,6 +108,9 @@ PROCESS(pms5003_timer_process, "PMS5003 periodic dust sensor process"); void pms5003_init() { + pms5003_config_sample_period(PMS_SAMPLE_PERIOD); + pms5003_config_warmup_interval(PMS_WARMUP_INTERVAL); + pms5003_event = process_alloc_event(); process_start(&pms5003_timer_process, NULL); @@ -117,8 +123,9 @@ pms5003_init() configured_on = 1; #ifdef DEBUG - printf("PMS5003: UART %d, I2C %d, sample period %d, startup interval %d\n", - PMS_SERIAL_UART, PMS_SERIAL_I2C, PMS_SAMPLE_PERIOD, PMS_STARTUP_INTERVAL); + printf("PMS5003: UART %d, I2C %d, sample period %d, warmup interval %d\n", + PMS_SERIAL_UART, PMS_SERIAL_I2C, + pms_config.sample_period, pms_config.warmup_interval); #endif /* DEBUG */ } /*---------------------------------------------------------------------------*/ @@ -207,6 +214,46 @@ pms5003_invalid_frames() { return invalid_frames; } + +void +pms5003_config_sample_period(unsigned int sample_period) { + pms_config.sample_period = sample_period; +} + +void +pms5003_config_warmup_interval(unsigned int warmup_interval) { + pms_config.warmup_interval = warmup_interval; +} + +unsigned +pms5003_get_sample_period(void) { + return pms_config.sample_period; +} + +unsigned +pms5003_get_warmup_interval(void) { + return pms_config.warmup_interval; +} + +/*---------------------------------------------------------------------------*/ +/** + * Check if it is time to put sensor in standby mode. + * The condition is that the time from when last sample was taken until the + * next is due, is greater than the time it takes to wake up the sensor. + */ +static int +timetosleep(void) { + return (timestamp + pms_config.sample_period > + clock_seconds() + pms_config.warmup_interval); +} +/*---------------------------------------------------------------------------*/ +/** + * Check if it is time to get the next sample. + */ +static int +timetoread(void) { + return (clock_seconds() - timestamp >= pms_config.sample_period); +} /*---------------------------------------------------------------------------*/ /** * Validate frame by checking preamble, length field and checksum. @@ -218,7 +265,7 @@ check_pmsframe(uint8_t *buf) int sum, pmssum; int i; int len; - + if(buf[0] != PRE1 || buf[1] != PRE2) { return 0; } @@ -308,7 +355,6 @@ static PT_THREAD(pms5003_uart_fsm_pt(struct pt *pt, uint8_t data)) { static uint8_t buf[PMSBUFFER], *bufp; static int remain; - static unsigned long mode_secs; PT_BEGIN(pt); bufp = buf; @@ -337,17 +383,16 @@ PT_THREAD(pms5003_uart_fsm_pt(struct pt *pt, uint8_t data)) { *bufp++ = data; } /* We have a frame! */ - mode_secs = clock_seconds() - when_mode; - /* Frames received while sensor is starting up are ignored */ - if((pms5003_get_standby_mode() == STANDBY_MODE_OFF) && - (mode_secs >= PMS_STARTUP_INTERVAL)) { + /* Is it time for next reading? Otherwise ignore. */ + if(timetoread()) { /* Check frame and update sensor readings */ if(pmsframe(buf)) { /* Tell other processes there is new data */ (void)process_post(PROCESS_BROADCAST, pms5003_event, NULL); - /* Enter standby mode */ - pms5003_set_standby_mode(STANDBY_MODE_ON); - when_mode = clock_seconds(); + /* Put sensor in standby mode? */ + if(timetosleep()) { + pms5003_set_standby_mode(STANDBY_MODE_ON); + } } } } @@ -399,13 +444,22 @@ PROCESS_THREAD(pms5003_uart_process, ev, data) PROCESS_THREAD(pms5003_timer_process, ev, data) { static struct etimer pmstimer; - static unsigned long mode_secs; static uint8_t standbymode; PROCESS_BEGIN(); etimer_set(&pmstimer, CLOCK_SECOND * PMS_PROCESS_PERIOD); - pms5003_set_standby_mode(STANDBY_MODE_ON); - when_mode = clock_seconds(); + +/* Pretend there is a fresh reading, to postpone the first + * reading for one cycle + */ + timestamp = clock_seconds(); + + /* Put sensor in standby, if there is enough time */ + if(timetosleep()) + pms5003_set_standby_mode(STANDBY_MODE_ON); + else + pms5003_set_standby_mode(STANDBY_MODE_OFF); + pms5003_event = process_alloc_event(); /* Main loop */ @@ -416,13 +470,12 @@ PROCESS_THREAD(pms5003_timer_process, ev, data) } if((ev == PROCESS_EVENT_TIMER) && (data == &pmstimer)) { - mode_secs = clock_seconds() - when_mode; standbymode = pms5003_get_standby_mode(); if(standbymode == STANDBY_MODE_OFF) { #if PMS_SERIAL_I2C static uint8_t buf[PMSBUFFER]; /* Read data over I2C if it is time */ - if(mode_secs >= PMS_STARTUP_INTERVAL) { + if(timetoread()) { if(pms5003_i2c_probe()) { leds_on(LEDS_RED); i2c_read_mem(I2C_PMS5003_ADDR, 0, buf, PMSBUFFER); @@ -432,19 +485,18 @@ PROCESS_THREAD(pms5003_timer_process, ev, data) if(process_post(PROCESS_BROADCAST, pms5003_event, NULL) == PROCESS_ERR_OK) { PROCESS_WAIT_EVENT_UNTIL(ev == pms5003_event); } - pms5003_set_standby_mode(STANDBY_MODE_ON); - when_mode = clock_seconds(); + /* Put sensor in standby, if there is enough time */ + if(timetosleep()) { + pms5003_set_standby_mode(STANDBY_MODE_ON); + } } } } -#else - /* Do nothing -- UART process puts sensor in standby */ - ; #endif /* PMS_SERIAL_I2C */ } else if(standbymode == STANDBY_MODE_ON) { - if(mode_secs >= (PMS_SAMPLE_PERIOD - PMS_STARTUP_INTERVAL)) { + /* Time to warm up sensor for next reading? */ + if(!timetosleep()) { pms5003_set_standby_mode(STANDBY_MODE_OFF); - when_mode = clock_seconds(); } } etimer_reset(&pmstimer); diff --git a/dev/pms5003/pms5003.h b/dev/pms5003/pms5003.h index ca5939b82..4a3282a94 100644 --- a/dev/pms5003/pms5003.h +++ b/dev/pms5003/pms5003.h @@ -36,7 +36,7 @@ #ifndef PMS5003_H #define PMS5003_H -/* How often sensor process runs (secs) -- defines resolution +/* How often sensor process runs (sec) -- defines resolution * of warmup time and sample period */ #ifdef PMS5003_CONF_PROCESS_PERIOD @@ -45,19 +45,19 @@ #define PMS_PROCESS_PERIOD 5 #endif /* PMS5003_CONF_PROCESS_PERIOD */ -/* How often sensor data is collected (secs) */ +/* Default sample period - how often sensor data is collected (sec) */ #ifdef PMS5003_CONF_SAMPLE_PERIOD #define PMS_SAMPLE_PERIOD PMS5003_CONF_SAMPLE_PERIOD #else -#define PMS_SAMPLE_PERIOD 30 +#define PMS_SAMPLE_PERIOD 60 #endif /* PMS5003_CONF_SAMPLE_PERIOD */ -/* Warmup time before sensor data can be read (secs) */ -#ifdef PMS5003_CONF_STARTUP_INTERVAL -#define PMS_STARTUP_INTERVAL PMS5003_CONF_STARTUP_INTERVAL +/* Default warmup time before sensor data can be read (sec) */ +#ifdef PMS5003_CONF_WARMUP_INTERVAL +#define PMS_WARMUP_INTERVAL PMS5003_CONF_WARMUP_INTERVAL #else -#define PMS_STARTUP_INTERVAL 10 -#endif /* PMS5003_STARTUP_INTERVAL */ +#define PMS_WARMUP_INTERVAL 30 +#endif /* PMS5003_WARMUP_INTERVAL */ /* Use I2C interface? */ #ifdef PMS5003_CONF_SERIAL_I2C @@ -108,5 +108,9 @@ uint16_t pms5003_db2_5(); uint16_t pms5003_db5(); uint16_t pms5003_db10(); uint32_t pms5003_timestamp(); +void pms5003_config_sample_period(unsigned int); +void pms5003_config_warmup_interval(unsigned int); +unsigned pms5003_get_sample_period(void); +unsigned pms5003_get_warmup_interval(void); #endif /* PMS5003_H */