Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
716 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
/* | ||
* Copyright (C) 2021 Inria | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @defgroup drivers_sm_pwm_01c SM_PWM_01C dust sensor | ||
* @ingroup drivers_sensors | ||
* @brief Driver for Amphenol SM_PWM_01C infrared dust sensor | ||
* @{ | ||
* | ||
* | ||
* * About | ||
* ===== | ||
* | ||
* This driver provides an interface for the Amphenol SM-PWM-Sensor. | ||
* The Datasheet can be found [here](https://www.cdiweb.com/datasheets/telaire-amphenol/01c%20dust%20sensor%20datasheet.pdf). | ||
* and the more complete application note [here](https://www.sgbotic.com/products/datasheets/sensors/app-SM-PWM-01C.pdf) | ||
* | ||
* The device can measure small particles (1~ 2μm) and large particle (3 ~10μm), | ||
* so similar to PM2.5 and PM10. The dust sensor cannot count particles only | ||
* measure estimated concentrations. | ||
* | ||
* It is recommended to compute values over a 30s moving average. By default | ||
* a moving average is used since the module MODULE_SM_PWM_01C_MA is | ||
* activated by default. To save memory an exponential average can be used | ||
* by disabling this module. | ||
* | ||
* @file | ||
* @brief SM_PWM_01C Device Driver | ||
* | ||
* @author Francisco Molina <francois-xavier.molina@inria.fr> | ||
*/ | ||
|
||
#ifndef SM_PWM_01C_H | ||
#define SM_PWM_01C_H | ||
|
||
#include <inttypes.h> | ||
|
||
#include "timex.h" | ||
#include "ztimer.h" | ||
#include "periph/gpio.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @defgroup drivers_sm_pwm_01c_conf SM_PWM_01C compile configurations | ||
* @ingroup drivers_sm_pwm_01c | ||
* @ingroup config | ||
* @{ | ||
*/ | ||
|
||
/** | ||
* @def CONFIG_SM_PWM_01C_SAMPLE_TIME | ||
* | ||
* @brief Frequency at witch LPO % is calculated | ||
*/ | ||
#ifndef CONFIG_SM_PWM_01C_SAMPLE_TIME | ||
#define CONFIG_SM_PWM_01C_SAMPLE_TIME (100 * US_PER_MS) | ||
#endif | ||
|
||
/** | ||
* @def CONFIG_SM_PWM_01C_WINDOW_TIME | ||
* | ||
* @brief Length in time of the measuring window, recommended 5-30s | ||
*/ | ||
#ifndef CONFIG_SM_PWM_01C_WINDOW_TIME | ||
#define CONFIG_SM_PWM_01C_WINDOW_TIME (10 * US_PER_SEC) | ||
#endif | ||
|
||
#if defined(MODULE_SM_PWM_01C_MA) || defined(DOXYGEN) | ||
/** | ||
* @def SM_PWM_01C_BUFFER_LEN | ||
* | ||
* @brief Length in time of the measuring window | ||
*/ | ||
#define SM_PWM_01C_BUFFER_LEN (CONFIG_SM_PWM_01C_WINDOW_TIME / \ | ||
CONFIG_SM_PWM_01C_SAMPLE_TIME) | ||
#else | ||
|
||
/** | ||
* @def CONFIG_SM_PWM_01C_EXP_WEIGHT | ||
* | ||
* @brief Weight of the exponential average filter where: | ||
* CONFIG_SM_PWM_01C_EXP_WEIGHT = 1 / (1 - alpha). | ||
* | ||
* @note Should be chosen wisely, it can be done my minimizing MSE | ||
* or other algorithms as Marquardt procedure. | ||
*/ | ||
#ifndef CONFIG_SM_PWM_01C_EXP_WEIGHT | ||
#define CONFIG_SM_PWM_01C_EXP_WEIGHT (5) | ||
#endif | ||
#endif | ||
|
||
/** @} */ | ||
|
||
#if defined(MODULE_SM_PWM_01C_MA) || defined(DOXYGEN) | ||
/** | ||
* @brief Circular buffer holding moving average values | ||
* @internal | ||
* | ||
*/ | ||
typedef struct { | ||
uint16_t buf[SM_PWM_01C_BUFFER_LEN]; /**< circular buffer memory */ | ||
size_t head; /**< current buffer head */ | ||
} circ_buf_t; | ||
#endif | ||
|
||
/** | ||
* @brief Parameters for the SM_PWM_01c sensor | ||
* | ||
* These parameters are needed to configure the device at startup. | ||
*/ | ||
typedef struct { | ||
gpio_t tsp_pin; /**< Low Pulse Signal Output (P1) of small Particle, | ||
active low, PM2.5 equivalent */ | ||
gpio_t tlp_pin; /**< Low Pulse Signal Output (P2) of large Particle, | ||
active low, PM10 equivalent */ | ||
} sm_pwm_01c_params_t; | ||
|
||
/** | ||
* @brief LPO and concentration (ug/m3) values for small and large particles | ||
* | ||
* @note Actual measured particle size are: 1~ 2μm for small particles and 3 ~10μm, | ||
* for large particles, but this values are exposed as standard PM2.5 and | ||
* PM10 measurements. | ||
*/ | ||
typedef struct { | ||
uint16_t mc_pm_2p5; /**< Small particle concentration ug/m3 */ | ||
uint16_t mc_pm_10; /**< Large particle concentration ug/m3 */ | ||
} sm_pwm_01c_data_t; | ||
|
||
/** | ||
* @brief LPO and concentration (ug/m3) values for small and large particles | ||
* @internal | ||
*/ | ||
typedef struct { | ||
uint32_t tsp_lpo; /**< Small particle low Pulse active time us */ | ||
uint32_t tlp_lpo; /**< Large Particle low Pulse active time us */ | ||
uint32_t tlp_start_time; /**< Last time tlp pin went low */ | ||
uint32_t tsp_start_time; /**< Last time tsp pin went low */ | ||
#ifdef MODULE_SM_PWM_01C_MA | ||
circ_buf_t tsp_circ_buf; /**< Small particle moving average values */ | ||
circ_buf_t tlp_circ_buf; /**< Large particle moving average values */ | ||
#else | ||
sm_pwm_01c_data_t data; /**< Current value for the exponentially averaged | ||
particle concentration values */ | ||
#endif | ||
} sm_pwm_01c_values_t; | ||
|
||
/** | ||
* @brief Device descriptor for the SM_PWM_01c sensor | ||
*/ | ||
typedef struct { | ||
sm_pwm_01c_params_t params; /**< Device driver parameters */ | ||
sm_pwm_01c_values_t _values; /**< Internal data to calculate concentration | ||
from tsl/tsp low Pulse Output Occupancy */ | ||
ztimer_t _sampler; /**< internal sampling timer */ | ||
} sm_pwm_01c_t; | ||
|
||
/** | ||
* @brief Initialize the given SM_PWM_01C device | ||
* | ||
* @param[out] dev Initialized device descriptor of SM_PWM_01C device | ||
* @param[in] params The parameters for the SM_PWM_01C device | ||
* | ||
* @retval 0 on success | ||
* @retval -EIO GPIO error | ||
*/ | ||
int sm_pwm_01c_init(sm_pwm_01c_t *dev, const sm_pwm_01c_params_t *params); | ||
|
||
/** | ||
* @brief Start continuous measurement of Large and Small particle | ||
* concentrations | ||
* | ||
* @param[in] dev Device descriptor of SM_PWM_01C device | ||
*/ | ||
void sm_pwm_01c_start(sm_pwm_01c_t *dev); | ||
|
||
/** | ||
* @brief Stops continuous measurement of Large and Small particle | ||
* concentration | ||
* | ||
* @param[in] dev Device descriptor of SM_PWM_01C device | ||
*/ | ||
void sm_pwm_01c_stop(sm_pwm_01c_t *dev); | ||
|
||
/** | ||
* @brief Reads particle concentration values | ||
* | ||
* @param[in] dev Device descriptor of SM_PWM_01C device | ||
* @param[out] data Pre-allocated memory to hold measured concentrations | ||
* | ||
*/ | ||
void sm_pwm_01c_read_data(sm_pwm_01c_t *dev, sm_pwm_01c_data_t *data); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* SM_PWM_01C_H */ | ||
/** @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright (C) 2021 Inria | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup sys_auto_init_saul | ||
* @{ | ||
* @file | ||
* @brief Auto initialization for SM_PWM_01C dust sensor | ||
* | ||
* @author Francisco Molina <francois-xavier.molina@inria.fr> | ||
* @} | ||
*/ | ||
|
||
#include "assert.h" | ||
#include "log.h" | ||
#include "saul_reg.h" | ||
#include "sm_pwm_01c_params.h" | ||
#include "sm_pwm_01c.h" | ||
|
||
/** | ||
* @brief Allocate memory for the device descriptors | ||
*/ | ||
static sm_pwm_01c_t sm_pwm_01c_devs[SM_PWM_01C_NUMOF]; | ||
|
||
#if IS_ACTIVE(MODULE_SAUL) | ||
/** | ||
* @brief Memory for the SAUL registry entries | ||
*/ | ||
static saul_reg_t saul_entries[SM_PWM_01C_NUMOF * 2]; | ||
|
||
/** | ||
* @brief Define the number of saul info | ||
*/ | ||
#define SM_PWM_01C_INFO_NUM ARRAY_SIZE(sm_pwm_01c_saul_info) | ||
|
||
/** | ||
* @name Import SAUL endpoints | ||
* @{ | ||
*/ | ||
extern const saul_driver_t sm_pwm_01c_saul_driver_mc_pm_2p5; | ||
extern const saul_driver_t sm_pwm_01c_saul_driver_mc_pm_10; | ||
/** @} */ | ||
#endif | ||
|
||
void auto_init_sm_pwm_01c(void) | ||
{ | ||
#if IS_ACTIVE(MODULE_SAUL) | ||
assert(SM_PWM_01C_INFO_NUM == SM_PWM_01C_NUMOF); | ||
#endif | ||
|
||
for (unsigned int i = 0; i < SM_PWM_01C_NUMOF; i++) { | ||
LOG_DEBUG("[auto_init_saul] initializing sm_pwm_01c #%u\n", i); | ||
|
||
if (sm_pwm_01c_init(&sm_pwm_01c_devs[i], &sm_pwm_01c_params[i])) { | ||
LOG_ERROR("[auto_init_saul] error initializing sm_pwm_01c #%u\n", | ||
i); | ||
continue; | ||
} | ||
sm_pwm_01c_start(&sm_pwm_01c_devs[i]); | ||
#if IS_ACTIVE(MODULE_SAUL) | ||
saul_entries[(i * 2)].dev = &(sm_pwm_01c_devs[i]); | ||
saul_entries[(i * 2)].name = sm_pwm_01c_saul_info[i].name; | ||
saul_entries[(i * 2)].driver = &sm_pwm_01c_saul_driver_mc_pm_2p5; | ||
saul_entries[(i * 2) + 1].dev = &(sm_pwm_01c_devs[i]); | ||
saul_entries[(i * 2) + 1].name = sm_pwm_01c_saul_info[i].name; | ||
saul_entries[(i * 2) + 1].driver = &sm_pwm_01c_saul_driver_mc_pm_10; | ||
saul_reg_add(&(saul_entries[(i * 2)])); | ||
saul_reg_add(&(saul_entries[(i * 2) + 1])); | ||
#endif | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Copyright (c) 2021 Inria | ||
# | ||
# This file is subject to the terms and conditions of the GNU Lesser | ||
# General Public License v2.1. See the file LICENSE in the top level | ||
# directory for more details. | ||
# | ||
menuconfig MODULE_SM_PWM_01C | ||
bool "SM_PWM_01C Amphenol infrared dust sensor" | ||
depends on HAS_PERIPH_GPIO | ||
depends on HAS_PERIPH_GPIO_IRQ | ||
depends on TEST_KCONFIG | ||
select MODULE_CHECKSUM | ||
select MODULE_PERIPH_GPIO | ||
select MODULE_PERIPH_GPIO_IRQ | ||
select MODULE_ZTIMER | ||
select MODULE_ZTIMER_USEC | ||
select MODULE_ZTIMER_PERIPH_TIMER | ||
|
||
config MODULE_SM_PWM_01C_MA | ||
bool "Use a moving average for sensor values" | ||
depends on MODULE_SM_PWM_01C | ||
default y | ||
|
||
menuconfig KCONFIG_USEMODULE_SM_PWM_01C | ||
bool "Configure SM_PWM_01C driver" | ||
depends on USEMODULE_SM_PWM_01C | ||
help | ||
Configure the SM_PWM_01C driver using Kconfig. | ||
|
||
if KCONFIG_USEMODULE_SM_PWM_01C | ||
|
||
config SM_PWM_01C_WINDOW_TIME | ||
int "Measuring Window length" | ||
default 10000000 | ||
help | ||
Length in time of the measuring window in microseconds, | ||
recommended 5-30s. | ||
|
||
config SM_PWM_01C_SAMPLE_TIME | ||
int "PWM occupancy sampling period" | ||
default 100000 | ||
help | ||
Time, expressed in microseconds, at witch LPO is occupancy is | ||
sampled and converted into particle matter concentration | ||
|
||
if !USEMODULE_SM_PWM_01C_MA | ||
|
||
config SM_PWM_01C_EXP_WEIGHT | ||
int "Weight of the exponential" | ||
default 100000 | ||
help | ||
Weight of the exponential average filter where: | ||
SM_PWM_01C_EXP_WEIGHT = 1 / (1 - alpha). | ||
|
||
Should be chosen wisely, it can be done my minimizing MSE | ||
or other algorithms as Marquardt procedure. | ||
|
||
endif # USEMODULE_SM_PWM_01C_MA | ||
|
||
endif # KCONFIG_USEMODULE_SM_PWM_01C |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
SRC := sm_pwm_01c.c | ||
|
||
ifneq (,$(filter saul,$(USEMODULE))) | ||
SRC += sm_pwm_01c_saul.c | ||
endif | ||
|
||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
USEMODULE += ztimer_usec | ||
DEFAULT_MODULE += sm_pwm_01c_ma | ||
|
||
FEATURES_REQUIRED += periph_gpio | ||
FEATURES_REQUIRED += periph_gpio_irq |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
USEMODULE_INCLUDES_sm_pwm_01c := $(LAST_MAKEFILEDIR)/include | ||
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_sm_pwm_01c) | ||
|
||
PSEUDOMODULES += sm_pwm_01c_ma |
Oops, something went wrong.