#include "AP_Periph.h"
#if AP_PERIPH_BATTERY_BALANCE_ENABLED
#include <dronecan_msgs.h>
extern const AP_HAL::HAL &hal;
#ifndef AP_PERIPH_BATTERY_BALANCE_NUMCELLS_DEFAULT
#define AP_PERIPH_BATTERY_BALANCE_NUMCELLS_DEFAULT 0
#endif
#ifndef AP_PERIPH_BATTERY_BALANCE_RATE_DEFAULT
#define AP_PERIPH_BATTERY_BALANCE_RATE_DEFAULT 1
#endif
#ifndef AP_PERIPH_BATTERY_BALANCE_CELL1_PIN_DEFAULT
#define AP_PERIPH_BATTERY_BALANCE_CELL1_PIN_DEFAULT 1
#endif
#ifndef AP_PERIPH_BATTERY_BALANCE_ID_DEFAULT
#define AP_PERIPH_BATTERY_BALANCE_ID_DEFAULT 0
#endif
const AP_Param::GroupInfo BattBalance::var_info[] {
AP_GROUPINFO("_NUM_CELLS", 1, BattBalance, num_cells, AP_PERIPH_BATTERY_BALANCE_NUMCELLS_DEFAULT),
AP_GROUPINFO("_ID", 2, BattBalance, id, AP_PERIPH_BATTERY_BALANCE_ID_DEFAULT),
AP_GROUPINFO("_RATE", 3, BattBalance, rate, AP_PERIPH_BATTERY_BALANCE_RATE_DEFAULT),
AP_GROUPINFO("_CELL1_PIN", 4, BattBalance, cell1_pin, AP_PERIPH_BATTERY_BALANCE_CELL1_PIN_DEFAULT),
AP_GROUPEND
};
BattBalance::BattBalance(void)
{
AP_Param::setup_object_defaults(this, var_info);
}
void AP_Periph_FW::batt_balance_update()
{
const int8_t ncell = battery_balance.num_cells;
if (ncell <= 0) {
return;
}
if (battery_balance.cells == nullptr) {
battery_balance.cells = NEW_NOTHROW AP_HAL::AnalogSource*[ncell];
if (battery_balance.cells == nullptr) {
return;
}
battery_balance.cells_allocated = ncell;
for (uint8_t i=0; i<battery_balance.cells_allocated; i++) {
battery_balance.cells[i] = hal.analogin->channel(battery_balance.cell1_pin + i);
}
}
const uint32_t now = AP_HAL::millis();
if (now - battery_balance.last_send_ms < 1000.0/battery_balance.rate.get()) {
return;
}
battery_balance.last_send_ms = now;
auto *pkt = NEW_NOTHROW ardupilot_equipment_power_BatteryInfoAux;
uint8_t *buffer = NEW_NOTHROW uint8_t[ARDUPILOT_EQUIPMENT_POWER_BATTERYINFOAUX_MAX_SIZE];
if (pkt == nullptr || buffer == nullptr) {
delete pkt;
delete [] buffer;
return;
}
pkt->voltage_cell.len = battery_balance.cells_allocated;
float last_cell = 0;
for (uint8_t i=0; i<battery_balance.cells_allocated; i++) {
auto *chan = battery_balance.cells[i];
if (chan == nullptr) {
continue;
}
const float v = chan->voltage_average();
pkt->voltage_cell.data[i] = v - last_cell;
last_cell = v;
}
pkt->max_current = nanf("");
pkt->nominal_voltage = nanf("");
pkt->battery_id = uint8_t(battery_balance.id);
const uint16_t total_size = ardupilot_equipment_power_BatteryInfoAux_encode(pkt, buffer, !periph.canfdout());
canard_broadcast(ARDUPILOT_EQUIPMENT_POWER_BATTERYINFOAUX_SIGNATURE,
ARDUPILOT_EQUIPMENT_POWER_BATTERYINFOAUX_ID,
CANARD_TRANSFER_PRIORITY_LOW,
buffer,
total_size);
delete pkt;
delete [] buffer;
}
#endif