1 1.1 brad /* 2 1.2 andvar * $NetBSD: sensirion_voc_algorithm.h,v 1.2 2022/09/25 12:41:46 andvar Exp $ 3 1.1 brad */ 4 1.1 brad 5 1.1 brad /* 6 1.1 brad * Copyright (c) 2021, Sensirion AG 7 1.1 brad * All rights reserved. 8 1.1 brad * 9 1.1 brad * Redistribution and use in source and binary forms, with or without 10 1.1 brad * modification, are permitted provided that the following conditions are met: 11 1.1 brad * 12 1.1 brad * * Redistributions of source code must retain the above copyright notice, this 13 1.1 brad * list of conditions and the following disclaimer. 14 1.1 brad * 15 1.1 brad * * Redistributions in binary form must reproduce the above copyright notice, 16 1.1 brad * this list of conditions and the following disclaimer in the documentation 17 1.1 brad * and/or other materials provided with the distribution. 18 1.1 brad * 19 1.1 brad * * Neither the name of Sensirion AG nor the names of its 20 1.1 brad * contributors may be used to endorse or promote products derived from 21 1.1 brad * this software without specific prior written permission. 22 1.1 brad * 23 1.1 brad * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 1.1 brad * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 brad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.1 brad * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 27 1.1 brad * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 1.1 brad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 1.1 brad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 1.1 brad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 1.1 brad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 1.1 brad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 1.1 brad * POSSIBILITY OF SUCH DAMAGE. 34 1.1 brad */ 35 1.1 brad 36 1.1 brad #ifndef VOCALGORITHM_H_ 37 1.1 brad #define VOCALGORITHM_H_ 38 1.1 brad 39 1.1 brad #include "sensirion_arch_config.h" 40 1.1 brad 41 1.1 brad /* The fixed point arithmetic parts of this code were originally created by 42 1.1 brad * https://github.com/PetteriAimonen/libfixmath 43 1.1 brad */ 44 1.1 brad 45 1.1 brad typedef int32_t fix16_t; 46 1.1 brad 47 1.1 brad #define F16(x) \ 48 1.1 brad ((fix16_t)(((x) >= 0) ? ((x)*65536.0 + 0.5) : ((x)*65536.0 - 0.5))) 49 1.1 brad 50 1.1 brad // Should be set by the building toolchain 51 1.1 brad #ifndef LIBRARY_VERSION_NAME 52 1.1 brad #define LIBRARY_VERSION_NAME "custom build" 53 1.1 brad #endif 54 1.1 brad 55 1.1 brad #define VocAlgorithm_SAMPLING_INTERVAL (1.) 56 1.1 brad #define VocAlgorithm_INITIAL_BLACKOUT (45.) 57 1.1 brad #define VocAlgorithm_VOC_INDEX_GAIN (230.) 58 1.1 brad #define VocAlgorithm_SRAW_STD_INITIAL (50.) 59 1.1 brad #define VocAlgorithm_SRAW_STD_BONUS (220.) 60 1.1 brad #define VocAlgorithm_TAU_MEAN_VARIANCE_HOURS (12.) 61 1.1 brad #define VocAlgorithm_TAU_INITIAL_MEAN (20.) 62 1.1 brad #define VocAlgorithm_INIT_DURATION_MEAN ((3600. * 0.75)) 63 1.1 brad #define VocAlgorithm_INIT_TRANSITION_MEAN (0.01) 64 1.1 brad #define VocAlgorithm_TAU_INITIAL_VARIANCE (2500.) 65 1.1 brad #define VocAlgorithm_INIT_DURATION_VARIANCE ((3600. * 1.45)) 66 1.1 brad #define VocAlgorithm_INIT_TRANSITION_VARIANCE (0.01) 67 1.1 brad #define VocAlgorithm_GATING_THRESHOLD (340.) 68 1.1 brad #define VocAlgorithm_GATING_THRESHOLD_INITIAL (510.) 69 1.1 brad #define VocAlgorithm_GATING_THRESHOLD_TRANSITION (0.09) 70 1.1 brad #define VocAlgorithm_GATING_MAX_DURATION_MINUTES ((60. * 3.)) 71 1.1 brad #define VocAlgorithm_GATING_MAX_RATIO (0.3) 72 1.1 brad #define VocAlgorithm_SIGMOID_L (500.) 73 1.1 brad #define VocAlgorithm_SIGMOID_K (-0.0065) 74 1.1 brad #define VocAlgorithm_SIGMOID_X0 (213.) 75 1.1 brad #define VocAlgorithm_VOC_INDEX_OFFSET_DEFAULT (100.) 76 1.1 brad #define VocAlgorithm_LP_TAU_FAST (20.0) 77 1.1 brad #define VocAlgorithm_LP_TAU_SLOW (500.0) 78 1.1 brad #define VocAlgorithm_LP_ALPHA (-0.2) 79 1.1 brad #define VocAlgorithm_PERSISTENCE_UPTIME_GAMMA ((3. * 3600.)) 80 1.1 brad #define VocAlgorithm_MEAN_VARIANCE_ESTIMATOR__GAMMA_SCALING (64.) 81 1.1 brad #define VocAlgorithm_MEAN_VARIANCE_ESTIMATOR__FIX16_MAX (32767.) 82 1.1 brad 83 1.1 brad /** 84 1.1 brad * Struct to hold all the states of the VOC algorithm. 85 1.1 brad */ 86 1.1 brad typedef struct { 87 1.1 brad fix16_t mVoc_Index_Offset; 88 1.1 brad fix16_t mTau_Mean_Variance_Hours; 89 1.1 brad fix16_t mGating_Max_Duration_Minutes; 90 1.1 brad fix16_t mSraw_Std_Initial; 91 1.1 brad fix16_t mUptime; 92 1.1 brad fix16_t mSraw; 93 1.1 brad fix16_t mVoc_Index; 94 1.1 brad fix16_t m_Mean_Variance_Estimator__Gating_Max_Duration_Minutes; 95 1.1 brad bool m_Mean_Variance_Estimator___Initialized; 96 1.1 brad fix16_t m_Mean_Variance_Estimator___Mean; 97 1.1 brad fix16_t m_Mean_Variance_Estimator___Sraw_Offset; 98 1.1 brad fix16_t m_Mean_Variance_Estimator___Std; 99 1.1 brad fix16_t m_Mean_Variance_Estimator___Gamma; 100 1.1 brad fix16_t m_Mean_Variance_Estimator___Gamma_Initial_Mean; 101 1.1 brad fix16_t m_Mean_Variance_Estimator___Gamma_Initial_Variance; 102 1.1 brad fix16_t m_Mean_Variance_Estimator__Gamma_Mean; 103 1.1 brad fix16_t m_Mean_Variance_Estimator__Gamma_Variance; 104 1.1 brad fix16_t m_Mean_Variance_Estimator___Uptime_Gamma; 105 1.1 brad fix16_t m_Mean_Variance_Estimator___Uptime_Gating; 106 1.1 brad fix16_t m_Mean_Variance_Estimator___Gating_Duration_Minutes; 107 1.1 brad fix16_t m_Mean_Variance_Estimator___Sigmoid__L; 108 1.1 brad fix16_t m_Mean_Variance_Estimator___Sigmoid__K; 109 1.1 brad fix16_t m_Mean_Variance_Estimator___Sigmoid__X0; 110 1.1 brad fix16_t m_Mox_Model__Sraw_Std; 111 1.1 brad fix16_t m_Mox_Model__Sraw_Mean; 112 1.1 brad fix16_t m_Sigmoid_Scaled__Offset; 113 1.1 brad fix16_t m_Adaptive_Lowpass__A1; 114 1.1 brad fix16_t m_Adaptive_Lowpass__A2; 115 1.1 brad bool m_Adaptive_Lowpass___Initialized; 116 1.1 brad fix16_t m_Adaptive_Lowpass___X1; 117 1.1 brad fix16_t m_Adaptive_Lowpass___X2; 118 1.1 brad fix16_t m_Adaptive_Lowpass___X3; 119 1.1 brad } VocAlgorithmParams; 120 1.1 brad 121 1.1 brad /** 122 1.1 brad * Initialize the VOC algorithm parameters. Call this once at the beginning or 123 1.1 brad * whenever the sensor stopped measurements. 124 1.1 brad * @param params Pointer to the VocAlgorithmParams struct 125 1.1 brad */ 126 1.1 brad void VocAlgorithm_init(VocAlgorithmParams* params); 127 1.1 brad 128 1.1 brad /** 129 1.1 brad * Get current algorithm states. Retrieved values can be used in 130 1.1 brad * VocAlgorithm_set_states() to resume operation after a short interruption, 131 1.1 brad * skipping initial learning phase. This feature can only be used after at least 132 1.1 brad * 3 hours of continuous operation. 133 1.1 brad * @param params Pointer to the VocAlgorithmParams struct 134 1.1 brad * @param state0 State0 to be stored 135 1.1 brad * @param state1 State1 to be stored 136 1.1 brad */ 137 1.1 brad void VocAlgorithm_get_states(VocAlgorithmParams* params, int32_t* state0, 138 1.1 brad int32_t* state1); 139 1.1 brad 140 1.1 brad /** 141 1.1 brad * Set previously retrieved algorithm states to resume operation after a short 142 1.1 brad * interruption, skipping initial learning phase. This feature should not be 143 1.2 andvar * used after interruptions of more than 10 minutes. Call this once after 144 1.1 brad * VocAlgorithm_init() and the optional VocAlgorithm_set_tuning_parameters(), if 145 1.1 brad * desired. Otherwise, the algorithm will start with initial learning phase. 146 1.1 brad * @param params Pointer to the VocAlgorithmParams struct 147 1.1 brad * @param state0 State0 to be restored 148 1.1 brad * @param state1 State1 to be restored 149 1.1 brad */ 150 1.1 brad void VocAlgorithm_set_states(VocAlgorithmParams* params, int32_t state0, 151 1.1 brad int32_t state1); 152 1.1 brad 153 1.1 brad /** 154 1.1 brad * Set parameters to customize the VOC algorithm. Call this once after 155 1.1 brad * VocAlgorithm_init(), if desired. Otherwise, the default values will be used. 156 1.1 brad * 157 1.1 brad * @param params Pointer to the VocAlgorithmParams struct 158 1.1 brad * @param voc_index_offset VOC index representing typical (average) 159 1.1 brad * conditions. Range 1..250, default 100 160 1.1 brad * @param learning_time_hours Time constant of long-term estimator. 161 1.1 brad * Past events will be forgotten after about 162 1.1 brad * twice the learning time. 163 1.1 brad * Range 1..72 [hours], default 12 [hours] 164 1.1 brad * @param gating_max_duration_minutes Maximum duration of gating (freeze of 165 1.1 brad * estimator during high VOC index signal). 166 1.1 brad * 0 (no gating) or range 1..720 [minutes], 167 1.1 brad * default 180 [minutes] 168 1.1 brad * @param std_initial Initial estimate for standard deviation. 169 1.1 brad * Lower value boosts events during initial 170 1.1 brad * learning period, but may result in larger 171 1.1 brad * device-to-device variations. 172 1.1 brad * Range 10..500, default 50 173 1.1 brad */ 174 1.1 brad void VocAlgorithm_set_tuning_parameters(VocAlgorithmParams* params, 175 1.1 brad int32_t voc_index_offset, 176 1.1 brad int32_t learning_time_hours, 177 1.1 brad int32_t gating_max_duration_minutes, 178 1.1 brad int32_t std_initial); 179 1.1 brad 180 1.1 brad /** 181 1.1 brad * Calculate the VOC index value from the raw sensor value. 182 1.1 brad * 183 1.1 brad * @param params Pointer to the VocAlgorithmParams struct 184 1.1 brad * @param sraw Raw value from the SGP40 sensor 185 1.1 brad * @param voc_index Calculated VOC index value from the raw sensor value. Zero 186 1.1 brad * during initial blackout period and 1..500 afterwards 187 1.1 brad */ 188 1.1 brad void VocAlgorithm_process(VocAlgorithmParams* params, int32_t sraw, 189 1.1 brad int32_t* voc_index); 190 1.1 brad 191 1.1 brad #endif /* VOCALGORITHM_H_ */ 192