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.

178 lines
5.6 KiB

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