1+ #include < EEPROM.h>
2+ #include " bsec.h"
3+ /* Configure the BSEC library with information about the sensor
4+ 18v/33v = Voltage at Vdd. 1.8V or 3.3V
5+ 3s/300s = BSEC operating mode, BSEC_SAMPLE_RATE_LP or BSEC_SAMPLE_RATE_ULP
6+ 4d/28d = Operating age of the sensor in days
7+ generic_18v_3s_4d
8+ generic_18v_3s_28d
9+ generic_18v_300s_4d
10+ generic_18v_300s_28d
11+ generic_33v_3s_4d
12+ generic_33v_3s_28d
13+ generic_33v_300s_4d
14+ generic_33v_300s_28d
15+ */
16+ const uint8_t bsec_config_iaq[] = {
17+ #include " config/generic_33v_3s_4d/bsec_iaq.txt"
18+ };
19+
20+ #define STATE_SAVE_PERIOD UINT32_C (300000 ) // 360 minutes - 4 times a day
21+ #define N_SENSORS 2
22+
23+ // Helper functions declarations
24+ void checkIaqSensorStatus (void );
25+ void errLeds (void );
26+ void loadState (void );
27+ void updateState (void );
28+
29+ // Create objects of the class Bsec
30+ Bsec iaqSensor1, iaqSensor2;
31+ uint8_t bsecState1[BSEC_MAX_STATE_BLOB_SIZE], bsecState2[BSEC_MAX_STATE_BLOB_SIZE];
32+ uint16_t stateUpdateCounter = 0 ;
33+
34+ String output;
35+
36+ // Entry point for the example
37+ void setup (void )
38+ {
39+ EEPROM.begin ((N_SENSORS * BSEC_MAX_STATE_BLOB_SIZE) + 1 ); // 1st address for the length of one state
40+ Serial.begin (115200 );
41+ Wire.begin ();
42+
43+ iaqSensor1.begin (BME680_I2C_ADDR_PRIMARY, Wire);
44+ iaqSensor2.begin (BME680_I2C_ADDR_SECONDARY, Wire);
45+ output = " \n BSEC library version " + String (iaqSensor1.version .major ) + " ." + String (iaqSensor1.version .minor ) + " ." + String (iaqSensor1.version .major_bugfix ) + " ." + String (iaqSensor1.version .minor_bugfix );
46+ Serial.println (output);
47+ checkIaqSensorStatus ();
48+
49+ iaqSensor1.setConfig (bsec_config_iaq);
50+ iaqSensor2.setConfig (bsec_config_iaq);
51+ checkIaqSensorStatus ();
52+
53+ loadState ();
54+
55+ bsec_virtual_sensor_t sensorList[7 ] = {
56+ BSEC_OUTPUT_RAW_TEMPERATURE,
57+ BSEC_OUTPUT_RAW_PRESSURE,
58+ BSEC_OUTPUT_RAW_HUMIDITY,
59+ BSEC_OUTPUT_RAW_GAS,
60+ BSEC_OUTPUT_IAQ,
61+ BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
62+ BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
63+ };
64+
65+ iaqSensor1.updateSubscription (sensorList, 7 , BSEC_SAMPLE_RATE_LP);
66+ iaqSensor2.updateSubscription (sensorList, 7 , BSEC_SAMPLE_RATE_LP);
67+ checkIaqSensorStatus ();
68+
69+ // Print the header
70+ output = " Sensor, Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%]" ;
71+ Serial.println (output);
72+ }
73+
74+ // Function that is looped forever
75+ void loop (void )
76+ {
77+ unsigned long time_trigger = millis ();
78+ if (iaqSensor1.run ()) { // If new data is available
79+ output = " 1, " + String (time_trigger);
80+ output += " , " + String (iaqSensor1.rawTemperature );
81+ output += " , " + String (iaqSensor1.pressure );
82+ output += " , " + String (iaqSensor1.rawHumidity );
83+ output += " , " + String (iaqSensor1.gasResistance );
84+ output += " , " + String (iaqSensor1.iaq );
85+ output += " , " + String (iaqSensor1.iaqAccuracy );
86+ output += " , " + String (iaqSensor1.temperature );
87+ output += " , " + String (iaqSensor1.humidity );
88+ Serial.println (output);
89+ updateState ();
90+ } else {
91+ checkIaqSensorStatus ();
92+ }
93+
94+ time_trigger = millis ();
95+ if (iaqSensor2.run ()) { // If new data is available
96+ output = " 2, " + String (time_trigger);
97+ output += " , " + String (iaqSensor2.rawTemperature );
98+ output += " , " + String (iaqSensor2.pressure );
99+ output += " , " + String (iaqSensor2.rawHumidity );
100+ output += " , " + String (iaqSensor2.gasResistance );
101+ output += " , " + String (iaqSensor2.iaq );
102+ output += " , " + String (iaqSensor2.iaqAccuracy );
103+ output += " , " + String (iaqSensor2.temperature );
104+ output += " , " + String (iaqSensor2.humidity );
105+ Serial.println (output);
106+ updateState ();
107+ } else {
108+ checkIaqSensorStatus ();
109+ }
110+ }
111+
112+ // Helper function definitions
113+ void checkIaqSensorStatus (void )
114+ {
115+ if (iaqSensor1.status != BSEC_OK) {
116+ if (iaqSensor1.status < BSEC_OK) {
117+ output = " BSEC1 error code : " + String (iaqSensor1.status );
118+ Serial.println (output);
119+ for (;;)
120+ errLeds (); /* Halt in case of failure */
121+ } else {
122+ output = " BSEC warning code : " + String (iaqSensor1.status );
123+ Serial.println (output);
124+ }
125+ }
126+
127+ if (iaqSensor1.bme680Status != BME680_OK) {
128+ if (iaqSensor1.bme680Status < BME680_OK) {
129+ output = " BME6801 error code : " + String (iaqSensor1.bme680Status );
130+ Serial.println (output);
131+ for (;;)
132+ errLeds (); /* Halt in case of failure */
133+ } else {
134+ output = " BME680 warning code : " + String (iaqSensor1.bme680Status );
135+ Serial.println (output);
136+ }
137+ }
138+ iaqSensor1.status = BSEC_OK;
139+
140+ if (iaqSensor2.status != BSEC_OK) {
141+ if (iaqSensor2.status < BSEC_OK) {
142+ output = " BSEC error code : " + String (iaqSensor2.status );
143+ Serial.println (output);
144+ for (;;)
145+ errLeds (); /* Halt in case of failure */
146+ } else {
147+ output = " BSEC warning code : " + String (iaqSensor2.status );
148+ Serial.println (output);
149+ }
150+ }
151+
152+ if (iaqSensor2.bme680Status != BME680_OK) {
153+ if (iaqSensor2.bme680Status < BME680_OK) {
154+ output = " BME680 error code : " + String (iaqSensor2.bme680Status );
155+ Serial.println (output);
156+ for (;;)
157+ errLeds (); /* Halt in case of failure */
158+ } else {
159+ output = " BME680 warning code : " + String (iaqSensor2.bme680Status );
160+ Serial.println (output);
161+ }
162+ }
163+ iaqSensor2.status = BSEC_OK;
164+ }
165+
166+ void errLeds (void )
167+ {
168+ pinMode (LED_BUILTIN, OUTPUT);
169+ digitalWrite (LED_BUILTIN, HIGH);
170+ delay (100 );
171+ digitalWrite (LED_BUILTIN, LOW);
172+ delay (100 );
173+ }
174+
175+ void loadState (void )
176+ {
177+ if (EEPROM.read (0 ) == BSEC_MAX_STATE_BLOB_SIZE) {
178+ // Existing state in EEPROM
179+ Serial.println (" Reading state from EEPROM" );
180+
181+ for (uint8_t i = 0 ; i < BSEC_MAX_STATE_BLOB_SIZE; i++) {
182+ bsecState1[i] = EEPROM.read (i + 1 );
183+ bsecState2[i] = EEPROM.read (i + 1 + BSEC_MAX_STATE_BLOB_SIZE);
184+ Serial.println (String (bsecState1[i], HEX) + " , " + String (bsecState2[i], HEX));
185+ }
186+
187+ iaqSensor1.setState (bsecState1);
188+ iaqSensor2.setState (bsecState2);
189+ checkIaqSensorStatus ();
190+ } else {
191+ // Erase the EEPROM with zeroes
192+ Serial.println (" Erasing EEPROM" );
193+
194+ for (uint16_t i = 0 ; i < (N_SENSORS * BSEC_MAX_STATE_BLOB_SIZE) + 1 ; i++) {
195+ EEPROM.write (i, 0 );
196+ }
197+
198+ EEPROM.commit ();
199+ }
200+ }
201+
202+ void updateState (void )
203+ {
204+ bool update = false ;
205+ /* Set a trigger to save the state. Here, the state is saved every STATE_SAVE_PERIOD with the first state being saved once the algorithm achieves full calibration, i.e. iaqAccuracy = 3 */
206+ if (stateUpdateCounter == 0 ) {
207+ if ((iaqSensor1.iaqAccuracy >= 3 ) || (iaqSensor2.iaqAccuracy >= 3 )) {
208+ update = true ;
209+ stateUpdateCounter++;
210+ }
211+ } else {
212+ /* Update every STATE_SAVE_PERIOD milliseconds */
213+ if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis ()) {
214+ update = true ;
215+ stateUpdateCounter++;
216+ }
217+ }
218+
219+ if (update) {
220+ iaqSensor1.getState (bsecState1);
221+ iaqSensor2.getState (bsecState2);
222+ checkIaqSensorStatus ();
223+
224+ Serial.println (" Writing state(s) to EEPROM" );
225+
226+ for (uint16_t i = 0 ; i < BSEC_MAX_STATE_BLOB_SIZE ; i++) {
227+ EEPROM.write (i + 1 , bsecState1[i]);
228+ EEPROM.write (i + 1 + BSEC_MAX_STATE_BLOB_SIZE, bsecState2[i]);
229+ Serial.println (String (bsecState1[i], HEX) + " , " + String (bsecState2[i], HEX));
230+ }
231+
232+ EEPROM.write (0 , BSEC_MAX_STATE_BLOB_SIZE);
233+ EEPROM.commit ();
234+ }
235+ }
0 commit comments