36
36
THE SOFTWARE.
37
37
*/
38
38
39
-
40
39
#include " SparkFun_SGP30_Arduino_Library.h"
41
40
42
-
43
41
// Constructor
44
- SGP30::SGP30 () {
42
+ SGP30::SGP30 ()
43
+ {
45
44
CO2 = 0 ;
46
45
TVOC = 0 ;
47
46
baselineCO2 = 0 ;
@@ -54,18 +53,20 @@ SGP30::SGP30() {
54
53
55
54
// Start I2C communication using specified port
56
55
// Returns true if successful or false if no sensor detected
57
- bool SGP30::begin (TwoWire &wirePort) {
56
+ bool SGP30::begin (TwoWire &wirePort)
57
+ {
58
58
_i2cPort = &wirePort; // Grab which port the user wants us to use
59
59
_i2cPort->begin ();
60
60
getSerialID ();
61
- if (serialID == 0 ) return false ;
61
+ if (serialID == 0 )
62
+ return false ;
62
63
return true ;
63
64
}
64
65
65
-
66
66
// Initilizes sensor for air quality readings
67
67
// measureAirQuality should be called in 1 second intervals after this function
68
- void SGP30::initAirQuality (void ) {
68
+ void SGP30::initAirQuality (void )
69
+ {
69
70
_i2cPort->beginTransmission (_SGP30Address);
70
71
_i2cPort->write (init_air_quality, 2 ); // command to initialize air quality readings
71
72
_i2cPort->endTransmission ();
@@ -76,7 +77,8 @@ void SGP30::initAirQuality(void) {
76
77
// CO2 returned in ppm, Total Volatile Organic Compounds (TVOC) returned in ppb
77
78
// Will give fixed values of CO2=400 and TVOC=0 for first 15 seconds after init
78
79
// Returns SUCCESS if successful or other error code if unsuccessful
79
- SGP30ERR SGP30::measureAirQuality (void ) {
80
+ SGP30ERR SGP30::measureAirQuality (void )
81
+ {
80
82
_i2cPort->beginTransmission (_SGP30Address);
81
83
_i2cPort->write (measure_air_quality, 2 ); // command to measure air quality
82
84
_i2cPort->endTransmission ();
@@ -85,17 +87,20 @@ SGP30ERR SGP30::measureAirQuality(void) {
85
87
// Comes back in 6 bytes, CO2 data(MSB) / data(LSB) / Checksum / TVOC data(MSB) / data(LSB) / Checksum
86
88
uint8_t toRead;
87
89
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )6 );
88
- if (toRead != 6 ) return ERR_I2C_TIMEOUT; // Error out
90
+ if (toRead != 6 )
91
+ return ERR_I2C_TIMEOUT; // Error out
89
92
uint16_t _CO2 = _i2cPort->read () << 8 ; // store MSB in CO2
90
- _CO2 |= _i2cPort->read (); // store LSB in CO2
91
- uint8_t checkSum = _i2cPort->read (); // verify checksum
92
- if (checkSum != _CRC8 (_CO2)) return ERR_BAD_CRC; // checksum failed
93
+ _CO2 |= _i2cPort->read (); // store LSB in CO2
94
+ uint8_t checkSum = _i2cPort->read (); // verify checksum
95
+ if (checkSum != _CRC8 (_CO2))
96
+ return ERR_BAD_CRC; // checksum failed
93
97
uint16_t _TVOC = _i2cPort->read () << 8 ; // store MSB in TVOC
94
- _TVOC |= _i2cPort->read (); // store LSB in TVOC
95
- checkSum = _i2cPort->read (); // verify checksum
96
- if (checkSum != _CRC8 (_TVOC)) return ERR_BAD_CRC; // checksum failed
97
- CO2 = _CO2; // publish valid data
98
- TVOC = _TVOC; // publish valid data
98
+ _TVOC |= _i2cPort->read (); // store LSB in TVOC
99
+ checkSum = _i2cPort->read (); // verify checksum
100
+ if (checkSum != _CRC8 (_TVOC))
101
+ return ERR_BAD_CRC; // checksum failed
102
+ CO2 = _CO2; // publish valid data
103
+ TVOC = _TVOC; // publish valid data
99
104
return SUCCESS;
100
105
}
101
106
@@ -105,7 +110,8 @@ SGP30ERR SGP30::measureAirQuality(void) {
105
110
// (like EEPROM) to restore after new power up or
106
111
// after soft reset using setBaseline();
107
112
// Returns SUCCESS if successful or other error code if unsuccessful
108
- SGP30ERR SGP30::getBaseline (void ) {
113
+ SGP30ERR SGP30::getBaseline (void )
114
+ {
109
115
_i2cPort->beginTransmission (_SGP30Address);
110
116
_i2cPort->write (get_baseline, 2 );
111
117
_i2cPort->endTransmission ();
@@ -114,32 +120,36 @@ SGP30ERR SGP30::getBaseline(void) {
114
120
uint8_t toRead;
115
121
// Comes back in 6 bytes, baselineCO2 data(MSB) / data(LSB) / Checksum / baselineTVOC data(MSB) / data(LSB) / Checksum
116
122
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )6 );
117
- if (toRead != 6 ) return ERR_I2C_TIMEOUT; // Error out
123
+ if (toRead != 6 )
124
+ return ERR_I2C_TIMEOUT; // Error out
118
125
uint16_t _baselineCO2 = _i2cPort->read () << 8 ; // store MSB in _baselineCO2
119
- _baselineCO2 |= _i2cPort->read (); // store LSB in _baselineCO2
120
- uint8_t checkSum = _i2cPort->read (); // verify checksum
121
- if (checkSum != _CRC8 (_baselineCO2)) return ERR_BAD_CRC; // checksum failed
126
+ _baselineCO2 |= _i2cPort->read (); // store LSB in _baselineCO2
127
+ uint8_t checkSum = _i2cPort->read (); // verify checksum
128
+ if (checkSum != _CRC8 (_baselineCO2))
129
+ return ERR_BAD_CRC; // checksum failed
122
130
uint16_t _baselineTVOC = _i2cPort->read () << 8 ; // store MSB in _baselineTVOC
123
- _baselineTVOC |= _i2cPort->read (); // store LSB in _baselineTVOC
124
- checkSum = _i2cPort->read (); // verify checksum
125
- if (checkSum != _CRC8 (_baselineTVOC)) return ERR_BAD_CRC; // checksum failed
126
- baselineCO2 = _baselineCO2; // publish valid data
131
+ _baselineTVOC |= _i2cPort->read (); // store LSB in _baselineTVOC
132
+ checkSum = _i2cPort->read (); // verify checksum
133
+ if (checkSum != _CRC8 (_baselineTVOC))
134
+ return ERR_BAD_CRC; // checksum failed
135
+ baselineCO2 = _baselineCO2; // publish valid data
127
136
baselineTVOC = _baselineTVOC; // publish valid data
128
137
return SUCCESS;
129
138
}
130
139
131
140
// Updates the baseline to a previous baseline
132
141
// Should only use with previously retrieved baselines
133
142
// to maintain accuracy
134
- void SGP30::setBaseline (uint16_t baselineCO2, uint16_t baselineTVOC) {
143
+ void SGP30::setBaseline (uint16_t baselineCO2, uint16_t baselineTVOC)
144
+ {
135
145
_i2cPort->beginTransmission (_SGP30Address);
136
- _i2cPort->write (set_baseline, 2 ); // command to set baseline
137
- _i2cPort->write (baselineTVOC >> 8 ); // write baseline TVOC MSB
138
- _i2cPort->write (baselineTVOC); // write baseline TVOC LSB
146
+ _i2cPort->write (set_baseline, 2 ); // command to set baseline
147
+ _i2cPort->write (baselineTVOC >> 8 ); // write baseline TVOC MSB
148
+ _i2cPort->write (baselineTVOC); // write baseline TVOC LSB
139
149
_i2cPort->write (_CRC8 (baselineTVOC)); // write checksum TVOC baseline
140
- _i2cPort->write (baselineCO2 >> 8 ); // write baseline CO2 MSB
141
- _i2cPort->write (baselineCO2); // write baseline CO2 LSB
142
- _i2cPort->write (_CRC8 (baselineCO2)); // write checksum CO2 baseline
150
+ _i2cPort->write (baselineCO2 >> 8 ); // write baseline CO2 MSB
151
+ _i2cPort->write (baselineCO2); // write baseline CO2 LSB
152
+ _i2cPort->write (_CRC8 (baselineCO2)); // write checksum CO2 baseline
143
153
_i2cPort->endTransmission ();
144
154
}
145
155
@@ -150,18 +160,20 @@ void SGP30::setBaseline(uint16_t baselineCO2, uint16_t baselineTVOC) {
150
160
// minimum value 0x0001 = 1/256g/m^3
151
161
// maximum value 0xFFFF = 255+255/256 g/m^3
152
162
// sending 0x0000 resets to default and turns off humidity compensation
153
- void SGP30::setHumidity (uint16_t humidity) {
163
+ void SGP30::setHumidity (uint16_t humidity)
164
+ {
154
165
_i2cPort->beginTransmission (_SGP30Address);
155
166
_i2cPort->write (set_humidity, 2 ); // command to set humidity
156
- _i2cPort->write (humidity >> 8 ); // write humidity MSB
157
- _i2cPort->write (humidity); // write humidity LSB
167
+ _i2cPort->write (humidity >> 8 ); // write humidity MSB
168
+ _i2cPort->write (humidity); // write humidity LSB
158
169
_i2cPort->write (_CRC8 (humidity)); // write humidity checksum
159
170
_i2cPort->endTransmission ();
160
171
}
161
172
162
173
// gives feature set version number (see data sheet)
163
174
// Returns SUCCESS if successful or other error code if unsuccessful
164
- SGP30ERR SGP30::getFeatureSetVersion (void ) {
175
+ SGP30ERR SGP30::getFeatureSetVersion (void )
176
+ {
165
177
_i2cPort->beginTransmission (_SGP30Address);
166
178
_i2cPort->write (get_feature_set_version, 2 ); // command to get feature version
167
179
_i2cPort->endTransmission ();
@@ -170,19 +182,22 @@ SGP30ERR SGP30::getFeatureSetVersion(void) {
170
182
uint8_t toRead;
171
183
// Comes back in 3 bytes, data(MSB) / data(LSB) / Checksum
172
184
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )3 );
173
- if (toRead != 3 ) return ERR_I2C_TIMEOUT; // Error out
185
+ if (toRead != 3 )
186
+ return ERR_I2C_TIMEOUT; // Error out
174
187
uint16_t _featureSetVersion = _i2cPort->read () << 8 ; // store MSB in featureSetVerison
175
- _featureSetVersion |= _i2cPort->read (); // store LSB in featureSetVersion
176
- uint8_t checkSum = _i2cPort->read (); // verify checksum
177
- if (checkSum != _CRC8 (_featureSetVersion)) return ERR_BAD_CRC; // checksum failed
188
+ _featureSetVersion |= _i2cPort->read (); // store LSB in featureSetVersion
189
+ uint8_t checkSum = _i2cPort->read (); // verify checksum
190
+ if (checkSum != _CRC8 (_featureSetVersion))
191
+ return ERR_BAD_CRC; // checksum failed
178
192
featureSetVersion = _featureSetVersion; // publish valid data
179
193
return SUCCESS;
180
194
}
181
195
182
196
// Intended for part verification and testing
183
197
// these raw signals are used as inputs to the onchip calibrations and algorithms
184
198
// Returns SUCCESS if successful or other error code if unsuccessful
185
- SGP30ERR SGP30::measureRawSignals (void ) {
199
+ SGP30ERR SGP30::measureRawSignals (void )
200
+ {
186
201
_i2cPort->beginTransmission (_SGP30Address);
187
202
_i2cPort->write (measure_raw_signals, 2 ); // command to measure raw signals
188
203
_i2cPort->endTransmission ();
@@ -191,31 +206,36 @@ SGP30ERR SGP30::measureRawSignals(void) {
191
206
uint8_t toRead;
192
207
// Comes back in 6 bytes, H2 data(MSB) / data(LSB) / Checksum / ethanol data(MSB) / data(LSB) / Checksum
193
208
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )6 );
194
- if (toRead != 6 ) return ERR_I2C_TIMEOUT; // Error out
209
+ if (toRead != 6 )
210
+ return ERR_I2C_TIMEOUT; // Error out
195
211
uint16_t _H2 = _i2cPort->read () << 8 ; // store MSB in _H2
196
- _H2 |= _i2cPort->read (); // store LSB in _H2
197
- uint8_t checkSum = _i2cPort->read (); // verify checksum
198
- if (checkSum != _CRC8 (_H2)) return ERR_BAD_CRC; // checksumfailed
212
+ _H2 |= _i2cPort->read (); // store LSB in _H2
213
+ uint8_t checkSum = _i2cPort->read (); // verify checksum
214
+ if (checkSum != _CRC8 (_H2))
215
+ return ERR_BAD_CRC; // checksumfailed
199
216
uint16_t _ethanol = _i2cPort->read () << 8 ; // store MSB in ethanol
200
- _ethanol |= _i2cPort->read (); // store LSB in ethanol
201
- checkSum = _i2cPort->read (); // verify checksum
202
- if (checkSum != _CRC8 (_ethanol)) return ERR_BAD_CRC; // checksum failed
203
- H2 = _H2; // publish valid data
204
- ethanol = _ethanol; // publish valid data
217
+ _ethanol |= _i2cPort->read (); // store LSB in ethanol
218
+ checkSum = _i2cPort->read (); // verify checksum
219
+ if (checkSum != _CRC8 (_ethanol))
220
+ return ERR_BAD_CRC; // checksum failed
221
+ H2 = _H2; // publish valid data
222
+ ethanol = _ethanol; // publish valid data
205
223
return SUCCESS;
206
224
}
207
225
208
226
// Soft reset - not device specific
209
227
// will reset all devices that support general call mode
210
- void SGP30::generalCallReset (void ) {
228
+ void SGP30::generalCallReset (void )
229
+ {
211
230
_i2cPort->beginTransmission (0x00 ); // general call address
212
- _i2cPort->write (0x06 ); // reset command
231
+ _i2cPort->write (0x06 ); // reset command
213
232
_i2cPort->endTransmission ();
214
233
}
215
234
216
235
// readout of serial ID register can identify chip and verify sensor presence
217
236
// Returns SUCCESS if successful or other error code if unsuccessful
218
- SGP30ERR SGP30::getSerialID (void ) {
237
+ SGP30ERR SGP30::getSerialID (void )
238
+ {
219
239
_i2cPort->beginTransmission (_SGP30Address);
220
240
_i2cPort->write (get_serial_id, 2 ); // command to get serial ID
221
241
_i2cPort->endTransmission ();
@@ -224,26 +244,31 @@ SGP30ERR SGP30::getSerialID(void) {
224
244
uint8_t toRead;
225
245
// Comes back in 9 bytes, H2 data(MSB) / data(LSB) / Checksum / ethanol data(MSB) / data(LSB) / Checksum
226
246
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )9 );
227
- if (toRead != 9 ) return ERR_I2C_TIMEOUT; // Error out
247
+ if (toRead != 9 )
248
+ return ERR_I2C_TIMEOUT; // Error out
228
249
uint16_t _serialID1 = _i2cPort->read () << 8 ; // store MSB to top of _serialID1
229
- _serialID1 |= _i2cPort->read (); // store next byte in _serialID1
230
- uint8_t checkSum1 = _i2cPort->read (); // verify checksum
231
- if (checkSum1 != _CRC8 (_serialID1)) return ERR_BAD_CRC; // checksum failed
250
+ _serialID1 |= _i2cPort->read (); // store next byte in _serialID1
251
+ uint8_t checkSum1 = _i2cPort->read (); // verify checksum
252
+ if (checkSum1 != _CRC8 (_serialID1))
253
+ return ERR_BAD_CRC; // checksum failed
232
254
uint16_t _serialID2 = _i2cPort->read () << 8 ; // store next byte to top of _serialID2
233
- _serialID2 |= _i2cPort->read (); // store next byte in _serialID2
234
- uint8_t checkSum2 = _i2cPort->read (); // verify checksum
235
- if (checkSum2 != _CRC8 (_serialID2)) return ERR_BAD_CRC; // checksum failed
255
+ _serialID2 |= _i2cPort->read (); // store next byte in _serialID2
256
+ uint8_t checkSum2 = _i2cPort->read (); // verify checksum
257
+ if (checkSum2 != _CRC8 (_serialID2))
258
+ return ERR_BAD_CRC; // checksum failed
236
259
uint16_t _serialID3 = _i2cPort->read () << 8 ; // store next byte to top of _serialID3
237
- _serialID3 |= _i2cPort->read () ; // store LSB in _serialID3
238
- uint8_t checkSum3 = _i2cPort->read (); // verify checksum
239
- if (checkSum3 != _CRC8 (_serialID3)) return ERR_BAD_CRC; // checksum failed
260
+ _serialID3 |= _i2cPort->read (); // store LSB in _serialID3
261
+ uint8_t checkSum3 = _i2cPort->read (); // verify checksum
262
+ if (checkSum3 != _CRC8 (_serialID3))
263
+ return ERR_BAD_CRC; // checksum failed
240
264
serialID = ((uint64_t )_serialID1 << 32 ) + ((uint64_t )_serialID2 << 16 ) + ((uint64_t )_serialID3); // publish valid data
241
265
return SUCCESS;
242
266
}
243
267
244
268
// Sensor runs on chip self test
245
269
// Returns SUCCESS if successful or other error code if unsuccessful
246
- SGP30ERR SGP30::measureTest (void ) {
270
+ SGP30ERR SGP30::measureTest (void )
271
+ {
247
272
_i2cPort->beginTransmission (_SGP30Address);
248
273
_i2cPort->write (measure_test, 2 ); // command to get self test
249
274
_i2cPort->endTransmission ();
@@ -252,12 +277,15 @@ SGP30ERR SGP30::measureTest(void) {
252
277
uint8_t toRead;
253
278
// Comes back in 3 bytes, data(MSB) / data(LSB) / Checksum
254
279
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )3 );
255
- if (toRead != 3 ) return ERR_I2C_TIMEOUT; // Error out
280
+ if (toRead != 3 )
281
+ return ERR_I2C_TIMEOUT; // Error out
256
282
uint16_t results = _i2cPort->read () << 8 ; // store MSB in results
257
- results |= _i2cPort->read (); // store LSB in results
258
- uint8_t checkSum = _i2cPort->read (); // verify checksum
259
- if (checkSum != _CRC8 (results)) return ERR_BAD_CRC; // checksum failed
260
- if (results != 0xD400 ) return SELF_TEST_FAIL; // self test results incorrect
283
+ results |= _i2cPort->read (); // store LSB in results
284
+ uint8_t checkSum = _i2cPort->read (); // verify checksum
285
+ if (checkSum != _CRC8 (results))
286
+ return ERR_BAD_CRC; // checksum failed
287
+ if (results != 0xD400 )
288
+ return SELF_TEST_FAIL; // self test results incorrect
261
289
return SUCCESS;
262
290
}
263
291
@@ -273,7 +301,7 @@ uint8_t SGP30::_CRC8(uint16_t data)
273
301
274
302
crc ^= (data >> 8 ); // XOR-in the first input byte
275
303
276
- for (uint8_t i = 0 ; i < 8 ; i++)
304
+ for (uint8_t i = 0 ; i < 8 ; i++)
277
305
{
278
306
if ((crc & 0x80 ) != 0 )
279
307
crc = (uint8_t )((crc << 1 ) ^ 0x31 );
@@ -282,7 +310,7 @@ uint8_t SGP30::_CRC8(uint16_t data)
282
310
}
283
311
crc ^= (uint8_t )data; // XOR-in the last input byte
284
312
285
- for (uint8_t i = 0 ; i < 8 ; i++)
313
+ for (uint8_t i = 0 ; i < 8 ; i++)
286
314
{
287
315
if ((crc & 0x80 ) != 0 )
288
316
crc = (uint8_t )((crc << 1 ) ^ 0x31 );
@@ -296,14 +324,13 @@ uint8_t SGP30::_CRC8(uint16_t data)
296
324
297
325
#ifdef SGP30_LOOKUP_TABLE
298
326
// Generates CRC8 for SGP30 from lookup table
299
- uint8_t SGP30::_CRC8 (uint16_t data) {
300
- uint8_t CRC = 0xFF ; // inital value
301
- CRC ^= (uint8_t )(data >> 8 ); // start with MSB
327
+ uint8_t SGP30::_CRC8 (uint16_t data)
328
+ {
329
+ uint8_t CRC = 0xFF ; // inital value
330
+ CRC ^= (uint8_t )(data >> 8 ); // start with MSB
302
331
CRC = _CRC8LookupTable[CRC >> 4 ][CRC & 0xF ]; // look up table [MSnibble][LSnibble]
303
- CRC ^= (uint8_t )data; // use LSB
332
+ CRC ^= (uint8_t )data; // use LSB
304
333
CRC = _CRC8LookupTable[CRC >> 4 ][CRC & 0xF ]; // look up table [MSnibble][LSnibble]
305
334
return CRC;
306
335
}
307
336
#endif
308
-
309
-
0 commit comments