LCOV - code coverage report
Current view: top level - AP_BattMonitor - AP_BattMonitor.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 17 22 77.3 %
Date: 2026-09-09 11:02:08 Functions: 13 17 76.5 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "AP_BattMonitor_config.h"
       4             : 
       5             : #if AP_BATTERY_ENABLED
       6             : 
       7             : #include <AP_Common/AP_Common.h>
       8             : #include <AP_Param/AP_Param.h>
       9             : #include <AP_Math/AP_Math.h>
      10             : #include <AP_TemperatureSensor/AP_TemperatureSensor_config.h>
      11             : #include <GCS_MAVLink/GCS_MAVLink.h>
      12             : #include "AP_BattMonitor_Params.h"
      13             : 
      14             : // first monitor is always the primary monitor
      15             : #define AP_BATT_PRIMARY_INSTANCE            0
      16             : 
      17             : #define AP_BATT_SERIAL_NUMBER_DEFAULT       -1
      18             : 
      19             : #define AP_BATT_MONITOR_TIMEOUT             5000
      20             : 
      21             : #define AP_BATT_MONITOR_RES_EST_TC_1        0.5f
      22             : #define AP_BATT_MONITOR_RES_EST_TC_2        0.1f
      23             : 
      24             : #if HAL_PROGRAM_SIZE_LIMIT_KB > 1024
      25             : #define AP_BATT_MONITOR_CELLS_MAX           14
      26             : #else
      27             : #define AP_BATT_MONITOR_CELLS_MAX           12
      28             : #endif
      29             : 
      30             : // declare backend class
      31             : class AP_BattMonitor_Backend;
      32             : class AP_BattMonitor_Analog;
      33             : class AP_BattMonitor_SMBus;
      34             : class AP_BattMonitor_SMBus_Solo;
      35             : class AP_BattMonitor_SMBus_Generic;
      36             : class AP_BattMonitor_SMBus_Maxell;
      37             : class AP_BattMonitor_SMBus_Rotoye;
      38             : class AP_BattMonitor_DroneCAN;
      39             : class AP_BattMonitor_Generator;
      40             : class AP_BattMonitor_INA2XX;
      41             : class AP_BattMonitor_INA239;
      42             : class AP_BattMonitor_LTC2946;
      43             : class AP_BattMonitor_Torqeedo;
      44             : class AP_BattMonitor_FuelLevel_Analog;
      45             : class AP_BattMonitor_EFI;
      46             : class AP_BattMonitor_Scripting;
      47             : 
      48             : 
      49             : class AP_BattMonitor
      50             : {
      51             :     friend class AP_BattMonitor_Backend;
      52             :     friend class AP_BattMonitor_Analog;
      53             :     friend class AP_BattMonitor_SMBus;
      54             :     friend class AP_BattMonitor_SMBus_Solo;
      55             :     friend class AP_BattMonitor_SMBus_Generic;
      56             :     friend class AP_BattMonitor_SMBus_Maxell;
      57             :     friend class AP_BattMonitor_SMBus_Rotoye;
      58             :     friend class AP_BattMonitor_DroneCAN;
      59             :     friend class AP_BattMonitor_Sum;
      60             :     friend class AP_BattMonitor_FuelFlow;
      61             :     friend class AP_BattMonitor_FuelLevel_PWM;
      62             :     friend class AP_BattMonitor_Generator;
      63             :     friend class AP_BattMonitor_EFI;
      64             :     friend class AP_BattMonitor_INA2XX;
      65             :     friend class AP_BattMonitor_INA239;
      66             :     friend class AP_BattMonitor_LTC2946;
      67             :     friend class AP_BattMonitor_AD7091R5;
      68             :     friend class AP_BattMonitor_INA3221;
      69             : 
      70             :     friend class AP_BattMonitor_Torqeedo;
      71             :     friend class AP_BattMonitor_FuelLevel_Analog;
      72             :     friend class AP_BattMonitor_Synthetic_Current;
      73             :     friend class AP_BattMonitor_Scripting;
      74             : 
      75             : public:
      76             : 
      77             :     // battery failsafes must be defined in levels of severity so that vehicles wont fall backwards
      78             :     enum class Failsafe : uint8_t {
      79             :         None = 0,
      80             :         Unhealthy,
      81             :         Low,
      82             :         Critical
      83             :     };
      84             : 
      85             :     // power states
      86             :     enum class ChargingState : uint8_t {
      87             :         UNKNOWN = 0,
      88             :         IDLE,
      89             :         CHARGING,
      90             :         DISCHARGING
      91             :     };
      92             : 
      93             :     // Battery monitor driver types
      94             :     using Type = AP_BattMonitor_Params::Type;
      95             : 
      96             :     FUNCTOR_TYPEDEF(battery_failsafe_handler_fn_t, void, const char *, const int8_t);
      97             : 
      98             :     AP_BattMonitor(uint32_t log_battery_bit, battery_failsafe_handler_fn_t battery_failsafe_handler_fn, const int8_t *failsafe_priorities);
      99             : 
     100             :     /* Do not allow copies */
     101             :     CLASS_NO_COPY(AP_BattMonitor);
     102             : 
     103    65052479 :     static AP_BattMonitor *get_singleton() {
     104    65052479 :         return _singleton;
     105             :     }
     106             : 
     107             :     // cell voltages in millivolts
     108             :     struct cells {
     109             :         uint16_t cells[AP_BATT_MONITOR_CELLS_MAX];
     110             :     };
     111             : 
     112             :     // The BattMonitor_State structure is filled in by the backend driver
     113             :     struct BattMonitor_State {
     114             :         cells       cell_voltages;             // battery cell voltages in millivolts, 10 cells matches the MAVLink spec
     115             :         float       voltage;                   // voltage in volts
     116             :         float       current_amps;              // current in amperes
     117             :         float       consumed_mah;              // total current draw in milliamp hours since start-up
     118             :         float       consumed_wh;               // total energy consumed in Wh since start-up
     119             :         uint32_t    last_time_micros;          // time when voltage and current was last read in microseconds
     120             :         uint32_t    low_voltage_start_ms;      // time when voltage dropped below the minimum in milliseconds
     121             :         uint32_t    critical_voltage_start_ms; // critical voltage failsafe start timer in milliseconds
     122             :         float       temperature;               // battery temperature in degrees Celsius
     123             : #if AP_TEMPERATURE_SENSOR_ENABLED
     124             :         bool        temperature_external_use;
     125             :         float       temperature_external;      // battery temperature set by an external source in degrees Celsius
     126             : #endif
     127             :         uint32_t    temperature_time;          // timestamp of the last received temperature message
     128             :         float       voltage_resting_estimate;  // voltage with sag removed based on current and resistance estimate in Volt
     129             :         float       resistance;                // resistance, in Ohms, calculated by comparing resting voltage vs in flight voltage
     130             :         Failsafe failsafe;                     // stage failsafe the battery is in
     131             :         bool        healthy;                   // battery monitor is communicating correctly
     132             :         uint32_t    last_healthy_ms;           // Time when monitor was last healthy
     133             :         bool        is_powering_off;           // true when power button commands power off
     134             :         bool        powerOffNotified;          // only send powering off notification once
     135             :         uint32_t    time_remaining;            // remaining battery time
     136             :         bool        has_time_remaining;        // time_remaining is only valid if this is true
     137             :         uint8_t     state_of_health_pct;       // state of health (SOH) in percent
     138             :         bool        has_state_of_health_pct;   // state_of_health_pct is only valid if this is true
     139             :         ChargingState charging_state;          // Charging state (unknown, idle, charging, discharging)
     140             :         uint8_t     instance;                  // instance number of this backend
     141             :         Type        type;                      // allocated instance type
     142             :         const struct AP_Param::GroupInfo *var_info;
     143             :     };
     144             : 
     145             :     static const struct AP_Param::GroupInfo *backend_var_info[AP_BATT_MONITOR_MAX_INSTANCES];
     146             : 
     147             :     // Return the number of battery monitor instances
     148     1121382 :     uint8_t num_instances(void) const { return _num_instances; }
     149             : 
     150             :     // detect and initialise any available battery monitors
     151             :     __INITFUNC__ void init();
     152             : 
     153             :     /// Read the battery voltage and current for all batteries.  Should be called at 10hz
     154             :     void read();
     155             : 
     156             :     // healthy - returns true if monitor is functioning
     157             :     bool healthy(uint8_t instance) const;
     158             : 
     159             :     // return true if all configured battery monitors are healthy
     160             :     bool healthy() const;
     161             : 
     162             :     /// voltage - returns battery voltage in volts
     163             :     float voltage(uint8_t instance) const;
     164     1388611 :     float voltage() const { return voltage(AP_BATT_PRIMARY_INSTANCE); }
     165             : 
     166             :     // voltage for a GCS, may be resistance compensated
     167             :     float gcs_voltage(uint8_t instance) const;
     168     1116947 :     float gcs_voltage(void) const { return gcs_voltage(AP_BATT_PRIMARY_INSTANCE); }
     169             : 
     170             :     /// get voltage with sag removed (based on battery current draw and resistance)
     171             :     /// this will always be greater than or equal to the raw voltage
     172             :     float voltage_resting_estimate(uint8_t instance) const;
     173             :     float voltage_resting_estimate() const { return voltage_resting_estimate(AP_BATT_PRIMARY_INSTANCE); }
     174             : 
     175             :     /// current_amps - returns the instantaneous current draw in amperes
     176             :     bool current_amps(float &current, const uint8_t instance = AP_BATT_PRIMARY_INSTANCE) const WARN_IF_UNUSED;
     177             : 
     178             :     /// consumed_mah - returns total current drawn since start-up in milliampere.hours
     179             :     bool consumed_mah(float &mah, const uint8_t instance = AP_BATT_PRIMARY_INSTANCE) const WARN_IF_UNUSED;
     180             : 
     181             :     /// consumed_wh - returns total energy drawn since start-up in watt.hours
     182             :     bool consumed_wh(float&wh, const uint8_t instance = AP_BATT_PRIMARY_INSTANCE) const WARN_IF_UNUSED;
     183             : 
     184             :     /// capacity_remaining_pct - returns true if the percentage is valid and writes to percentage argument
     185             :     virtual bool capacity_remaining_pct(uint8_t &percentage, uint8_t instance) const WARN_IF_UNUSED;
     186         671 :     bool capacity_remaining_pct(uint8_t &percentage) const WARN_IF_UNUSED { return capacity_remaining_pct(percentage, AP_BATT_PRIMARY_INSTANCE); }
     187             : 
     188             :     /// time_remaining - returns remaining battery time
     189             :     bool time_remaining(uint32_t &seconds, const uint8_t instance = AP_BATT_PRIMARY_INSTANCE) const WARN_IF_UNUSED;
     190             : 
     191             :     /// pack_capacity_mah - returns the capacity of the battery pack in mAh when the pack is full
     192             :     int32_t pack_capacity_mah(uint8_t instance) const;
     193         126 :     int32_t pack_capacity_mah() const { return pack_capacity_mah(AP_BATT_PRIMARY_INSTANCE); }
     194             :  
     195             :     /// returns true if a battery failsafe has ever been triggered
     196     1359585 :     bool has_failsafed(void) const { return _has_triggered_failsafe; };
     197             : 
     198             :     /// returns the highest failsafe action that has been triggered
     199           1 :     int8_t get_highest_failsafe_priority(void) const { return _highest_failsafe_priority; };
     200             : 
     201             :     /// configured_type - returns battery monitor type as configured in parameters
     202    17324368 :     Type configured_type(uint8_t instance) const {
     203    17324368 :         return (Type)_params[instance]._type.get();
     204             :     }
     205             :     /// allocated_type - returns battery monitor type as allocated
     206     4018470 :     Type allocated_type(uint8_t instance) const {
     207     4018470 :         return state[instance].type;
     208             :     }
     209             : 
     210             :     /// get_serial_number - returns battery serial number
     211             :     int32_t get_serial_number() const { return get_serial_number(AP_BATT_PRIMARY_INSTANCE); }
     212           0 :     int32_t get_serial_number(uint8_t instance) const {
     213           0 :         return _params[instance]._serial_number;
     214             :     }
     215             : 
     216             :     /// true when (voltage * current) > watt_max
     217             :     bool overpower_detected() const;
     218             :     bool overpower_detected(uint8_t instance) const;
     219             : 
     220             : #if AP_BATTERY_WATT_MAX_ENABLED
     221             :     /// get_watt_max - returns maximum power in watts
     222      628798 :     float get_watt_max() const { return get_watt_max(AP_BATT_PRIMARY_INSTANCE); }
     223      628798 :     float get_watt_max(uint8_t instance) const {
     224      628798 :         return _params[instance]._watt_max;
     225             :     }
     226             : #endif // AP_BATTERY_WATT_MAX_ENABLED
     227             : 
     228             :     // cell voltages in millivolts
     229           0 :     bool has_cell_voltages() const { return has_cell_voltages(AP_BATT_PRIMARY_INSTANCE); }
     230             :     bool has_cell_voltages(const uint8_t instance) const;
     231           0 :     const cells &get_cell_voltages() const { return get_cell_voltages(AP_BATT_PRIMARY_INSTANCE); }
     232             :     const cells &get_cell_voltages(const uint8_t instance) const;
     233             : 
     234             :     // get once cell voltage (for scripting)
     235             :     bool get_cell_voltage(uint8_t instance, uint8_t cell, float &voltage) const;
     236             : 
     237             :     // temperature
     238             :     bool get_temperature(float &temperature) const { return get_temperature(temperature, AP_BATT_PRIMARY_INSTANCE); }
     239             :     bool get_temperature(float &temperature, const uint8_t instance) const;
     240             : #if AP_TEMPERATURE_SENSOR_ENABLED
     241             :     bool set_temperature(const float temperature, const uint8_t instance);
     242             :     bool set_temperature_by_serial_number(const float temperature, const int32_t serial_number);
     243             : #endif
     244             : 
     245             :     // Set powered state (Solar Panels, BMS)
     246             :     void set_powered_state_to_all(const bool power_on);
     247             :     void set_powered_state(const uint8_t instance, const bool power_on);
     248             : 
     249             :     bool option_is_set(uint8_t instance, AP_BattMonitor_Params::Options option) const;
     250             : 
     251             :     // cycle count
     252             :     bool get_cycle_count(uint8_t instance, uint16_t &cycles) const;
     253             : 
     254             :     // get battery resistance estimate in ohms
     255             :     float get_resistance() const { return get_resistance(AP_BATT_PRIMARY_INSTANCE); }
     256       94857 :     float get_resistance(uint8_t instance) const { return state[instance].resistance; }
     257             : 
     258             :     // returns false if we fail arming checks, in which case the buffer will be populated with a failure message
     259             :     bool arming_checks(size_t buflen, char *buffer) const;
     260             : 
     261             :     // sends powering off mavlink broadcasts and sets notify flag
     262             :     void checkPoweringOff(void);
     263             : 
     264             :     // reset battery remaining percentage
     265             :     bool reset_remaining_mask(uint16_t battery_mask, float percentage);
     266           0 :     bool reset_remaining(uint8_t instance, float percentage) { return reset_remaining_mask(1U<<instance, percentage);}
     267             : 
     268             :     // Returns mavlink charge state
     269             :     MAV_BATTERY_CHARGE_STATE get_mavlink_charge_state(const uint8_t instance) const;
     270             : 
     271             :     // Returns mavlink fault state
     272             :     uint32_t get_mavlink_fault_bitmask(const uint8_t instance) const;
     273             : 
     274             :     // return true if state of health (as a percentage) can be provided and fills in soh_pct argument
     275             :     bool get_state_of_health_pct(uint8_t instance, uint8_t &soh_pct) const;
     276             : 
     277             :     // get charging state (idle, charging, discharging)
     278             :     ChargingState get_charging_state() const { return get_charging_state(AP_BATT_PRIMARY_INSTANCE); }
     279             :     ChargingState get_charging_state(uint8_t instance) const { return state[instance].charging_state; }
     280             : 
     281             :     static const struct AP_Param::GroupInfo var_info[];
     282             : 
     283             : #if AP_BATTERY_SCRIPTING_ENABLED
     284             :     bool handle_scripting(uint8_t idx, const struct BattMonitorScript_State &state);
     285             : #endif
     286             : 
     287             :     // set battery BMS sleep timeout in seconds
     288             :     // set to zero to disable sleep
     289             :     void set_sleep_timeout(uint16_t timeout_sec) { return set_sleep_timeout(AP_BATT_PRIMARY_INSTANCE, timeout_sec); }
     290             :     void set_sleep_timeout(uint8_t instance, uint16_t timeout_sec);
     291             : 
     292             : protected:
     293             : 
     294             :     /// parameters
     295             :     AP_BattMonitor_Params _params[AP_BATT_MONITOR_MAX_INSTANCES];
     296             : 
     297             : private:
     298             :     static AP_BattMonitor *_singleton;
     299             : 
     300             :     BattMonitor_State state[AP_BATT_MONITOR_MAX_INSTANCES];
     301             :     AP_BattMonitor_Backend *drivers[AP_BATT_MONITOR_MAX_INSTANCES];
     302             :     uint32_t    _log_battery_bit;
     303             :     uint8_t     _num_instances;                                     /// number of monitors
     304             : 
     305             :     /// returns the failsafe state of the battery
     306             :     Failsafe check_failsafe(const uint8_t instance);
     307             :     void check_failsafes(void); // checks all batteries failsafes
     308             : 
     309             :     battery_failsafe_handler_fn_t _battery_failsafe_handler_fn;
     310             :     const int8_t *_failsafe_priorities; // array of failsafe priorities, sorted highest to lowest priority, -1 indicates no more entries
     311             : 
     312             :     int8_t      _highest_failsafe_priority; // highest selected failsafe action level (used to restrict what actions we move into)
     313             :     bool        _has_triggered_failsafe;  // true after a battery failsafe has been triggered for the first time
     314             : 
     315             : };
     316             : 
     317             : namespace AP {
     318             :     AP_BattMonitor &battery();
     319             : };
     320             : 
     321             : #endif  // AP_BATTERY_ENABLED

Generated by: LCOV version 1.14