123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /*
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <AP_HAL/AP_HAL.h>
- #if CONFIG_HAL_BOARD == HAL_BOARD_LINUX && \
- (CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP || CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO)
- #include "AP_BattMonitor_Bebop.h"
- #include <AP_HAL_Linux/RCOutput_Bebop.h>
- #include <AP_HAL_Linux/RCOutput_Disco.h>
- #define BATTERY_VOLTAGE_COMPENSATION_LANDED (0.2f)
- extern const AP_HAL::HAL &hal;
- using namespace Linux;
- /* polynomial compensation coefficients */
- static const float bat_comp_polynomial_coeffs[5] = {
- -1.2471059149657287e-16f,
- 3.2072883440944087e-12f,
- -3.3012241016211356e-08f,
- 1.4612693130825659e-04f,
- -1.9236755589522961e-01f
- };
- /* battery percent lookup table */
- static const struct {
- float voltage;
- float percent;
- } bat_lut[] = {
- #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO
- {9.5, 0},
- {11.04, 5},
- {11.11, 10},
- {11.21, 15},
- {11.3, 25},
- {11.4, 45},
- {11.6, 55},
- {11.9, 79},
- {12.02, 84},
- {12.11, 88},
- {12.19, 91},
- {12.26, 94},
- {12.35, 96},
- {12.45, 98},
- {12.5, 100}
- #else
- // bebop
- {10.50f, 0.0f},
- {10.741699f, 2.6063901f},
- {10.835779f, 5.1693798f},
- {10.867705f, 7.7323696f},
- {10.900651f, 10.295359f},
- {11.008754f, 20.547318f},
- {11.148267f, 38.488246f},
- {11.322504f, 53.866185f},
- {11.505738f, 66.681133f},
- {11.746556f, 79.496082f},
- {12.110226f, 94.874021f},
- {12.3f, 100.0f }
- #endif
- };
- #define BATTERY_PERCENT_LUT_SIZE ARRAY_SIZE(bat_lut)
-
- void AP_BattMonitor_Bebop::init(void)
- {
- _battery_voltage_max = bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage;
- _prev_vbat_raw = bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage;
- _prev_vbat = bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage;
- }
- float AP_BattMonitor_Bebop::_filter_voltage(float vbat_raw)
- {
- static const float a[2] = {
- 1.0f, -9.9686333183343789e-01f
- };
- static const float b[2] = {
- 1.5683340832810533e-03f, 1.5683340832810533e-03f
- };
- float vbat;
- static int only_once = 1;
- /* on first time reset filter with first raw value */
- if (only_once) {
- vbat = vbat_raw;
- _prev_vbat_raw = vbat_raw;
- _prev_vbat = vbat_raw;
- only_once = 0;
- } else if (vbat_raw > 0.0f) {
- /* 1st order fitler */
- vbat = b[0] * vbat_raw +
- b[1] * _prev_vbat_raw - a[1] * _prev_vbat;
- _prev_vbat_raw = vbat_raw;
- _prev_vbat = vbat;
- } else {
- vbat = _prev_vbat;
- }
- return vbat;
- }
- float AP_BattMonitor_Bebop::_compute_compensation(const uint16_t *rpm,
- float vbat_raw)
- {
- float vbat, res;
- size_t i, j;
- vbat = vbat_raw;
- for (i = 0; i < BEBOP_BLDC_MOTORS_NUM; i++) {
- res = 0;
- for (j = 0; j < ARRAY_SIZE(bat_comp_polynomial_coeffs); j++)
- res = res * rpm[i] + bat_comp_polynomial_coeffs[j];
- vbat -= res;
- }
- return vbat;
- }
- float AP_BattMonitor_Bebop::_compute_battery_percentage(float vbat)
- {
- float percent = 0.0f;
- int i;
- if (vbat <= bat_lut[0].voltage) {
- percent = 0.0f;
- } else if (vbat >= bat_lut[BATTERY_PERCENT_LUT_SIZE - 1].voltage) {
- percent = 100.0f;
- } else {
- i = 0;
- while (vbat >= bat_lut[i].voltage)
- i++;
- percent += bat_lut[i - 1].percent +
- (vbat - bat_lut[i - 1].voltage) *
- (bat_lut[i].percent - bat_lut[i - 1].percent) /
- (bat_lut[i].voltage - bat_lut[i - 1].voltage);
- }
- return percent;
- }
- void AP_BattMonitor_Bebop::read(void)
- {
- int ret;
- uint32_t tnow;
- BebopBLDC_ObsData data;
- float capacity, remaining, vbat, vbat_raw;
- #if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BEBOP
- auto rcout = Linux::RCOutput_Bebop::from(hal.rcout);
- #elif CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_DISCO
- auto rcout = Linux::RCOutput_Disco::from(hal.rcout);
- #endif
- tnow = AP_HAL::micros();
- ret = rcout->read_obs_data(data);
- if (ret < 0) {
- _state.healthy = false;
- return;
- }
- /* get battery voltage observed by cypress */
- vbat_raw = (float)data.batt_mv / 1000.0f;
- /* do not compute battery status on ramping or braking transition */
- if (data.status == BEBOP_BLDC_STATUS_RAMPING ||
- data.status == BEBOP_BLDC_STATUS_STOPPING)
- return;
- /* if motors are spinning compute polynomial compensation */
- if (data.status == BEBOP_BLDC_STATUS_SPINNING_1 ||
- data.status == BEBOP_BLDC_STATUS_SPINNING_2) {
- vbat = _compute_compensation(data.rpm, vbat_raw);
- /* otherwise compute constant compensation */
- } else {
- vbat = vbat_raw - BATTERY_VOLTAGE_COMPENSATION_LANDED;
- }
- /* filter raw value */
- vbat = _filter_voltage(vbat);
- /* ensure battery voltage/percent will not grow up during use */
- if (vbat > _battery_voltage_max) {
- vbat = _battery_voltage_max;
- } else if (vbat < 0.0f) {
- vbat = 0.0f;
- _battery_voltage_max = 0.0f;
- } else {
- _battery_voltage_max = vbat;
- }
- /* compute remaining battery percent and get battery capacity */
- remaining = _compute_battery_percentage(vbat);
- capacity = (float) _params._pack_capacity;
- /* fillup battery state */
- _state.voltage = vbat;
- _state.last_time_micros = tnow;
- _state.healthy = true;
- _state.consumed_mah = capacity - (remaining * capacity) / 100.0f;
- }
- #endif
|