2013-09-28 10:35:27 -03:00
|
|
|
#include "AP_BattMonitor.h"
|
2014-12-04 01:27:56 -04:00
|
|
|
#include "AP_BattMonitor_Analog.h"
|
|
|
|
#include "AP_BattMonitor_SMBus.h"
|
2020-06-02 07:57:47 -03:00
|
|
|
#include "AP_BattMonitor_SMBus_Solo.h"
|
|
|
|
#include "AP_BattMonitor_SMBus_Generic.h"
|
|
|
|
#include "AP_BattMonitor_SMBus_Maxell.h"
|
2019-09-16 12:44:31 -03:00
|
|
|
#include "AP_BattMonitor_SMBus_Rotoye.h"
|
2015-07-23 06:16:37 -03:00
|
|
|
#include "AP_BattMonitor_Bebop.h"
|
2021-03-01 16:38:54 -04:00
|
|
|
#include "AP_BattMonitor_ESC.h"
|
2019-12-04 08:03:33 -04:00
|
|
|
#include "AP_BattMonitor_SMBus_SUI.h"
|
2020-01-16 14:54:18 -04:00
|
|
|
#include "AP_BattMonitor_SMBus_NeoDesign.h"
|
2018-11-19 04:59:58 -04:00
|
|
|
#include "AP_BattMonitor_Sum.h"
|
2019-03-12 05:02:29 -03:00
|
|
|
#include "AP_BattMonitor_FuelFlow.h"
|
2019-06-18 18:20:55 -03:00
|
|
|
#include "AP_BattMonitor_FuelLevel_PWM.h"
|
2019-11-28 19:04:33 -04:00
|
|
|
#include "AP_BattMonitor_Generator.h"
|
2023-01-23 00:39:59 -04:00
|
|
|
#include "AP_BattMonitor_EFI.h"
|
2021-10-24 21:58:19 -03:00
|
|
|
#include "AP_BattMonitor_INA2xx.h"
|
2022-12-11 22:25:31 -04:00
|
|
|
#include "AP_BattMonitor_INA239.h"
|
2021-10-10 05:56:41 -03:00
|
|
|
#include "AP_BattMonitor_LTC2946.h"
|
2021-10-12 05:15:52 -03:00
|
|
|
#include "AP_BattMonitor_Torqeedo.h"
|
2022-06-28 13:48:15 -03:00
|
|
|
#include "AP_BattMonitor_FuelLevel_Analog.h"
|
2022-11-22 17:00:11 -04:00
|
|
|
#include "AP_BattMonitor_Synthetic_Current.h"
|
2018-07-20 10:01:13 -03:00
|
|
|
|
|
|
|
#include <AP_HAL/AP_HAL.h>
|
|
|
|
|
2023-04-08 01:09:10 -03:00
|
|
|
#if HAL_ENABLE_DRONECAN_DRIVERS
|
2023-04-08 00:55:39 -03:00
|
|
|
#include "AP_BattMonitor_DroneCAN.h"
|
2018-02-16 18:32:25 -04:00
|
|
|
#endif
|
2018-07-20 10:01:13 -03:00
|
|
|
|
2016-07-25 22:10:17 -03:00
|
|
|
#include <AP_Vehicle/AP_Vehicle_Type.h>
|
2019-01-18 00:23:42 -04:00
|
|
|
#include <AP_Logger/AP_Logger.h>
|
2017-11-09 18:33:44 -04:00
|
|
|
#include <GCS_MAVLink/GCS.h>
|
2018-11-27 20:37:13 -04:00
|
|
|
#include <AP_Notify/AP_Notify.h>
|
2013-09-28 10:35:27 -03:00
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
|
2018-01-16 15:09:28 -04:00
|
|
|
AP_BattMonitor *AP_BattMonitor::_singleton;
|
|
|
|
|
2015-10-25 14:03:46 -03:00
|
|
|
const AP_Param::GroupInfo AP_BattMonitor::var_info[] = {
|
2017-10-27 02:36:49 -03:00
|
|
|
// 0 - 18, 20- 22 used by old parameter indexes
|
2016-01-08 13:16:29 -04:00
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// Monitor 1
|
|
|
|
|
2017-10-27 02:36:49 -03:00
|
|
|
// @Group: _
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
2018-02-28 17:29:36 -04:00
|
|
|
AP_SUBGROUPINFO(_params[0], "_", 23, AP_BattMonitor, AP_BattMonitor_Params),
|
2016-01-08 13:16:29 -04:00
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: _
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: _
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: _
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: _
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: _
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: _
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[0], "_", 41, AP_BattMonitor, backend_var_info[0]),
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 1
|
2017-10-27 02:36:49 -03:00
|
|
|
// @Group: 2_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[1], "2_", 24, AP_BattMonitor, AP_BattMonitor_Params),
|
2014-12-04 01:27:56 -04:00
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 2_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 2_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: 2_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 2_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 2_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 2_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[1], "2_", 42, AP_BattMonitor, backend_var_info[1]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 2
|
2018-09-12 20:01:04 -03:00
|
|
|
// @Group: 3_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[2], "3_", 25, AP_BattMonitor, AP_BattMonitor_Params),
|
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 3_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 3_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: 3_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 3_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 3_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 3_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[2], "3_", 43, AP_BattMonitor, backend_var_info[2]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 3
|
2018-09-12 20:01:04 -03:00
|
|
|
// @Group: 4_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[3], "4_", 26, AP_BattMonitor, AP_BattMonitor_Params),
|
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 4_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 4_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: 4_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 4_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 4_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 4_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[3], "4_", 44, AP_BattMonitor, backend_var_info[3]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 4
|
2018-09-12 20:01:04 -03:00
|
|
|
// @Group: 5_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[4], "5_", 27, AP_BattMonitor, AP_BattMonitor_Params),
|
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 5_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 5_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: 5_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 5_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 5_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 5_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[4], "5_", 45, AP_BattMonitor, backend_var_info[4]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 5
|
2018-09-12 20:01:04 -03:00
|
|
|
// @Group: 6_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[5], "6_", 28, AP_BattMonitor, AP_BattMonitor_Params),
|
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 6_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 6_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: 6_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 6_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 6_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 6_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[5], "6_", 46, AP_BattMonitor, backend_var_info[5]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 6
|
2018-09-12 20:01:04 -03:00
|
|
|
// @Group: 7_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[6], "7_", 29, AP_BattMonitor, AP_BattMonitor_Params),
|
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 7_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 7_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: 7_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 7_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 7_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 7_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[6], "7_", 47, AP_BattMonitor, backend_var_info[6]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 7
|
2018-09-12 20:01:04 -03:00
|
|
|
// @Group: 8_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[7], "8_", 30, AP_BattMonitor, AP_BattMonitor_Params),
|
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 8_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 8_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
|
|
|
// @Group: 8_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 8_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 8_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 8_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[7], "8_", 48, AP_BattMonitor, backend_var_info[7]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-24 02:38:19 -03:00
|
|
|
|
2021-08-30 09:23:55 -03:00
|
|
|
#if AP_BATT_MONITOR_MAX_INSTANCES > 8
|
2018-09-12 20:01:04 -03:00
|
|
|
// @Group: 9_
|
|
|
|
// @Path: AP_BattMonitor_Params.cpp
|
|
|
|
AP_SUBGROUPINFO(_params[8], "9_", 31, AP_BattMonitor, AP_BattMonitor_Params),
|
|
|
|
|
2021-06-24 02:38:19 -03:00
|
|
|
// @Group: 9_
|
|
|
|
// @Path: AP_BattMonitor_Analog.cpp
|
2021-06-18 18:16:06 -03:00
|
|
|
// @Group: 9_
|
|
|
|
// @Path: AP_BattMonitor_SMBus.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
// @Group: 9_
|
|
|
|
// @Path: AP_BattMonitor_Sum.cpp
|
2022-02-11 04:59:28 -04:00
|
|
|
// @Group: 9_
|
2023-04-08 00:55:39 -03:00
|
|
|
// @Path: AP_BattMonitor_DroneCAN.cpp
|
2022-06-28 13:48:15 -03:00
|
|
|
// @Group: 9_
|
|
|
|
// @Path: AP_BattMonitor_FuelLevel_Analog.cpp
|
2022-11-28 19:06:15 -04:00
|
|
|
// @Group: 9_
|
|
|
|
// @Path: AP_BattMonitor_Synthetic_Current.cpp
|
2021-11-01 13:23:28 -03:00
|
|
|
AP_SUBGROUPVARPTR(drivers[8], "9_", 49, AP_BattMonitor, backend_var_info[8]),
|
2021-08-30 09:23:55 -03:00
|
|
|
#endif
|
2021-06-18 18:16:06 -03:00
|
|
|
|
2013-09-28 10:35:27 -03:00
|
|
|
AP_GROUPEND
|
|
|
|
};
|
|
|
|
|
2021-11-01 13:23:28 -03:00
|
|
|
const AP_Param::GroupInfo *AP_BattMonitor::backend_var_info[AP_BATT_MONITOR_MAX_INSTANCES];
|
2021-06-18 18:16:06 -03:00
|
|
|
|
2013-09-28 10:35:27 -03:00
|
|
|
// Default constructor.
|
|
|
|
// Note that the Vector/Matrix constructors already implicitly zero
|
|
|
|
// their values.
|
|
|
|
//
|
2017-11-09 18:33:44 -04:00
|
|
|
AP_BattMonitor::AP_BattMonitor(uint32_t log_battery_bit, battery_failsafe_handler_fn_t battery_failsafe_handler_fn, const int8_t *failsafe_priorities) :
|
2018-01-16 15:09:28 -04:00
|
|
|
_log_battery_bit(log_battery_bit),
|
2017-11-09 18:33:44 -04:00
|
|
|
_battery_failsafe_handler_fn(battery_failsafe_handler_fn),
|
2018-03-28 03:04:30 -03:00
|
|
|
_failsafe_priorities(failsafe_priorities)
|
2013-09-28 10:35:27 -03:00
|
|
|
{
|
|
|
|
AP_Param::setup_object_defaults(this, var_info);
|
2018-01-16 15:09:28 -04:00
|
|
|
|
|
|
|
if (_singleton != nullptr) {
|
|
|
|
AP_HAL::panic("AP_BattMonitor must be singleton");
|
|
|
|
}
|
|
|
|
_singleton = this;
|
2013-09-28 10:35:27 -03:00
|
|
|
}
|
|
|
|
|
2014-12-04 01:27:56 -04:00
|
|
|
// init - instantiate the battery monitors
|
2013-09-28 10:35:27 -03:00
|
|
|
void
|
|
|
|
AP_BattMonitor::init()
|
|
|
|
{
|
2014-12-04 01:27:56 -04:00
|
|
|
// check init has not been called before
|
|
|
|
if (_num_instances != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-09 18:33:44 -04:00
|
|
|
_highest_failsafe_priority = INT8_MAX;
|
|
|
|
|
2018-10-30 18:26:54 -03:00
|
|
|
#ifdef HAL_BATT_MONITOR_DEFAULT
|
2021-11-15 15:13:01 -04:00
|
|
|
_params[0]._type.set_default(int8_t(HAL_BATT_MONITOR_DEFAULT));
|
2015-07-23 07:49:48 -03:00
|
|
|
#endif
|
2023-03-08 14:49:09 -04:00
|
|
|
#ifdef HAL_BATT2_MONITOR_DEFAULT
|
|
|
|
_params[1]._type.set_default(int8_t(HAL_BATT2_MONITOR_DEFAULT));
|
|
|
|
#endif
|
2015-07-23 07:49:48 -03:00
|
|
|
|
2014-12-04 01:27:56 -04:00
|
|
|
// create each instance
|
|
|
|
for (uint8_t instance=0; instance<AP_BATT_MONITOR_MAX_INSTANCES; instance++) {
|
2017-04-08 00:27:31 -03:00
|
|
|
// clear out the cell voltages
|
|
|
|
memset(&state[instance].cell_voltages, 0xFF, sizeof(cells));
|
2023-03-08 14:49:09 -04:00
|
|
|
state[instance].instance = instance;
|
2017-04-08 00:27:31 -03:00
|
|
|
|
2017-10-27 02:36:49 -03:00
|
|
|
switch (get_type(instance)) {
|
2023-04-07 05:26:24 -03:00
|
|
|
#if AP_BATTERY_ANALOG_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::ANALOG_VOLTAGE_ONLY:
|
|
|
|
case Type::ANALOG_VOLTAGE_AND_CURRENT:
|
2017-10-27 02:36:49 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_Analog(*this, state[instance], _params[instance]);
|
2015-07-23 07:49:48 -03:00
|
|
|
break;
|
2023-04-07 05:26:24 -03:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_SMBUS_SOLO_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::SOLO:
|
2021-06-18 18:16:06 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_SMBus_Solo(*this, state[instance], _params[instance]);
|
2017-02-08 20:28:14 -04:00
|
|
|
break;
|
2023-01-25 00:42:24 -04:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_SMBUS_GENERIC_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::SMBus_Generic:
|
2021-06-18 18:16:06 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_SMBus_Generic(*this, state[instance], _params[instance]);
|
2020-06-02 04:44:38 -03:00
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif
|
|
|
|
#if AP_BATTERY_SMBUS_SUI_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::SUI3:
|
2021-06-18 18:16:06 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_SMBus_SUI(*this, state[instance], _params[instance], 3);
|
2019-12-04 08:03:33 -04:00
|
|
|
break;
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::SUI6:
|
2021-06-18 18:16:06 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_SMBus_SUI(*this, state[instance], _params[instance], 6);
|
2019-12-04 08:03:33 -04:00
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif
|
|
|
|
#if AP_BATTERY_SMBUS_MAXELL_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::MAXELL:
|
2021-06-18 18:16:06 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_SMBus_Maxell(*this, state[instance], _params[instance]);
|
2019-09-16 12:44:31 -03:00
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif
|
|
|
|
#if AP_BATTERY_SMBUS_ROTOYE_ENABLED
|
2019-09-16 12:44:31 -03:00
|
|
|
case Type::Rotoye:
|
2021-06-18 18:16:06 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_SMBus_Rotoye(*this, state[instance], _params[instance]);
|
2015-07-23 07:49:48 -03:00
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif
|
|
|
|
#if AP_BATTERY_SMBUS_NEODESIGN_ENABLED
|
2021-07-18 05:06:18 -03:00
|
|
|
case Type::NeoDesign:
|
2021-06-18 18:16:06 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_SMBus_NeoDesign(*this, state[instance], _params[instance]);
|
2021-07-18 05:06:18 -03:00
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif
|
|
|
|
#if AP_BATTERY_BEBOP_ENABLED
|
2023-03-13 20:30:23 -03:00
|
|
|
case Type::BEBOP:
|
2017-10-27 02:36:49 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_Bebop(*this, state[instance], _params[instance]);
|
2018-02-16 18:32:25 -04:00
|
|
|
break;
|
2023-03-13 20:30:23 -03:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_UAVCAN_BATTERYINFO_ENABLED
|
2023-03-13 20:30:23 -03:00
|
|
|
case Type::UAVCAN_BatteryInfo:
|
2023-04-08 01:09:10 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_DroneCAN(*this, state[instance], AP_BattMonitor_DroneCAN::UAVCAN_BATTERY_INFO, _params[instance]);
|
2018-05-30 18:35:11 -03:00
|
|
|
break;
|
2023-03-13 20:30:23 -03:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_ESC_ENABLED
|
2023-03-13 20:30:23 -03:00
|
|
|
case Type::BLHeliESC:
|
2021-03-01 16:38:54 -04:00
|
|
|
drivers[instance] = new AP_BattMonitor_ESC(*this, state[instance], _params[instance]);
|
2015-07-23 07:49:48 -03:00
|
|
|
break;
|
2023-03-13 20:30:23 -03:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_SUM_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::Sum:
|
2018-11-19 04:59:58 -04:00
|
|
|
drivers[instance] = new AP_BattMonitor_Sum(*this, state[instance], _params[instance], instance);
|
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif
|
|
|
|
#if AP_BATTERY_FUELFLOW_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::FuelFlow:
|
2019-03-12 05:02:29 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_FuelFlow(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif // AP_BATTERY_FUELFLOW_ENABLED
|
|
|
|
#if AP_BATTERY_FUELLEVEL_PWM_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::FuelLevel_PWM:
|
2019-06-18 18:20:55 -03:00
|
|
|
drivers[instance] = new AP_BattMonitor_FuelLevel_PWM(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif // AP_BATTERY_FUELLEVEL_PWM_ENABLED
|
|
|
|
#if AP_BATTERY_FUELLEVEL_ANALOG_ENABLED
|
2022-06-28 13:48:15 -03:00
|
|
|
case Type::FuelLevel_Analog:
|
|
|
|
drivers[instance] = new AP_BattMonitor_FuelLevel_Analog(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif // AP_BATTERY_FUELLEVEL_ANALOG_ENABLED
|
2021-09-24 00:10:46 -03:00
|
|
|
#if HAL_GENERATOR_ENABLED
|
2020-10-22 14:11:47 -03:00
|
|
|
case Type::GENERATOR_ELEC:
|
|
|
|
drivers[instance] = new AP_BattMonitor_Generator_Elec(*this, state[instance], _params[instance]);
|
2019-11-28 19:04:33 -04:00
|
|
|
break;
|
2020-10-22 14:11:47 -03:00
|
|
|
case Type::GENERATOR_FUEL:
|
|
|
|
drivers[instance] = new AP_BattMonitor_Generator_FuelLevel(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2021-09-24 00:10:46 -03:00
|
|
|
#endif // HAL_GENERATOR_ENABLED
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_INA2XX_ENABLED
|
2021-10-24 21:58:19 -03:00
|
|
|
case Type::INA2XX:
|
|
|
|
drivers[instance] = new AP_BattMonitor_INA2XX(*this, state[instance], _params[instance]);
|
2021-10-07 08:19:01 -03:00
|
|
|
break;
|
2021-10-10 05:56:41 -03:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_LTC2946_ENABLED
|
2021-10-10 05:56:41 -03:00
|
|
|
case Type::LTC2946:
|
|
|
|
drivers[instance] = new AP_BattMonitor_LTC2946(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2021-10-12 05:15:52 -03:00
|
|
|
#endif
|
|
|
|
#if HAL_TORQEEDO_ENABLED
|
|
|
|
case Type::Torqeedo:
|
|
|
|
drivers[instance] = new AP_BattMonitor_Torqeedo(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2022-11-22 17:00:11 -04:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_SYNTHETIC_CURRENT_ENABLED
|
2022-11-22 17:00:11 -04:00
|
|
|
case Type::Analog_Volt_Synthetic_Current:
|
|
|
|
drivers[instance] = new AP_BattMonitor_Synthetic_Current(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2022-12-11 22:25:31 -04:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_INA239_ENABLED
|
2022-12-11 22:25:31 -04:00
|
|
|
case Type::INA239_SPI:
|
|
|
|
drivers[instance] = new AP_BattMonitor_INA239(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2021-10-07 08:19:01 -03:00
|
|
|
#endif
|
2023-03-06 22:02:49 -04:00
|
|
|
#if AP_BATTERY_EFI_ENABLED
|
2023-01-23 00:39:59 -04:00
|
|
|
case Type::EFI:
|
|
|
|
drivers[instance] = new AP_BattMonitor_EFI(*this, state[instance], _params[instance]);
|
|
|
|
break;
|
2023-03-06 22:02:49 -04:00
|
|
|
#endif // AP_BATTERY_EFI_ENABLED
|
2020-08-06 02:33:07 -03:00
|
|
|
case Type::NONE:
|
2017-10-27 02:36:49 -03:00
|
|
|
default:
|
|
|
|
break;
|
2014-12-04 01:27:56 -04:00
|
|
|
}
|
2015-04-09 02:37:15 -03:00
|
|
|
|
2021-06-18 18:16:06 -03:00
|
|
|
// if the backend has some local parameters then make those available in the tree
|
|
|
|
if (drivers[instance] && state[instance].var_info) {
|
2021-11-01 13:23:28 -03:00
|
|
|
backend_var_info[instance] = state[instance].var_info;
|
|
|
|
AP_Param::load_object_from_eeprom(drivers[instance], backend_var_info[instance]);
|
|
|
|
|
2021-06-18 18:16:06 -03:00
|
|
|
// param count could have changed
|
|
|
|
AP_Param::invalidate_count();
|
|
|
|
}
|
|
|
|
|
2015-04-09 02:37:15 -03:00
|
|
|
// call init function for each backend
|
2016-10-30 02:24:21 -03:00
|
|
|
if (drivers[instance] != nullptr) {
|
2015-04-09 02:37:15 -03:00
|
|
|
drivers[instance]->init();
|
2018-11-19 00:25:45 -04:00
|
|
|
// _num_instances is actually the index for looping over instances
|
|
|
|
// the user may have BATT_MONITOR=0 and BATT2_MONITOR=7, in which case
|
|
|
|
// there will be a gap, but as we always check for drivers[instances] being nullptr
|
|
|
|
// this is safe
|
|
|
|
_num_instances = instance + 1;
|
2021-06-18 18:16:06 -03:00
|
|
|
|
|
|
|
// Convert the old analog & Bus parameters to the new dynamic parameter groups
|
|
|
|
convert_dynamic_param_groups(instance);
|
2015-04-09 02:37:15 -03:00
|
|
|
}
|
2014-08-08 23:13:49 -03:00
|
|
|
}
|
2013-09-28 10:35:27 -03:00
|
|
|
}
|
|
|
|
|
2021-06-18 18:16:06 -03:00
|
|
|
void AP_BattMonitor::convert_dynamic_param_groups(uint8_t instance)
|
|
|
|
{
|
|
|
|
AP_Param::ConversionInfo info;
|
|
|
|
if (!AP_Param::find_top_level_key_by_pointer(this, info.old_key)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char param_prefix[6] {};
|
|
|
|
char param_name[17] {};
|
|
|
|
info.new_name = param_name;
|
|
|
|
|
|
|
|
const uint8_t param_instance = instance + 1;
|
|
|
|
// first battmonitor does not have '1' in the param name
|
|
|
|
if(param_instance == 1) {
|
|
|
|
hal.util->snprintf(param_prefix, sizeof(param_prefix), "BATT");
|
|
|
|
} else {
|
|
|
|
hal.util->snprintf(param_prefix, sizeof(param_prefix), "BATT%X", param_instance);
|
|
|
|
}
|
|
|
|
param_prefix[sizeof(param_prefix)-1] = '\0';
|
|
|
|
|
|
|
|
hal.util->snprintf(param_name, sizeof(param_name), "%s_%s", param_prefix, "MONITOR");
|
|
|
|
param_name[sizeof(param_name)-1] = '\0';
|
|
|
|
|
|
|
|
// Find the index of the BATTn_MONITOR which is not moving to index the moving parameters off from
|
|
|
|
AP_Param::ParamToken token = AP_Param::ParamToken {};
|
|
|
|
ap_var_type type;
|
|
|
|
AP_Param* param = AP_Param::find_by_name(param_name, &type, &token);
|
|
|
|
const uint8_t battmonitor_index = 1;
|
|
|
|
if( param == nullptr) {
|
|
|
|
// BATTn_MONITOR not found
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct convert_table {
|
|
|
|
uint32_t old_group_element;
|
|
|
|
ap_var_type type;
|
|
|
|
const char* new_name;
|
|
|
|
} conversion_table[] = {
|
2022-04-25 21:24:59 -03:00
|
|
|
// PARAMETER_CONVERSION - Added: Aug-2021
|
2021-06-24 02:38:19 -03:00
|
|
|
{ 2, AP_PARAM_INT8, "VOLT_PIN" },
|
|
|
|
{ 3, AP_PARAM_INT8, "CURR_PIN" },
|
|
|
|
{ 4, AP_PARAM_FLOAT, "VOLT_MULT" },
|
|
|
|
{ 5, AP_PARAM_FLOAT, "AMP_PERVLT"},
|
|
|
|
{ 6, AP_PARAM_FLOAT, "AMP_OFFSET"},
|
2021-06-18 18:16:06 -03:00
|
|
|
{ 20, AP_PARAM_INT8, "I2C_BUS" },
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const auto & elem : conversion_table) {
|
2022-02-05 08:17:42 -04:00
|
|
|
info.old_group_element = token.group_element + ((elem.old_group_element - battmonitor_index) * 64);
|
2021-06-18 18:16:06 -03:00
|
|
|
info.type = elem.type;
|
|
|
|
|
|
|
|
hal.util->snprintf(param_name, sizeof(param_name), "%s_%s", param_prefix, elem.new_name);
|
|
|
|
AP_Param::convert_old_parameter(&info, 1.0f, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-06 20:51:50 -04:00
|
|
|
// read - For all active instances read voltage & current; log BAT, BCL, POWR
|
|
|
|
void AP_BattMonitor::read()
|
2013-09-28 10:35:27 -03:00
|
|
|
{
|
2021-11-23 01:15:39 -04:00
|
|
|
#if HAL_LOGGING_ENABLED
|
2019-02-11 04:16:49 -04:00
|
|
|
AP_Logger *logger = AP_Logger::get_singleton();
|
2020-11-21 01:25:59 -04:00
|
|
|
if (logger != nullptr && logger->should_log(_log_battery_bit)) {
|
2019-02-11 04:16:49 -04:00
|
|
|
logger->Write_Power();
|
2018-01-16 15:09:28 -04:00
|
|
|
}
|
2020-11-21 01:25:59 -04:00
|
|
|
#endif
|
2017-11-09 18:33:44 -04:00
|
|
|
|
2021-01-06 20:51:50 -04:00
|
|
|
for (uint8_t i=0; i<_num_instances; i++) {
|
|
|
|
if (drivers[i] != nullptr && get_type(i) != Type::NONE) {
|
|
|
|
drivers[i]->read();
|
|
|
|
drivers[i]->update_resistance_estimate();
|
2021-11-23 01:15:39 -04:00
|
|
|
|
|
|
|
#if HAL_LOGGING_ENABLED
|
2021-01-06 20:51:50 -04:00
|
|
|
if (logger != nullptr && logger->should_log(_log_battery_bit)) {
|
|
|
|
const uint64_t time_us = AP_HAL::micros64();
|
|
|
|
drivers[i]->Log_Write_BAT(i, time_us);
|
|
|
|
drivers[i]->Log_Write_BCL(i, time_us);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-09 18:33:44 -04:00
|
|
|
check_failsafes();
|
2018-11-27 20:37:13 -04:00
|
|
|
|
|
|
|
checkPoweringOff();
|
2014-12-04 01:27:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// healthy - returns true if monitor is functioning
|
|
|
|
bool AP_BattMonitor::healthy(uint8_t instance) const {
|
2017-10-27 02:36:49 -03:00
|
|
|
return instance < _num_instances && state[instance].healthy;
|
2014-12-04 01:27:56 -04:00
|
|
|
}
|
2013-09-28 10:35:27 -03:00
|
|
|
|
2014-12-04 01:27:56 -04:00
|
|
|
/// voltage - returns battery voltage in volts
|
|
|
|
float AP_BattMonitor::voltage(uint8_t instance) const
|
|
|
|
{
|
2016-06-02 19:02:20 -03:00
|
|
|
if (instance < _num_instances) {
|
2017-10-27 02:36:49 -03:00
|
|
|
return state[instance].voltage;
|
2014-12-04 01:27:56 -04:00
|
|
|
} else {
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-23 04:12:58 -03:00
|
|
|
/// get voltage with sag removed (based on battery current draw and resistance)
|
2017-05-25 02:09:20 -03:00
|
|
|
/// this will always be greater than or equal to the raw voltage
|
2017-05-23 04:12:58 -03:00
|
|
|
float AP_BattMonitor::voltage_resting_estimate(uint8_t instance) const
|
|
|
|
{
|
2018-09-12 18:18:06 -03:00
|
|
|
if (instance < _num_instances && drivers[instance] != nullptr) {
|
|
|
|
return drivers[instance]->voltage_resting_estimate();
|
2017-05-23 04:12:58 -03:00
|
|
|
} else {
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-19 04:09:45 -03:00
|
|
|
/// voltage - returns battery voltage in volts for GCS, may be resting voltage if option enabled
|
|
|
|
float AP_BattMonitor::gcs_voltage(uint8_t instance) const
|
|
|
|
{
|
2023-02-23 14:08:22 -04:00
|
|
|
if (instance >= _num_instances || drivers[instance] == nullptr) {
|
|
|
|
return 0.0f;
|
|
|
|
}
|
2023-02-20 23:27:07 -04:00
|
|
|
if (drivers[instance]->option_is_set(AP_BattMonitor_Params::Options::GCS_Resting_Voltage)) {
|
2022-03-19 04:09:45 -03:00
|
|
|
return voltage_resting_estimate(instance);
|
|
|
|
}
|
2023-02-23 14:08:22 -04:00
|
|
|
return state[instance].voltage;
|
2022-03-19 04:09:45 -03:00
|
|
|
}
|
|
|
|
|
2014-12-04 01:27:56 -04:00
|
|
|
/// current_amps - returns the instantaneous current draw in amperes
|
2019-07-07 11:34:41 -03:00
|
|
|
bool AP_BattMonitor::current_amps(float ¤t, uint8_t instance) const {
|
|
|
|
if ((instance < _num_instances) && (drivers[instance] != nullptr) && drivers[instance]->has_current()) {
|
|
|
|
current = state[instance].current_amps;
|
|
|
|
return true;
|
2014-12-04 01:27:56 -04:00
|
|
|
} else {
|
2019-07-07 11:34:41 -03:00
|
|
|
return false;
|
2014-12-04 01:27:56 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-15 12:10:36 -04:00
|
|
|
/// consumed_mah - returns total current drawn since start-up in milliampere.hours
|
2019-07-07 11:34:41 -03:00
|
|
|
bool AP_BattMonitor::consumed_mah(float &mah, const uint8_t instance) const {
|
|
|
|
if ((instance < _num_instances) && (drivers[instance] != nullptr) && drivers[instance]->has_current()) {
|
|
|
|
mah = state[instance].consumed_mah;
|
|
|
|
return true;
|
2014-12-04 01:27:56 -04:00
|
|
|
} else {
|
2019-07-07 11:34:41 -03:00
|
|
|
return false;
|
2013-09-28 10:35:27 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-15 12:10:36 -04:00
|
|
|
/// consumed_wh - returns energy consumed since start-up in Watt.hours
|
2019-07-07 11:34:41 -03:00
|
|
|
bool AP_BattMonitor::consumed_wh(float &wh, const uint8_t instance) const {
|
|
|
|
if (instance < _num_instances && drivers[instance] != nullptr && drivers[instance]->has_consumed_energy()) {
|
|
|
|
wh = state[instance].consumed_wh;
|
|
|
|
return true;
|
2016-08-25 09:53:33 -03:00
|
|
|
} else {
|
2019-07-07 11:34:41 -03:00
|
|
|
return false;
|
2016-08-25 09:53:33 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-23 13:15:34 -03:00
|
|
|
/// capacity_remaining_pct - returns true if the percentage is valid and writes to percentage argument
|
|
|
|
bool AP_BattMonitor::capacity_remaining_pct(uint8_t &percentage, uint8_t instance) const
|
2013-09-28 10:35:27 -03:00
|
|
|
{
|
2016-10-30 02:24:21 -03:00
|
|
|
if (instance < _num_instances && drivers[instance] != nullptr) {
|
2020-04-23 13:15:34 -03:00
|
|
|
return drivers[instance]->capacity_remaining_pct(percentage);
|
2014-12-04 01:27:56 -04:00
|
|
|
}
|
2020-04-23 13:15:34 -03:00
|
|
|
return false;
|
2013-09-30 11:14:09 -03:00
|
|
|
}
|
|
|
|
|
2021-10-11 04:25:04 -03:00
|
|
|
/// time_remaining - returns remaining battery time
|
|
|
|
bool AP_BattMonitor::time_remaining(uint32_t &seconds, uint8_t instance) const
|
|
|
|
{
|
|
|
|
if (instance < _num_instances && drivers[instance] != nullptr && state[instance].has_time_remaining) {
|
|
|
|
seconds = state[instance].time_remaining;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-03 11:40:00 -03:00
|
|
|
/// pack_capacity_mah - returns the capacity of the battery pack in mAh when the pack is full
|
2017-10-27 02:36:49 -03:00
|
|
|
int32_t AP_BattMonitor::pack_capacity_mah(uint8_t instance) const
|
|
|
|
{
|
|
|
|
if (instance < AP_BATT_MONITOR_MAX_INSTANCES) {
|
|
|
|
return _params[instance]._pack_capacity;
|
2016-05-03 11:40:00 -03:00
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2017-10-27 02:36:49 -03:00
|
|
|
}
|
2017-02-08 20:28:57 -04:00
|
|
|
|
2017-11-09 18:33:44 -04:00
|
|
|
void AP_BattMonitor::check_failsafes(void)
|
|
|
|
{
|
|
|
|
if (hal.util->get_soft_armed()) {
|
|
|
|
for (uint8_t i = 0; i < _num_instances; i++) {
|
2018-09-12 18:18:06 -03:00
|
|
|
if (drivers[i] == nullptr) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-10-22 22:33:03 -03:00
|
|
|
const Failsafe type = drivers[i]->update_failsafes();
|
2017-11-09 18:33:44 -04:00
|
|
|
if (type <= state[i].failsafe) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int8_t action = 0;
|
|
|
|
const char *type_str = nullptr;
|
|
|
|
switch (type) {
|
2020-10-22 22:33:03 -03:00
|
|
|
case Failsafe::None:
|
2017-11-09 18:33:44 -04:00
|
|
|
continue; // should not have been called in this case
|
2020-10-22 22:33:03 -03:00
|
|
|
case Failsafe::Low:
|
2017-11-09 18:33:44 -04:00
|
|
|
action = _params[i]._failsafe_low_action;
|
|
|
|
type_str = "low";
|
|
|
|
break;
|
2020-10-22 22:33:03 -03:00
|
|
|
case Failsafe::Critical:
|
2017-11-09 18:33:44 -04:00
|
|
|
action = _params[i]._failsafe_critical_action;
|
|
|
|
type_str = "critical";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-11-21 01:25:59 -04:00
|
|
|
GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Battery %d is %s %.2fV used %.0f mAh", i + 1, type_str,
|
2019-07-07 11:34:41 -03:00
|
|
|
(double)voltage(i), (double)state[i].consumed_mah);
|
2017-11-09 18:33:44 -04:00
|
|
|
_has_triggered_failsafe = true;
|
2020-11-21 01:25:59 -04:00
|
|
|
#ifndef HAL_BUILD_AP_PERIPH
|
2017-11-09 18:33:44 -04:00
|
|
|
AP_Notify::flags.failsafe_battery = true;
|
2020-11-21 01:25:59 -04:00
|
|
|
#endif
|
2017-11-09 18:33:44 -04:00
|
|
|
state[i].failsafe = type;
|
|
|
|
|
|
|
|
// map the desired failsafe action to a prioritiy level
|
|
|
|
int8_t priority = 0;
|
|
|
|
if (_failsafe_priorities != nullptr) {
|
|
|
|
while (_failsafe_priorities[priority] != -1) {
|
|
|
|
if (_failsafe_priorities[priority] == action) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
priority++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// trigger failsafe if the action was equal or higher priority
|
|
|
|
// It's valid to retrigger the same action if a different battery provoked the event
|
|
|
|
if (priority <= _highest_failsafe_priority) {
|
|
|
|
_battery_failsafe_handler_fn(type_str, action);
|
|
|
|
_highest_failsafe_priority = priority;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-08 13:16:29 -04:00
|
|
|
// return true if any battery is pushing too much power
|
|
|
|
bool AP_BattMonitor::overpower_detected() const
|
|
|
|
{
|
|
|
|
bool result = false;
|
2017-05-31 00:30:48 -03:00
|
|
|
for (uint8_t instance = 0; instance < _num_instances; instance++) {
|
2016-01-08 13:16:29 -04:00
|
|
|
result |= overpower_detected(instance);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AP_BattMonitor::overpower_detected(uint8_t instance) const
|
|
|
|
{
|
2016-07-25 22:10:17 -03:00
|
|
|
#if APM_BUILD_TYPE(APM_BUILD_ArduPlane)
|
2017-10-27 02:36:49 -03:00
|
|
|
if (instance < _num_instances && _params[instance]._watt_max > 0) {
|
|
|
|
float power = state[instance].current_amps * state[instance].voltage;
|
|
|
|
return state[instance].healthy && (power > _params[instance]._watt_max);
|
2016-01-08 13:16:29 -04:00
|
|
|
}
|
|
|
|
return false;
|
2016-07-25 22:10:17 -03:00
|
|
|
#else
|
|
|
|
return false;
|
2016-04-19 21:21:48 -03:00
|
|
|
#endif
|
2016-07-25 22:10:17 -03:00
|
|
|
}
|
2017-04-08 00:27:31 -03:00
|
|
|
|
2017-05-31 00:31:18 -03:00
|
|
|
bool AP_BattMonitor::has_cell_voltages(const uint8_t instance) const
|
|
|
|
{
|
|
|
|
if (instance < _num_instances && drivers[instance] != nullptr) {
|
|
|
|
return drivers[instance]->has_cell_voltages();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-04-08 00:27:31 -03:00
|
|
|
// return the current cell voltages, returns the first monitor instances cells if the instance is out of range
|
|
|
|
const AP_BattMonitor::cells & AP_BattMonitor::get_cell_voltages(const uint8_t instance) const
|
|
|
|
{
|
|
|
|
if (instance >= AP_BATT_MONITOR_MAX_INSTANCES) {
|
|
|
|
return state[AP_BATT_PRIMARY_INSTANCE].cell_voltages;
|
|
|
|
} else {
|
|
|
|
return state[instance].cell_voltages;
|
|
|
|
}
|
|
|
|
}
|
2017-04-08 05:20:08 -03:00
|
|
|
|
|
|
|
// returns true if there is a temperature reading
|
|
|
|
bool AP_BattMonitor::get_temperature(float &temperature, const uint8_t instance) const
|
|
|
|
{
|
2023-02-23 14:08:22 -04:00
|
|
|
if (instance >= _num_instances || drivers[instance] == nullptr) {
|
2017-04-08 05:20:08 -03:00
|
|
|
return false;
|
2021-01-07 22:11:56 -04:00
|
|
|
}
|
|
|
|
|
2022-10-12 15:02:19 -03:00
|
|
|
#if AP_TEMPERATURE_SENSOR_ENABLED
|
|
|
|
if (state[instance].temperature_external_use) {
|
|
|
|
temperature = state[instance].temperature_external;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-01-07 22:11:56 -04:00
|
|
|
temperature = state[instance].temperature;
|
|
|
|
|
|
|
|
return drivers[instance]->has_temperature();
|
2017-04-08 05:20:08 -03:00
|
|
|
}
|
2018-01-16 15:09:28 -04:00
|
|
|
|
2022-10-12 15:02:19 -03:00
|
|
|
#if AP_TEMPERATURE_SENSOR_ENABLED
|
|
|
|
// return true when successfully setting a battery temperature from an external source by instance
|
|
|
|
bool AP_BattMonitor::set_temperature(const float temperature, const uint8_t instance)
|
|
|
|
{
|
2023-02-23 14:08:22 -04:00
|
|
|
if (instance >= _num_instances || drivers[instance] == nullptr) {
|
2022-10-12 15:02:19 -03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
state[instance].temperature_external = temperature;
|
|
|
|
state[instance].temperature_external_use = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return true when successfully setting a battery temperature from an external source by serial_number
|
|
|
|
bool AP_BattMonitor::set_temperature_by_serial_number(const float temperature, const int32_t serial_number)
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
for (uint8_t i = 0; i < _num_instances; i++) {
|
|
|
|
if (drivers[i] != nullptr && get_serial_number(i) == serial_number) {
|
|
|
|
success |= set_temperature(temperature, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
#endif // AP_TEMPERATURE_SENSOR_ENABLED
|
|
|
|
|
2019-12-10 20:55:20 -04:00
|
|
|
// return true if cycle count can be provided and fills in cycles argument
|
|
|
|
bool AP_BattMonitor::get_cycle_count(uint8_t instance, uint16_t &cycles) const
|
|
|
|
{
|
2023-02-23 14:08:22 -04:00
|
|
|
if (instance >= _num_instances || (drivers[instance] == nullptr)) {
|
2019-12-10 20:55:20 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return drivers[instance]->get_cycle_count(cycles);
|
|
|
|
}
|
|
|
|
|
2018-09-12 19:26:39 -03:00
|
|
|
bool AP_BattMonitor::arming_checks(size_t buflen, char *buffer) const
|
|
|
|
{
|
|
|
|
char temp_buffer[MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN+1] {};
|
|
|
|
|
2023-02-23 14:08:22 -04:00
|
|
|
for (uint8_t i = 0; i < _num_instances; i++) {
|
2018-09-12 19:26:39 -03:00
|
|
|
if (drivers[i] != nullptr && !(drivers[i]->arming_checks(temp_buffer, sizeof(temp_buffer)))) {
|
|
|
|
hal.util->snprintf(buffer, buflen, "Battery %d %s", i + 1, temp_buffer);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2018-01-16 15:09:28 -04:00
|
|
|
|
2018-11-27 20:37:13 -04:00
|
|
|
// Check's each smart battery instance for its powering off state and broadcasts notifications
|
|
|
|
void AP_BattMonitor::checkPoweringOff(void)
|
|
|
|
{
|
|
|
|
for (uint8_t i = 0; i < _num_instances; i++) {
|
|
|
|
if (state[i].is_powering_off && !state[i].powerOffNotified) {
|
2020-11-21 01:25:59 -04:00
|
|
|
#ifndef HAL_BUILD_AP_PERIPH
|
2018-11-27 20:37:13 -04:00
|
|
|
// Set the AP_Notify flag, which plays the power off tones
|
|
|
|
AP_Notify::flags.powering_off = true;
|
2020-11-21 01:25:59 -04:00
|
|
|
#endif
|
2018-11-27 20:37:13 -04:00
|
|
|
|
|
|
|
// Send a Mavlink broadcast announcing the shutdown
|
2021-08-18 08:42:16 -03:00
|
|
|
#if HAL_GCS_ENABLED
|
2019-01-28 22:03:11 -04:00
|
|
|
mavlink_command_long_t cmd_msg{};
|
2018-11-27 20:37:13 -04:00
|
|
|
cmd_msg.command = MAV_CMD_POWER_OFF_INITIATED;
|
|
|
|
cmd_msg.param1 = i+1;
|
2019-10-17 04:08:17 -03:00
|
|
|
GCS_MAVLINK::send_to_components(MAVLINK_MSG_ID_COMMAND_LONG, (char*)&cmd_msg, sizeof(cmd_msg));
|
2018-11-27 20:37:13 -04:00
|
|
|
gcs().send_text(MAV_SEVERITY_WARNING, "Vehicle %d battery %d is powering off", mavlink_system.sysid, i+1);
|
2020-11-21 01:25:59 -04:00
|
|
|
#endif
|
2018-11-27 20:37:13 -04:00
|
|
|
|
|
|
|
// only send this once
|
|
|
|
state[i].powerOffNotified = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-18 06:30:18 -03:00
|
|
|
/*
|
|
|
|
reset battery remaining percentage for batteries that integrate to
|
|
|
|
calculate percentage remaining
|
|
|
|
*/
|
2021-03-26 17:14:21 -03:00
|
|
|
bool AP_BattMonitor::reset_remaining_mask(uint16_t battery_mask, float percentage)
|
2019-06-18 06:30:18 -03:00
|
|
|
{
|
2021-03-26 22:10:17 -03:00
|
|
|
static_assert(AP_BATT_MONITOR_MAX_INSTANCES <= 16, "More batteries are enabled then can be reset");
|
2019-06-18 06:30:18 -03:00
|
|
|
bool ret = true;
|
2020-10-22 22:33:03 -03:00
|
|
|
Failsafe highest_failsafe = Failsafe::None;
|
2019-06-18 06:30:18 -03:00
|
|
|
for (uint8_t i = 0; i < _num_instances; i++) {
|
|
|
|
if ((1U<<i) & battery_mask) {
|
2021-03-26 22:10:17 -03:00
|
|
|
if (drivers[i] != nullptr) {
|
|
|
|
ret &= drivers[i]->reset_remaining(percentage);
|
|
|
|
} else {
|
|
|
|
ret = false;
|
|
|
|
}
|
2019-06-18 06:30:18 -03:00
|
|
|
}
|
2019-06-18 21:14:46 -03:00
|
|
|
if (state[i].failsafe > highest_failsafe) {
|
|
|
|
highest_failsafe = state[i].failsafe;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all backends are not in failsafe then set overall failsafe state
|
2020-10-22 22:33:03 -03:00
|
|
|
if (highest_failsafe == Failsafe::None) {
|
2019-06-18 21:14:46 -03:00
|
|
|
_highest_failsafe_priority = INT8_MAX;
|
|
|
|
_has_triggered_failsafe = false;
|
|
|
|
// and reset notify flag
|
|
|
|
AP_Notify::flags.failsafe_battery = false;
|
2019-06-18 06:30:18 -03:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-01-02 15:50:26 -04:00
|
|
|
// Returns the mavlink charge state. The following mavlink charge states are not used
|
|
|
|
// MAV_BATTERY_CHARGE_STATE_EMERGENCY , MAV_BATTERY_CHARGE_STATE_FAILED
|
|
|
|
// MAV_BATTERY_CHARGE_STATE_UNHEALTHY, MAV_BATTERY_CHARGE_STATE_CHARGING
|
|
|
|
MAV_BATTERY_CHARGE_STATE AP_BattMonitor::get_mavlink_charge_state(const uint8_t instance) const
|
|
|
|
{
|
|
|
|
if (instance >= _num_instances) {
|
|
|
|
return MAV_BATTERY_CHARGE_STATE_UNDEFINED;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (state[instance].failsafe) {
|
|
|
|
|
|
|
|
case Failsafe::None:
|
2021-12-06 09:32:49 -04:00
|
|
|
if (get_mavlink_fault_bitmask(instance) != 0 || !healthy()) {
|
|
|
|
return MAV_BATTERY_CHARGE_STATE_UNHEALTHY;
|
|
|
|
}
|
2021-01-02 15:50:26 -04:00
|
|
|
return MAV_BATTERY_CHARGE_STATE_OK;
|
|
|
|
|
|
|
|
case Failsafe::Low:
|
|
|
|
return MAV_BATTERY_CHARGE_STATE_LOW;
|
|
|
|
|
|
|
|
case Failsafe::Critical:
|
|
|
|
return MAV_BATTERY_CHARGE_STATE_CRITICAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should not reach this
|
|
|
|
return MAV_BATTERY_CHARGE_STATE_UNDEFINED;
|
|
|
|
}
|
|
|
|
|
2021-12-06 09:32:49 -04:00
|
|
|
// Returns mavlink fault state
|
|
|
|
uint32_t AP_BattMonitor::get_mavlink_fault_bitmask(const uint8_t instance) const
|
|
|
|
{
|
2023-02-23 14:08:22 -04:00
|
|
|
if (instance >= _num_instances || drivers[instance] == nullptr) {
|
2021-12-06 09:32:49 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return drivers[instance]->get_mavlink_fault_bitmask();
|
|
|
|
}
|
|
|
|
|
2023-02-17 17:19:24 -04:00
|
|
|
// Enable/Disable (Turn on/off) MPPT power to all backends who are MPPTs
|
|
|
|
void AP_BattMonitor::MPPT_set_powered_state_to_all(const bool power_on)
|
|
|
|
{
|
|
|
|
for (uint8_t i=0; i < _num_instances; i++) {
|
|
|
|
MPPT_set_powered_state(i, power_on);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable/Disable (Turn on/off) MPPT power. When disabled, the MPPT does not
|
|
|
|
// supply energy to the system regardless if it's capable to or not. When enabled
|
|
|
|
// it will supply energy if available.
|
|
|
|
void AP_BattMonitor::MPPT_set_powered_state(const uint8_t instance, const bool power_on)
|
|
|
|
{
|
|
|
|
if (instance < _num_instances) {
|
|
|
|
drivers[instance]->mppt_set_powered_state(power_on);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-22 06:32:31 -03:00
|
|
|
/*
|
|
|
|
check that all configured battery monitors are healthy
|
|
|
|
*/
|
|
|
|
bool AP_BattMonitor::healthy() const
|
|
|
|
{
|
|
|
|
for (uint8_t i=0; i< _num_instances; i++) {
|
|
|
|
if (get_type(i) != Type::NONE && !healthy(i)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-01-16 15:09:28 -04:00
|
|
|
namespace AP {
|
|
|
|
|
|
|
|
AP_BattMonitor &battery()
|
|
|
|
{
|
2019-02-10 14:56:13 -04:00
|
|
|
return *AP_BattMonitor::get_singleton();
|
2018-01-16 15:09:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
};
|