Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_BattMonitor/AP_BattMonitor_Bebop.cpp
Views: 1798
/*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_BEBOP_ENABLED1819#include <AP_HAL/AP_HAL.h>20#include <AP_HAL_Linux/RCOutput_Bebop.h>21#include <AP_HAL_Linux/RCOutput_Disco.h>2223#include "AP_BattMonitor_Bebop.h"2425#define BATTERY_VOLTAGE_COMPENSATION_LANDED (0.2f)262728extern const AP_HAL::HAL &hal;2930using namespace Linux;3132/* polynomial compensation coefficients */33static const float bat_comp_polynomial_coeffs[5] = {34-1.2471059149657287e-16f,353.2072883440944087e-12f,36-3.3012241016211356e-08f,371.4612693130825659e-04f,38-1.9236755589522961e-01f39};4041/* battery percent lookup table */42static const struct {43float voltage;44float percent;45} bat_lut[] = {46#if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO47{9.5, 0},48{11.04, 5},49{11.11, 10},50{11.21, 15},51{11.3, 25},52{11.4, 45},53{11.6, 55},54{11.9, 79},55{12.02, 84},56{12.11, 88},57{12.19, 91},58{12.26, 94},59{12.35, 96},60{12.45, 98},61{12.5, 100}62#else63// bebop64{10.50f, 0.0f},65{10.741699f, 2.6063901f},66{10.835779f, 5.1693798f},67{10.867705f, 7.7323696f},68{10.900651f, 10.295359f},69{11.008754f, 20.547318f},70{11.148267f, 38.488246f},71{11.322504f, 53.866185f},72{11.505738f, 66.681133f},73{11.746556f, 79.496082f},74{12.110226f, 94.874021f},75{12.3f, 100.0f }76#endif77};78#define BATTERY_PERCENT_LUT_SIZE ARRAY_SIZE(bat_lut)7980void AP_BattMonitor_Bebop::init(void)81{82_battery_voltage_max = bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage;83_prev_vbat_raw = bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage;84_prev_vbat = bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage;85}8687float AP_BattMonitor_Bebop::_filter_voltage(float vbat_raw)88{89static const float a[2] = {901.0f, -9.9686333183343789e-01f91};92static const float b[2] = {931.5683340832810533e-03f, 1.5683340832810533e-03f94};95float vbat;96static int only_once = 1;9798/* on first time reset filter with first raw value */99if (only_once) {100vbat = vbat_raw;101_prev_vbat_raw = vbat_raw;102_prev_vbat = vbat_raw;103only_once = 0;104} else if (vbat_raw > 0.0f) {105/* 1st order filter */106vbat = b[0] * vbat_raw +107b[1] * _prev_vbat_raw - a[1] * _prev_vbat;108_prev_vbat_raw = vbat_raw;109_prev_vbat = vbat;110} else {111vbat = _prev_vbat;112}113114return vbat;115}116117float AP_BattMonitor_Bebop::_compute_compensation(const uint16_t *rpm,118float vbat_raw)119{120float vbat, res;121size_t i, j;122123vbat = vbat_raw;124for (i = 0; i < BEBOP_BLDC_MOTORS_NUM; i++) {125res = 0;126for (j = 0; j < ARRAY_SIZE(bat_comp_polynomial_coeffs); j++)127res = res * rpm[i] + bat_comp_polynomial_coeffs[j];128129vbat -= res;130}131132return vbat;133}134135float AP_BattMonitor_Bebop::_compute_battery_percentage(float vbat)136{137float percent = 0.0f;138int i;139140if (vbat <= bat_lut[0].voltage) {141percent = 0.0f;142} else if (vbat >= bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage) {143percent = 100.0f;144} else {145i = 0;146while (vbat >= bat_lut[i].voltage)147i++;148149percent += bat_lut[i - 1].percent +150(vbat - bat_lut[i - 1].voltage) *151(bat_lut[i].percent - bat_lut[i - 1].percent) /152(bat_lut[i].voltage - bat_lut[i - 1].voltage);153}154155return percent;156}157158void AP_BattMonitor_Bebop::read(void)159{160int ret;161uint32_t tnow;162BebopBLDC_ObsData data;163float capacity, remaining, vbat, vbat_raw;164165#if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP166auto rcout = Linux::RCOutput_Bebop::from(hal.rcout);167#elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO168auto rcout = Linux::RCOutput_Disco::from(hal.rcout);169#endif170tnow = AP_HAL::micros();171172ret = rcout->read_obs_data(data);173if (ret < 0) {174_state.healthy = false;175return;176}177178/* get battery voltage observed by cypress */179vbat_raw = (float)data.batt_mv * 0.001f;180181/* do not compute battery status on ramping or braking transition */182if (data.status == BEBOP_BLDC_STATUS_RAMPING ||183data.status == BEBOP_BLDC_STATUS_STOPPING)184return;185186/* if motors are spinning compute polynomial compensation */187if (data.status == BEBOP_BLDC_STATUS_SPINNING_1 ||188data.status == BEBOP_BLDC_STATUS_SPINNING_2) {189vbat = _compute_compensation(data.rpm, vbat_raw);190/* otherwise compute constant compensation */191} else {192vbat = vbat_raw - BATTERY_VOLTAGE_COMPENSATION_LANDED;193}194195/* filter raw value */196vbat = _filter_voltage(vbat);197198/* ensure battery voltage/percent will not grow up during use */199if (vbat > _battery_voltage_max) {200vbat = _battery_voltage_max;201} else if (vbat < 0.0f) {202vbat = 0.0f;203_battery_voltage_max = 0.0f;204} else {205_battery_voltage_max = vbat;206}207208/* compute remaining battery percent and get battery capacity */209remaining = _compute_battery_percentage(vbat);210capacity = (float) _params._pack_capacity;211212/* fillup battery state */213_state.voltage = vbat;214_state.last_time_micros = tnow;215_state.healthy = true;216_state.consumed_mah = capacity - (remaining * capacity) * 0.01f;217}218219#endif // AP_BATTERY_BEBOP_ENABLED220221222