1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/include/sm_pwm_01c.h
2021-04-07 12:05:09 +02:00

208 lines
6.2 KiB
C

/*
* 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 */
/** @} */