1 /* bme280.c - Driver for Bosch BME280 temperature and pressure sensor */
2
3 /*
4 * Copyright (c) 2016, 2017 Intel Corporation
5 * Copyright (c) 2017 IpTronix S.r.l.
6 * Copyright (c) 2021 Nordic Semiconductor ASA
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/drivers/sensor.h>
13 #include <zephyr/init.h>
14 #include <zephyr/drivers/gpio.h>
15 #include <zephyr/pm/device.h>
16 #include <zephyr/sys/byteorder.h>
17 #include <zephyr/sys/__assert.h>
18
19 #include <zephyr/logging/log.h>
20
21 #include "bme280.h"
22
23 LOG_MODULE_REGISTER(BME280, CONFIG_SENSOR_LOG_LEVEL);
24
25 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
26 #warning "BME280 driver enabled without any devices"
27 #endif
28
29 /* Maximum oversampling rate on each channel is 16x.
30 * Maximum measurement time is given by (Datasheet appendix B 9.1):
31 * 1.25 + [2.3 * T_over] + [2.3 * P_over + 0.575] + [2.3 * H_over + 0.575]
32 * = 112.8 ms
33 */
34 #define BME280_MEASUREMENT_TIMEOUT_MS 150
35
36 /* Equation 9.1, with the fractional parts rounded down */
37 #define BME280_EXPECTED_SAMPLE_TIME_MS \
38 1 + BME280_TEMP_SAMPLE_TIME + BME280_PRESS_SAMPLE_TIME + BME280_HUMIDITY_SAMPLE_TIME
39
40 BUILD_ASSERT(BME280_EXPECTED_SAMPLE_TIME_MS < BME280_MEASUREMENT_TIMEOUT_MS,
41 "Expected duration over timeout duration");
42
43 struct bme280_config {
44 union bme280_bus bus;
45 const struct bme280_bus_io *bus_io;
46 };
47
bme280_bus_check(const struct device * dev)48 static inline int bme280_bus_check(const struct device *dev)
49 {
50 const struct bme280_config *cfg = dev->config;
51
52 return cfg->bus_io->check(&cfg->bus);
53 }
54
bme280_reg_read(const struct device * dev,uint8_t start,uint8_t * buf,int size)55 static inline int bme280_reg_read(const struct device *dev,
56 uint8_t start, uint8_t *buf, int size)
57 {
58 const struct bme280_config *cfg = dev->config;
59
60 return cfg->bus_io->read(&cfg->bus, start, buf, size);
61 }
62
bme280_reg_write(const struct device * dev,uint8_t reg,uint8_t val)63 static inline int bme280_reg_write(const struct device *dev, uint8_t reg,
64 uint8_t val)
65 {
66 const struct bme280_config *cfg = dev->config;
67
68 return cfg->bus_io->write(&cfg->bus, reg, val);
69 }
70
71 /*
72 * Compensation code taken from BME280 datasheet, Section 4.2.3
73 * "Compensation formula".
74 */
bme280_compensate_temp(struct bme280_data * data,int32_t adc_temp)75 static int32_t bme280_compensate_temp(struct bme280_data *data, int32_t adc_temp)
76 {
77 int32_t var1, var2;
78
79 var1 = (((adc_temp >> 3) - ((int32_t)data->dig_t1 << 1)) *
80 ((int32_t)data->dig_t2)) >> 11;
81 var2 = (((((adc_temp >> 4) - ((int32_t)data->dig_t1)) *
82 ((adc_temp >> 4) - ((int32_t)data->dig_t1))) >> 12) *
83 ((int32_t)data->dig_t3)) >> 14;
84
85 data->t_fine = var1 + var2;
86 return (data->t_fine * 5 + 128) >> 8;
87 }
88
bme280_compensate_press(struct bme280_data * data,int32_t adc_press)89 static uint32_t bme280_compensate_press(struct bme280_data *data, int32_t adc_press)
90 {
91 int64_t var1, var2, p;
92
93 var1 = ((int64_t)data->t_fine) - 128000;
94 var2 = var1 * var1 * (int64_t)data->dig_p6;
95 var2 = var2 + ((var1 * (int64_t)data->dig_p5) << 17);
96 var2 = var2 + (((int64_t)data->dig_p4) << 35);
97 var1 = ((var1 * var1 * (int64_t)data->dig_p3) >> 8) +
98 ((var1 * (int64_t)data->dig_p2) << 12);
99 var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)data->dig_p1) >> 33;
100
101 /* Avoid exception caused by division by zero. */
102 if (var1 == 0) {
103 return 0;
104 }
105
106 p = 1048576 - adc_press;
107 p = (((p << 31) - var2) * 3125) / var1;
108 var1 = (((int64_t)data->dig_p9) * (p >> 13) * (p >> 13)) >> 25;
109 var2 = (((int64_t)data->dig_p8) * p) >> 19;
110 p = ((p + var1 + var2) >> 8) + (((int64_t)data->dig_p7) << 4);
111
112 return (uint32_t)p;
113 }
114
bme280_compensate_humidity(struct bme280_data * data,int32_t adc_humidity)115 static uint32_t bme280_compensate_humidity(struct bme280_data *data,
116 int32_t adc_humidity)
117 {
118 int32_t h;
119
120 h = (data->t_fine - ((int32_t)76800));
121 h = ((((adc_humidity << 14) - (((int32_t)data->dig_h4) << 20) -
122 (((int32_t)data->dig_h5) * h)) + ((int32_t)16384)) >> 15) *
123 (((((((h * ((int32_t)data->dig_h6)) >> 10) * (((h *
124 ((int32_t)data->dig_h3)) >> 11) + ((int32_t)32768))) >> 10) +
125 ((int32_t)2097152)) * ((int32_t)data->dig_h2) + 8192) >> 14);
126 h = (h - (((((h >> 15) * (h >> 15)) >> 7) *
127 ((int32_t)data->dig_h1)) >> 4));
128 h = (h > 419430400 ? 419430400 : h);
129
130 return (uint32_t)(h >> 12);
131 }
132
bme280_wait_until_ready(const struct device * dev,k_timeout_t timeout)133 static int bme280_wait_until_ready(const struct device *dev, k_timeout_t timeout)
134 {
135 k_timepoint_t end = sys_timepoint_calc(timeout);
136 uint8_t status;
137 int ret;
138
139 /* Wait for relevant flags to clear */
140 while (1) {
141 ret = bme280_reg_read(dev, BME280_REG_STATUS, &status, 1);
142 if (ret < 0) {
143 return ret;
144 }
145 if (!(status & (BME280_STATUS_MEASURING | BME280_STATUS_IM_UPDATE))) {
146 break;
147 }
148 /* Check if waiting has timed out */
149 if (sys_timepoint_expired(end)) {
150 return -EAGAIN;
151 }
152 k_sleep(K_MSEC(3));
153 }
154
155 return 0;
156 }
157
bme280_sample_fetch_helper(const struct device * dev,enum sensor_channel chan,struct bme280_reading * reading)158 int bme280_sample_fetch_helper(const struct device *dev,
159 enum sensor_channel chan, struct bme280_reading *reading)
160 {
161 struct bme280_data *dev_data = dev->data;
162 uint8_t buf[8];
163 int32_t adc_press, adc_temp, adc_humidity;
164 uint32_t poll_timeout;
165 int size = 6;
166 int ret;
167
168 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);
169
170 #ifdef CONFIG_PM_DEVICE
171 enum pm_device_state state;
172 (void)pm_device_state_get(dev, &state);
173 /* Do not allow sample fetching from suspended state */
174 if (state == PM_DEVICE_STATE_SUSPENDED) {
175 return -EIO;
176 }
177 #endif
178
179 #ifdef CONFIG_BME280_MODE_FORCED
180 ret = bme280_reg_write(dev, BME280_REG_CTRL_MEAS, BME280_CTRL_MEAS_VAL);
181 if (ret < 0) {
182 return ret;
183 }
184 /* Wait until the expected measurement time elapses */
185 k_sleep(K_MSEC(BME280_EXPECTED_SAMPLE_TIME_MS));
186 poll_timeout = BME280_MEASUREMENT_TIMEOUT_MS - BME280_EXPECTED_SAMPLE_TIME_MS;
187 #else
188 poll_timeout = BME280_MEASUREMENT_TIMEOUT_MS;
189 #endif
190
191 ret = bme280_wait_until_ready(dev, K_MSEC(poll_timeout));
192 if (ret < 0) {
193 return ret;
194 }
195
196 if (dev_data->chip_id == BME280_CHIP_ID) {
197 size = 8;
198 }
199 ret = bme280_reg_read(dev, BME280_REG_PRESS_MSB, buf, size);
200 if (ret < 0) {
201 return ret;
202 }
203
204 adc_press = (buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4);
205 adc_temp = (buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4);
206
207 reading->comp_temp = bme280_compensate_temp(dev_data, adc_temp);
208 reading->comp_press = bme280_compensate_press(dev_data, adc_press);
209
210 if (dev_data->chip_id == BME280_CHIP_ID) {
211 adc_humidity = (buf[6] << 8) | buf[7];
212 reading->comp_humidity = bme280_compensate_humidity(dev_data, adc_humidity);
213 }
214
215 return 0;
216 }
217
bme280_sample_fetch(const struct device * dev,enum sensor_channel chan)218 int bme280_sample_fetch(const struct device *dev, enum sensor_channel chan)
219 {
220 struct bme280_data *data = dev->data;
221
222 return bme280_sample_fetch_helper(dev, chan, &data->reading);
223 }
224
bme280_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)225 static int bme280_channel_get(const struct device *dev,
226 enum sensor_channel chan,
227 struct sensor_value *val)
228 {
229 struct bme280_data *data = dev->data;
230
231 switch (chan) {
232 case SENSOR_CHAN_AMBIENT_TEMP:
233 /*
234 * comp_temp has a resolution of 0.01 degC. So
235 * 5123 equals 51.23 degC.
236 */
237 val->val1 = data->reading.comp_temp / 100;
238 val->val2 = data->reading.comp_temp % 100 * 10000;
239 break;
240 case SENSOR_CHAN_PRESS:
241 /*
242 * comp_press has 24 integer bits and 8
243 * fractional. Output value of 24674867 represents
244 * 24674867/256 = 96386.2 Pa = 963.862 hPa
245 */
246 val->val1 = (data->reading.comp_press >> 8) / 1000U;
247 val->val2 = (data->reading.comp_press >> 8) % 1000 * 1000U +
248 (((data->reading.comp_press & 0xff) * 1000U) >> 8);
249 break;
250 case SENSOR_CHAN_HUMIDITY:
251 /* The BMP280 doesn't have a humidity sensor */
252 if (data->chip_id != BME280_CHIP_ID) {
253 return -ENOTSUP;
254 }
255 /*
256 * comp_humidity has 22 integer bits and 10
257 * fractional. Output value of 47445 represents
258 * 47445/1024 = 46.333 %RH
259 */
260 val->val1 = (data->reading.comp_humidity >> 10);
261 val->val2 = (((data->reading.comp_humidity & 0x3ff) * 1000U * 1000U) >> 10);
262 break;
263 default:
264 return -ENOTSUP;
265 }
266
267 return 0;
268 }
269
270 static DEVICE_API(sensor, bme280_api_funcs) = {
271 .sample_fetch = bme280_sample_fetch,
272 .channel_get = bme280_channel_get,
273 #ifdef CONFIG_SENSOR_ASYNC_API
274 .submit = bme280_submit,
275 .get_decoder = bme280_get_decoder,
276 #endif
277 };
278
bme280_read_compensation(const struct device * dev)279 static int bme280_read_compensation(const struct device *dev)
280 {
281 struct bme280_data *data = dev->data;
282 uint16_t buf[12];
283 uint8_t hbuf[7];
284 int err = 0;
285
286 err = bme280_reg_read(dev, BME280_REG_COMP_START,
287 (uint8_t *)buf, sizeof(buf));
288
289 if (err < 0) {
290 LOG_DBG("COMP_START read failed: %d", err);
291 return err;
292 }
293
294 data->dig_t1 = sys_le16_to_cpu(buf[0]);
295 data->dig_t2 = sys_le16_to_cpu(buf[1]);
296 data->dig_t3 = sys_le16_to_cpu(buf[2]);
297
298 data->dig_p1 = sys_le16_to_cpu(buf[3]);
299 data->dig_p2 = sys_le16_to_cpu(buf[4]);
300 data->dig_p3 = sys_le16_to_cpu(buf[5]);
301 data->dig_p4 = sys_le16_to_cpu(buf[6]);
302 data->dig_p5 = sys_le16_to_cpu(buf[7]);
303 data->dig_p6 = sys_le16_to_cpu(buf[8]);
304 data->dig_p7 = sys_le16_to_cpu(buf[9]);
305 data->dig_p8 = sys_le16_to_cpu(buf[10]);
306 data->dig_p9 = sys_le16_to_cpu(buf[11]);
307
308 if (data->chip_id == BME280_CHIP_ID) {
309 err = bme280_reg_read(dev, BME280_REG_HUM_COMP_PART1,
310 &data->dig_h1, 1);
311 if (err < 0) {
312 LOG_DBG("HUM_COMP_PART1 read failed: %d", err);
313 return err;
314 }
315
316 err = bme280_reg_read(dev, BME280_REG_HUM_COMP_PART2, hbuf, 7);
317 if (err < 0) {
318 LOG_DBG("HUM_COMP_PART2 read failed: %d", err);
319 return err;
320 }
321
322 data->dig_h2 = (hbuf[1] << 8) | hbuf[0];
323 data->dig_h3 = hbuf[2];
324 data->dig_h4 = (hbuf[3] << 4) | (hbuf[4] & 0x0F);
325 data->dig_h5 = ((hbuf[4] >> 4) & 0x0F) | (hbuf[5] << 4);
326 data->dig_h6 = hbuf[6];
327 }
328
329 return 0;
330 }
331
bme280_chip_init(const struct device * dev)332 static int bme280_chip_init(const struct device *dev)
333 {
334 struct bme280_data *data = dev->data;
335 int err;
336
337 err = bme280_bus_check(dev);
338 if (err < 0) {
339 LOG_DBG("bus check failed: %d", err);
340 return err;
341 }
342
343 err = bme280_reg_read(dev, BME280_REG_ID, &data->chip_id, 1);
344 if (err < 0) {
345 LOG_DBG("ID read failed: %d", err);
346 return err;
347 }
348
349 if (data->chip_id == BME280_CHIP_ID) {
350 LOG_DBG("ID OK");
351 } else if (data->chip_id == BMP280_CHIP_ID_MP ||
352 data->chip_id == BMP280_CHIP_ID_SAMPLE_1) {
353 LOG_DBG("ID OK (BMP280)");
354 } else {
355 LOG_DBG("bad chip id 0x%x", data->chip_id);
356 return -ENOTSUP;
357 }
358
359 err = bme280_reg_write(dev, BME280_REG_RESET, BME280_CMD_SOFT_RESET);
360 if (err < 0) {
361 LOG_DBG("Soft-reset failed: %d", err);
362 }
363
364 /* The only mention of a soft reset duration is 2ms from the self test timeouts */
365 err = bme280_wait_until_ready(dev, K_MSEC(100));
366 if (err < 0) {
367 return err;
368 }
369
370 err = bme280_read_compensation(dev);
371 if (err < 0) {
372 return err;
373 }
374
375 if (data->chip_id == BME280_CHIP_ID) {
376 err = bme280_reg_write(dev, BME280_REG_CTRL_HUM,
377 BME280_HUMIDITY_OVER);
378 if (err < 0) {
379 LOG_DBG("CTRL_HUM write failed: %d", err);
380 return err;
381 }
382 }
383
384 err = bme280_reg_write(dev, BME280_REG_CTRL_MEAS,
385 BME280_CTRL_MEAS_VAL);
386 if (err < 0) {
387 LOG_DBG("CTRL_MEAS write failed: %d", err);
388 return err;
389 }
390
391 err = bme280_reg_write(dev, BME280_REG_CONFIG,
392 BME280_CONFIG_VAL);
393 if (err < 0) {
394 LOG_DBG("CONFIG write failed: %d", err);
395 return err;
396 }
397 /* Wait for the sensor to be ready */
398 k_sleep(K_MSEC(1));
399
400 LOG_DBG("\"%s\" OK", dev->name);
401 return 0;
402 }
403
404 #ifdef CONFIG_PM_DEVICE
bme280_pm_action(const struct device * dev,enum pm_device_action action)405 static int bme280_pm_action(const struct device *dev,
406 enum pm_device_action action)
407 {
408 int ret = 0;
409
410 switch (action) {
411 #ifdef CONFIG_BME280_MODE_NORMAL
412 case PM_DEVICE_ACTION_RESUME:
413 /* Re-enable periodic measurement */
414 ret = bme280_reg_write(dev, BME280_REG_CTRL_MEAS, BME280_CTRL_MEAS_VAL);
415 break;
416 case PM_DEVICE_ACTION_SUSPEND:
417 /* Put the chip into sleep mode */
418 ret = bme280_reg_write(dev, BME280_REG_CTRL_MEAS, BME280_CTRL_MEAS_OFF_VAL);
419 break;
420 #else
421 case PM_DEVICE_ACTION_RESUME:
422 case PM_DEVICE_ACTION_SUSPEND:
423 /* Nothing to do in forced mode */
424 break;
425 #endif
426 default:
427 return -ENOTSUP;
428 }
429
430 return ret;
431 }
432 #endif /* CONFIG_PM_DEVICE */
433
434 /* Initializes a struct bme280_config for an instance on a SPI bus. */
435 #define BME280_CONFIG_SPI(inst) \
436 { \
437 .bus.spi = SPI_DT_SPEC_INST_GET( \
438 inst, BME280_SPI_OPERATION, 0), \
439 .bus_io = &bme280_bus_io_spi, \
440 }
441
442 /* Initializes a struct bme280_config for an instance on an I2C bus. */
443 #define BME280_CONFIG_I2C(inst) \
444 { \
445 .bus.i2c = I2C_DT_SPEC_INST_GET(inst), \
446 .bus_io = &bme280_bus_io_i2c, \
447 }
448
449 /*
450 * Main instantiation macro, which selects the correct bus-specific
451 * instantiation macros for the instance.
452 */
453 #define BME280_DEFINE(inst) \
454 static struct bme280_data bme280_data_##inst; \
455 static const struct bme280_config bme280_config_##inst = \
456 COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
457 (BME280_CONFIG_SPI(inst)), \
458 (BME280_CONFIG_I2C(inst))); \
459 \
460 PM_DEVICE_DT_INST_DEFINE(inst, bme280_pm_action); \
461 \
462 SENSOR_DEVICE_DT_INST_DEFINE(inst, \
463 bme280_chip_init, \
464 PM_DEVICE_DT_INST_GET(inst), \
465 &bme280_data_##inst, \
466 &bme280_config_##inst, \
467 POST_KERNEL, \
468 CONFIG_SENSOR_INIT_PRIORITY, \
469 &bme280_api_funcs);
470
471 /* Create the struct device for every status "okay" node in the devicetree. */
472 DT_INST_FOREACH_STATUS_OKAY(BME280_DEFINE)
473