Skip to content

Commit 8959d28

Browse files
konrad1skartben
authored andcommitted
drivers: sensor: Fixed issues in DHT20 measurement
Refactor DHT20 sensor init and measurement handling. Added 100ms power-on wait to comply with datasheet. Simplified measurement frame handling. Initialize status register only once after power-on. Signed-off-by: Konrad Sikora <kontakt@konradsikora.pl>
1 parent e1f4181 commit 8959d28

File tree

1 file changed

+47
-48
lines changed

1 file changed

+47
-48
lines changed

drivers/sensor/aosong/dht20/dht20.c

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818

1919
#define DHT20_STATUS_MASK (BIT(0) | BIT(1))
2020

21-
#define DHT20_STATUS_MASK_CHECK 0x18
22-
#define DHT20_STATUS_MASK_POLL_STATE 0x80
21+
#define DHT20_STATUS_MASK_CHECK 0x18
2322

2423
#define DHT20_MASK_RESET_REGISTER 0xB0
2524

@@ -38,16 +37,24 @@
3837
#define DHT20_RESET_REGISTER_1 0x1C
3938
#define DHT20_RESET_REGISTER_2 0x1E
4039

41-
/** Length of the buffer used for data measurement */
42-
#define DHT20_MEASUREMENT_BUFFER_LENGTH 7
40+
/** Measurement frame data indexes */
41+
#define DHT20_MEAS_STATUS_IDX 0
42+
#define DHT20_MEAS_HUMIDITY_IDX 1
43+
#define DHT20_MEAS_HUM_TEMP_IDX 3
44+
#define DHT20_MEAS_TEMPERATURE_IDX 4
45+
#define DHT20_MEAS_CRC_IDX 6
46+
#define DHT20_MEAS_FRAME_LENGTH 7
4347

44-
/** Wait some time after reset sequence (in ms) */
45-
#define DHT20_RESET_SEQUENCE_WAIT_MS 10
48+
#define DHT20_STATUS_BUSY_BIT BIT(7)
49+
#define DHT20_IS_STATUS_BUSY(status) ((status) & DHT20_STATUS_BUSY_BIT)
4650

47-
/** Wait after power on (in ms) */
48-
#define DHT20_POWER_ON_WAIT_MS 75
49-
/** Wait during polling after power on (in ms) */
50-
#define DHT20_INIT_POLL_STATUS_WAIT_MS 5
51+
/** Wait some time after status reset sequence (in ms) */
52+
#define DHT20_STATUS_RESET_SEQUENCE_WAIT_MS 10
53+
54+
/* According to datasheet 7.4: Wait time after power-on should be at least 100ms */
55+
#define DHT20_POWER_ON_WAIT_TIME_MS 100
56+
/** Wait for the measurement to be completed (in ms) */
57+
#define DHT20_MEASUREMENT_TIME_MS 80
5158

5259
LOG_MODULE_REGISTER(DHT20, CONFIG_SENSOR_LOG_LEVEL);
5360

@@ -75,15 +82,9 @@ static inline int read_status(const struct device *dev, uint8_t *status)
7582
uint8_t rx_buf[1];
7683

7784
/* Write DHT20_STATUS_REGISTER then read to get status */
78-
rc = i2c_write_dt(&cfg->bus, tx_buf, sizeof(tx_buf));
79-
if (rc < 0) {
80-
LOG_ERR("Failed to start measurement.");
81-
return rc;
82-
}
83-
84-
rc = i2c_read_dt(&cfg->bus, rx_buf, sizeof(rx_buf));
85+
rc = i2c_write_read_dt(&cfg->bus, tx_buf, sizeof(tx_buf), &rx_buf, sizeof(rx_buf));
8586
if (rc < 0) {
86-
LOG_ERR("Failed to read data from device.");
87+
LOG_ERR("Failed to read status register.");
8788
return rc;
8889
}
8990

@@ -119,7 +120,7 @@ static inline int reset_register(const struct device *dev, uint8_t reg)
119120
return rc;
120121
}
121122

122-
static inline int reset_sensor(const struct device *dev)
123+
static inline int initialize_status_register(const struct device *dev)
123124
{
124125
int rc;
125126
uint8_t status;
@@ -147,16 +148,15 @@ static inline int reset_sensor(const struct device *dev)
147148
if (rc < 0) {
148149
return rc;
149150
}
150-
/* Wait 10ms after reset sequence */
151-
k_msleep(DHT20_RESET_SEQUENCE_WAIT_MS);
151+
/* Wait 10ms after status reset sequence */
152+
k_msleep(DHT20_STATUS_RESET_SEQUENCE_WAIT_MS);
152153
}
153154

154155
return 0;
155156
}
156157

157-
static int dht20_read_sample(const struct device *dev, uint32_t *t_sample, uint32_t *rh_sample)
158+
static int dht20_read_sample(const struct dht20_config *cfg, struct dht20_data *data)
158159
{
159-
const struct dht20_config *cfg = dev->config;
160160
/*
161161
* Datasheet shows content of the measurement data as follow
162162
*
@@ -172,32 +172,36 @@ static int dht20_read_sample(const struct device *dev, uint32_t *t_sample, uint3
172172
* | 6 | CRC |
173173
* +------+----------------------------------------+
174174
*/
175-
uint8_t rx_buf[DHT20_MEASUREMENT_BUFFER_LENGTH];
175+
176+
uint8_t rx_buf[DHT20_MEAS_FRAME_LENGTH];
176177
int rc;
177-
uint8_t status;
178178

179179
rc = i2c_read_dt(&cfg->bus, rx_buf, sizeof(rx_buf));
180180
if (rc < 0) {
181-
LOG_ERR("Failed to read data from device.");
181+
LOG_ERR("Failed to read measurement frame.");
182182
return rc;
183183
}
184184

185-
status = rx_buf[0];
185+
if (DHT20_IS_STATUS_BUSY(rx_buf[DHT20_MEAS_STATUS_IDX])) {
186+
LOG_WRN("Sensor measurement is not ready");
187+
return -EBUSY;
188+
}
189+
186190
/* Extract 20 bits for humidity data */
187-
*rh_sample = sys_get_be24(&rx_buf[1]) >> 4;
191+
data->rh_sample = sys_get_be24(&rx_buf[DHT20_MEAS_HUMIDITY_IDX]) >> 4;
188192
/* Extract 20 bits for temperature data */
189-
*t_sample = sys_get_be24(&rx_buf[3]) & 0x0FFFFF;
193+
data->t_sample = sys_get_be24(&rx_buf[DHT20_MEAS_HUM_TEMP_IDX]) & 0x0FFFFF;
190194

191195
#if defined(CONFIG_DHT20_CRC)
192196
/* Compute and check CRC with last byte of measurement data */
193197
uint8_t crc = crc8(rx_buf, 6, DHT20_CRC_POLYNOM, 0xFF, false);
194198

195-
if (crc != rx_buf[6]) {
196-
rc = -EIO;
199+
if (crc != rx_buf[DHT20_MEAS_CRC_IDX]) {
200+
return -EIO;
197201
}
198202
#endif
199203

200-
return rc;
204+
return 0;
201205
}
202206

203207
static int dht20_sample_fetch(const struct device *dev, enum sensor_channel chan)
@@ -207,16 +211,12 @@ static int dht20_sample_fetch(const struct device *dev, enum sensor_channel chan
207211
int rc;
208212
uint8_t tx_buf[DHT20_TRIGGER_MEASUREMENT_BUFFER_LENGTH] = {
209213
DHT20_TRIGGER_MEASUREMENT_COMMAND};
210-
uint8_t status;
211214

212215
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP &&
213216
chan != SENSOR_CHAN_HUMIDITY) {
214217
return -ENOTSUP;
215218
}
216219

217-
/* Reset sensor if needed */
218-
reset_sensor(dev);
219-
220220
/* Send trigger measurement command */
221221
rc = i2c_write_dt(&cfg->bus, tx_buf, sizeof(tx_buf));
222222
if (rc < 0) {
@@ -228,19 +228,9 @@ static int dht20_sample_fetch(const struct device *dev, enum sensor_channel chan
228228
* According to datasheet maximum time to make temperature and humidity
229229
* measurements is 80ms
230230
*/
231-
k_msleep(DHT20_POWER_ON_WAIT_MS);
232-
233-
do {
234-
k_msleep(DHT20_INIT_POLL_STATUS_WAIT_MS);
235-
236-
rc = read_status(dev, &status);
237-
if (rc < 0) {
238-
LOG_ERR("Failed to read status.");
239-
return rc;
240-
}
241-
} while ((status & DHT20_STATUS_MASK_POLL_STATE) != 0);
231+
k_msleep(DHT20_MEASUREMENT_TIME_MS);
242232

243-
rc = dht20_read_sample(dev, &data->t_sample, &data->rh_sample);
233+
rc = dht20_read_sample(cfg, data);
244234
if (rc < 0) {
245235
LOG_ERR("Failed to fetch data.");
246236
return rc;
@@ -298,12 +288,21 @@ static int dht20_channel_get(const struct device *dev, enum sensor_channel chan,
298288
static int dht20_init(const struct device *dev)
299289
{
300290
const struct dht20_config *cfg = dev->config;
291+
int rc;
301292

302293
if (!i2c_is_ready_dt(&cfg->bus)) {
303294
LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name);
304295
return -ENODEV;
305296
}
306297

298+
k_msleep(DHT20_POWER_ON_WAIT_TIME_MS);
299+
300+
rc = initialize_status_register(dev);
301+
if (rc < 0) {
302+
LOG_ERR("Failed to initialize status register.");
303+
return rc;
304+
}
305+
307306
return 0;
308307
}
309308

0 commit comments

Comments
 (0)