ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_interface_bme280.c
Go to the documentation of this file.
2 #if RI_BME280_ENABLED || DOXYGEN
3 // Ruuvi headers
4 #include "ruuvi_driver_error.h"
5 #include "ruuvi_driver_sensor.h"
8 #include "ruuvi_interface_gpio.h"
9 #include "ruuvi_interface_spi.h"
11 #include "ruuvi_interface_i2c.h"
13 #include "ruuvi_interface_yield.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 
68 typedef float bme_float;
69 
71 #ifndef CEEDLING
72 static
73 #endif
74 struct bme280_dev dev = {0};
75 static uint64_t tsample;
76 static const char m_sensor_name[] = "BME280";
77 
79 #ifndef CEEDLING
80 static
81 #endif
82 rd_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 
97 static 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 
115 static 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 
128 void bosch_delay_ms (uint32_t time_ms)
129 {
130  ri_delay_ms (time_ms);
131 }
132 
133 // BME280 datasheet Appendix B.
134 #ifndef CEEDLING
135 static
136 #endif
137 uint32_t bme280_max_meas_time (const uint8_t oversampling)
138 {
139  // Time
140  bme_float rd_time = BME280_MEAS_TIME_CONST1 + \
141  BME280_MEAS_TIME_CONST2 * BME280_MEAS_TIME_CONST3 * oversampling + \
142  BME280_MEAS_TIME_CONST4 * BME280_MEAS_TIME_CONST5;
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
150 static
151 #endif
152 rd_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
168 static
169 #endif
170 rd_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 
185 static 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 
209 rd_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
284 static
285 #endif
286 rd_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 
312 rd_status_t ri_bme280_samplerate_set (uint8_t * samplerate)
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 
338 rd_status_t ri_bme280_samplerate_get (uint8_t * samplerate)
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 
390 rd_status_t ri_bme280_resolution_set (uint8_t * resolution)
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 
418 rd_status_t ri_bme280_resolution_get (uint8_t * resolution)
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 
478 static 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 
529 static 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 
600 rd_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 
655 static void ri_bme280_dsp_get_param (uint8_t * dsp, uint8_t * parameter)
656 {
657  // Assume default / 0,
658  *dsp = RD_SENSOR_CFG_DEFAULT;
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  {
664  *dsp |= RD_SENSOR_DSP_LOW_PASS;
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
724 rd_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 
745 static 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  {
754  *mode = RD_SENSOR_CFG_CONTINUOUS;
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  {
785  case RD_SENSOR_CFG_SLEEP:
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:
832  *mode = RD_SENSOR_CFG_CONTINUOUS;
833  break;
834 
835  default:
836  *mode = RD_SENSOR_ERR_INVALID;
837  break;
838  }
839  }
840  }
841 
842  return err_code;
843 }
844 
845 static 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;
894  rd_sensor_data_populate (p_data,
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
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_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.