AP_Baro_MPM258.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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_MPM258.h"
  14. #include <utility>
  15. #include <stdio.h>
  16. #include <AP_Math/AP_Math.h>
  17. #include <AP_Math/crc.h>
  18. #include "../../ArduSub/Sub.h"
  19. extern const AP_HAL::HAL &hal;
  20. static const uint8_t MPM258_ADDR =0x6D;
  21. static const uint8_t MPM258_ADDR_CMD_I2C_WRITE =0xDA;
  22. static const uint8_t MPM258_ADDR_CMD_I2C_READ= 0xDB;
  23. /* write to one of these addresses to start pressure conversion */
  24. static const uint8_t ADDR_CMD_PRESS1= 0x06;
  25. static const uint8_t ADDR_CMD_PRESS2= 0x07;
  26. static const uint8_t ADDR_CMD_PRESS3= 0x08;
  27. /* write to one of these addresses to start temperature conversion */
  28. static const uint8_t ADDR_CMD_TEMPRATURE1= 0x09;
  29. static const uint8_t ADDR_CMD_TEMPRATURE2= 0x0A;
  30. static const uint8_t ADDR_CMD_TEMPRATURE3= 0x0B;
  31. /*
  32. constructor
  33. */
  34. AP_Baro_MPM258::AP_Baro_MPM258(AP_Baro &baro, AP_HAL::OwnPtr<AP_HAL::Device> dev)
  35. : AP_Baro_Backend(baro)
  36. , _dev(std::move(dev))
  37. {
  38. }
  39. AP_Baro_Backend *AP_Baro_MPM258::probe(AP_Baro &baro,
  40. AP_HAL::OwnPtr<AP_HAL::Device> dev)
  41. {
  42. if (!dev) {
  43. return nullptr;
  44. }
  45. AP_Baro_MPM258 *sensor = new AP_Baro_MPM258(baro, std::move(dev));
  46. if (!sensor || !sensor->_init()) {
  47. delete sensor;
  48. return nullptr;
  49. }
  50. return sensor;
  51. }
  52. bool AP_Baro_MPM258::_init()
  53. {
  54. //uint8_t press_data[3];
  55. //uint8_t temp_data[3];
  56. if (!_dev) {
  57. return false;
  58. }
  59. if (!_dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
  60. AP_HAL::panic("PANIC: AP_Baro_MPM258: failed to take serial semaphore for init");
  61. }
  62. // high retries for init
  63. _dev->set_retries(10);
  64. //如果不能发送成功说明这个I2C口没有传感器
  65. if(!_dev->transfer(&MPM258_ADDR_CMD_I2C_WRITE, 1, nullptr, 0)){
  66. _dev->get_semaphore()->give();
  67. return false;
  68. }
  69. _state = 0;
  70. memset(&_accum, 0, sizeof(_accum));
  71. _instance = _frontend.register_sensor();
  72. _frontend.set_type(_instance, AP_Baro::BARO_TYPE_WATER);
  73. // lower retries for run
  74. _dev->set_retries(3);
  75. _dev->get_semaphore()->give();
  76. hal.scheduler->delay(150);
  77. /* Request 50HZpdate */
  78. _dev->register_periodic_callback(20 * AP_USEC_PER_MSEC,
  79. FUNCTOR_BIND_MEMBER(&AP_Baro_MPM258::_timer, void));
  80. return true;
  81. }
  82. /*
  83. * Read the sensor with a state machine
  84. * We read one time temperature (state=0) and then 4 times pressure (states 1-4)
  85. *
  86. * Temperature is used to calculate the compensated pressure and doesn't vary
  87. * as fast as pressure. Hence we reuse the same temperature for 4 samples of
  88. * pressure.
  89. */
  90. void AP_Baro_MPM258::_timer(void)
  91. {
  92. _read();
  93. }
  94. void AP_Baro_MPM258::_update_and_wrap_accumulator(int32_t pressure, int32_t temperature, uint8_t max_count)
  95. {
  96. _accum.sum_pressure += pressure;
  97. _accum.sum_temperature += temperature;
  98. _accum.num_samples += 1;
  99. if (_accum.num_samples == max_count) {
  100. _accum.sum_pressure /= 2;
  101. _accum.sum_temperature /= 2;
  102. _accum.num_samples /= 2;
  103. }
  104. }
  105. bool AP_Baro_MPM258::_read(){
  106. uint8_t press_data[3]={0,0,0};
  107. uint8_t temp_data[3] = {0,0,0};
  108. uint32_t pressure_raw =0;
  109. uint32_t temperature_raw =0;
  110. _dev->transfer(&MPM258_ADDR_CMD_I2C_WRITE, 1, nullptr, 0);
  111. _dev->transfer(&ADDR_CMD_PRESS1, 1, nullptr, 0);
  112. if(!_dev->transfer(&MPM258_ADDR_CMD_I2C_READ, 0,press_data, 3))
  113. {
  114. return FALSE;
  115. }
  116. _dev->transfer(&MPM258_ADDR_CMD_I2C_WRITE, 1, nullptr, 0);
  117. _dev->transfer(&ADDR_CMD_TEMPRATURE1, 1, nullptr, 0);
  118. if(!_dev->transfer(&MPM258_ADDR_CMD_I2C_READ, 0,temp_data, 3))
  119. {
  120. return FALSE;
  121. }
  122. WITH_SEMAPHORE(_sem);
  123. pressure_raw = ((int32_t)press_data[0] << 16) |((int32_t)press_data[1] << 8) | press_data[2];
  124. temperature_raw = ((int32_t)temp_data[0] << 16) |((int32_t)temp_data[1] << 8) | temp_data[2];
  125. _update_and_wrap_accumulator(pressure_raw, temperature_raw, 128);
  126. return TRUE;
  127. }
  128. void AP_Baro_MPM258::update()
  129. {
  130. int32_t sum_pressure, sum_temperature;
  131. int32_t num_samples;
  132. {
  133. WITH_SEMAPHORE(_sem);
  134. if (_accum.num_samples == 0) {
  135. return;
  136. }
  137. sum_pressure = _accum.sum_pressure;
  138. sum_temperature = _accum.sum_temperature;
  139. num_samples = _accum.num_samples;
  140. memset(&_accum, 0, sizeof(_accum));
  141. }
  142. int32_t raw_pressure_avg = sum_pressure / num_samples;
  143. int32_t raw_temperature_avg = sum_temperature / num_samples;
  144. if(raw_pressure_avg>8388608){
  145. raw_pressure_avg = raw_pressure_avg- 16777216;
  146. }
  147. if(raw_temperature_avg>8388608){
  148. raw_temperature_avg = raw_temperature_avg- 16777216;
  149. }
  150. float pressure = 1000000*((float)raw_pressure_avg/8388608-0.1)/(0.9-0.1);//量程是1MPA
  151. float temperature = (float)raw_temperature_avg/65536+25;
  152. static int16_t cnt = 0;
  153. cnt++;
  154. if(cnt>20){
  155. cnt = 0;
  156. gcs().send_text(MAV_SEVERITY_INFO, "pressure %d %d %f %f.",raw_pressure_avg,raw_temperature_avg,pressure,temperature);
  157. }
  158. _copy_to_frontend(_instance, pressure, temperature);
  159. }