Skip to content

Commit fb192b7

Browse files
authored
Merge pull request #32 from arduino/bsec+examples
Add support for Bsec sensors
2 parents 7afd70c + 938ad1d commit fb192b7

File tree

6 files changed

+131
-18
lines changed

6 files changed

+131
-18
lines changed

src/Arduino_BHY2.h

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "sensors/SensorOrientation.h"
1010
#include "sensors/SensorXYZ.h"
1111
#include "sensors/SensorQuaternion.h"
12+
#include "sensors/SensorBSEC.h"
1213
#include "sensors/SensorActivity.h"
1314
#include "sensors/Sensor.h"
1415

src/sensors/DataParser.cpp

+30-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,35 @@ void DataParser::parseQuaternion(SensorDataPacket& data, DataQuaternion& vector)
2424
vector.accuracy = data.getUint16(8);
2525
}
2626

27+
void DataParser::parseBSEC(SensorDataPacket& data, DataBSEC& vector) {
28+
const float SCALE_BSEC_BVOC_EQ = 0.01f;
29+
const float SCALE_BSEC_COMP_T = 1.0f / 256;
30+
const float SCALE_BSEC_COMP_H = 1.0f / 500;
31+
32+
vector.iaq = data.getUint16(0);
33+
vector.iaq_s = data.getUint16(2);
34+
vector.b_voc_eq = data.getUint16(4) * SCALE_BSEC_BVOC_EQ; //b-VOC-eq in the FIFO frame is scaled up by 100
35+
vector.co2_eq = data.getUint24(6);
36+
vector.accuracy = data.getUint8(9);
37+
vector.comp_t = data.getInt16(10) * SCALE_BSEC_COMP_T;
38+
vector.comp_h = data.getUint16(12) * SCALE_BSEC_COMP_H;
39+
vector.comp_g = (uint32_t)(data.getFloat(14));
40+
}
41+
42+
void DataParser::parseBSECLegacy(SensorDataPacket& data, DataBSEC& vector) {
43+
vector.comp_t = data.getFloat(0);
44+
vector.comp_h = data.getFloat(4);
45+
//note that: SENSOR_DATA_FIXED_LENGTH is defined as 10 by default,
46+
//so all the fields below are 0 unless it's redefined to 29 and above
47+
vector.comp_g = (uint32_t)(data.getFloat(8));
48+
vector.iaq = (uint16_t)(data.getFloat(12));
49+
vector.iaq_s = (uint16_t)(data.getFloat(16));
50+
vector.co2_eq = (uint32_t)data.getFloat(20);
51+
vector.b_voc_eq = data.getFloat(24);
52+
vector.accuracy = data.getUint8(28);
53+
}
54+
55+
2756
void DataParser::parseData(SensorDataPacket& data, float& value, float scaleFactor, SensorPayload format) {
2857
uint8_t id = data.sensorId;
2958
switch (format) {
@@ -58,4 +87,4 @@ void DataParser::parseData(SensorDataPacket& data, float& value, float scaleFact
5887

5988
void DataParser::parseActivity(SensorDataPacket& data, uint16_t& value) {
6089
value = data.getUint16(0);
61-
}
90+
}

src/sensors/DataParser.h

+31-5
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ struct DataOrientation {
2323
float roll;
2424

2525
String toString() {
26-
return (String)("Orientation values - heading: " + String(heading, 3)
27-
+ " pitch: " + String(pitch, 3)
26+
return (String)("Orientation values - heading: " + String(heading, 3)
27+
+ " pitch: " + String(pitch, 3)
2828
+ " roll: " + String(roll, 3) + "\n");
2929
}
3030
};
@@ -39,19 +39,45 @@ struct DataQuaternion {
3939
String toString() {
4040
return (String)("Quaternion values - X: " + String(x)
4141
+ " Y: " + String(y)
42-
+ " Z: " + String(z)
43-
+ " W: " + String(w)
44-
+ " Accuracy: " + String(accuracy)
42+
+ " Z: " + String(z)
43+
+ " W: " + String(w)
44+
+ " Accuracy: " + String(accuracy)
4545
+ "\n");
4646
}
4747
};
4848

49+
struct DataBSEC {
50+
uint16_t iaq; //iaq value for regular use case
51+
uint16_t iaq_s; //iaq value for stationary use cases
52+
float b_voc_eq; //breath VOC equivalent (ppm)
53+
uint32_t co2_eq; //CO2 equivalent (ppm) [400,]
54+
float comp_t; //compensated temperature (celcius)
55+
float comp_h; //compensated humidity
56+
uint32_t comp_g; //compensated gas resistance (Ohms)
57+
uint8_t accuracy; //accuracy level: [0-3]
58+
59+
String toString() {
60+
return (String)("BSEC output values - iaq: " + String(iaq)
61+
+ " iaq_s: " + String(iaq_s)
62+
+ " b_voc_eq: " + String(b_voc_eq, 2)
63+
+ " co2_eq: " + String(co2_eq)
64+
+ " accuracy: " + String(accuracy)
65+
+ " comp_t: " + String(comp_t, 2)
66+
+ " comp_h: " + String(comp_h, 2)
67+
+ " comp_g: " + String(comp_g)
68+
+ "\n");
69+
}
70+
};
71+
72+
4973
class DataParser {
5074
public:
5175
static void parse3DVector(SensorDataPacket& data, DataXYZ& vector);
5276
static void parseEuler(SensorDataPacket& data, DataOrientation& vector);
5377
static void parseEuler(SensorDataPacket& data, DataOrientation& vector, float scaleFactor);
5478
static void parseQuaternion(SensorDataPacket& data, DataQuaternion& vector);
79+
static void parseBSEC(SensorDataPacket& data, DataBSEC& vector);
80+
static void parseBSECLegacy(SensorDataPacket& data, DataBSEC& vector);
5581
static void parseData(SensorDataPacket& data, float& value, float scaleFactor, SensorPayload format);
5682
static void parseActivity(SensorDataPacket& data, uint16_t& value);
5783
};

src/sensors/SensorBSEC.h

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef SENSOR_BSEC_H_
2+
#define SENSOR_BSEC_H_
3+
4+
#include "SensorClass.h"
5+
6+
7+
class SensorBSEC : public SensorClass {
8+
public:
9+
SensorBSEC() {}
10+
SensorBSEC(uint8_t id) : SensorClass(id), _data() {}
11+
12+
/*
13+
BSEC sensor frames are:
14+
- 18 bytes for BSEC new format (SID=115 SENSOR_ID_BSEC_LEGACY)
15+
- 29 bytes for legacy format (SID=171 SENSOR_ID_BSEC)
16+
If the default size of SENSOR_DATA_FIXED_LENGTH is used (10 bytes), some fields of BSEC might be always 0.
17+
Enlarge SENSOR_DATA_FIXED_LENGTH to see all the fields of the BSEC sensor.
18+
For the new format (SID=115), if the compensated values (comp_t, comp_h, comp_g) are not important,
19+
keep SENSOR_DATA_FIXED_LENGTH to the default value (10) to save bandwidth.
20+
*/
21+
uint16_t iaq() {return _data.iaq;}
22+
uint16_t iaq_s() {return _data.iaq_s;}
23+
float b_voc_eq() {return _data.b_voc_eq;}
24+
uint32_t co2_eq() {return _data.co2_eq;}
25+
uint8_t accuracy() {return _data.accuracy;}
26+
float comp_t() {return _data.comp_t;}
27+
float comp_h() {return _data.comp_h;}
28+
uint32_t comp_g() {return _data.comp_g;}
29+
30+
31+
void setData(SensorDataPacket &data)
32+
{
33+
if (_id == SENSOR_ID_BSEC ) {
34+
DataParser::parseBSEC(data, _data);
35+
} else if (_id == SENSOR_ID_BSEC_LEGACY) {
36+
DataParser::parseBSECLegacy(data, _data);
37+
}
38+
}
39+
40+
String toString()
41+
{
42+
return _data.toString();
43+
}
44+
45+
private:
46+
DataBSEC _data;
47+
};
48+
#endif

src/sensors/SensorID.h

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ enum SensorID {
5252
SENSOR_ID_GYRO_BIAS_WU = 92, /* Gyroscope offset wake up */
5353
SENSOR_ID_MAG_BIAS_WU = 93, /* Magnetometer offset wake up */
5454
SENSOR_ID_STD_WU = 94, /* Step detector wake up */
55+
SENSOR_ID_BSEC = 115, /* BSEC 1.x output */
5556
SENSOR_ID_TEMP = 128, /* Temperature */
5657
SENSOR_ID_BARO = 129, /* Barometer */
5758
SENSOR_ID_HUM = 130, /* Humidity */
@@ -74,6 +75,7 @@ enum SensorID {
7475
SENSOR_ID_PROX = 147, /* Proximity */
7576
SENSOR_ID_LIGHT_WU = 148, /* Light wake up */
7677
SENSOR_ID_PROX_WU = 149, /* Proximity wake up */
78+
SENSOR_ID_BSEC_LEGACY = 171, /* BSEC 1.x output (legacy, deprecated) */
7779
DEBUG_DATA_EVENT = 250, /* Binary or string debug data */
7880
TIMESTAMP_SMALL_DELTA = 251, /* Incremental time change from previous read */
7981
TIMESTAMP_SMALL_DELTA_WU = 245, /* Incremental time change from previous read wake up */

src/sensors/SensorTypes.h

+19-12
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ struct __attribute__((packed)) SensorDataPacket {
2525
float result = 0;
2626
uint8_t length = sizeof(result);
2727
if (index + length > SENSOR_DATA_FIXED_LENGTH) {
28-
length = SENSOR_DATA_FIXED_LENGTH - index;
28+
//to safe guard against overflow
29+
length = SENSOR_DATA_FIXED_LENGTH > index ? SENSOR_DATA_FIXED_LENGTH - index : 0;
2930
}
30-
memcpy(&result, &data[index], sizeof(result));
31+
if (length > 0)
32+
memcpy(&result, &data[index], length);
3133
return result;
3234
}
3335

@@ -42,29 +44,32 @@ struct __attribute__((packed)) SensorDataPacket {
4244
uint16_t result = 0;
4345
uint8_t length = sizeof(result);
4446
if (index + length > SENSOR_DATA_FIXED_LENGTH) {
45-
length = SENSOR_DATA_FIXED_LENGTH - index;
47+
length = SENSOR_DATA_FIXED_LENGTH > index ? SENSOR_DATA_FIXED_LENGTH - index : 0;
4648
}
47-
memcpy(&result, &data[index], length);
49+
if (length > 0)
50+
memcpy(&result, &data[index], length);
4851
return result;
4952
}
5053

5154
uint32_t getUint24(uint8_t index) {
5255
uint32_t result = 0;
5356
uint8_t length = 3;
5457
if (index + length > SENSOR_DATA_FIXED_LENGTH) {
55-
length = SENSOR_DATA_FIXED_LENGTH - index;
58+
length = SENSOR_DATA_FIXED_LENGTH > index ? SENSOR_DATA_FIXED_LENGTH - index : 0;
5659
}
57-
memcpy(&result, &data[index], length);
60+
if (length > 0)
61+
memcpy(&result, &data[index], length);
5862
return result;
5963
}
6064

6165
uint32_t getUint32(uint8_t index) {
6266
uint32_t result = 0;
6367
uint8_t length = sizeof(result);
6468
if (index + length > SENSOR_DATA_FIXED_LENGTH) {
65-
length = SENSOR_DATA_FIXED_LENGTH - index;
69+
length = SENSOR_DATA_FIXED_LENGTH > index ? SENSOR_DATA_FIXED_LENGTH - index : 0;
6670
}
67-
memcpy(&result, &data[index], length);
71+
if (length > 0)
72+
memcpy(&result, &data[index], length);
6873
return result;
6974
}
7075

@@ -79,19 +84,21 @@ struct __attribute__((packed)) SensorDataPacket {
7984
int16_t result = 0;
8085
uint8_t length = sizeof(result);
8186
if (index + length > SENSOR_DATA_FIXED_LENGTH) {
82-
length = SENSOR_DATA_FIXED_LENGTH - index;
87+
length = SENSOR_DATA_FIXED_LENGTH > index ? SENSOR_DATA_FIXED_LENGTH - index : 0;
8388
}
84-
memcpy(&result, &data[index], length);
89+
if (length > 0)
90+
memcpy(&result, &data[index], length);
8591
return result;
8692
}
8793

8894
int32_t getInt32(uint8_t index) {
8995
int32_t result = 0;
9096
uint8_t length = sizeof(result);
9197
if (index + length > SENSOR_DATA_FIXED_LENGTH) {
92-
length = SENSOR_DATA_FIXED_LENGTH - index;
98+
length = SENSOR_DATA_FIXED_LENGTH > index ? SENSOR_DATA_FIXED_LENGTH - index : 0;
9399
}
94-
memcpy(&result, &data[index], length);
100+
if (length > 0)
101+
memcpy(&result, &data[index], length);
95102
return result;
96103
}
97104
};

0 commit comments

Comments
 (0)