ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_interface_bme280.c
Go to the documentation of this file.
2#if RI_BME280_ENABLED || DOXYGEN
3// Ruuvi headers
11#include "ruuvi_interface_i2c.h"
14
15#include <string.h>
16
17// Bosch driver.
18#include "bme280.h"
19#include "bme280_defs.h"
20#include "bme280_selftest.h"
21#if !(BME280_FLOAT_ENABLE || DOXYGEN)
22#error "Please #define BME280_FLOAT_ENABLE in makefile CFLAGS"
23#endif
24
40#define BME280_MEAS_TIME_CONST1 (1.25F)
41#define BME280_MEAS_TIME_CONST2 (2.3F)
42#define BME280_MEAS_TIME_CONST3 (3.0F)
43#define BME280_MEAS_TIME_CONST4 (2.0F)
44#define BME280_MEAS_TIME_CONST5 (0.575F)
45#define BME280_MEAS_TIME_CONST6 (2U)
46
47#define BME280_SAMPLERATE_1000MS (1U)
48#define BME280_SAMPLERATE_500MS (2U)
49#define BME280_SAMPLERATE_125MS (8U)
50#define BME280_SAMPLERATE_62_5MS (16U)
51#define BME280_SAMPLERATE_20MS (50U)
52#define BME280_SAMPLERATE_10MS (100U)
53#define BME280_SAMPLERATE_0_5MS (200U)
54
55#define BME280_DSP_MODE_0 (1U)
56#define BME280_DSP_MODE_1 (2U)
57#define BME280_DSP_MODE_2 (4U)
58#define BME280_DSP_MODE_3 (8U)
59#define BME280_DSP_MODE_4 (16U)
60
61#define BME280_HUMIDITY (0)
62#define BME280_PRESSURE (1)
63#define BME280_TEMPERATURE (2)
64#define BME280_SENS_NUM (3)
65
66#define BME280_HUMIDITY_MAX_VALUE (100.0f)
67
68typedef float bme_float;
69
71#ifndef CEEDLING
72static
73#endif
74struct bme280_dev dev = {0};
75static uint64_t tsample;
76static const char m_sensor_name[] = "BME280";
77
79#ifndef CEEDLING
80static
81#endif
82rd_status_t bme280_verify_sensor_sleep (void)
83{
84 rd_status_t err_code = RD_SUCCESS;
85 uint8_t mode = 0;
86 ri_bme280_mode_get (&mode);
87
88 if (RD_SENSOR_CFG_SLEEP != mode)
89 {
90 err_code = RD_ERROR_INVALID_STATE;
91 }
92
93 return err_code;
94}
95
97static rd_status_t bme280_success_on_valid (uint8_t param)
98{
100
101 if ( (RD_SENSOR_CFG_DEFAULT == param) ||
102 (RD_SENSOR_CFG_MIN == param) ||
103 (RD_SENSOR_CFG_MAX == param) ||
104 (RD_SENSOR_CFG_NO_CHANGE == param))
105 {
106 err_code = RD_SUCCESS;
107 }
108
109 return err_code;
110}
111
115static rd_status_t BME_TO_RUUVI_ERROR (int8_t rslt)
116{
117 rd_status_t err_code = RD_SUCCESS;
118
119 if (BME280_OK == rslt) { err_code = RD_SUCCESS; }
120 else if (BME280_E_DEV_NOT_FOUND == rslt) { err_code = RD_ERROR_NOT_FOUND; }
121 else if (BME280_E_NULL_PTR == rslt) { err_code = RD_ERROR_NULL; }
122 else if (BME280_E_COMM_FAIL == rslt) { err_code = RD_ERROR_BUSY; }
123 else { err_code = RD_ERROR_INTERNAL; }
124
125 return err_code;
126}
127
128void bosch_delay_ms (uint32_t time_ms)
129{
130 ri_delay_ms (time_ms);
131}
132
133// BME280 datasheet Appendix B.
134#ifndef CEEDLING
135static
136#endif
137uint32_t bme280_max_meas_time (const uint8_t oversampling)
138{
139 // Time
143 // Roundoff + margin
144 uint32_t ret_time = (uint32_t) rd_time;
145 ret_time += BME280_MEAS_TIME_CONST6;
146 return ret_time;
147}
148
149#ifndef CEEDLING
150static
151#endif
152rd_status_t bme280_spi_init (const struct bme280_dev * const p_dev, const uint8_t handle)
153{
154 (void) (p_dev);
156#if RI_BME280_SPI_ENABLED
157 dev.dev_id = handle;
158 dev.intf = BME280_SPI_INTF;
159 dev.read = &ri_spi_bme280_read;
160 dev.write = &ri_spi_bme280_write;
161 dev.delay_ms = bosch_delay_ms;
162 err_code = BME_TO_RUUVI_ERROR (bme280_init (&dev));
163#endif
164 return err_code;
165}
166
167#ifndef CEEDLING
168static
169#endif
170rd_status_t bme280_i2c_init (const struct bme280_dev * const p_dev, const uint8_t handle)
171{
172 (void) (p_dev);
174#if RI_BME280_I2C_ENABLED
175 dev.dev_id = handle;
176 dev.intf = BME280_I2C_INTF;
177 dev.read = &ri_i2c_bme280_read;
178 dev.write = &ri_i2c_bme280_write;
179 dev.delay_ms = bosch_delay_ms;
180 err_code = BME_TO_RUUVI_ERROR (bme280_init (&dev));
181#endif
182 return err_code;
183}
184
185static void bme280_ri_setup (rd_sensor_t * const environmental_sensor)
186{
187 environmental_sensor->init = ri_bme280_init;
188 environmental_sensor->uninit = ri_bme280_uninit;
189 environmental_sensor->samplerate_set = ri_bme280_samplerate_set;
190 environmental_sensor->samplerate_get = ri_bme280_samplerate_get;
191 environmental_sensor->resolution_set = ri_bme280_resolution_set;
192 environmental_sensor->resolution_get = ri_bme280_resolution_get;
193 environmental_sensor->scale_set = ri_bme280_scale_set;
194 environmental_sensor->scale_get = ri_bme280_scale_get;
195 environmental_sensor->dsp_set = ri_bme280_dsp_set;
196 environmental_sensor->dsp_get = ri_bme280_dsp_get;
197 environmental_sensor->mode_set = ri_bme280_mode_set;
198 environmental_sensor->mode_get = ri_bme280_mode_get;
199 environmental_sensor->data_get = ri_bme280_data_get;
200 environmental_sensor->configuration_set = rd_sensor_configuration_set;
201 environmental_sensor->configuration_get = rd_sensor_configuration_get;
202 environmental_sensor->provides.datas.temperature_c = 1;
203 environmental_sensor->provides.datas.humidity_rh = 1;
204 environmental_sensor->provides.datas.pressure_pa = 1;
205 tsample = RD_UINT64_INVALID;
206}
207
209rd_status_t ri_bme280_init (rd_sensor_t * p_sensor, rd_bus_t bus, uint8_t handle)
210{
211 rd_status_t err_code = RD_SUCCESS;
212
213 if (NULL == p_sensor)
214 {
215 err_code = RD_ERROR_NULL;
216 }
217 else if (rd_sensor_is_init (p_sensor))
218 {
219 err_code = RD_ERROR_INVALID_STATE;
220 }
221 else
222 {
223 rd_sensor_initialize (p_sensor);
224 p_sensor->name = m_sensor_name;
225
226 if (RD_BUS_SPI == bus)
227 {
228 err_code |= bme280_spi_init (&dev, handle);
229 }
230 else if (RD_BUS_I2C == bus)
231 {
232 err_code |= bme280_i2c_init (&dev, handle);
233 }
234 else
235 {
236 err_code |= RD_ERROR_INVALID_PARAM;
237 }
238
239 if (RD_SUCCESS == err_code)
240 {
241 err_code |= BME_TO_RUUVI_ERROR (bme280_soft_reset (&dev));
242 // Setup Oversampling 1 to enable sensor
243 uint8_t dsp = RD_SENSOR_DSP_OS;
244 uint8_t dsp_parameter = 1;
245 err_code |= ri_bme280_dsp_set (&dsp, &dsp_parameter);
246 }
247
248 if (RD_SUCCESS == err_code)
249 {
250 bme280_ri_setup (p_sensor);
251 }
252 }
253
254 return err_code;
255}
256
258 rd_bus_t bus, uint8_t handle)
259{
260 rd_status_t err_code = RD_SUCCESS;
261 (void) bus;
262 (void) handle;
263
264 if (NULL == sensor)
265 {
266 err_code = RD_ERROR_NULL;
267 }
268 else
269 {
270 err_code = BME_TO_RUUVI_ERROR (bme280_soft_reset (&dev));
271
272 if (RD_SUCCESS == err_code)
273 {
274 rd_sensor_uninitialize (sensor);
275 memset (&dev, 0, sizeof (dev));
276 tsample = RD_UINT64_INVALID;
277 }
278 }
279
280 return err_code;
281}
282
283#ifndef CEEDLING
284static
285#endif
286rd_status_t ri2bme_rate (struct bme280_dev * p_dev, uint8_t * const samplerate)
287{
288 rd_status_t err_code = RD_SUCCESS;
289
290 if (RD_SENSOR_CFG_DEFAULT == *samplerate) { p_dev->settings.standby_time = BME280_STANDBY_TIME_1000_MS; }
291 else if (BME280_SAMPLERATE_1000MS == *samplerate) { p_dev->settings.standby_time = BME280_STANDBY_TIME_1000_MS; }
292 else if (BME280_SAMPLERATE_500MS == *samplerate) { p_dev->settings.standby_time = BME280_STANDBY_TIME_500_MS; }
293 else if (*samplerate <= BME280_SAMPLERATE_125MS) { p_dev->settings.standby_time = BME280_STANDBY_TIME_125_MS; }
294 else if (*samplerate <= BME280_SAMPLERATE_62_5MS) { p_dev->settings.standby_time = BME280_STANDBY_TIME_62_5_MS; }
295 else if (*samplerate <= BME280_SAMPLERATE_20MS) { p_dev->settings.standby_time = BME280_STANDBY_TIME_20_MS; }
296 else if (*samplerate <= BME280_SAMPLERATE_10MS) { p_dev->settings.standby_time = BME280_STANDBY_TIME_10_MS; }
297 else if (*samplerate <= BME280_SAMPLERATE_0_5MS) { p_dev->settings.standby_time = BME280_STANDBY_TIME_0_5_MS; }
298 else if (RD_SENSOR_CFG_MIN == *samplerate) { p_dev->settings.standby_time = BME280_STANDBY_TIME_1000_MS; }
299 else if (RD_SENSOR_CFG_MAX == *samplerate) { p_dev->settings.standby_time = BME280_STANDBY_TIME_0_5_MS; }
300 else
301 {
302 if (RD_SENSOR_CFG_NO_CHANGE != *samplerate)
303 {
304 *samplerate = RD_SENSOR_ERR_NOT_SUPPORTED;
305 err_code |= RD_ERROR_NOT_SUPPORTED;
306 }
307 }
308
309 return err_code;
310}
311
313{
314 rd_status_t err_code = RD_SUCCESS;
315
316 if (NULL == samplerate)
317 {
318 err_code = RD_ERROR_NULL;
319 }
320 else if (RD_SUCCESS == bme280_verify_sensor_sleep())
321 {
322 err_code = ri2bme_rate (&dev, samplerate);
323
324 if (RD_SUCCESS == err_code)
325 {
326 err_code |= BME_TO_RUUVI_ERROR (bme280_set_sensor_settings (BME280_STANDBY_SEL, &dev));
327 err_code |= ri_bme280_samplerate_get (samplerate);
328 }
329 }
330 else
331 {
332 err_code |= RD_ERROR_INVALID_STATE;
333 }
334
335 return err_code;
336}
337
339{
340 rd_status_t err_code = RD_SUCCESS;
341
342 if (NULL == samplerate)
343 {
344 err_code = RD_ERROR_NULL;
345 }
346 else
347 {
348 err_code = BME_TO_RUUVI_ERROR (bme280_get_sensor_settings (&dev));
349
350 if (RD_SUCCESS == err_code)
351 {
352 if (BME280_STANDBY_TIME_1000_MS == dev.settings.standby_time)
353 {
354 *samplerate = BME280_SAMPLERATE_1000MS;
355 }
356 else if (BME280_STANDBY_TIME_500_MS == dev.settings.standby_time)
357 {
358 *samplerate = BME280_SAMPLERATE_500MS;
359 }
360 else if (BME280_STANDBY_TIME_125_MS == dev.settings.standby_time)
361 {
362 *samplerate = BME280_SAMPLERATE_125MS;
363 }
364 else if (BME280_STANDBY_TIME_62_5_MS == dev.settings.standby_time)
365 {
366 *samplerate = BME280_SAMPLERATE_62_5MS;
367 }
368 else if (BME280_STANDBY_TIME_20_MS == dev.settings.standby_time)
369 {
370 *samplerate = BME280_SAMPLERATE_20MS;
371 }
372 else if (BME280_STANDBY_TIME_10_MS == dev.settings.standby_time)
373 {
374 *samplerate = BME280_SAMPLERATE_10MS;
375 }
376 else if (BME280_STANDBY_TIME_0_5_MS == dev.settings.standby_time)
377 {
378 *samplerate = BME280_SAMPLERATE_0_5MS;
379 }
380 else
381 {
382 *samplerate = RD_SENSOR_ERR_NOT_SUPPORTED;
383 }
384 }
385 }
386
387 return err_code;
388}
389
391{
393
394 if (NULL == resolution)
395 {
396 err_code = RD_ERROR_NULL;
397 }
398 else
399 {
400 err_code = bme280_verify_sensor_sleep();
401
402 if (RD_SUCCESS == err_code)
403 {
404 uint8_t original = *resolution;
405 *resolution = RD_SENSOR_CFG_DEFAULT;
406 err_code = bme280_success_on_valid (original);
407
408 if (RD_SUCCESS != err_code)
409 {
410 err_code = RD_ERROR_NOT_SUPPORTED;
411 }
412 }
413 }
414
415 return err_code;
416}
417
419{
420 rd_status_t err_code = RD_SUCCESS;
421
422 if (NULL == resolution)
423 {
424 err_code = RD_ERROR_NULL;
425 }
426 else
427 {
428 *resolution = RD_SENSOR_CFG_DEFAULT;
429 }
430
431 return err_code;
432}
433
435{
437
438 if (NULL == scale)
439 {
440 err_code = RD_ERROR_NULL;
441 }
442 else
443 {
444 err_code = bme280_verify_sensor_sleep();
445
446 if (RD_SUCCESS == err_code)
447 {
448 uint8_t original = *scale;
449 *scale = RD_SENSOR_CFG_DEFAULT;
450 err_code = bme280_success_on_valid (original);
451
452 if (RD_SUCCESS != err_code)
453 {
454 err_code = RD_ERROR_NOT_SUPPORTED;
455 }
456 }
457 }
458
459 return err_code;
460}
461
463{
464 rd_status_t err_code = RD_SUCCESS;
465
466 if (NULL == scale)
467 {
468 err_code = RD_ERROR_NULL;
469 }
470 else
471 {
472 *scale = RD_SENSOR_CFG_DEFAULT;
473 }
474
475 return err_code;
476}
477
478static rd_status_t ri_bme280_dsp_setup_over (uint8_t * parameter)
479{
480 rd_status_t err_code = RD_SUCCESS;
481
482 if ( (RD_SENSOR_CFG_DEFAULT == *parameter) || \
483 (RD_SENSOR_CFG_MIN == *parameter) || \
484 (BME280_DSP_MODE_0 == *parameter))
485 {
486 dev.settings.osr_h = BME280_OVERSAMPLING_1X;
487 dev.settings.osr_p = BME280_OVERSAMPLING_1X;
488 dev.settings.osr_t = BME280_OVERSAMPLING_1X;
489 *parameter = BME280_DSP_MODE_0;
490 }
491 else if (BME280_DSP_MODE_1 == *parameter)
492 {
493 dev.settings.osr_h = BME280_OVERSAMPLING_2X;
494 dev.settings.osr_p = BME280_OVERSAMPLING_2X;
495 dev.settings.osr_t = BME280_OVERSAMPLING_2X;
496 *parameter = BME280_DSP_MODE_1;
497 }
498 else if (BME280_DSP_MODE_2 >= *parameter)
499 {
500 dev.settings.osr_h = BME280_OVERSAMPLING_4X;
501 dev.settings.osr_p = BME280_OVERSAMPLING_4X;
502 dev.settings.osr_t = BME280_OVERSAMPLING_4X;
503 *parameter = BME280_DSP_MODE_2;
504 }
505 else if (BME280_DSP_MODE_3 >= *parameter)
506 {
507 dev.settings.osr_h = BME280_OVERSAMPLING_8X;
508 dev.settings.osr_p = BME280_OVERSAMPLING_8X;
509 dev.settings.osr_t = BME280_OVERSAMPLING_8X;
510 *parameter = BME280_DSP_MODE_3;
511 }
512 else if ( (BME280_DSP_MODE_4 >= *parameter) || \
513 (RD_SENSOR_CFG_MAX == *parameter))
514 {
515 dev.settings.osr_h = BME280_OVERSAMPLING_16X;
516 dev.settings.osr_p = BME280_OVERSAMPLING_16X;
517 dev.settings.osr_t = BME280_OVERSAMPLING_16X;
518 *parameter = BME280_DSP_MODE_4;
519 }
520 else
521 {
522 *parameter = RD_SENSOR_ERR_NOT_SUPPORTED;
523 err_code = RD_ERROR_NOT_SUPPORTED;
524 }
525
526 return err_code;
527}
528
529static rd_status_t ri_bme280_dsp_setup (uint8_t * p_settings_sel, const uint8_t * dsp,
530 uint8_t * parameter)
531{
532 rd_status_t err_code = RD_SUCCESS;
533
534 // Error if DSP is not last, and if dsp is something else than IIR or OS
535 if ( (RD_SENSOR_DSP_LAST != *dsp) &&
536 (~ (RD_SENSOR_DSP_LOW_PASS | RD_SENSOR_DSP_OS) & (*dsp)) != 0)
537 {
538 err_code = RD_ERROR_NOT_SUPPORTED;
539 }
540 else
541 {
542 // Always 1x oversampling to keep sensing element enabled
543 dev.settings.osr_h = BME280_OVERSAMPLING_1X;
544 dev.settings.osr_p = BME280_OVERSAMPLING_1X;
545 dev.settings.osr_t = BME280_OVERSAMPLING_1X;
546 dev.settings.filter = BME280_FILTER_COEFF_OFF;
547 *p_settings_sel |= BME280_OSR_PRESS_SEL;
548 *p_settings_sel |= BME280_OSR_TEMP_SEL;
549 *p_settings_sel |= BME280_OSR_HUM_SEL;
550 *p_settings_sel |= BME280_FILTER_SEL;
551
552 // Setup IIR
553 if (RD_SENSOR_DSP_LOW_PASS & *dsp)
554 {
555 if ( (RD_SENSOR_CFG_DEFAULT == *parameter) || \
556 (RD_SENSOR_CFG_MIN == *parameter) || \
557 (BME280_DSP_MODE_0 == *parameter))
558 {
559 dev.settings.filter = BME280_FILTER_COEFF_OFF;
560 *parameter = BME280_DSP_MODE_0;
561 }
562 else if (BME280_DSP_MODE_1 == *parameter)
563 {
564 dev.settings.filter = BME280_FILTER_COEFF_2;
565 *parameter = BME280_DSP_MODE_1;
566 }
567 else if (BME280_DSP_MODE_2 >= *parameter)
568 {
569 dev.settings.filter = BME280_FILTER_COEFF_4;
570 *parameter = BME280_DSP_MODE_2;
571 }
572 else if (BME280_DSP_MODE_3 >= *parameter)
573 {
574 dev.settings.filter = BME280_FILTER_COEFF_8;
575 *parameter = BME280_DSP_MODE_3;
576 }
577 else if ( (RD_SENSOR_CFG_MAX == *parameter) || \
578 (BME280_DSP_MODE_4 >= *parameter))
579 {
580 dev.settings.filter = BME280_FILTER_COEFF_16;
581 *parameter = BME280_DSP_MODE_4;
582 }
583 else
584 {
585 *parameter = RD_SENSOR_ERR_NOT_SUPPORTED;
586 err_code = RD_ERROR_NOT_SUPPORTED;
587 }
588 }
589
590 if ( (RD_SUCCESS == err_code) &&
591 ( (RD_SENSOR_DSP_OS & *dsp) != 0))
592 {
593 err_code = ri_bme280_dsp_setup_over (parameter);
594 }
595 }
596
597 return err_code;
598}
599
600rd_status_t ri_bme280_dsp_set (uint8_t * dsp, uint8_t * parameter)
601{
602 rd_status_t err_code = RD_SUCCESS;
603 uint8_t settings_sel = 0U;
604
605 if ( (NULL == dsp) || (NULL == parameter))
606 {
607 err_code = RD_ERROR_NULL;
608 }
609 else
610 {
611 err_code = bme280_verify_sensor_sleep();
612
613 if (RD_SUCCESS == err_code)
614 {
615 // Validate configuration
616 if ( (RD_SENSOR_CFG_DEFAULT != *parameter)
617 && (RD_SENSOR_CFG_MIN != *parameter)
618 && (RD_SENSOR_CFG_MAX != *parameter))
619 {
620 err_code = RD_ERROR_NOT_SUPPORTED;
621 }
622
623 if ( (RD_SUCCESS != err_code) &&
624 ( (RD_SENSOR_DSP_LAST == *dsp) ||
625 (BME280_DSP_MODE_0 == *parameter) ||
626 (BME280_DSP_MODE_1 == *parameter)))
627 {
628 err_code = RD_SUCCESS;
629 }
630
631 if ( (RD_SUCCESS != err_code) &&
632 ( (BME280_DSP_MODE_2 == *parameter) ||
633 (BME280_DSP_MODE_3 == *parameter) ||
634 (BME280_DSP_MODE_4 == *parameter)))
635 {
636 err_code = RD_SUCCESS;
637 }
638
639 if (RD_SUCCESS == err_code)
640 {
641 err_code = ri_bme280_dsp_setup (&settings_sel, dsp, parameter);
642 }
643 }
644 }
645
646 if (RD_SUCCESS == err_code)
647 {
648 //Write configuration
649 err_code = BME_TO_RUUVI_ERROR (bme280_set_sensor_settings (settings_sel, &dev));
650 }
651
652 return err_code;
653}
654
655static void ri_bme280_dsp_get_param (uint8_t * dsp, uint8_t * parameter)
656{
657 // Assume default / 0,
659 *parameter = RD_SENSOR_CFG_DEFAULT;
660
661 // Check if IIR has been set. If yes, read DSP param from there.
662 if (BME280_FILTER_COEFF_OFF != dev.settings.filter)
663 {
665
666 switch (dev.settings.filter)
667 {
668 case BME280_FILTER_COEFF_2:
669 *parameter = BME280_DSP_MODE_1;
670 break;
671
672 case BME280_FILTER_COEFF_4:
673 *parameter = BME280_DSP_MODE_2;
674 break;
675
676 case BME280_FILTER_COEFF_8:
677 *parameter = BME280_DSP_MODE_3;
678 break;
679
680 case BME280_FILTER_COEFF_16:
681 *parameter = BME280_DSP_MODE_4;
682 break;
683
684 default:
685 *parameter = BME280_DSP_MODE_1;
686 break;
687 }
688 }
689
690 // Check if OS has been set. If yes, read DSP param from there.
691 // Param should be same for OS and IIR if it is >1.
692 // OSR is same for every element.
693 if ( (BME280_NO_OVERSAMPLING != dev.settings.osr_h)
694 && (BME280_OVERSAMPLING_1X != dev.settings.osr_h))
695 {
696 *dsp |= RD_SENSOR_DSP_OS;
697
698 switch (dev.settings.osr_h)
699 {
700 case BME280_OVERSAMPLING_2X:
701 *parameter = BME280_DSP_MODE_1;
702 break;
703
704 case BME280_OVERSAMPLING_4X:
705 *parameter = BME280_DSP_MODE_2;
706 break;
707
708 case BME280_OVERSAMPLING_8X:
709 *parameter = BME280_DSP_MODE_3;
710 break;
711
712 case BME280_OVERSAMPLING_16X:
713 *parameter = BME280_DSP_MODE_4;
714 break;
715
716 default:
717 *parameter = BME280_DSP_MODE_1;
718 break;
719 }
720 }
721}
722
723// Read configuration
724rd_status_t ri_bme280_dsp_get (uint8_t * dsp, uint8_t * parameter)
725{
726 rd_status_t err_code = RD_SUCCESS;
727
728 if ( (NULL == dsp) || (NULL == parameter))
729 {
730 err_code = RD_ERROR_NULL;
731 }
732 else
733 {
734 err_code |= BME_TO_RUUVI_ERROR (bme280_get_sensor_settings (&dev));
735
736 if (RD_SUCCESS == err_code)
737 {
738 ri_bme280_dsp_get_param (dsp, parameter);
739 }
740 }
741
742 return err_code;
743}
744
745static rd_status_t ri_bme280_mode_set_single (uint8_t * mode)
746{
747 rd_status_t err_code = RD_SUCCESS;
748 uint8_t current_mode = RD_SENSOR_CFG_SLEEP;
749 // Do nothing if sensor is in continuous mode
750 ri_bme280_mode_get (&current_mode);
751
752 if (RD_SENSOR_CFG_CONTINUOUS == current_mode)
753 {
755 err_code = RD_ERROR_INVALID_STATE;
756 }
757 else
758 {
759 err_code = BME_TO_RUUVI_ERROR (bme280_set_sensor_mode (BME280_FORCED_MODE, &dev));
760 // We assume that dev struct is in sync with the state of the BME280 and underlying interface
761 // which has the number of settings as 2^OSR is not changed.
762 // We also assume that each element runs same OSR
763 uint8_t samples = (uint8_t) (1U << (dev.settings.osr_h - 1U));
764 ri_delay_ms (bme280_max_meas_time (samples));
765 tsample = rd_sensor_timestamp_get();
766 // BME280 returns to SLEEP after forced sample
767 *mode = RD_SENSOR_CFG_SLEEP;
768 }
769
770 return err_code;
771}
772
774{
775 rd_status_t err_code = RD_SUCCESS;
776
777 if (NULL == mode)
778 {
779 err_code = RD_ERROR_NULL;
780 }
781 else
782 {
783 switch (*mode)
784 {
786 err_code = BME_TO_RUUVI_ERROR (bme280_set_sensor_mode (BME280_SLEEP_MODE, &dev));
787 break;
788
790 err_code = ri_bme280_mode_set_single (mode);
791 break;
792
794 err_code = BME_TO_RUUVI_ERROR (bme280_set_sensor_mode (BME280_NORMAL_MODE, &dev));
795 break;
796
797 default:
798 err_code = RD_ERROR_INVALID_PARAM;
799 break;
800 }
801 }
802
803 return err_code;
804}
805
807{
808 rd_status_t err_code = RD_SUCCESS;
809
810 if (NULL == mode)
811 {
812 err_code = RD_ERROR_NULL;
813 }
814 else
815 {
816 uint8_t bme_mode = 0U;
817 err_code = BME_TO_RUUVI_ERROR (bme280_get_sensor_mode (&bme_mode, &dev));
818
819 if (RD_SUCCESS == err_code)
820 {
821 switch (bme_mode)
822 {
823 case BME280_SLEEP_MODE:
824 *mode = RD_SENSOR_CFG_SLEEP;
825 break;
826
827 case BME280_FORCED_MODE:
828 *mode = RD_SENSOR_CFG_SINGLE;
829 break;
830
831 case BME280_NORMAL_MODE:
833 break;
834
835 default:
836 *mode = RD_SENSOR_ERR_INVALID;
837 break;
838 }
839 }
840 }
841
842 return err_code;
843}
844
845static void ri_bme280_check_humiduty (float * p_value)
846{
847 if (*p_value > BME280_HUMIDITY_MAX_VALUE)
848 {
849 *p_value = BME280_HUMIDITY_MAX_VALUE;
850 }
851}
852
854 p_data)
855{
856 rd_status_t err_code = RD_SUCCESS;
857
858 if (NULL == p_data)
859 {
860 err_code = RD_ERROR_NULL;
861 }
862 else
863 {
864 struct bme280_data comp_data;
865 err_code = BME_TO_RUUVI_ERROR (bme280_get_sensor_data (BME280_ALL, &comp_data, &dev));
866
867 if (RD_SUCCESS == err_code)
868 {
869 // Write tsample if we're in single mode, current time if we're in continuous mode
870 // Leave sample time as invalid if forced mode is ongoing.
871 uint8_t mode = 0U;
872 err_code |= ri_bme280_mode_get (&mode);
873
874 if (RD_SENSOR_CFG_SLEEP == mode) { p_data->timestamp_ms = tsample; }
875 else if (RD_SENSOR_CFG_CONTINUOUS == mode) { p_data->timestamp_ms = rd_sensor_timestamp_get(); }
877
878 // If we have valid data, return it.
879 if (RD_UINT64_INVALID != p_data->timestamp_ms)
880 {
881 rd_sensor_data_t d_environmental = {0};
882 rd_sensor_data_fields_t env_fields = {.bitfield = 0};
883 float env_values[BME280_SENS_NUM];
884 env_values[BME280_HUMIDITY] = (float) (comp_data.humidity - BME280_HUMIDITY_OFFSET);
885 ri_bme280_check_humiduty (&env_values[BME280_HUMIDITY]);
886 env_values[BME280_PRESSURE] = (float) comp_data.pressure;
887 env_values[BME280_TEMPERATURE] = (float) comp_data.temperature;
888 env_fields.datas.humidity_rh = 1U;
889 env_fields.datas.pressure_pa = 1U;
890 env_fields.datas.temperature_c = 1U;
891 d_environmental.data = env_values;
892 d_environmental.fields = env_fields;
893 d_environmental.valid = env_fields;
895 &d_environmental,
896 p_data->fields);
897 }
898 }
899 }
900
901 return err_code;
902}
904#endif
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
#define RD_ERROR_NULL
Null Pointer.
#define RD_ERROR_FATAL
Program should always reset after this.
uint32_t rd_status_t
bitfield for representing errors
#define RD_ERROR_CHECK(error, mask)
Shorthand macro for calling the rd_error_check with current file & line.
#define RD_ERROR_NOT_ENABLED
Driver is not enabled.
#define RD_ERROR_NOT_SUPPORTED
Not supported.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_NOT_FOUND
Not found.
#define RD_UINT64_INVALID
Signal that value should not be used.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#define RD_ERROR_INTERNAL
Internal Error.
#define RD_ERROR_BUSY
Busy.
int8_t ri_i2c_bme280_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *p_reg_data, uint16_t len)
I2C Read function for BME280.
int8_t ri_i2c_bme280_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *p_reg_data, uint16_t len)
I2C write function for BME280.
int8_t ri_spi_bme280_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
SPI write function for BME280.
int8_t ri_spi_bme280_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
SPI Read function for BME280.
#define RD_SENSOR_DSP_LAST
Return last value from sensor. Parameter: No effect. Use default.
#define RD_SENSOR_ERR_NOT_SUPPORTED
Error code, given parameter is not supported by sensor.
bool rd_sensor_is_init(const rd_sensor_t *const sensor)
Check if given sensor structure is already initialized.
#define RD_SENSOR_CFG_SLEEP
Sensor should go to sleep immediately.
#define RD_SENSOR_CFG_MAX
Configure largest supported and implemented value.
#define RD_SENSOR_CFG_DEFAULT
Default value, always valid for the sensor.
void rd_sensor_uninitialize(rd_sensor_t *const p_sensor)
Mark sensor as uninitialized by calling the generic initialization. Will not clear the name of the se...
#define RD_SENSOR_DSP_OS
Oversample sensor values. Parameter: Number of samples.
rd_status_t rd_sensor_configuration_get(const rd_sensor_t *sensor, rd_sensor_configuration_t *config)
Implementation of ref rd_configuration_fp.
void rd_sensor_initialize(rd_sensor_t *const p_sensor)
Initialize sensor struct with non-null pointers which return RD_ERROR_NOT_INITIALIZED.
#define RD_SENSOR_DSP_LOW_PASS
Low pass sensor values Parameter: coefficient.
#define RD_SENSOR_ERR_INVALID
Error code, given parameter is invalid.
void rd_sensor_data_populate(rd_sensor_data_t *const target, const rd_sensor_data_t *const provided, const rd_sensor_data_fields_t requested)
Populate given target data with data provided by sensor as requested.
rd_status_t rd_sensor_configuration_set(const rd_sensor_t *sensor, rd_sensor_configuration_t *config)
Implementation of ref rd_configuration_fp.
#define RD_SENSOR_CFG_MIN
Configure smallest supported and implemented value.
#define RD_SENSOR_CFG_CONTINUOUS
Sensor will keep sampling at defined sample rate.
#define RD_SENSOR_CFG_NO_CHANGE
Do not change configured value.
rd_bus_t
Type of bus sensor uses.
uint64_t rd_sensor_timestamp_get(void)
Calls the timestamp function and returns its value.
#define RD_SENSOR_CFG_SINGLE
Sensor should go to sleep after single measurement.
@ RD_BUS_SPI
SPI bus.
@ RD_BUS_I2C
I2C bus.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Ruuvi sensor interface Lifecycle: Beta
rd_status_t ri_bme280_uninit(rd_sensor_t *sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
#define BME280_SAMPLERATE_0_5MS
#define BME280_TEMPERATURE
#define BME280_SAMPLERATE_20MS
rd_status_t ri_bme280_samplerate_get(uint8_t *samplerate)
rd_sensor_setup_fp
#define BME280_SAMPLERATE_10MS
float bme_float
#define BME280_SAMPLERATE_1000MS
rd_status_t ri_bme280_dsp_set(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
#define BME280_HUMIDITY
#define BME280_DSP_MODE_0
rd_status_t ri_bme280_mode_get(uint8_t *mode)
rd_sensor_setup_fp
#define BME280_MEAS_TIME_CONST2
rd_status_t ri_bme280_dsp_get(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
#define BME280_MEAS_TIME_CONST3
rd_status_t ri_bme280_resolution_get(uint8_t *resolution)
rd_sensor_setup_fp
rd_status_t ri_bme280_resolution_set(uint8_t *resolution)
rd_sensor_setup_fp
#define BME280_SAMPLERATE_500MS
#define BME280_SAMPLERATE_125MS
rd_status_t ri_bme280_data_get(rd_sensor_data_t *const p_data)
rd_sensor_data_fp
#define BME280_DSP_MODE_2
#define BME280_SAMPLERATE_62_5MS
#define BME280_DSP_MODE_3
rd_status_t ri_bme280_scale_get(uint8_t *scale)
rd_sensor_setup_fp
rd_status_t ri_bme280_mode_set(uint8_t *mode)
rd_sensor_setup_fp
#define BME280_MEAS_TIME_CONST4
#define BME280_MEAS_TIME_CONST6
#define BME280_DSP_MODE_1
rd_status_t ri_bme280_scale_set(uint8_t *scale)
rd_sensor_setup_fp
#define BME280_SENS_NUM
#define BME280_DSP_MODE_4
rd_status_t ri_bme280_init(rd_sensor_t *p_sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
#define BME280_MEAS_TIME_CONST5
rd_status_t ri_bme280_samplerate_set(uint8_t *samplerate)
rd_sensor_setup_fp
#define BME280_MEAS_TIME_CONST1
#define BME280_HUMIDITY_MAX_VALUE
void bosch_delay_ms(uint32_t time_ms)
Implement delay in Bosch signature.
#define BME280_PRESSURE
#define BME280_HUMIDITY_OFFSET
Generally, BMEs show 3% too little. Compensate.
Interface for I2C operations.
I2C read/write functions for Bosch BME280.
Interface for SPI operations.
SPI read/write functions for Bosch BME280.
rd_status_t ri_delay_ms(uint32_t time)
Delay a given number of milliseconds.
unsigned int humidity_rh
Relative humidity, %.
unsigned int temperature_c
Temperature, celcius.
unsigned int pressure_pa
Pressure, pascals.
Generic sensor data struct.
float * data
Data of sensor. Must contain as many elements as fields has bits set.
uint64_t timestamp_ms
Timestamp of the event, rd_sensor_timestamp_get.
rd_sensor_data_fields_t valid
Listing of valid data in this sample.
rd_sensor_data_fields_t fields
Description of datafields which may be contained in this sample.
Interface to sensor. Some sensors can implement additional functions. The additional functions are de...
rd_sensor_data_fp data_get
rd_sensor_data_fp
rd_configuration_fp configuration_set
rd_configuration_fp
rd_sensor_setup_fp samplerate_get
rd_sensor_setup_fp
rd_sensor_setup_fp resolution_get
rd_sensor_setup_fp
rd_sensor_init_fp uninit
rd_sensor_init_fp
rd_configuration_fp configuration_get
rd_configuration_fp
rd_sensor_dsp_fp dsp_get
rd_sensor_dsp_fp
rd_sensor_data_fields_t provides
Description of data fields the sensor is able to provide.
rd_sensor_dsp_fp dsp_set
rd_sensor_dsp_fp
rd_sensor_setup_fp mode_set
rd_sensor_setup_fp
const char * name
Sensor human-readable name. Should be at most 8 bytes long.
rd_sensor_setup_fp mode_get
rd_sensor_setup_fp
rd_sensor_setup_fp samplerate_set
rd_sensor_setup_fp
rd_sensor_init_fp init
rd_sensor_init_fp
rd_sensor_setup_fp scale_set
rd_sensor_setup_fp
rd_sensor_setup_fp resolution_set
rd_sensor_setup_fp
rd_sensor_setup_fp scale_get
rd_sensor_setup_fp
Union to access sensor data.
uint32_t bitfield
Bitfield used to access sensor data.
rd_sensor_data_bitfield_t datas
Structured data field.