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.

176 lines
5.5 KiB

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