39
39
40
40
#include " SparkFun_SGP30_Library.h"
41
41
42
- // const uint8_t init_air_quality[2] = {0x20, 0x03};
43
- // const uint8_t measure_air_quality[2] = {0x20, 0x08};
44
- // const uint8_t get_baseline[2] = {0x20, 0x15};
45
- // const uint8_t set_baseline[2] = {0x20, 0x1E};
46
- // const uint8_t set_humidity[2] = {0x20, 0x61};
47
- // const uint8_t measure_test[2] = {0x20, 0x32};
48
- // const uint8_t get_feature_set_version[2] = {0x20, 0x2F};
49
- // const uint8_t get_serial_id[2] = {0x36, 0x82};
50
- // const uint8_t measure_raw_signals[2] = {0x20, 0x50};
51
42
52
43
// Constructor
53
44
SGP30::SGP30 () {
@@ -59,9 +50,6 @@ SGP30::SGP30() {
59
50
H2 = 0 ;
60
51
ethanol = 0 ;
61
52
serialID = 0 ;
62
- _serialID1 = 0 ;
63
- _serialID2 = 0 ;
64
- _serialID3 = 0 ;
65
53
}
66
54
67
55
// Start I2C communication using specified port
@@ -103,11 +91,11 @@ SGP30ERR SGP30::measureAirQuality(void) {
103
91
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )6 );
104
92
}
105
93
if (counter == 12 ) return ERR_I2C_TIMEOUT; // Error out
106
- _CO2 = _i2cPort->read () << 8 ; // store MSB in CO2
94
+ uint16_t _CO2 = _i2cPort->read () << 8 ; // store MSB in CO2
107
95
_CO2 |= _i2cPort->read (); // store LSB in CO2
108
96
uint8_t checkSum = _i2cPort->read (); // verify checksum
109
97
if (checkSum != _CRC8 (_CO2)) return ERR_BAD_CRC; // checksum failed
110
- _TVOC = _i2cPort->read () << 8 ; // store MSB in TVOC
98
+ uint16_t _TVOC = _i2cPort->read () << 8 ; // store MSB in TVOC
111
99
_TVOC |= _i2cPort->read (); // store LSB in TVOC
112
100
checkSum = _i2cPort->read (); // verify checksum
113
101
if (checkSum != _CRC8 (_TVOC)) return ERR_BAD_CRC; // checksum failed
@@ -137,11 +125,11 @@ SGP30ERR SGP30::getBaseline(void) {
137
125
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )6 );
138
126
}
139
127
if (counter == 12 ) return ERR_I2C_TIMEOUT; // Error out
140
- _baselineCO2 = _i2cPort->read () << 8 ; // store MSB in _baselineCO2
128
+ uint16_t _baselineCO2 = _i2cPort->read () << 8 ; // store MSB in _baselineCO2
141
129
_baselineCO2 |= _i2cPort->read (); // store LSB in _baselineCO2
142
130
uint8_t checkSum = _i2cPort->read (); // verify checksum
143
131
if (checkSum != _CRC8 (_baselineCO2)) return ERR_BAD_CRC; // checksum failed
144
- _baselineTVOC = _i2cPort->read () << 8 ; // store MSB in _baselineTVOC
132
+ uint16_t _baselineTVOC = _i2cPort->read () << 8 ; // store MSB in _baselineTVOC
145
133
_baselineTVOC |= _i2cPort->read (); // store LSB in _baselineTVOC
146
134
checkSum = _i2cPort->read (); // verify checksum
147
135
if (checkSum != _CRC8 (_baselineTVOC)) return ERR_BAD_CRC; // checksum failed
@@ -198,7 +186,7 @@ SGP30ERR SGP30::getFeatureSetVersion(void) {
198
186
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )3 );
199
187
}
200
188
if (counter == 3 ) return ERR_I2C_TIMEOUT; // Error out
201
- _featureSetVersion = _i2cPort->read () << 8 ; // store MSB in featureSetVerison
189
+ uint16_t _featureSetVersion = _i2cPort->read () << 8 ; // store MSB in featureSetVerison
202
190
_featureSetVersion |= _i2cPort->read (); // store LSB in featureSetVersion
203
191
uint8_t checkSum = _i2cPort->read (); // verify checksum
204
192
if (checkSum != _CRC8 (_featureSetVersion)) return ERR_BAD_CRC; // checksum failed
@@ -224,11 +212,11 @@ SGP30ERR SGP30::measureRawSignals(void) {
224
212
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )6 );
225
213
}
226
214
if (counter == 5 ) return ERR_I2C_TIMEOUT; // Error out
227
- _H2 = _i2cPort->read () << 8 ; // store MSB in H2
228
- _H2 |= _i2cPort->read (); // store LSB in H2
215
+ uint16_t _H2 = _i2cPort->read () << 8 ; // store MSB in _H2
216
+ _H2 |= _i2cPort->read (); // store LSB in _H2
229
217
uint8_t checkSum = _i2cPort->read (); // verify checksum
230
218
if (checkSum != _CRC8 (_H2)) return ERR_BAD_CRC; // checksumfailed
231
- _ethanol = _i2cPort->read () << 8 ; // store MSB in ethanol
219
+ uint16_t _ethanol = _i2cPort->read () << 8 ; // store MSB in ethanol
232
220
_ethanol |= _i2cPort->read (); // store LSB in ethanol
233
221
checkSum = _i2cPort->read (); // verify checksum
234
222
if (checkSum != _CRC8 (_ethanol)) return ERR_BAD_CRC; // checksum failed
@@ -262,15 +250,15 @@ SGP30ERR SGP30::getSerialID(void) {
262
250
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )9 );
263
251
}
264
252
if (counter == 5 ) return ERR_I2C_TIMEOUT; // Error out
265
- _serialID1 = _i2cPort->read () << 8 ; // store MSB to top of _serialID1
253
+ uint16_t _serialID1 = _i2cPort->read () << 8 ; // store MSB to top of _serialID1
266
254
_serialID1 |= _i2cPort->read (); // store next byte in _serialID1
267
255
uint8_t checkSum1 = _i2cPort->read (); // verify checksum
268
256
if (checkSum1 != _CRC8 (_serialID1)) return ERR_BAD_CRC; // checksum failed
269
- _serialID2 = _i2cPort->read () << 8 ; // store next byte to top of _serialID2
257
+ uint16_t _serialID2 = _i2cPort->read () << 8 ; // store next byte to top of _serialID2
270
258
_serialID2 |= _i2cPort->read (); // store next byte in _serialID2
271
259
uint8_t checkSum2 = _i2cPort->read (); // verify checksum
272
260
if (checkSum2 != _CRC8 (_serialID2)) return ERR_BAD_CRC; // checksum failed
273
- _serialID3 = _i2cPort->read () << 8 ; // store next byte to top of _serialID3
261
+ uint16_t _serialID3 = _i2cPort->read () << 8 ; // store next byte to top of _serialID3
274
262
_serialID3 |= _i2cPort->read () ; // store LSB in _serialID3
275
263
uint8_t checkSum3 = _i2cPort->read (); // verify checksum
276
264
if (checkSum3 != _CRC8 (_serialID3)) return ERR_BAD_CRC; // checksum failed
@@ -295,24 +283,57 @@ SGP30ERR SGP30::measureTest(void) {
295
283
toRead = _i2cPort->requestFrom (_SGP30Address, (uint8_t )3 );
296
284
}
297
285
if (counter == 22 ) return ERR_I2C_TIMEOUT; // Error out
298
- uint16_t results;
299
- results = _i2cPort->read () << 8 ; // store MSB in results
286
+ uint16_t results = _i2cPort->read () << 8 ; // store MSB in results
300
287
results |= _i2cPort->read (); // store LSB in results
301
288
uint8_t checkSum = _i2cPort->read (); // verify checksum
302
289
if (checkSum != _CRC8 (results)) return ERR_BAD_CRC; // checksum failed
303
290
if (results != 0xD400 ) return SELF_TEST_FAIL; // self test results incorrect
304
291
return SUCCESS;
305
292
}
306
293
294
+ #ifndef LOOKUP_TABLE
295
+ // Given an array and a number of bytes, this calculate CRC8 for those bytes
296
+ // CRC is only calc'd on the data portion (two bytes) of the four bytes being sent
297
+ // From: http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html
298
+ // Tested with: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
299
+ // x^8+x^5+x^4+1 = 0x31
300
+ uint8_t SGP30::_CRC8 (uint16_t data)
301
+ {
302
+ uint8_t crc = 0xFF ; // Init with 0xFF
303
+
304
+ crc ^= (data >> 8 ); // XOR-in the first input byte
305
+
306
+ for (uint8_t i = 0 ; i < 8 ; i++)
307
+ {
308
+ if ((crc & 0x80 ) != 0 )
309
+ crc = (uint8_t )((crc << 1 ) ^ 0x31 );
310
+ else
311
+ crc <<= 1 ;
312
+ }
313
+ crc ^= (uint8_t )data; // XOR-in the last input byte
314
+
315
+ for (uint8_t i = 0 ; i < 8 ; i++)
316
+ {
317
+ if ((crc & 0x80 ) != 0 )
318
+ crc = (uint8_t )((crc << 1 ) ^ 0x31 );
319
+ else
320
+ crc <<= 1 ;
321
+ }
322
+
323
+ return crc; // No output reflection
324
+ }
325
+ #endif
326
+
327
+ #ifdef LOOKUP_TABLE
307
328
// Generates CRC8 for SGP30 from lookup table
308
- uint8_t SGP30::_CRC8 (uint16_t twoBytes ) {
329
+ uint8_t SGP30::_CRC8 (uint16_t data ) {
309
330
uint8_t CRC = 0xFF ; // inital value
310
- CRC ^= (uint8_t )(twoBytes >> 8 ); // start with MSB
331
+ CRC ^= (uint8_t )(data >> 8 ); // start with MSB
311
332
CRC = _CRC8LookupTable[CRC >> 4 ][CRC & 0xF ]; // look up table [MSnibble][LSnibble]
312
- CRC ^= (uint8_t )twoBytes ; // use LSB
333
+ CRC ^= (uint8_t )data ; // use LSB
313
334
CRC = _CRC8LookupTable[CRC >> 4 ][CRC & 0xF ]; // look up table [MSnibble][LSnibble]
314
335
return CRC;
315
336
}
316
-
337
+ # endif
317
338
318
339
0 commit comments