From 508ea88a3f68315fc37a1d3f459be6af71e1ffee Mon Sep 17 00:00:00 2001 From: Andreas Brauchli Date: Tue, 5 Nov 2019 11:26:51 +0100 Subject: [PATCH 1/3] SPS30: Add start_manual_fan_cleaning() * Add start_manual_fan_cleaning() * Update changelog --- CHANGELOG.md | 2 ++ sps30-uart/sps30.c | 7 +++++++ sps30-uart/sps30.h | 11 +++++++++++ 3 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18cf692..5abb7dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [`changed`] Split out `default_config.inc` from Makefile to configure paths and CFLAGS * [`fixed`] Fix strict-aliasing ans sign-conversion compiler warnings + * [`added`] instantly start manual fan cleaning with + `sps30_start_manual_fan_cleaning()` ## [2.0.0] - 2019-05-14 diff --git a/sps30-uart/sps30.c b/sps30-uart/sps30.c index 7874be5..defcfe5 100644 --- a/sps30-uart/sps30.c +++ b/sps30-uart/sps30.c @@ -214,6 +214,13 @@ int16_t sps30_set_fan_auto_cleaning_interval_days(uint8_t interval_days) { 60 * 60); } +int16_t sps30_start_manual_fan_cleaning() { + struct sensirion_shdlc_rx_header header; + + return sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_START_FAN_CLEANING, 0, NULL, 0, + &header, NULL); +} + int16_t sps30_reset() { return sensirion_shdlc_tx(SPS_ADDR, SPS_CMD_RESET, 0, NULL); } diff --git a/sps30-uart/sps30.h b/sps30-uart/sps30.h index 82d1165..6bcd2e3 100644 --- a/sps30-uart/sps30.h +++ b/sps30-uart/sps30.h @@ -163,6 +163,17 @@ int16_t sps30_get_fan_auto_cleaning_interval_days(uint8_t *interval_days); */ int16_t sps30_set_fan_auto_cleaning_interval_days(uint8_t interval_days); +/** + * sps30_start_manual_fan_cleaning() - Immediately trigger the fan cleaning + * + * Note that this command can only be run when the sensor is in measurement + * mode, i.e. after sps30_start_measurement() without subsequent + * sps30_stop_measurement(). + * + * Return: 0 on success, an error code otherwise + */ +int16_t sps30_start_manual_fan_cleaning(); + /** * sps30_reset() - reset the SGP30 * From 78670da89d9f313e47ac8b0e311243f3ecfe996c Mon Sep 17 00:00:00 2001 From: Andreas Brauchli Date: Tue, 5 Nov 2019 11:34:19 +0100 Subject: [PATCH 2/3] SPS30: Refactor constants to reflect full sensor name Rename SPS_* to SPS30_* variables in both source and header. The header changes reflect an interface change (e.g. `SPS30_MAX_SERIAL_LEN`) Remove undocumented method --- CHANGELOG.md | 1 + .../linux/sensirion_uart_implementation.c | 2 +- .../sensirion_uart_implementation.c | 2 +- sps30-uart/sps30.c | 89 ++++++++----------- sps30-uart/sps30.h | 20 ++--- sps30-uart/sps30_example_usage.c | 12 +-- 6 files changed, 51 insertions(+), 75 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5abb7dd..cad94f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [`fixed`] Fix strict-aliasing ans sign-conversion compiler warnings * [`added`] instantly start manual fan cleaning with `sps30_start_manual_fan_cleaning()` + * [`changed`] rename `SPS_*` constants to `SPS30_` ## [2.0.0] - 2019-05-14 diff --git a/embedded-uart-common/sample-implementations/linux/sensirion_uart_implementation.c b/embedded-uart-common/sample-implementations/linux/sensirion_uart_implementation.c index 86e99d6..c066432 100644 --- a/embedded-uart-common/sample-implementations/linux/sensirion_uart_implementation.c +++ b/embedded-uart-common/sample-implementations/linux/sensirion_uart_implementation.c @@ -29,8 +29,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "sensirion_uart.h" #include "sensirion_arch_config.h" +#include "sensirion_uart.h" #include #include #include diff --git a/embedded-uart-common/sensirion_uart_implementation.c b/embedded-uart-common/sensirion_uart_implementation.c index 69bc517..4a20338 100644 --- a/embedded-uart-common/sensirion_uart_implementation.c +++ b/embedded-uart-common/sensirion_uart_implementation.c @@ -29,8 +29,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "sensirion_uart.h" #include "sensirion_arch_config.h" +#include "sensirion_uart.h" /* * INSTRUCTIONS diff --git a/sps30-uart/sps30.c b/sps30-uart/sps30.c index defcfe5..995d9c6 100644 --- a/sps30-uart/sps30.c +++ b/sps30-uart/sps30.c @@ -33,28 +33,29 @@ #include "sensirion_shdlc.h" #include "sps_git_version.h" -#define SPS_ADDR 0x00 -#define SPS_CMD_START_MEASUREMENT 0x00 -#define SPS_CMD_STOP_MEASUREMENT 0x01 -#define SPS_SUBCMD_MEASUREMENT_START \ +#define SPS30_ADDR 0x00 +#define SPS30_CMD_START_MEASUREMENT 0x00 +#define SPS30_CMD_STOP_MEASUREMENT 0x01 +#define SPS30_SUBCMD_MEASUREMENT_START \ { 0x01, 0x03 } -#define SPS_CMD_READ_MEASUREMENT 0x03 -#define SPS_CMD_READ_FAN_SPEED 0x40 -#define SPS_CMD_FAN_CLEAN_INTV 0x80 -#define SPS_SUBCMD_READ_FAN_CLEAN_INTV 0x00 -#define SPS_CMD_DEV_INFO 0xd0 -#define SPS_CMD_DEV_INFO_SUBCMD_GET_SERIAL \ +#define SPS30_CMD_READ_MEASUREMENT 0x03 +#define SPS30_CMD_READ_FAN_SPEED 0x40 +#define SPS30_CMD_FAN_CLEAN_INTV 0x80 +#define SPS30_CMD_FAN_CLEAN_INTV_LEN 5 +#define SPS30_SUBCMD_READ_FAN_CLEAN_INTV 0x00 +#define SPS30_CMD_START_FAN_CLEANING 0x56 +#define SPS30_CMD_DEV_INFO 0xd0 +#define SPS30_CMD_DEV_INFO_SUBCMD_GET_SERIAL \ { 0x03 } -#define SPS_CMD_RESET 0xd3 -#define SPS_ERR_STATE(state) (SPS_ERR_STATE_MASK | (state)) -#define SPS_CMD_FAN_CLEAN_LENGTH 5 +#define SPS30_CMD_RESET 0xd3 +#define SPS30_ERR_STATE(state) (SPS30_ERR_STATE_MASK | (state)) const char *sps_get_driver_version() { return SPS_DRV_VERSION_STR; } int16_t sps30_probe() { - char serial[SPS_MAX_SERIAL_LEN]; + char serial[SPS30_MAX_SERIAL_LEN]; int16_t ret = sps30_get_serial(serial); return ret; @@ -62,34 +63,34 @@ int16_t sps30_probe() { int16_t sps30_get_serial(char *serial) { struct sensirion_shdlc_rx_header header; - uint8_t param_buf[] = SPS_CMD_DEV_INFO_SUBCMD_GET_SERIAL; + uint8_t param_buf[] = SPS30_CMD_DEV_INFO_SUBCMD_GET_SERIAL; int16_t ret; - ret = sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_DEV_INFO, sizeof(param_buf), - param_buf, SPS_MAX_SERIAL_LEN, &header, + ret = sensirion_shdlc_xcv(SPS30_ADDR, SPS30_CMD_DEV_INFO, sizeof(param_buf), + param_buf, SPS30_MAX_SERIAL_LEN, &header, (uint8_t *)serial); if (ret < 0) return ret; if (header.state) - return SPS_ERR_STATE(header.state); + return SPS30_ERR_STATE(header.state); return 0; } int16_t sps30_start_measurement() { struct sensirion_shdlc_rx_header header; - uint8_t param_buf[] = SPS_SUBCMD_MEASUREMENT_START; + uint8_t param_buf[] = SPS30_SUBCMD_MEASUREMENT_START; - return sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_START_MEASUREMENT, + return sensirion_shdlc_xcv(SPS30_ADDR, SPS30_CMD_START_MEASUREMENT, sizeof(param_buf), param_buf, 0, &header, NULL); } int16_t sps30_stop_measurement() { struct sensirion_shdlc_rx_header header; - return sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_STOP_MEASUREMENT, 0, NULL, 0, - &header, NULL); + return sensirion_shdlc_xcv(SPS30_ADDR, SPS30_CMD_STOP_MEASUREMENT, 0, NULL, + 0, &header, NULL); } int16_t sps30_read_measurement(struct sps30_measurement *measurement) { @@ -102,13 +103,13 @@ int16_t sps30_read_measurement(struct sps30_measurement *measurement) { float32_t f32_value; } val, data[10]; - ret = sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_READ_MEASUREMENT, 0, NULL, + ret = sensirion_shdlc_xcv(SPS30_ADDR, SPS30_CMD_READ_MEASUREMENT, 0, NULL, sizeof(data), &header, (uint8_t *)data); if (ret) return ret; if (header.data_len != sizeof(data)) - return SPS_ERR_NOT_ENOUGH_DATA; + return SPS30_ERR_NOT_ENOUGH_DATA; idx = 0; val.u32_value = be32_to_cpu(data[idx].u32_value); @@ -142,42 +143,26 @@ int16_t sps30_read_measurement(struct sps30_measurement *measurement) { measurement->typical_particle_size = val.f32_value; if (header.state) - return SPS_ERR_STATE(header.state); - - return 0; -} - -int16_t sps30_read_fan_speed(uint16_t *fan_rpm) { - struct sensirion_shdlc_rx_header header; - int16_t ret; - - ret = sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_READ_FAN_SPEED, 0, NULL, - sizeof(*fan_rpm), &header, (uint8_t *)fan_rpm); - if (ret < 0) - return ret; - - *fan_rpm = be16_to_cpu(*fan_rpm); - if (header.state) - return SPS_ERR_STATE(header.state); + return SPS30_ERR_STATE(header.state); return 0; } int16_t sps30_get_fan_auto_cleaning_interval(uint32_t *interval_seconds) { struct sensirion_shdlc_rx_header header; - uint8_t tx_data[] = {SPS_SUBCMD_READ_FAN_CLEAN_INTV}; + uint8_t tx_data[] = {SPS30_SUBCMD_READ_FAN_CLEAN_INTV}; int16_t ret; - ret = sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_FAN_CLEAN_INTV, sizeof(tx_data), - tx_data, sizeof(*interval_seconds), &header, - (uint8_t *)interval_seconds); + ret = sensirion_shdlc_xcv( + SPS30_ADDR, SPS30_CMD_FAN_CLEAN_INTV, sizeof(tx_data), tx_data, + sizeof(*interval_seconds), &header, (uint8_t *)interval_seconds); if (ret < 0) return ret; *interval_seconds = be32_to_cpu(*interval_seconds); if (header.state) - return SPS_ERR_STATE(header.state); + return SPS30_ERR_STATE(header.state); return 0; } @@ -185,14 +170,14 @@ int16_t sps30_get_fan_auto_cleaning_interval(uint32_t *interval_seconds) { int16_t sps30_set_fan_auto_cleaning_interval(uint32_t interval_seconds) { struct sensirion_shdlc_rx_header header; uint8_t ix; - uint8_t cleaning_command[SPS_CMD_FAN_CLEAN_LENGTH]; + uint8_t cleaning_command[SPS30_CMD_FAN_CLEAN_INTV_LEN]; uint32_t value = be32_to_cpu(interval_seconds); - cleaning_command[0] = SPS_SUBCMD_READ_FAN_CLEAN_INTV; + cleaning_command[0] = SPS30_SUBCMD_READ_FAN_CLEAN_INTV; for (ix = 0; ix < sizeof(uint32_t); ix++) cleaning_command[ix + 1] = (uint8_t)(value >> (8 * ix)); return sensirion_shdlc_xcv( - SPS_ADDR, SPS_CMD_FAN_CLEAN_INTV, sizeof(cleaning_command), + SPS30_ADDR, SPS30_CMD_FAN_CLEAN_INTV, sizeof(cleaning_command), (const uint8_t *)cleaning_command, sizeof(interval_seconds), &header, (uint8_t *)&interval_seconds); } @@ -217,10 +202,10 @@ int16_t sps30_set_fan_auto_cleaning_interval_days(uint8_t interval_days) { int16_t sps30_start_manual_fan_cleaning() { struct sensirion_shdlc_rx_header header; - return sensirion_shdlc_xcv(SPS_ADDR, SPS_CMD_START_FAN_CLEANING, 0, NULL, 0, - &header, NULL); + return sensirion_shdlc_xcv(SPS30_ADDR, SPS30_CMD_START_FAN_CLEANING, 0, + NULL, 0, &header, NULL); } int16_t sps30_reset() { - return sensirion_shdlc_tx(SPS_ADDR, SPS_CMD_RESET, 0, NULL); + return sensirion_shdlc_tx(SPS30_ADDR, SPS30_CMD_RESET, 0, NULL); } diff --git a/sps30-uart/sps30.h b/sps30-uart/sps30.h index 6bcd2e3..97c8795 100644 --- a/sps30-uart/sps30.h +++ b/sps30-uart/sps30.h @@ -38,11 +38,11 @@ extern "C" { #include "sensirion_arch_config.h" -#define SPS_MAX_SERIAL_LEN 32 -#define SPS_ERR_NOT_ENOUGH_DATA (-1) -#define SPS_ERR_STATE_MASK (0x100) -#define SPS_IS_ERR_STATE(err_code) (((err_code) | 0xff) == 0x1ff) -#define SPS_GET_ERR_STATE(err_code) ((err_code)&0xff) +#define SPS30_MAX_SERIAL_LEN 32 +#define SPS30_ERR_NOT_ENOUGH_DATA (-1) +#define SPS30_ERR_STATE_MASK (0x100) +#define SPS30_IS_ERR_STATE(err_code) (((err_code) | 0xff) == 0x1ff) +#define SPS30_GET_ERR_STATE(err_code) ((err_code)&0xff) struct sps30_measurement { float32_t mc_1p0; @@ -107,16 +107,6 @@ int16_t sps30_stop_measurement(); */ int16_t sps30_read_measurement(struct sps30_measurement *measurement); -/** - * sps30_read_fan_speed() - read the current fan speed - * - * Note that fan_rpm must be discarded when the return code is non-zero. - * - * @fan_rpm: Memory where the fan speed in rpm is stored - * Return: 0 on success, an error code otherwise - */ -int16_t sps30_read_fan_speed(uint16_t *fan_rpm); - /** * sps30_get_fan_auto_cleaning_interval() - read the current auto-cleaning * interval diff --git a/sps30-uart/sps30_example_usage.c b/sps30-uart/sps30_example_usage.c index afad6bd..75b74a2 100644 --- a/sps30-uart/sps30_example_usage.c +++ b/sps30-uart/sps30_example_usage.c @@ -44,7 +44,7 @@ int main(void) { struct sps30_measurement m; - char serial[SPS_MAX_SERIAL_LEN]; + char serial[SPS30_MAX_SERIAL_LEN]; uint8_t auto_clean_days = 4; uint32_t auto_clean; int16_t ret; @@ -58,16 +58,16 @@ int main(void) { * a sensor. */ while (sps30_probe() != 0) { - printf("SPS sensor probing failed\n"); + printf("SPS30 sensor probing failed\n"); sleep(1); } - printf("SPS sensor probing successful\n"); + printf("SPS30 sensor probing successful\n"); ret = sps30_get_serial(serial); if (ret) printf("error %d reading serial\n", ret); else - printf("SPS Serial: %s\n", serial); + printf("SPS30 Serial: %s\n", serial); ret = sps30_get_fan_auto_cleaning_interval(&auto_clean); if (ret) @@ -96,9 +96,9 @@ int main(void) { printf("error reading measurement\n"); } else { - if (SPS_IS_ERR_STATE(ret)) { + if (SPS30_IS_ERR_STATE(ret)) { printf("Chip state: %u - measurements may not be accurate\n", - SPS_GET_ERR_STATE(ret)); + SPS30_GET_ERR_STATE(ret)); } printf("measured values:\n" From 31aef25c7cbe112ccc9f27d7b4178e514fadcd42 Mon Sep 17 00:00:00 2001 From: Andreas Brauchli Date: Tue, 5 Nov 2019 14:49:10 +0100 Subject: [PATCH 3/3] SPS30: Simplify sps30_example_usage.c * Remove dependency on unistd.h and replace sleep() with `sensirion_sleep_usec()` * Remove retrieving the auto cleaning interval from example * Turn the auto clean interval into a constant --- sps30-uart/sps30_example_usage.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/sps30-uart/sps30_example_usage.c b/sps30-uart/sps30_example_usage.c index 75b74a2..202e313 100644 --- a/sps30-uart/sps30_example_usage.c +++ b/sps30-uart/sps30_example_usage.c @@ -29,8 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include // printf -#include // sleep +#include // printf #include "sensirion_uart.h" #include "sps30.h" @@ -40,18 +39,16 @@ * PLATFORM */ //#define printf(...) -//#define sleep(...) int main(void) { struct sps30_measurement m; char serial[SPS30_MAX_SERIAL_LEN]; - uint8_t auto_clean_days = 4; - uint32_t auto_clean; + const uint8_t AUTO_CLEAN_DAYS = 4; int16_t ret; while (sensirion_uart_open() != 0) { printf("UART init failed\n"); - sleep(1); + sensirion_sleep_usec(1000000); /* sleep for 1s */ } /* Busy loop for initialization, because the main loop does not work without @@ -59,7 +56,7 @@ int main(void) { */ while (sps30_probe() != 0) { printf("SPS30 sensor probing failed\n"); - sleep(1); + sensirion_sleep_usec(1000000); /* sleep for 1s */ } printf("SPS30 sensor probing successful\n"); @@ -69,22 +66,10 @@ int main(void) { else printf("SPS30 Serial: %s\n", serial); - ret = sps30_get_fan_auto_cleaning_interval(&auto_clean); - if (ret) - printf("error %d retrieving the auto-clean interval\n", ret); - else - printf("auto-cleaning interval is %d seconds\n", auto_clean); - - ret = sps30_set_fan_auto_cleaning_interval_days(auto_clean_days); + ret = sps30_set_fan_auto_cleaning_interval_days(AUTO_CLEAN_DAYS); if (ret) printf("error %d setting the auto-clean interval\n", ret); - ret = sps30_get_fan_auto_cleaning_interval_days(&auto_clean_days); - if (ret) - printf("error retrieving the auto-clean interval\n"); - else - printf("auto-cleaning interval set to %u days\n", auto_clean_days); - ret = sps30_start_measurement(); if (ret < 0) printf("error starting measurement\n"); @@ -116,7 +101,7 @@ int main(void) { m.nc_2p5, m.nc_4p0, m.nc_10p0, m.typical_particle_size); } - sleep(1); + sensirion_sleep_usec(1000000); /* sleep for 1s */ } while (1); if (sensirion_uart_close() != 0)