AP_Airspeed_DLVR.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. /*
  14. driver for DLVR differential airspeed sensor
  15. https://www.allsensors.com/products/DLVR-L01D
  16. */
  17. #include "AP_Airspeed_DLVR.h"
  18. #include <AP_Math/AP_Math.h>
  19. extern const AP_HAL::HAL &hal;
  20. #define DLVR_I2C_ADDR 0x28
  21. #ifdef DLVR_DEBUGGING
  22. # define Debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); hal.scheduler->delay(1); } while(0)
  23. #else
  24. # define Debug(fmt, args ...)
  25. #endif
  26. AP_Airspeed_DLVR::AP_Airspeed_DLVR(AP_Airspeed &_frontend, uint8_t _instance, const float _range_inH2O) :
  27. AP_Airspeed_Backend(_frontend, _instance),
  28. range_inH2O(_range_inH2O)
  29. {}
  30. // probe and initialise the sensor
  31. bool AP_Airspeed_DLVR::init()
  32. {
  33. dev = hal.i2c_mgr->get_device(get_bus(), DLVR_I2C_ADDR);
  34. if (!dev) {
  35. return false;
  36. }
  37. dev->get_semaphore()->take_blocking();
  38. dev->set_speed(AP_HAL::Device::SPEED_LOW);
  39. dev->set_retries(2);
  40. dev->get_semaphore()->give();
  41. dev->register_periodic_callback(1000000UL/50U,
  42. FUNCTOR_BIND_MEMBER(&AP_Airspeed_DLVR::timer, void));
  43. return true;
  44. }
  45. #define STATUS_SHIFT 30
  46. #define TEMPERATURE_SHIFT 5
  47. #define TEMPERATURE_MASK ((1 << 11) - 1)
  48. #define PRESSURE_SHIFT 16
  49. #define PRESSURE_MASK ((1 << 14) - 1)
  50. #define DLVR_OFFSET 8192.0f
  51. #define DLVR_SCALE 16384.0f
  52. // 50Hz timer
  53. void AP_Airspeed_DLVR::timer()
  54. {
  55. uint8_t raw_bytes[4];
  56. if (!dev->read((uint8_t *)&raw_bytes, sizeof(raw_bytes))) {
  57. return;
  58. }
  59. uint32_t data = (raw_bytes[0] << 24) |
  60. (raw_bytes[1] << 16) |
  61. (raw_bytes[2] << 8) |
  62. raw_bytes[3];
  63. if ((data >> STATUS_SHIFT)) {
  64. // anything other then 00 in the status bits is an error
  65. Debug("DLVR: Bad status read %d", data >> STATUS_SHIFT);
  66. return;
  67. }
  68. uint32_t pres_raw = (data >> PRESSURE_SHIFT) & PRESSURE_MASK;
  69. uint32_t temp_raw = (data >> TEMPERATURE_SHIFT) & TEMPERATURE_MASK;
  70. float press_h2o = 1.25f * 2.0f * range_inH2O * ((pres_raw - DLVR_OFFSET) / DLVR_SCALE);
  71. float temp = temp_raw * (200.0f / 2047.0f) - 50.0f;
  72. WITH_SEMAPHORE(sem);
  73. pressure_sum += INCH_OF_H2O_TO_PASCAL * press_h2o;
  74. temperature_sum += temp;
  75. press_count++;
  76. temp_count++;
  77. last_sample_time_ms = AP_HAL::millis();
  78. }
  79. // return the current differential_pressure in Pascal
  80. bool AP_Airspeed_DLVR::get_differential_pressure(float &_pressure)
  81. {
  82. if ((AP_HAL::millis() - last_sample_time_ms) > 100) {
  83. return false;
  84. }
  85. {
  86. WITH_SEMAPHORE(sem);
  87. if (press_count > 0) {
  88. pressure = pressure_sum / press_count;
  89. press_count = 0;
  90. pressure_sum = 0;
  91. }
  92. }
  93. _pressure = pressure;
  94. return true;
  95. }
  96. // return the current temperature in degrees C, if available
  97. bool AP_Airspeed_DLVR::get_temperature(float &_temperature)
  98. {
  99. if ((AP_HAL::millis() - last_sample_time_ms) > 100) {
  100. return false;
  101. }
  102. WITH_SEMAPHORE(sem);
  103. if (temp_count > 0) {
  104. temperature = temperature_sum / temp_count;
  105. temp_count = 0;
  106. temperature_sum = 0;
  107. }
  108. _temperature = temperature;
  109. return true;
  110. }