AP_BattMonitor_FuelFlow.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include <AP_HAL/AP_HAL.h>
  2. #include "AP_BattMonitor_FuelFlow.h"
  3. #include <GCS_MAVLink/GCS.h>
  4. /*
  5. "battery" monitor for liquid fuel flow systems that give a pulse on
  6. a pin for fixed volumes of fuel.
  7. this driver assumes that BATTx_AMP_PERVLT is set to give the
  8. number of millilitres per pulse.
  9. Output is:
  10. - current in Amps maps to in litres/hour
  11. - consumed mAh is in consumed millilitres
  12. - fixed 1.0v voltage
  13. */
  14. extern const AP_HAL::HAL& hal;
  15. #define FUELFLOW_MIN_PULSE_DELTA_US 10
  16. /// Constructor
  17. AP_BattMonitor_FuelFlow::AP_BattMonitor_FuelFlow(AP_BattMonitor &mon,
  18. AP_BattMonitor::BattMonitor_State &mon_state,
  19. AP_BattMonitor_Params &params) :
  20. AP_BattMonitor_Backend(mon, mon_state, params)
  21. {
  22. _state.voltage = 1.0; // show a fixed voltage of 1v
  23. // we can't tell if it is healthy as we expect zero pulses when no
  24. // fuel is flowing
  25. _state.healthy = true;
  26. }
  27. /*
  28. handle interrupt on an instance
  29. */
  30. void AP_BattMonitor_FuelFlow::irq_handler(uint8_t pin, bool pin_state, uint32_t timestamp)
  31. {
  32. if (irq_state.last_pulse_us == 0) {
  33. irq_state.last_pulse_us = timestamp;
  34. return;
  35. }
  36. uint32_t delta = timestamp - irq_state.last_pulse_us;
  37. if (delta < FUELFLOW_MIN_PULSE_DELTA_US) {
  38. // simple de-bounce
  39. return;
  40. }
  41. irq_state.pulse_count++;
  42. irq_state.total_us += delta;
  43. irq_state.last_pulse_us = timestamp;
  44. }
  45. /*
  46. read - read the "voltage" and "current"
  47. */
  48. void AP_BattMonitor_FuelFlow::read()
  49. {
  50. int8_t pin = _params._curr_pin;
  51. if (last_pin != pin) {
  52. // detach from last pin
  53. if (last_pin != -1) {
  54. hal.gpio->detach_interrupt(last_pin);
  55. }
  56. // attach to new pin
  57. last_pin = pin;
  58. if (last_pin > 0) {
  59. hal.gpio->pinMode(last_pin, HAL_GPIO_INPUT);
  60. if (!hal.gpio->attach_interrupt(
  61. last_pin,
  62. FUNCTOR_BIND_MEMBER(&AP_BattMonitor_FuelFlow::irq_handler, void, uint8_t, bool, uint32_t),
  63. AP_HAL::GPIO::INTERRUPT_RISING)) {
  64. gcs().send_text(MAV_SEVERITY_WARNING, "FuelFlow: Failed to attach to pin %u", last_pin);
  65. }
  66. }
  67. }
  68. uint32_t now_us = AP_HAL::micros();
  69. if (_state.last_time_micros == 0) {
  70. // need initial time, so we can work out expected pulse rate
  71. _state.last_time_micros = now_us;
  72. return;
  73. }
  74. float dt = (now_us - _state.last_time_micros) * 1.0e-6f;
  75. if (dt < 1 && irq_state.pulse_count == 0) {
  76. // we allow for up to 1 second with no pulses to cope with low
  77. // flow idling. After that we will start reading zero current
  78. return;
  79. }
  80. // get the IRQ state with interrupts disabled
  81. struct IrqState state;
  82. void *irqstate = hal.scheduler->disable_interrupts_save();
  83. state = irq_state;
  84. irq_state.pulse_count = 0;
  85. irq_state.total_us = 0;
  86. hal.scheduler->restore_interrupts(irqstate);
  87. /*
  88. this driver assumes that BATTx_AMP_PERVLT is set to give the
  89. number of millilitres per pulse.
  90. */
  91. float irq_dt = state.total_us * 1.0e-6f;
  92. float litres, litres_pec_sec;
  93. if (state.pulse_count == 0) {
  94. litres = 0;
  95. litres_pec_sec = 0;
  96. } else {
  97. litres = state.pulse_count * _params._curr_amp_per_volt * 0.001f;
  98. litres_pec_sec = litres / irq_dt;
  99. }
  100. _state.last_time_micros = now_us;
  101. // map amps to litres/hour
  102. _state.current_amps = litres_pec_sec * (60*60);
  103. // map consumed_mah to consumed millilitres
  104. _state.consumed_mah += litres * 1000;
  105. // map consumed_wh using fixed voltage of 1
  106. _state.consumed_wh = _state.consumed_mah;
  107. }