AP_Baro_BMP280.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #include "AP_Baro_BMP280.h"
  14. #include <utility>
  15. extern const AP_HAL::HAL &hal;
  16. #define BMP280_MODE_SLEEP 0
  17. #define BMP280_MODE_FORCED 1
  18. #define BMP280_MODE_NORMAL 3
  19. #define BMP280_MODE BMP280_MODE_NORMAL
  20. #define BMP280_OVERSAMPLING_1 1
  21. #define BMP280_OVERSAMPLING_2 2
  22. #define BMP280_OVERSAMPLING_4 3
  23. #define BMP280_OVERSAMPLING_8 4
  24. #define BMP280_OVERSAMPLING_16 5
  25. #define BMP280_OVERSAMPLING_P BMP280_OVERSAMPLING_16
  26. #define BMP280_OVERSAMPLING_T BMP280_OVERSAMPLING_2
  27. #define BMP280_FILTER_COEFFICIENT 2
  28. #define BMP280_ID 0x58
  29. #define BME280_ID 0x60
  30. #define BMP280_REG_CALIB 0x88
  31. #define BMP280_REG_ID 0xD0
  32. #define BMP280_REG_RESET 0xE0
  33. #define BMP280_REG_STATUS 0xF3
  34. #define BMP280_REG_CTRL_MEAS 0xF4
  35. #define BMP280_REG_CONFIG 0xF5
  36. #define BMP280_REG_DATA 0xF7
  37. AP_Baro_BMP280::AP_Baro_BMP280(AP_Baro &baro, AP_HAL::OwnPtr<AP_HAL::Device> dev)
  38. : AP_Baro_Backend(baro)
  39. , _dev(std::move(dev))
  40. {
  41. }
  42. AP_Baro_Backend *AP_Baro_BMP280::probe(AP_Baro &baro,
  43. AP_HAL::OwnPtr<AP_HAL::Device> dev)
  44. {
  45. if (!dev) {
  46. return nullptr;
  47. }
  48. AP_Baro_BMP280 *sensor = new AP_Baro_BMP280(baro, std::move(dev));
  49. if (!sensor || !sensor->_init()) {
  50. delete sensor;
  51. return nullptr;
  52. }
  53. return sensor;
  54. }
  55. bool AP_Baro_BMP280::_init()
  56. {
  57. if (!_dev) {
  58. return false;
  59. }
  60. WITH_SEMAPHORE(_dev->get_semaphore());
  61. _has_sample = false;
  62. _dev->set_speed(AP_HAL::Device::SPEED_HIGH);
  63. uint8_t whoami;
  64. if (!_dev->read_registers(BMP280_REG_ID, &whoami, 1) ||
  65. (whoami != BME280_ID && whoami != BMP280_ID)) {
  66. // not a BMP280 or BME280
  67. return false;
  68. }
  69. // read the calibration data
  70. uint8_t buf[24];
  71. _dev->read_registers(BMP280_REG_CALIB, buf, sizeof(buf));
  72. _t1 = ((int16_t)buf[1] << 8) | buf[0];
  73. _t2 = ((int16_t)buf[3] << 8) | buf[2];
  74. _t3 = ((int16_t)buf[5] << 8) | buf[4];
  75. _p1 = ((int16_t)buf[7] << 8) | buf[6];
  76. _p2 = ((int16_t)buf[9] << 8) | buf[8];
  77. _p3 = ((int16_t)buf[11] << 8) | buf[10];
  78. _p4 = ((int16_t)buf[13] << 8) | buf[12];
  79. _p5 = ((int16_t)buf[15] << 8) | buf[14];
  80. _p6 = ((int16_t)buf[17] << 8) | buf[16];
  81. _p7 = ((int16_t)buf[19] << 8) | buf[18];
  82. _p8 = ((int16_t)buf[21] << 8) | buf[20];
  83. _p9 = ((int16_t)buf[23] << 8) | buf[22];
  84. // SPI write needs bit mask
  85. uint8_t mask = 0xFF;
  86. if (_dev->bus_type() == AP_HAL::Device::BUS_TYPE_SPI) {
  87. mask = 0x7F;
  88. }
  89. _dev->setup_checked_registers(2, 20);
  90. _dev->write_register((BMP280_REG_CTRL_MEAS & mask), (BMP280_OVERSAMPLING_T << 5) |
  91. (BMP280_OVERSAMPLING_P << 2) | BMP280_MODE, true);
  92. _dev->write_register((BMP280_REG_CONFIG & mask), BMP280_FILTER_COEFFICIENT << 2, true);
  93. _instance = _frontend.register_sensor();
  94. // request 50Hz update
  95. _dev->register_periodic_callback(20 * AP_USEC_PER_MSEC, FUNCTOR_BIND_MEMBER(&AP_Baro_BMP280::_timer, void));
  96. return true;
  97. }
  98. // acumulate a new sensor reading
  99. void AP_Baro_BMP280::_timer(void)
  100. {
  101. uint8_t buf[6];
  102. _dev->read_registers(BMP280_REG_DATA, buf, sizeof(buf));
  103. _update_temperature((buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4));
  104. _update_pressure((buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4));
  105. _dev->check_next_register();
  106. }
  107. // transfer data to the frontend
  108. void AP_Baro_BMP280::update(void)
  109. {
  110. WITH_SEMAPHORE(_sem);
  111. if (!_has_sample) {
  112. return;
  113. }
  114. _copy_to_frontend(_instance, _pressure, _temperature);
  115. _has_sample = false;
  116. }
  117. // calculate temperature
  118. void AP_Baro_BMP280::_update_temperature(int32_t temp_raw)
  119. {
  120. int32_t var1, var2, t;
  121. // according to datasheet page 22
  122. var1 = ((((temp_raw >> 3) - ((int32_t)_t1 << 1))) * ((int32_t)_t2)) >> 11;
  123. var2 = (((((temp_raw >> 4) - ((int32_t)_t1)) * ((temp_raw >> 4) - ((int32_t)_t1))) >> 12) * ((int32_t)_t3)) >> 14;
  124. _t_fine = var1 + var2;
  125. t = (_t_fine * 5 + 128) >> 8;
  126. const float temp = ((float)t) / 100.0f;
  127. WITH_SEMAPHORE(_sem);
  128. _temperature = temp;
  129. }
  130. // calculate pressure
  131. void AP_Baro_BMP280::_update_pressure(int32_t press_raw)
  132. {
  133. int64_t var1, var2, p;
  134. // according to datasheet page 22
  135. var1 = ((int64_t)_t_fine) - 128000;
  136. var2 = var1 * var1 * (int64_t)_p6;
  137. var2 = var2 + ((var1 * (int64_t)_p5) << 17);
  138. var2 = var2 + (((int64_t)_p4) << 35);
  139. var1 = ((var1 * var1 * (int64_t)_p3) >> 8) + ((var1 * (int64_t)_p2) << 12);
  140. var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)_p1) >> 33;
  141. if (var1 == 0) {
  142. return;
  143. }
  144. p = 1048576 - press_raw;
  145. p = (((p << 31) - var2) * 3125) / var1;
  146. var1 = (((int64_t)_p9) * (p >> 13) * (p >> 13)) >> 25;
  147. var2 = (((int64_t)_p8) * p) >> 19;
  148. p = ((p + var1 + var2) >> 8) + (((int64_t)_p7) << 4);
  149. const float press = (float)p / 256.0f;
  150. if (!pressure_ok(press)) {
  151. return;
  152. }
  153. WITH_SEMAPHORE(_sem);
  154. _pressure = press;
  155. _has_sample = true;
  156. }