Skip to content

Commit c5503e0

Browse files
author
Bosch Sensortec
authored
Merge pull request #49 from BoschSensortec/experimental/multi-instance-support
Merged Experimental/multi instance support to master
2 parents 7101334 + be6042c commit c5503e0

15 files changed

Lines changed: 1209 additions & 770 deletions

File tree

LICENSE

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,33 @@ The binaries and includes for the core BSEC library in this repository are licen
22

33
The Arduino wrapper and BME680 Sensor API are licensed under the following license.
44

5-
Copyright (C) 2017 - 2019 Bosch Sensortec GmbH
5+
Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
6+
7+
BSD-3-Clause
68

79
Redistribution and use in source and binary forms, with or without
810
modification, are permitted provided that the following conditions are met:
911

10-
Redistributions of source code must retain the above copyright
11-
notice, this list of conditions and the following disclaimer.
12-
13-
Redistributions in binary form must reproduce the above copyright
14-
notice, this list of conditions and the following disclaimer in the
15-
documentation and/or other materials provided with the distribution.
16-
17-
Neither the name of the copyright holder nor the names of the
18-
contributors may be used to endorse or promote products derived from
19-
this software without specific prior written permission.
20-
21-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
22-
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
23-
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25-
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
26-
OR CONTRIBUTORS BE LIABLE FOR ANY
27-
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
28-
OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
29-
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31-
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32-
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34-
ANY WAY OUT OF THE USE OF THIS
35-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
36-
37-
The information provided is believed to be accurate and reliable.
38-
The copyright holder assumes no responsibility
39-
for the consequences of use
40-
of such information nor for any infringement of patents or
41-
other rights of third parties which may result from its use.
42-
No license is granted by implication or otherwise under any patent or
43-
patent rights of the copyright holder.
12+
1. Redistributions of source code must retain the above copyright
13+
notice, this list of conditions and the following disclaimer.
14+
15+
2. Redistributions in binary form must reproduce the above copyright
16+
notice, this list of conditions and the following disclaimer in the
17+
documentation and/or other materials provided with the distribution.
18+
19+
3. Neither the name of the copyright holder nor the names of its
20+
contributors may be used to endorse or promote products derived from
21+
this software without specific prior written permission.
22+
23+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26+
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27+
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34+
POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,4 @@ The current list of tested boards include,
184184
| Esp32 | Sparkfun ESP32 Thing | v1.0.3-rc1 | https://github.com/espressif/arduino-esp32 |
185185
| Esp8266 | Adafruit Feather HUZZAH | Upstream of v2.5.1 SHA-1 hash 625c3a62c4991347e8298fb5e4021bc6f6df7099 | https://github.com/esp8266/Arduino |
186186

187-
## Copyright (C) 2017 - 2019 Bosch Sensortec GmbH
187+
## Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved.

examples/basic_config_state/basic_config_state.ino

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
#include <EEPROM.h>
22
#include "bsec.h"
33
/* 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-
*/
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+
*/
1616
const uint8_t bsec_config_iaq[] = {
17-
#include "config/generic_33v_3s_4d/bsec_iaq.txt"
17+
#include "config/generic_33v_3s_4d/bsec_iaq.txt"
1818
};
1919

2020
#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // 360 minutes - 4 times a day
@@ -114,6 +114,7 @@ void checkIaqSensorStatus(void)
114114
Serial.println(output);
115115
}
116116
}
117+
iaqSensor.status = BSEC_OK;
117118
}
118119

119120
void errLeds(void)
@@ -180,4 +181,4 @@ void updateState(void)
180181
EEPROM.write(0, BSEC_MAX_STATE_BLOB_SIZE);
181182
EEPROM.commit();
182183
}
183-
}
184+
}
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
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 = "\nBSEC 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

Comments
 (0)