Path: blob/master/libraries/AP_BattMonitor/AP_BattMonitor_Generator.cpp
9417 views
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/1415#include "AP_BattMonitor_config.h"1617#if AP_BATTERY_GENERATOR_ENABLED1819#include <AP_Common/AP_Common.h>20#include <AP_Math/AP_Math.h>2122#include "AP_BattMonitor_Generator.h"2324/*25Fuel class26*/27// This is where we tell the battery monitor 'we have current' if we want to report a fuel level remaining28bool AP_BattMonitor_Generator_FuelLevel::has_current(void) const29{30// If the generator has fuel remaining we must also state that we have current31return has_consumed_energy();32}3334// This is where we tell the battery monitor 'we have consumed energy' if we want to report a fuel level remaining35bool AP_BattMonitor_Generator_FuelLevel::has_consumed_energy(void) const36{37// Get pointer to generator singleton38AP_Generator *generator = AP::generator();3940if (generator == nullptr) {41return false;42}4344// Use consumed_mAh in BattMonitor to display fuel remaining45return generator->has_consumed_energy();46}4748bool AP_BattMonitor_Generator_FuelLevel::reset_remaining(float percentage)49{50// Get pointer to generator singleton51AP_Generator *generator = AP::generator();5253if (generator == nullptr) {54return false;55}5657if (generator->reset_consumed_energy()) {58percentage = constrain_float(percentage, 0.0, 100.0);59_initial_fuel_pct = percentage;60return true;61}6263return false;64}6566void AP_BattMonitor_Generator_FuelLevel::init()67{68}6970// Read the fuel level. Should be called at 10hz71void AP_BattMonitor_Generator_FuelLevel::read()72{73_state.healthy = false;7475// Get pointer to generator singleton76AP_Generator *generator = AP::generator();7778// Not healthy if we can't find a generator79if (generator == nullptr) {80return;81}8283if (!generator->healthy()) {84return;85}8687if (generator->has_fuel_remaining()) {88// Set params for users:89// Fuel level is only reported as a percentage90_params._pack_capacity.set(100);91// Fuel only reports a fixed 1v, don't want batt monitor failsafes on this instance92_params._low_voltage.set(0);93_params._critical_voltage.set(0);94}9596// As this is a battery monitor instance report voltage97// Report fixed voltage of 1V98_state.voltage = 1.0f;99100// This is a bodge to display tank level as a percentage on GCS. Users should set _params.pack_capacity == 100 to get a clear percentage in GCS101if (generator->has_fuel_remaining()) {102_state.consumed_mah = (1 - generator->get_fuel_remaining()) * _params._pack_capacity.get();103} else {104_state.consumed_mah = generator->get_batt_consumed();105}106107// If we got this far then must be healthy108_state.healthy = true;109_state.last_time_micros = AP_HAL::micros();110}111112// capacity_remaining_ml - returns true if the capacity remaining in (mL) is valid and writes to capacity_ml113bool AP_BattMonitor_Generator_FuelLevel::capacity_remaining_ml(float &capacity_ml) const114{115// we consider anything under 10 ml as being an invalid capacity and so will be our measurement of remaining capacity116if ( _params._pack_capacity <= 10) {117return false;118}119120// we get the initial fuel multiplying pack capacity parameter by initial fuel percentage.121// this initial fuel percentage will be 100% by default, but we can change it using the122// mavlink command MAV_CMD_BATTERY_RESET123const float initial_fuel = _params._pack_capacity * _initial_fuel_pct * 0.01;124125// to get the actual remaining level we need to substract the consumed ml126capacity_ml = initial_fuel - _state.consumed_mah;127128return true;129}130131bool AP_BattMonitor_Generator_FuelLevel::capacity_remaining_pct(uint8_t &percentage) const132{133// Get pointer to generator singleton134AP_Generator *generator = AP::generator();135136// If generator is not setup or not healthy, use the base class method137if (generator == nullptr) {138return AP_BattMonitor_Backend::capacity_remaining_pct(percentage);139}140141if (!generator->healthy()) {142return AP_BattMonitor_Backend::capacity_remaining_pct(percentage);143}144145// If generator doesn't have its own pct count, use ours146if (!generator->has_fuel_remaining()) {147float remaining_ml;148// return false if _params._pack_capacity is too small149if (!capacity_remaining_ml(remaining_ml)) {150return false;151}152153// now we get the percentage according to tank capacity (pack_capacity parameter)154percentage = constrain_float(100 * remaining_ml / _params._pack_capacity, 0, UINT8_MAX);;155return true;156157// Otherwise use generator's own percentage158} else {159percentage = generator->get_fuel_remaining() * 100; // convert from scale to actual percentage160return true;161}162}163164AP_BattMonitor::Failsafe AP_BattMonitor_Generator_FuelLevel::update_failsafes()165{166AP_Generator *generator = AP::generator();167if (generator == nullptr) {168return AP_BattMonitor::Failsafe::None;169}170171if (generator->has_fuel_remaining()) {172// work is being done for us by the generator173return AP_BattMonitor_Backend::update_failsafes();174}175176// If we are using our own calculated percentage, not the one from177// the generator, manage capacity failsafes here178float remaining_ml;179// only returns false if _params._pack_capacity is too small less than 10 mL180if (!capacity_remaining_ml(remaining_ml)) {181return AP_BattMonitor::Failsafe::Critical;182}183184if (remaining_ml < _params._critical_capacity) {185return AP_BattMonitor::Failsafe::Critical;186}187188if (remaining_ml < _params._low_capacity) {189return AP_BattMonitor::Failsafe::Low;190}191192return AP_BattMonitor::Failsafe::None;193}194195/*196Electrical class197*/198bool AP_BattMonitor_Generator_Elec::has_current(void) const199{200// Get pointer to generator singleton201AP_Generator *generator = AP::generator();202203if (generator == nullptr) {204return false;205}206207return generator->has_current();208}209210bool AP_BattMonitor_Generator_Elec::has_consumed_energy(void) const211{212// Get pointer to generator singleton213AP_Generator *generator = AP::generator();214215if (generator == nullptr) {216return false;217}218219return generator->has_consumed_energy();220}221222// Read the electrical measurements from the generator223void AP_BattMonitor_Generator_Elec::read()224{225_state.healthy = false;226227// Get pointer to generator singleton228AP_Generator *generator = AP::generator();229230// Not healthy if we can't find a generator231if (generator == nullptr) {232return;233}234235if (!generator->healthy()) {236return;237}238239// Update readings240_state.voltage = generator->get_voltage();241242_state.current_amps = generator->get_current();243244// Always reset consumed value, integration is done in AP_Generator library245_state.consumed_mah = generator->get_batt_consumed();246_state.consumed_wh = 0.001f * _state.consumed_mah * _state.voltage;247248// If we got this far then must be healthy249_state.healthy = true;250_state.last_time_micros = AP_HAL::micros();251}252253AP_BattMonitor::Failsafe AP_BattMonitor_Generator_Elec::update_failsafes()254{255AP_BattMonitor::Failsafe failsafe = AP_BattMonitor::Failsafe::None;256257AP_Generator *generator = AP::generator();258259// Only check for failsafes on the electrical monitor260// no point in having the same failsafe on two battery monitors261if (generator != nullptr) {262failsafe = generator->update_failsafes();263}264return MAX(AP_BattMonitor_Backend::update_failsafes(), failsafe);265}266#endif // AP_BATTERY_GENERATOR_ENABLED267268269