26
26
#include < SparkFun_Qwiic_Humidity_AHT20.h>
27
27
28
28
/* --------------------------- Device Status ------------------------------*/
29
- bool AHT20::begin (uint8_t address, TwoWire &wirePort)
29
+ bool AHT20::begin (TwoWire &wirePort)
30
30
{
31
- _deviceAddress = address; // Grab the address that the humidity sensor is on
32
- _i2cPort = &wirePort; // Grab the port the user wants to communicate on
31
+ _i2cPort = &wirePort; // Grab the port the user wants to communicate on
33
32
34
- // DEBUGGING: do we need to do this?!
35
- // We need to wait 20 ms at power on for sensor to receive commands
36
- // Datasheet pg 7
37
- delay (20 );
33
+ _deviceAddress = AHT20_DEFAULT_ADDRESS; // We had hoped the AHT20 would support two addresses but it doesn't seem to
38
34
39
35
if (isConnected () == false )
40
36
return false ;
41
37
38
+ // Wait 40 ms after power-on before reading temp or humidity. Datasheet pg 8
39
+ delay (40 );
40
+
41
+ // Check if the calibrated bit is set. If not, init the sensor.
42
+ if (isCalibrated () == false )
43
+ {
44
+ // Send 0xBE0800
45
+ initialize ();
46
+
47
+ // Immediately trigger a measurement. Send 0xAC3300
48
+ triggerMeasurement ();
49
+
50
+ delay (75 ); // Wait for measurement to complete
51
+
52
+ uint8_t counter = 0 ;
53
+ while (isBusy ())
54
+ {
55
+ delay (1 );
56
+ if (counter++ > 100 )
57
+ return (false ); // Give up after 100ms
58
+ }
59
+
60
+ // This calibration sequence is not completely proven. It's not clear how and when the cal bit clears
61
+ // This seems to work but it's not easily testable
62
+ if (isCalibrated () == false )
63
+ {
64
+ return (false );
65
+ }
66
+ }
67
+
68
+ // Check that the cal bit has been set
69
+ if (isCalibrated () == false )
70
+ return false ;
71
+
72
+ // Mark all datums as fresh (not read before)
73
+ sensorQueried.temperature = true ;
74
+ sensorQueried.humidity = true ;
75
+
42
76
return true ;
43
77
}
44
78
@@ -49,51 +83,46 @@ bool AHT20::isConnected()
49
83
_i2cPort->beginTransmission (_deviceAddress);
50
84
if (_i2cPort->endTransmission () == 0 )
51
85
return true ;
86
+
87
+ // If IC failed to respond, give it 20ms more for Power On Startup
88
+ // Datasheet pg 7
89
+ delay (20 );
90
+
91
+ _i2cPort->beginTransmission (_deviceAddress);
92
+ if (_i2cPort->endTransmission () == 0 )
93
+ return true ;
94
+
52
95
return false ;
53
96
}
54
97
55
98
/* ------------------------ Measurement Helpers ---------------------------*/
56
99
57
100
uint8_t AHT20::getStatus ()
58
101
{
59
- uint8_t stat;
60
- _i2cPort->requestFrom (_deviceAddress, 1 );
61
- while (_i2cPort->available ())
62
- {
63
- stat = _i2cPort->read ();
64
- }
65
- return stat;
102
+ _i2cPort->requestFrom (_deviceAddress, (uint8_t )1 );
103
+ if (_i2cPort->available ())
104
+ return (_i2cPort->read ());
105
+ return (0 );
66
106
}
67
107
68
108
// Returns the state of the cal bit in the status byte
69
- bool AHT20::checkCalBit ( uint8_t stat )
109
+ bool AHT20::isCalibrated ( )
70
110
{
71
- // Check that the third status bit is a 1
72
- // The third bit is the CAL enable bit
73
- uint8_t temp = 1 ;
74
- temp = temp << 3 ;
75
- if (stat & temp)
76
- return true ; // AHT20 has been callibrated
77
- return false ; // AHT20 has not been callibrated
111
+ return (getStatus () & (1 << 3 ));
78
112
}
79
113
80
114
// Returns the state of the busy bit in the status byte
81
- bool AHT20::checkBusyBit ( uint8_t stat )
115
+ bool AHT20::isBusy ( )
82
116
{
83
- // Check that the seventh status bit is a 1
84
- // The seventh bit is the busy indication bit
85
- uint8_t temp = 1 ;
86
- temp = temp << 7 ;
87
- if (stat & temp)
88
- return true ; // AHT20 is busy taking a measurement
89
- return false ; // AHT20 is not busy
117
+ return (getStatus () & (1 << 7 ));
90
118
}
91
119
92
120
bool AHT20::initialize ()
93
- {
121
+ {
94
122
_i2cPort->beginTransmission (_deviceAddress);
95
- _i2cPort->write (INITIALIZATION);
96
- _i2cPort->write ((uint8_t *)INIT_CMD, 2 );
123
+ _i2cPort->write (sfe_aht20_reg_initialize);
124
+ _i2cPort->write (0x80 );
125
+ _i2cPort->write (0x00 );
97
126
if (_i2cPort->endTransmission () == 0 )
98
127
return true ;
99
128
return false ;
@@ -102,94 +131,73 @@ bool AHT20::initialize()
102
131
bool AHT20::triggerMeasurement ()
103
132
{
104
133
_i2cPort->beginTransmission (_deviceAddress);
105
- _i2cPort->write (MEASUREMENT);
106
- _i2cPort->write ((uint8_t *)MEAS_CMD, 2 );
134
+ _i2cPort->write (sfe_aht20_reg_measure);
135
+ _i2cPort->write (0x33 );
136
+ _i2cPort->write (0x00 );
107
137
if (_i2cPort->endTransmission () == 0 )
108
138
return true ;
109
139
return false ;
110
140
}
111
141
112
- // Read and return six bytes of data
113
- dataStruct AHT20::readData ()
142
+ // Loads the
143
+ void AHT20::readData ()
114
144
{
115
- raw_data data;
145
+ // Clear previous data
146
+ sensorData.temperature = 0 ;
147
+ sensorData.humidity = 0 ;
116
148
117
- if (_i2cPort->requestFrom (_deviceAddress, 6 ) > 0 )
149
+ if (_i2cPort->requestFrom (_deviceAddress, ( uint8_t ) 6 ) > 0 )
118
150
{
119
151
uint8_t state = _i2cPort->read ();
120
- // Serial.print("State: 0x");
121
- // Serial.println(state, HEX);
122
152
123
153
uint32_t incoming = 0 ;
124
154
incoming |= (uint32_t )_i2cPort->read () << (8 * 2 );
125
- // Serial.println(incoming, HEX);
126
155
incoming |= (uint32_t )_i2cPort->read () << (8 * 1 );
127
- // Serial.println(incoming, HEX);
128
156
uint8_t midByte = _i2cPort->read ();
129
157
130
- incoming |= midByte << (8 * 0 );
131
- // Serial.println(incoming, HEX);
132
- data.humidity = incoming >> 4 ;
133
- // Serial.println(data.humidity, HEX);
134
- // Serial.println("Read-in humidity correct, I think?");
158
+ incoming |= midByte;
159
+ sensorData.humidity = incoming >> 4 ;
135
160
136
- data.temperature = (uint32_t )midByte << (8 * 2 );
137
- // Serial.println(data.temperature, HEX);
138
- data.temperature |= (uint32_t )_i2cPort->read () << (8 * 1 );
139
- // Serial.println(data.temperature, HEX);
140
- data.temperature |= (uint32_t )_i2cPort->read () << (8 * 0 );
141
- // Serial.println(data.temperature, HEX);
161
+ sensorData.temperature = (uint32_t )midByte << (8 * 2 );
162
+ sensorData.temperature |= (uint32_t )_i2cPort->read () << (8 * 1 );
163
+ sensorData.temperature |= (uint32_t )_i2cPort->read () << (8 * 0 );
142
164
143
165
// Need to get rid of data in bits > 20
144
- data.temperature = data.temperature & ~(0xFFF00000 );
145
- // Serial.println(data.temperature, HEX);
146
- // Serial.println("Read-in temperature correct, too.");
147
- }
148
-
149
- // Serial.println("Read-in AHT20 raw data");
150
- // Serial.print("Raw temp: 0x");
151
- // Serial.println(data.temperature, HEX);
152
- // Serial.print("Raw humidity: 0x");
153
- // Serial.println(data.humidity, HEX);
154
- // Serial.println();
166
+ sensorData.temperature = sensorData.temperature & ~(0xFFF00000 );
155
167
156
- return data;
168
+ // Mark data as fresh
169
+ sensorQueried.temperature = false ;
170
+ sensorQueried.humidity = false ;
171
+ }
157
172
}
158
173
159
- // Returns temperature in degrees celcius
160
- float AHT20::calculateTemperature (dataStruct data)
174
+ // Triggers a measurement if one has not been previously started, then returns false
175
+ // If measurement has been started, checks to see if complete.
176
+ // If not complete, returns false
177
+ // If complete, readData(), mark measurement as not started, return true
178
+ bool AHT20::available ()
161
179
{
162
- float tempCelcius;
163
- // From datasheet pg 8
164
- tempCelcius = ((float )data.temperature / 1048576 ) * 200 - 50 ;
165
-
166
- // //DEBUGGING
167
- // float relHumidity;
168
- // relHumidity = ((float)data.humidity / 1048576) * 100;
169
- // //Print the result
170
- // Serial.print("Temperature: ");
171
- // Serial.print(tempCelcius);
172
- // Serial.print(" C \t Humidity: ");
173
- // Serial.print(relHumidity);
174
- // Serial.println("% RH");
175
- // Serial.println();
176
-
177
- return tempCelcius;
178
- }
180
+ if (measurementStarted == false )
181
+ {
182
+ triggerMeasurement ();
183
+ measurementStarted = true ;
184
+ return (false );
185
+ }
179
186
180
- // Returns humidity in %RH
181
- float AHT20::calculateHumidity (dataStruct data)
182
- {
183
- float relHumidity;
184
- // From datasheet pg 8
185
- relHumidity = ((float )data.humidity / 1048576 ) * 100 ;
186
- return relHumidity;
187
+ if (isBusy () == true )
188
+ {
189
+ return (false );
190
+ }
191
+
192
+ readData ();
193
+ measurementStarted = false ;
194
+ return (true );
187
195
}
188
196
189
197
bool AHT20::softReset ()
190
198
{
191
199
_i2cPort->beginTransmission (_deviceAddress);
192
- _i2cPort->write (RESET );
200
+ _i2cPort->write (sfe_aht20_reg_reset );
193
201
if (_i2cPort->endTransmission () == 0 )
194
202
return true ;
195
203
return false ;
@@ -199,204 +207,58 @@ bool AHT20::softReset()
199
207
200
208
float AHT20::getTemperature ()
201
209
{
202
- float temperature;
203
-
204
- // Wait 40 ms - datasheet pg 8
205
- delay (40 );
206
-
207
- // Check calibration bit of status byte
208
- uint8_t status;
209
- status = getStatus ();
210
- // DEBUGGING
211
- // Serial.print("State: 0x");
212
- // Serial.println(status, HEX);
213
- if (checkCalBit (status))
210
+ if (sensorQueried.temperature == true )
214
211
{
215
- // Continue
216
- // Serial.println("AHT20 callibrated!");
217
-
218
- // Initialize
219
- initialize ();
220
- // Serial.println("AHT20 has been initialized.");
221
-
222
- // Trigger measurement
212
+ // We've got old data so trigger new measurement
223
213
triggerMeasurement ();
224
- // Serial.println("AHT20 measurement has been triggered.");
225
-
226
- // Wait 100 ms
227
- // DEBUG: turn this into an available() function??
228
- // Serial.println("Wait 100 ms");
229
- delay (400 );
230
-
231
- // Check the busy bit
232
- status = getStatus ();
233
- // DEBUGGING
234
- // Serial.print("State: 0x");
235
- // Serial.println(status, HEX);
236
- if (!checkBusyBit (status))
237
- {
238
- // Continue
239
- // Serial.println("AHT20 not busy. Continue.");
240
214
241
- raw_data newData = readData ();
242
- temperature = calculateTemperature (newData);
243
- }
244
- else
215
+ delay ( 75 ); // Wait for measurement to complete
216
+
217
+ uint8_t counter = 0 ;
218
+ while ( isBusy ())
245
219
{
246
- // Serial.println("Can't continue. AHT20 indicating busy taking measurement. Freezing.");
247
- while (1 );
220
+ delay (1 );
221
+ if (counter++ > 100 )
222
+ return (false ); // Give up after 100ms
248
223
}
224
+
225
+ readData ();
249
226
}
250
- else
251
- {
252
- // Serial.println("Chip not callibrated! Freezing.");
253
- while (1 );
254
- }
255
227
256
- return temperature;
228
+ // From datasheet pg 8
229
+ float tempCelsius = ((float )sensorData.temperature / 1048576 ) * 200 - 50 ;
230
+
231
+ // Mark data as old
232
+ sensorQueried.temperature = true ;
233
+
234
+ return tempCelsius;
257
235
}
258
236
259
237
float AHT20::getHumidity ()
260
238
{
261
- float humidity;
262
-
263
- // Wait 40 ms - datasheet pg 8
264
- delay (40 );
265
-
266
- // Check calibration bit of status byte
267
- uint8_t status;
268
- status = getStatus ();
269
- // DEBUGGING
270
- // Serial.print("State: 0x");
271
- // Serial.println(status, HEX);
272
- if (checkCalBit (status))
239
+ if (sensorQueried.humidity == true )
273
240
{
274
- // Continue
275
- // Serial.println("AHT20 callibrated!");
276
-
277
- // Initialize
278
- initialize ();
279
- Serial.println (" AHT20 has been initialized." );
280
-
281
- // Trigger measurement
241
+ // We've got old data so trigger new measurement
282
242
triggerMeasurement ();
283
- Serial.println (" AHT20 measurement has been triggered." );
284
-
285
- // Wait 100 ms
286
- // DEBUG: turn this into an available() function??
287
- Serial.println (" Wait 100 ms" );
288
- delay (400 );
289
-
290
- // Check the busy bit
291
- status = getStatus ();
292
- // DEBUGGING
293
- Serial.print (" State: 0x" );
294
- Serial.println (status, HEX);
295
- if (!checkBusyBit (status))
296
- {
297
- // Continue
298
- Serial.println (" AHT20 not busy. Continue." );
299
243
300
- raw_data newData = readData ();
301
- humidity = calculateHumidity (newData);
302
- }
303
- else
244
+ delay ( 75 ); // Wait for measurement to complete
245
+
246
+ uint8_t counter = 0 ;
247
+ while ( isBusy ())
304
248
{
305
- Serial.println (" Can't continue. AHT20 indicating busy taking measurement. Freezing." );
306
- while (1 );
249
+ delay (1 );
250
+ if (counter++ > 100 )
251
+ return (false ); // Give up after 100ms
307
252
}
253
+
254
+ readData ();
308
255
}
309
- else
310
- {
311
- Serial.println (" Chip not callibrated! Freezing." );
312
- while (1 );
313
- }
314
-
315
- return humidity;
316
- }
317
256
318
- // float AHT20::getTemperature()
319
- // {
320
- // //wait 40 ms - datasheet pg 8
321
- // delay(40);
322
-
323
- // //Check the calibration bit of the status byte
324
- // uint8_t status;
325
- // status = getStatus();
326
- // if (checkCalBit(status))
327
- // {
328
- // //Continue with the measurement sequence
329
-
330
- // //Send initialization bytes
331
- // initialize();
332
-
333
- // //Signal ready to take measurement
334
- // triggerMeasurement();
335
-
336
- // //wait 100 ms for measurement to complete - datasheet pg 8
337
- // delay(100);
338
-
339
- // //Get status again and check that AHT20 is NOT still busy measuring
340
- // status = getStatus();
341
- // if (!checkBusyBit(status))
342
- // {
343
- // //Continue with measurement sequence
344
-
345
- // //Read next six bytes (data)
346
- // raw_data data = readData();
347
-
348
- // //Convert to temperature in celcius
349
- // float temp = calculateTemperature(data);
350
-
351
- // return temp;
352
- // }
353
- // }
354
-
355
- // Serial.println("I've failed!");
356
-
357
- // //Else, fail
358
- // return 0;
359
- // }
360
-
361
- // float AHT20::getHumidity()
362
- // {
363
- // //Wait 40 ms - datasheet pg 8
364
- // delay(40);
365
-
366
- // //Check the calibration bit of the status byte
367
- // uint8_t status;
368
- // status = getStatus();
369
- // if (checkCalBit(status))
370
- // {
371
- // //Continue with the measurement sequence
372
-
373
- // //Send the initialization bytes
374
- // initialize();
375
-
376
- // //Signal ready to take measurement
377
- // triggerMeasurement();
378
-
379
- // //wait 100 ms for measurement to complete - datasheet pg 8
380
- // delay(100);
381
-
382
- // //Get status again and check that AHT20 is NOT still busy measuring
383
- // status = getStatus();
384
- // if (!checkBusyBit(status))
385
- // {
386
- // //Continue with measurement sequence
387
-
388
- // //Read next six bytes (data)
389
- // raw_data data = readData();
390
-
391
- // //Convert to % RH
392
- // float humidity = calculateHumidity(data);
393
-
394
- // return humidity;
395
- // }
396
- // }
397
-
398
- // Serial.println("I've failed!");
399
-
400
- // //Else, fail
401
- // return 0;
402
- // }
257
+ // From datasheet pg 8
258
+ float relHumidity = ((float )sensorData.humidity / 1048576 ) * 100 ;
259
+
260
+ // Mark data as old
261
+ sensorQueried.humidity = true ;
262
+
263
+ return relHumidity;
264
+ }
0 commit comments