Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
5.1 KiB

  1. // -----------------------------------------------------------------------------
  2. // BME280 Sensor
  3. // -----------------------------------------------------------------------------
  4. #pragma once
  5. #include "Arduino.h"
  6. #include "BaseSensor.h"
  7. #include <SparkFunBME280.h>
  8. #define BME280_ERROR_UNKNOW_CHIP -1
  9. class BME280Sensor : public BaseSensor {
  10. public:
  11. BME280Sensor(unsigned char address = BME280_ADDRESS): BaseSensor() {
  12. // Cache
  13. _address = address;
  14. _measurement_delay = bmeMeasurementTime();
  15. #if BME280_TEMPERATURE > 0
  16. ++_count;
  17. #endif
  18. #if BME280_HUMIDITY > 0
  19. ++_count;
  20. #endif
  21. #if BME280_PRESSURE > 0
  22. ++_count;
  23. #endif
  24. // Init
  25. bme = new BME280();
  26. bme->settings.commInterface = I2C_MODE;
  27. bme->settings.I2CAddress = _address;
  28. bme->settings.runMode = BME280_MODE;
  29. bme->settings.tStandby = 0;
  30. bme->settings.filter = 0;
  31. bme->settings.tempOverSample = BME280_TEMPERATURE;
  32. bme->settings.pressOverSample = BME280_PRESSURE;
  33. bme->settings.humidOverSample = BME280_HUMIDITY;
  34. // Fix when not measuring temperature, t_fine should have a sensible value
  35. if (BME280_TEMPERATURE == 0) bme->t_fine = 100000; // aprox 20ºC
  36. // Make sure sensor had enough time to turn on. BME280 requires 2ms to start up
  37. delay(10);
  38. // Check sensor correctly initialized
  39. unsigned char response = bme->begin();
  40. if (response == 0x60) {
  41. _ready = true;
  42. } else {
  43. _error = BME280_ERROR_UNKNOW_CHIP;
  44. }
  45. }
  46. // Descriptive name of the sensor
  47. String name() {
  48. char buffer[20];
  49. snprintf(buffer, sizeof(buffer), "BME280 @ I2C (0x%02X)", _address);
  50. return String(buffer);
  51. }
  52. // Descriptive name of the slot # index
  53. String slot(unsigned char index) {
  54. return name();
  55. }
  56. // Type for slot # index
  57. magnitude_t type(unsigned char index) {
  58. if (index < _count) {
  59. _error = SENSOR_ERROR_OK;
  60. unsigned char i = 0;
  61. #if BME280_TEMPERATURE > 0
  62. if (index == i++) return MAGNITUDE_TEMPERATURE;
  63. #endif
  64. #if BME280_HUMIDITY > 0
  65. if (index == i++) return MAGNITUDE_HUMIDITY;
  66. #endif
  67. #if BME280_PRESSURE > 0
  68. if (index == i) return MAGNITUDE_PRESSURE;
  69. #endif
  70. }
  71. _error = SENSOR_ERROR_OUT_OF_RANGE;
  72. return MAGNITUDE_NONE;
  73. }
  74. // Pre-read hook (usually to populate registers with up-to-date data)
  75. virtual void pre() {
  76. if (!_ready) {
  77. _error = BME280_ERROR_UNKNOW_CHIP;
  78. return;
  79. }
  80. #if BME280_MODE == 1
  81. bmeForceRead();
  82. #endif
  83. }
  84. // Current value for slot # index
  85. double value(unsigned char index) {
  86. if (index < _count) {
  87. _error = SENSOR_ERROR_OK;
  88. unsigned char i = 0;
  89. #if BME280_TEMPERATURE > 0
  90. if (index == i++) return bme->readTempC();
  91. #endif
  92. #if BME280_HUMIDITY > 0
  93. if (index == i++) return bme->readFloatHumidity();
  94. #endif
  95. #if BME280_PRESSURE > 0
  96. if (index == i) return bme->readFloatPressure() / 100;
  97. #endif
  98. }
  99. _error = SENSOR_ERROR_OUT_OF_RANGE;
  100. return 0;
  101. }
  102. protected:
  103. unsigned long bmeMeasurementTime() {
  104. // Measurement Time (as per BME280 datasheet section 9.1)
  105. // T_max(ms) = 1.25
  106. // + (2.3 * T_oversampling)
  107. // + (2.3 * P_oversampling + 0.575)
  108. // + (2.4 * H_oversampling + 0.575)
  109. // ~ 9.3ms for current settings
  110. double t = 1.25;
  111. #if BME280_TEMPERATURE > 0
  112. t += (2.3 * BME280_TEMPERATURE);
  113. #endif
  114. #if BME280_HUMIDITY > 0
  115. t += (2.4 * BME280_HUMIDITY + 0.575);
  116. #endif
  117. #if BME280_PRESSURE > 0
  118. t += (2.3 * BME280_PRESSURE + 0.575);
  119. #endif
  120. return round(t + 1); // round up
  121. }
  122. void bmeForceRead() {
  123. // We set the sensor in "forced mode" to force a reading.
  124. // After the reading the sensor will go back to sleep mode.
  125. uint8_t value = bme->readRegister(BME280_CTRL_MEAS_REG);
  126. value = (value & 0xFC) + 0x01;
  127. bme->writeRegister(BME280_CTRL_MEAS_REG, value);
  128. delay(_measurement_delay);
  129. }
  130. // ---------------------------------------------------------------------
  131. BME280 * bme;
  132. unsigned char _address;
  133. unsigned long _measurement_delay;
  134. bool _ready = false;
  135. };