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_Baro/AP_Baro_FBM320.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*/14/*15FCM320 barometer driver16*/1718#include "AP_Baro_FBM320.h"1920#if AP_BARO_FBM320_ENABLED2122#include <utility>23#include <stdio.h>24#include <AP_Math/definitions.h>2526extern const AP_HAL::HAL &hal;2728#define FBM320_REG_ID 0x6B29#define FBM320_REG_DATA 0xF630#define FBM320_REG_CMD 0xF43132#define FBM320_CMD_READ_T 0x2E33#define FBM320_CMD_READ_P 0xF43435#define FBM320_WHOAMI 0x423637AP_Baro_FBM320::AP_Baro_FBM320(AP_Baro &baro, AP_HAL::OwnPtr<AP_HAL::Device> _dev)38: AP_Baro_Backend(baro)39, dev(std::move(_dev))40{41}4243AP_Baro_Backend *AP_Baro_FBM320::probe(AP_Baro &baro,44AP_HAL::OwnPtr<AP_HAL::Device> _dev)45{46if (!_dev) {47return nullptr;48}4950AP_Baro_FBM320 *sensor = NEW_NOTHROW AP_Baro_FBM320(baro, std::move(_dev));51if (!sensor || !sensor->init()) {52delete sensor;53return nullptr;54}55return sensor;56}5758/*59read calibration data60*/61bool AP_Baro_FBM320::read_calibration(void)62{63uint8_t tmp[2];64uint16_t R[10];6566for (uint8_t i=0; i<9; i++) {67if (!dev->read_registers(0xAA+(i*2),&tmp[0],1)) {68return false;69}70if (!dev->read_registers(0xAB+(i*2),&tmp[1],1)) {71return false;72}73R[i] = ((uint8_t)tmp[0] << 8 | tmp[1]);74}7576if (!dev->read_registers(0xA4,&tmp[0],1)) {77return false;78}79if (!dev->read_registers(0xF1,&tmp[0],1)) {80return false;81}82R[9] = ((uint8_t)tmp[0] << 8) | tmp[1];838485/* Use R0~R9 calculate C0~C12 of FBM320-02 */86calibration.C0 = R[0] >> 4;87calibration.C1 = ((R[1] & 0xFF00) >> 5) | (R[2] & 7);88calibration.C2 = ((R[1] & 0xFF) << 1) | (R[4] & 1);89calibration.C3 = R[2] >> 3;90calibration.C4 = ((uint32_t)R[3] << 2) | (R[0] & 3);91calibration.C5 = R[4] >> 1;92calibration.C6 = R[5] >> 3;93calibration.C7 = ((uint32_t)R[6] << 3) | (R[5] & 7);94calibration.C8 = R[7] >> 3;95calibration.C9 = R[8] >> 2;96calibration.C10 = ((R[9] & 0xFF00) >> 6) | (R[8] & 3);97calibration.C11 = R[9] & 0xFF;98calibration.C12 = ((R[0] & 0x0C) << 1) | (R[7] & 7);99100return true;101}102103bool AP_Baro_FBM320::init()104{105if (!dev) {106return false;107}108dev->get_semaphore()->take_blocking();109110dev->set_speed(AP_HAL::Device::SPEED_HIGH);111112uint8_t whoami;113if (!dev->read_registers(FBM320_REG_ID, &whoami, 1) ||114whoami != FBM320_WHOAMI) {115// not a FBM320116dev->get_semaphore()->give();117return false;118}119printf("FBM320 ID 0x%x\n", whoami);120121if (!read_calibration()) {122dev->get_semaphore()->give();123return false;124}125126dev->write_register(FBM320_REG_CMD, FBM320_CMD_READ_T);127128instance = _frontend.register_sensor();129130dev->set_device_type(DEVTYPE_BARO_FBM320);131set_bus_id(instance, dev->get_bus_id());132133dev->get_semaphore()->give();134135// request 50Hz update136dev->register_periodic_callback(20 * AP_USEC_PER_MSEC, FUNCTOR_BIND_MEMBER(&AP_Baro_FBM320::timer, void));137138return true;139}140141/*142calculate corrected pressure and temperature143*/144void AP_Baro_FBM320::calculate_PT(int32_t UT, int32_t UP, int32_t &pressure, int32_t &temperature)145{146const struct fbm320_calibration &cal = calibration;147int32_t DT, DT2, X01, X02, X03, X11, X12, X13, X21, X22, X23, X24, X25, X26, X31, X32, CF, PP1, PP2, PP3, PP4;148149DT = ((UT - 8388608) >> 4) + (cal.C0 << 4);150X01 = (cal.C1 + 4459) * DT >> 1;151X02 = ((((cal.C2 - 256) * DT) >> 14) * DT) >> 4;152X03 = (((((cal.C3 * DT) >> 18) * DT) >> 18) * DT);153154temperature = ((2500 << 15) - X01 - X02 - X03) >> 15;155156DT2 = (X01 + X02 + X03) >> 12;157X11 = ((cal.C5 - 4443) * DT2);158X12 = (((cal.C6 * DT2) >> 16) * DT2) >> 2;159X13 = ((X11 + X12) >> 10) + ((cal.C4 + 120586) << 4);160161X21 = ((cal.C8 + 7180) * DT2) >> 10;162X22 = (((cal.C9 * DT2) >> 17) * DT2) >> 12;163X23 = (X22 >= X21) ? (X22 - X21) : (X21 - X22);164165X24 = (X23 >> 11) * (cal.C7 + 166426);166X25 = ((X23 & 0x7FF) * (cal.C7 + 166426)) >> 11;167X26 = (X21 >= X22) ? (((0 - X24 - X25) >> 11) + cal.C7 + 166426) : (((X24 + X25) >> 11) + cal.C7 + 166426);168169PP1 = ((UP - 8388608) - X13) >> 3;170PP2 = (X26 >> 11) * PP1;171PP3 = ((X26 & 0x7FF) * PP1) >> 11;172PP4 = (PP2 + PP3) >> 10;173174CF = (2097152 + cal.C12 * DT2) >> 3;175X31 = (((CF * cal.C10) >> 17) * PP4) >> 2;176X32 = (((((CF * cal.C11) >> 15) * PP4) >> 18) * PP4);177178pressure = ((X31 + X32) >> 15) + PP4 + 99880;179}180181// accumulate a new sensor reading182void AP_Baro_FBM320::timer(void)183{184uint8_t buf[3];185186if (!dev->read_registers(0xF6, buf, sizeof(buf))) {187return;188}189int32_t value = ((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | (uint32_t)buf[2];190191if (step == 0) {192value_T = value;193} else {194int32_t pressure, temperature;195calculate_PT(value_T, value, pressure, temperature);196if (pressure_ok(pressure)) {197WITH_SEMAPHORE(_sem);198pressure_sum += pressure;199// sum and convert to degrees200temperature_sum += temperature*0.01;201count++;202}203}204205if (step++ >= 5) {206dev->write_register(FBM320_REG_CMD, FBM320_CMD_READ_T);207step = 0;208} else {209dev->write_register(FBM320_REG_CMD, FBM320_CMD_READ_P);210}211}212213// transfer data to the frontend214void AP_Baro_FBM320::update(void)215{216if (count == 0) {217return;218}219WITH_SEMAPHORE(_sem);220221_copy_to_frontend(instance, pressure_sum/count, temperature_sum/count);222pressure_sum = 0;223temperature_sum = 0;224count=0;225}226227#endif // AP_BARO_FBM320_ENABLED228229230