diff --git a/conf/firmwares/rotorcraft.makefile b/conf/firmwares/rotorcraft.makefile index 58b2b6187e..b5cd13d64e 100644 --- a/conf/firmwares/rotorcraft.makefile +++ b/conf/firmwares/rotorcraft.makefile @@ -172,13 +172,18 @@ LISA_M_BARO ?= BARO_BOARD_BMP085 ifeq ($(LISA_M_BARO), BARO_MS5611_SPI) include $(CFG_SHARED)/spi_master.makefile ap.CFLAGS += -DUSE_SPI2 -DUSE_SPI_SLAVE3 - ap.srcs += $(SRC_BOARD)/baro_ms5611_spi.c + ap.srcs += peripherals/ms5611.c + ap.srcs += peripherals/ms5611_spi.c + ap.srcs += subsystems/sensors/baro_ms5611_spi.c else ifeq ($(LISA_M_BARO), BARO_MS5611_I2C) ap.CFLAGS += -DUSE_I2C2 - ap.srcs += $(SRC_BOARD)/baro_ms5611_i2c.c + ap.srcs += peripherals/ms5611.c + ap.srcs += peripherals/ms5611_i2c.c + ap.srcs += subsystems/sensors/baro_ms5611_i2c.c else ifeq ($(LISA_M_BARO), BARO_BOARD_BMP085) + ap.srcs += peripherals/bmp085.c ap.srcs += $(SRC_BOARD)/baro_board.c - ap.CFLAGS += -DUSE_I2C2 + ap.CFLAGS += -DUSE_I2C2 endif ap.CFLAGS += -D$(LISA_M_BARO) @@ -189,10 +194,14 @@ LIA_BARO ?= BARO_MS5611_SPI ifeq ($(LIA_BARO), BARO_MS5611_SPI) include $(CFG_SHARED)/spi_master.makefile ap.CFLAGS += -DUSE_SPI2 -DUSE_SPI_SLAVE3 - ap.srcs += boards/lisa_m/baro_ms5611_spi.c + ap.srcs += peripherals/ms5611.c + ap.srcs += peripherals/ms5611_spi.c + ap.srcs += subsystems/sensors/baro_ms5611_spi.c else ifeq ($(LIA_BARO), BARO_MS5611_I2C) ap.CFLAGS += -DUSE_I2C2 - ap.srcs += boards/lisa_m/baro_ms5611_i2c.c + ap.srcs += peripherals/ms5611.c + ap.srcs += peripherals/ms5611_i2c.c + ap.srcs += subsystems/sensors/baro_ms5611_i2c.c endif ap.CFLAGS += -D$(LIA_BARO) @@ -206,7 +215,10 @@ ap.srcs += $(SRC_BOARD)/baro_board.c # krooz baro else ifeq ($(BOARD), krooz) -ap.srcs += $(SRC_BOARD)/baro_board.c +ap.CFLAGS += -DMS5611_I2C_DEV=i2c2 -DMS5611_SLAVE_ADDR=0xEC +ap.srcs += peripherals/ms5611.c +ap.srcs += peripherals/ms5611_i2c.c +ap.srcs += subsystems/sensors/baro_ms5611_i2c.c # apogee baro else ifeq ($(BOARD), apogee) diff --git a/conf/firmwares/subsystems/shared/imu_krooz_sd.makefile b/conf/firmwares/subsystems/shared/imu_krooz_sd.makefile index c2a7e83fe0..878dadfac1 100644 --- a/conf/firmwares/subsystems/shared/imu_krooz_sd.makefile +++ b/conf/firmwares/subsystems/shared/imu_krooz_sd.makefile @@ -14,11 +14,9 @@ IMU_KROOZ_I2C_DEV=i2c2 IMU_KROOZ_CFLAGS += -DUSE_I2C -DUSE_I2C2 -DI2C2_CLOCK_SPEED=400000 IMU_KROOZ_CFLAGS += -DIMU_KROOZ_I2C_DEV=$(IMU_KROOZ_I2C_DEV) -IMU_KROOZ_CFLAGS += -DMS5611_I2C_DEV=$(IMU_KROOZ_I2C_DEV) -DMS5611_SLAVE_ADDR=0xEC IMU_KROOZ_SRCS += peripherals/mpu60x0.c IMU_KROOZ_SRCS += peripherals/mpu60x0_i2c.c IMU_KROOZ_SRCS += peripherals/hmc58xx.c -IMU_KROOZ_SRCS += modules/sensors/baro_ms5611_i2c.c AHRS_PROPAGATE_FREQUENCY ?= 512 AHRS_CORRECT_FREQUENCY ?= 512 diff --git a/conf/modules/baro_bmp.xml b/conf/modules/baro_bmp.xml index 0fa9cc1edf..1bf6bde874 100644 --- a/conf/modules/baro_bmp.xml +++ b/conf/modules/baro_bmp.xml @@ -10,10 +10,11 @@ - + - + + diff --git a/conf/modules/baro_ms5611_i2c.xml b/conf/modules/baro_ms5611_i2c.xml index 412c725338..027cd4061c 100644 --- a/conf/modules/baro_ms5611_i2c.xml +++ b/conf/modules/baro_ms5611_i2c.xml @@ -13,12 +13,13 @@ - - - + + + + diff --git a/conf/modules/baro_ms5611_spi.xml b/conf/modules/baro_ms5611_spi.xml new file mode 100644 index 0000000000..2ec153e554 --- /dev/null +++ b/conf/modules/baro_ms5611_spi.xml @@ -0,0 +1,25 @@ + + + + + + Baro MS5611 (SPI) + Measurement Specialties MS5611-01BA pressure sensor (SPI) + + + + + +
+ +
+ + + + + + + + + +
diff --git a/sw/airborne/boards/krooz/baro_board.c b/sw/airborne/boards/krooz/baro_board.c deleted file mode 100644 index bc042c6cd0..0000000000 --- a/sw/airborne/boards/krooz/baro_board.c +++ /dev/null @@ -1,30 +0,0 @@ - -#include "subsystems/sensors/baro.h" -#include "baro_board.h" - -struct Baro baro; - -void baro_init(void) { - baro_ms5611_init(); -} - -void baro_periodic(void) { - static uint8_t cnt; - switch(cnt) { - case 0: - baro_ms5611_periodic(); - cnt++; - break; - case 1: - baro_ms5611_d1(); - cnt++; - break; - case 2: - baro_ms5611_d2(); - cnt = 0; - break; - default: - cnt = 0; - break; - } -} diff --git a/sw/airborne/boards/krooz/baro_board.h b/sw/airborne/boards/krooz/baro_board.h index b73f33d90d..5f47ad650e 100644 --- a/sw/airborne/boards/krooz/baro_board.h +++ b/sw/airborne/boards/krooz/baro_board.h @@ -1,30 +1,14 @@ /* - * board specific fonctions for the KroozSD board + * board specific interface for the KroozSD board * + * It uses the subsystems/sensors/baro_ms5611_i2c.c driver */ #ifndef BOARDS_KROOZ_BARO_H #define BOARDS_KROOZ_BARO_H -#include "std.h" -#include "mcu_periph/i2c.h" -#include "modules/sensors/baro_ms5611_i2c.h" -#include "math/pprz_algebra_int.h" - -//#include "led.h" - -static inline void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)) -{ - baro_ms5611_event(); - if(baro_ms5611_valid) { - baro.status = BS_RUNNING; - baro.absolute = (int32_t)baroms; - b_abs_handler(); - baro_ms5611_valid = FALSE; - } -} - -#define BaroEvent(_b_abs_handler, _b_diff_handler) baro_event(_b_abs_handler,_b_diff_handler) +extern void baro_event(void (*b_abs_handler)(void)); +#define BaroEvent(_b_abs_handler, _b_diff_handler) baro_event(_b_abs_handler) #endif /* BOARDS_KROOZ_SD_BARO_H */ diff --git a/sw/airborne/boards/lia/baro_board.h b/sw/airborne/boards/lia/baro_board.h index d65c11d266..59782132c8 100644 --- a/sw/airborne/boards/lia/baro_board.h +++ b/sw/airborne/boards/lia/baro_board.h @@ -9,8 +9,8 @@ #include "std.h" -extern void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)); +extern void baro_event(void (*b_abs_handler)(void)); -#define BaroEvent(_b_abs_handler, _b_diff_handler) baro_event(_b_abs_handler,_b_diff_handler) +#define BaroEvent(_b_abs_handler, _b_diff_handler) baro_event(_b_abs_handler) #endif /* BOARDS_LIA_BARO_H */ diff --git a/sw/airborne/boards/lisa_m/baro_board.c b/sw/airborne/boards/lisa_m/baro_board.c index b51743c30a..9c09b97d90 100644 --- a/sw/airborne/boards/lisa_m/baro_board.c +++ b/sw/airborne/boards/lisa_m/baro_board.c @@ -1,195 +1,81 @@ +/* + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** @file boards/lisa_m/baro_board.c + * Baro board interface for Bosch BMP085 on LisaM I2C2 with EOC check. + */ #include "subsystems/sensors/baro.h" -#include +#include "peripherals/bmp085_regs.h" +#include + +#include "led.h" struct Baro baro; -struct BaroBoard baro_board; -struct i2c_transaction baro_trans; -struct bmp085_baro_calibration calibration; +struct Bmp085 baro_bmp085; -#define BMP085_SAMPLE_PERIOD_MS (3 + (2 << BMP085_OSS) * 3) -#define BMP085_SAMPLE_PERIOD (BMP075_SAMPLE_PERIOD_MS >> 1) - -// FIXME: BARO DRDY connected to PB0 for lisa/m - -static inline void bmp085_write_reg(uint8_t addr, uint8_t value) +static bool_t baro_eoc(void) { - baro_trans.buf[0] = addr; - baro_trans.buf[1] = value; - - i2c_transmit(&i2c2, &baro_trans, BMP085_ADDR, 2); - - // FIXME, no while loops without timeout!! - while (baro_trans.status == I2CTransPending || baro_trans.status == I2CTransRunning); -} - -static inline void bmp085_read_reg16(uint8_t addr) -{ - baro_trans.buf[0] = addr; - i2c_transceive(&i2c2, &baro_trans, BMP085_ADDR, 1, 2); -} - -static inline int16_t bmp085_read_reg16_blocking(uint8_t addr, uint32_t timeout) -{ - uint32_t time = 0; - - bmp085_read_reg16(addr); - - while (baro_trans.status == I2CTransPending || baro_trans.status == I2CTransRunning) { - if ((time == timeout) && (timeout != 0)) { - return 0; /* Timeout of the i2c read */ - } else { - time++; - } - } - - return ((baro_trans.buf[0] << 8) | baro_trans.buf[1]); -} - -static inline void bmp085_read_reg24(uint8_t addr) -{ - baro_trans.buf[0] = addr; - i2c_transceive(&i2c2, &baro_trans, BMP085_ADDR, 1, 3); -} - -static void bmp085_baro_read_calibration(void) -{ - calibration.ac1 = bmp085_read_reg16_blocking(0xAA, 10000); // AC1 - calibration.ac2 = bmp085_read_reg16_blocking(0xAC, 10000); // AC2 - calibration.ac3 = bmp085_read_reg16_blocking(0xAE, 10000); // AC3 - calibration.ac4 = bmp085_read_reg16_blocking(0xB0, 10000); // AC4 - calibration.ac5 = bmp085_read_reg16_blocking(0xB2, 10000); // AC5 - calibration.ac6 = bmp085_read_reg16_blocking(0xB4, 10000); // AC6 - calibration.b1 = bmp085_read_reg16_blocking(0xB6, 10000); // B1 - calibration.b2 = bmp085_read_reg16_blocking(0xB8, 10000); // B2 - calibration.mb = bmp085_read_reg16_blocking(0xBA, 10000); // MB - calibration.mc = bmp085_read_reg16_blocking(0xBC, 10000); // MC - calibration.md = bmp085_read_reg16_blocking(0xBE, 10000); // MD + return gpio_get(GPIOB, GPIO0); } void baro_init(void) { baro.status = BS_UNINITIALIZED; baro.absolute = 0; baro.differential = 0; - baro_board.status = LBS_UNINITIALIZED; - bmp085_baro_read_calibration(); - /* STM32 specific (maybe this is a LISA/M specific driver anyway?) */ + bmp085_init(&baro_bmp085, &i2c2, BMP085_SLAVE_ADDR); + + /* setup eoc check function */ + baro_bmp085.eoc = &baro_eoc; + gpio_clear(GPIOB, GPIO0); gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); } -static inline int baro_eoc(void) -{ - return gpio_get(GPIOB, GPIO0); -} - -static inline void bmp085_request_pressure(void) -{ - bmp085_write_reg(0xF4, 0x34 + (BMP085_OSS << 6)); -} - -static inline void bmp085_request_temp(void) -{ - bmp085_write_reg(0xF4, 0x2E); -} - -static inline void bmp085_read_pressure(void) -{ - bmp085_read_reg24(0xF6); -} - -static inline void bmp085_read_temp(void) -{ - bmp085_read_reg16(0xF6); -} void baro_periodic(void) { - // check that nothing is in progress - if (baro_trans.status == I2CTransPending) return; - if (baro_trans.status == I2CTransRunning) return; - if (!i2c_idle(&i2c2)) return; - switch (baro_board.status) { - case LBS_UNINITIALIZED: - baro_board_send_reset(); - baro_board.status = LBS_REQUEST; + if (baro_bmp085.initialized) { baro.status = BS_RUNNING; - break; - case LBS_REQUEST: - bmp085_request_pressure(); - baro_board.status = LBS_READ; - break; - case LBS_READ: - if (baro_eoc()) { - bmp085_read_pressure(); - baro_board.status = LBS_READING; - } - break; - case LBS_REQUEST_TEMP: - bmp085_request_temp(); - baro_board.status = LBS_READ_TEMP; - break; - case LBS_READ_TEMP: - if (baro_eoc()) { - bmp085_read_temp(); - baro_board.status = LBS_READING_TEMP; - } - break; - default: - break; + bmp085_periodic(&baro_bmp085); } - + else + bmp085_read_eeprom_calib(&baro_bmp085); } -void baro_board_send_reset(void) { - // This is a NOP at the moment -} -// Apply temp calibration and sensor calibration to raw measurement to get Pa (from BMP085 datasheet) -static int32_t baro_apply_calibration(int32_t raw) + +void baro_event(void (*b_abs_handler)(void)) { - int32_t b6 = calibration.b5 - 4000; - int x1 = (calibration.b2 * (b6 * b6 >> 12)) >> 11; - int x2 = calibration.ac2 * b6 >> 11; - int32_t x3 = x1 + x2; - int32_t b3 = (((calibration.ac1 * 4 + x3) << BMP085_OSS) + 2)/4; - x1 = calibration.ac3 * b6 >> 13; - x2 = (calibration.b1 * (b6 * b6 >> 12)) >> 16; - x3 = ((x1 + x2) + 2) >> 2; - uint32_t b4 = (calibration.ac4 * (uint32_t) (x3 + 32768)) >> 15; - uint32_t b7 = (raw - b3) * (50000 >> BMP085_OSS); - int32_t p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2; - x1 = (p >> 8) * (p >> 8); - x1 = (x1 * 3038) >> 16; - x2 = (-7357 * p) >> 16; - return p + ((x1 + x2 + 3791) >> 4); -} + bmp085_event(&baro_bmp085); -void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)) -{ - if (baro_board.status == LBS_READING && - baro_trans.status != I2CTransPending && baro_trans.status != I2CTransRunning) { - baro_board.status = LBS_REQUEST_TEMP; - if (baro_trans.status == I2CTransSuccess) { - int32_t tmp = (baro_trans.buf[0]<<16) | (baro_trans.buf[1] << 8) | baro_trans.buf[2]; - tmp = tmp >> (8 - BMP085_OSS); - baro.absolute = baro_apply_calibration(tmp); - b_abs_handler(); - } - } - if (baro_board.status == LBS_READING_TEMP && - baro_trans.status != I2CTransPending && baro_trans.status != I2CTransRunning) { - baro_board.status = LBS_REQUEST; - if (baro_trans.status == I2CTransSuccess) { - // abuse differential to store temp in 0.1C for now - int32_t tmp = (baro_trans.buf[0] << 8) | baro_trans.buf[1]; - int32_t x1 = ((tmp - calibration.ac6) * calibration.ac5) >> 15; - int32_t x2 = (calibration.mc << 11) / (x1 + calibration.md); - calibration.b5 = x1 + x2; - baro.differential = (calibration.b5 + 8) >> 4; - b_diff_handler(); - } + if (baro_bmp085.data_available) { + baro.absolute = baro_bmp085.pressure; + b_abs_handler(); + baro_bmp085.data_available = FALSE; + +#ifdef ROTORCRAFT_BARO_LED + RunOnceEvery(10,LED_TOGGLE(ROTORCRAFT_BARO_LED)); +#endif } } diff --git a/sw/airborne/boards/lisa_m/baro_board.h b/sw/airborne/boards/lisa_m/baro_board.h index 42014ddeee..b84a11a7da 100644 --- a/sw/airborne/boards/lisa_m/baro_board.h +++ b/sw/airborne/boards/lisa_m/baro_board.h @@ -12,56 +12,15 @@ // for right now we abuse this file for the ms5611 baro on aspirin as well #if !BARO_MS5611_I2C && !BARO_MS5611 -#include "mcu_periph/i2c.h" +#include "peripherals/bmp085.h" -// absolute addr -#define BMP085_ADDR 0xEE -// Over sample setting (0-3) -#define BMP085_OSS 3 +extern struct Bmp085 baro_bmp085; -enum LisaBaroStatus { - LBS_UNINITIALIZED, - LBS_REQUEST, - LBS_READING, - LBS_READ, - LBS_REQUEST_TEMP, - LBS_READING_TEMP, - LBS_READ_TEMP, -}; - -struct BaroBoard { - enum LisaBaroStatus status; -}; - -struct bmp085_baro_calibration { - // These values come from EEPROM on sensor - int16_t ac1; - int16_t ac2; - int16_t ac3; - uint16_t ac4; - uint16_t ac5; - uint16_t ac6; - int16_t b1; - int16_t b2; - int16_t mb; - int16_t mc; - int16_t md; - - // These values are calculated - int32_t b5; -}; - -extern struct BaroBoard baro_board; -extern struct i2c_transaction baro_trans; -extern struct bmp085_baro_calibration calibration; - -extern void baro_board_send_reset(void); -extern void baro_board_send_config(void); #endif // !BARO_MS5611_xx -extern void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)); +extern void baro_event(void (*b_abs_handler)(void)); -#define BaroEvent(_b_abs_handler, _b_diff_handler) baro_event(_b_abs_handler,_b_diff_handler) +#define BaroEvent(_b_abs_handler, _b_diff_handler) baro_event(_b_abs_handler) #endif /* BOARDS_LISA_M_BARO_H */ diff --git a/sw/airborne/boards/lisa_m/baro_ms5611_i2c.c b/sw/airborne/boards/lisa_m/baro_ms5611_i2c.c deleted file mode 100644 index 10994d5948..0000000000 --- a/sw/airborne/boards/lisa_m/baro_ms5611_i2c.c +++ /dev/null @@ -1,206 +0,0 @@ -/** - * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for I2C - * - * Edit by: Michal Podhradsky, michal.podhradsky@aggiemail.usu.edu - * Utah State University, http://aggieair.usu.edu/ - */ -#include "subsystems/sensors/baro.h" -#include "peripherals/ms5611.h" -#include "led.h" -#include "std.h" -#include "mcu_periph/sys_time.h" - -#include "mcu_periph/i2c.h" -#ifndef MS5611_I2C_DEV -#define MS5611_I2C_DEV i2c2 -#endif - -#ifdef DEBUG -#ifndef DOWNLINK_DEVICE -#define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE -#endif -#include "mcu_periph/uart.h" -#include "messages.h" -#include "subsystems/datalink/downlink.h" -#endif - -struct Baro baro; -struct i2c_transaction ms5611_trans; -uint8_t ms5611_status; -int32_t prom_cnt; -uint16_t ms5611_c[PROM_NB]; -uint32_t ms5611_d1, ms5611_d2; -float fbaroms, ftempms; - -static int8_t baro_ms5611_crc(uint16_t* prom) { - int32_t i, j; - uint32_t res = 0; - uint8_t crc = prom[7] & 0xF; - prom[7] &= 0xFF00; - for (i = 0; i < 16; i++) { - if (i & 1) res ^= ((prom[i>>1]) & 0x00FF); - else res ^= (prom[i>>1]>>8); - for (j = 8; j > 0; j--) { - if (res & 0x8000) res ^= 0x1800; - res <<= 1; - } - } - prom[7] |= crc; - if (crc == ((res >> 12) & 0xF)) return 0; - else return -1; -} - -void baro_init(void) { - ms5611_status = MS5611_UNINIT; - baro.status = BS_UNINITIALIZED; - prom_cnt = 0; -} - -void baro_periodic(void) { - if (sys_time.nb_sec > 1) { - if (ms5611_status == MS5611_IDLE) { - /* start D1 conversion */ - ms5611_status = MS5611_CONV_D1; - ms5611_trans.buf[0] = MS5611_START_CONV_D1; - i2c_transmit(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1); - #ifdef DEBUG - RunOnceEvery(60, { DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, - &ms5611_c[0], &ms5611_c[1], &ms5611_c[2], &ms5611_c[3], - &ms5611_c[4], &ms5611_c[5], &ms5611_c[6], &ms5611_c[7]);}); - #endif - } - else if (ms5611_status == MS5611_CONV_D1) { - /* assume D1 conversion is done */ - ms5611_status = MS5611_CONV_D1_OK; - } - else if (ms5611_status == MS5611_CONV_D1_OK) { - /* read D1 adc */ - ms5611_status = MS5611_ADC_D1; - ms5611_trans.buf[0] = MS5611_ADC_READ; - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 3); - } - else if (ms5611_status == MS5611_CONV_D2) { - /* assume D2 conversion is done */ - ms5611_status = MS5611_CONV_D2_OK; - } - else if (ms5611_status == MS5611_CONV_D2_OK) { - /* read D2 adc */ - ms5611_status = MS5611_ADC_D2; - ms5611_trans.buf[0] = MS5611_ADC_READ; - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 3); - } - else if (ms5611_status == MS5611_UNINIT) { - /* reset sensor */ - ms5611_status = MS5611_RESET; - ms5611_trans.buf[0] = MS5611_SOFT_RESET; - i2c_transmit(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1); - } - else if (ms5611_status == MS5611_RESET_OK) { - /* start getting prom data */ - ms5611_status = MS5611_PROM; - ms5611_trans.buf[0] = MS5611_PROM_READ | (prom_cnt << 1); - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 2); - } - } -} - -void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)){ - if (ms5611_trans.status == I2CTransSuccess) { - #ifdef ROTORCRAFT_BARO_LED - RunOnceEvery(10,LED_TOGGLE(ROTORCRAFT_BARO_LED)); - #endif - switch (ms5611_status) { - - case MS5611_RESET: - ms5611_status = MS5611_RESET_OK; - ms5611_trans.status = I2CTransDone; - break; - - case MS5611_PROM: - /* read prom data */ - ms5611_c[prom_cnt++] = (ms5611_trans.buf[0] << 8) | ms5611_trans.buf[1]; - if (prom_cnt < PROM_NB) {//8 bytes at PROM - /* get next prom data */ - ms5611_trans.buf[0] = MS5611_PROM_READ | (prom_cnt << 1); - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 2); - } - else { - /* done reading prom */ - ms5611_trans.status = I2CTransDone; - /* check prom crc */ - if (baro_ms5611_crc(ms5611_c) == 0) { - ms5611_status = MS5611_IDLE; - baro.status = BS_RUNNING; - } - else { - /* checksum error, try again */ - baro_init(); - } - } - break; - - case MS5611_ADC_D1: - /* read D1 (pressure) */ - ms5611_d1 = (ms5611_trans.buf[0] << 16) | - (ms5611_trans.buf[1] << 8) | - ms5611_trans.buf[2]; - /* start D2 conversion */ - ms5611_status = MS5611_CONV_D2; - ms5611_trans.buf[0] = MS5611_START_CONV_D2; - i2c_transmit(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1); - break; - - case MS5611_ADC_D2: { - int64_t dt, baroms, tempms, off, sens, t2, off2, sens2; - /* read D2 (temperature) */ - ms5611_d2 = (ms5611_trans.buf[0] << 16) | - (ms5611_trans.buf[1] << 8) | - ms5611_trans.buf[2]; - ms5611_status = MS5611_IDLE; - ms5611_trans.status = I2CTransDone; - - /* difference between actual and ref temperature */ - dt = ms5611_d2 - (int64_t)ms5611_c[5] * (1<<8); - /* actual temperature */ - tempms = 2000 + ((int64_t)dt * ms5611_c[6]) / (1<<23); - /* offset at actual temperature */ - off = ((int64_t)ms5611_c[2] * (1<<16)) + ((int64_t)ms5611_c[4] * dt) / (1<<7); - /* sensitivity at actual temperature */ - sens = ((int64_t)ms5611_c[1] * (1<<15)) + ((int64_t)ms5611_c[3] * dt) / (1<<8); - /* second order temperature compensation */ - if (tempms < 2000) { - t2 = (dt*dt) / (1<<31); - off2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<1); - sens2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<2); - if (tempms < -1500) { - off2 = off2 + 7 * (int64_t)(tempms+1500)*(tempms+1500); - sens2 = sens2 + 11 * ((int64_t)(tempms+1500)*(tempms+1500)) / (1<<1); - } - tempms = tempms - t2; - off = off - off2; - sens = sens - sens2; - } - /* temperature compensated pressure */ - baroms = (((int64_t)ms5611_d1 * sens) / (1<<21) - off) / (1<<15); - - /* Update baro structure */ - baro.absolute = (int32_t)baroms; - - b_abs_handler(); - b_diff_handler(); - - #ifdef DEBUG - ftempms = tempms / 100.; - fbaroms = baroms / 100.; - DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, - &ms5611_d1, &ms5611_d2, &fbaroms, &ftempms, &baro.status); - #endif - break; - } - - default: - ms5611_trans.status = I2CTransDone; - break; - } - } -} diff --git a/sw/airborne/boards/lisa_m/baro_ms5611_spi.c b/sw/airborne/boards/lisa_m/baro_ms5611_spi.c deleted file mode 100644 index bd437cd318..0000000000 --- a/sw/airborne/boards/lisa_m/baro_ms5611_spi.c +++ /dev/null @@ -1,226 +0,0 @@ -/** - * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for I2C - * - * Edit by: Michal Podhradsky, michal.podhradsky@aggiemail.usu.edu - * Utah State University, http://aggieair.usu.edu/ - */ -#include "subsystems/sensors/baro.h" -#include "peripherals/ms5611.h" -#include "led.h" -#include "std.h" -#include "mcu_periph/sys_time.h" - -#include "mcu_periph/spi.h" -#ifndef MS5611_SPI_DEV -#define MS5611_SPI_DEV spi2 -#endif -#define MS5611_BUFFER_LENGTH 4 - -#ifdef DEBUG -#ifndef DOWNLINK_DEVICE -#define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE -#endif -#include "mcu_periph/uart.h" -#include "messages.h" -#include "subsystems/datalink/downlink.h" -#endif - -struct Baro baro; -struct spi_transaction ms5611_trans; -uint8_t ms5611_status; -int32_t prom_cnt; -uint16_t ms5611_c[PROM_NB]; -uint32_t ms5611_d1, ms5611_d2; -float fbaroms, ftempms; -volatile uint8_t input_buf_ms5611[MS5611_BUFFER_LENGTH]; -volatile uint8_t output_buf_ms5611[MS5611_BUFFER_LENGTH]; -static void trans_cb_ms5611( struct spi_transaction *trans ); - -static int8_t baro_ms5611_crc(uint16_t* prom) { - int32_t i, j; - uint32_t res = 0; - uint8_t crc = prom[7] & 0xF; - prom[7] &= 0xFF00; - for (i = 0; i < 16; i++) { - if (i & 1) res ^= ((prom[i>>1]) & 0x00FF); - else res ^= (prom[i>>1]>>8); - for (j = 8; j > 0; j--) { - if (res & 0x8000) res ^= 0x1800; - res <<= 1; - } - } - prom[7] |= crc; - if (crc == ((res >> 12) & 0xF)) return 0; - else return -1; -} - -static void trans_cb_ms5611( struct spi_transaction *trans ) { -#ifdef ROTORCRAFT_BARO_LED - RunOnceEvery(10,LED_TOGGLE(ROTORCRAFT_BARO_LED)); -#endif -} - -void baro_init(void) { - ms5611_trans.select = SPISelectUnselect; - ms5611_trans.cpol = SPICpolIdleHigh; - ms5611_trans.cpha = SPICphaEdge2; - ms5611_trans.dss = SPIDss8bit; - ms5611_trans.bitorder = SPIMSBFirst; - ms5611_trans.cdiv = SPIDiv64; - ms5611_trans.slave_idx = MS5611_SLAVE_DEV; - ms5611_trans.output_length = MS5611_BUFFER_LENGTH; - ms5611_trans.input_length = MS5611_BUFFER_LENGTH; - ms5611_trans.after_cb = trans_cb_ms5611; - ms5611_trans.input_buf = &input_buf_ms5611[0]; - ms5611_trans.output_buf = &input_buf_ms5611[0]; - - ms5611_status = MS5611_UNINIT; - baro.status = BS_UNINITIALIZED; - prom_cnt = 0; -} - -void baro_periodic(void) { - if (sys_time.nb_sec > 1) { - if (ms5611_status == MS5611_IDLE) { - /* start D1 conversion */ - ms5611_status = MS5611_CONV_D1; - ms5611_trans.output_buf[0] = MS5611_START_CONV_D1; - spi_submit(&(MS5611_SPI_DEV), &ms5611_trans); - #ifdef DEBUG - RunOnceEvery(300, { DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, - &ms5611_c[0], &ms5611_c[1], &ms5611_c[2], &ms5611_c[3], - &ms5611_c[4], &ms5611_c[5], &ms5611_c[6], &ms5611_c[7]);}); - #endif - } - else if (ms5611_status == MS5611_CONV_D1) { - /* assume D1 conversion is done */ - ms5611_status = MS5611_CONV_D1_OK; - } - else if (ms5611_status == MS5611_CONV_D1_OK) { - /* read D1 adc */ - ms5611_status = MS5611_ADC_D1; - ms5611_trans.output_buf[0] = MS5611_ADC_READ; - spi_submit(&(MS5611_SPI_DEV), &ms5611_trans); - } - else if (ms5611_status == MS5611_CONV_D2) { - /* assume D2 conversion is done */ - ms5611_status = MS5611_CONV_D2_OK; - } - else if (ms5611_status == MS5611_CONV_D2_OK) { - /* read D2 adc */ - ms5611_status = MS5611_ADC_D2; - ms5611_trans.output_buf[0] = MS5611_ADC_READ; - spi_submit(&(MS5611_SPI_DEV), &ms5611_trans); - } - else if (ms5611_status == MS5611_UNINIT) { - /* reset sensor */ - ms5611_status = MS5611_RESET; - ms5611_trans.output_buf[0] = MS5611_SOFT_RESET; - spi_submit(&(MS5611_SPI_DEV), &ms5611_trans); - } - else if (ms5611_status == MS5611_RESET_OK) { - /* start getting prom data */ - ms5611_status = MS5611_PROM; - ms5611_trans.output_buf[0] = MS5611_PROM_READ | (prom_cnt << 1); - spi_submit(&(MS5611_SPI_DEV), &ms5611_trans); - } - } -} - -void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)){ - if (ms5611_trans.status == SPITransSuccess) { - switch (ms5611_status) { - - case MS5611_RESET: - ms5611_status = MS5611_RESET_OK; - ms5611_trans.status = SPITransDone; - break; - - case MS5611_PROM: - /* read prom data */ - ms5611_c[prom_cnt++] = (ms5611_trans.input_buf[1] << 8) | ms5611_trans.input_buf[2]; - if (prom_cnt < PROM_NB) {//8 bytes at PROM - /* get next prom data */ - ms5611_trans.output_buf[0] = MS5611_PROM_READ | (prom_cnt << 1); - spi_submit(&(MS5611_SPI_DEV), &ms5611_trans); - } - else { - /* done reading prom */ - ms5611_trans.status = SPITransDone; - /* check prom crc */ - if (baro_ms5611_crc(ms5611_c) == 0) { - ms5611_status = MS5611_IDLE; - baro.status = BS_RUNNING; - } - else { - /* checksum error, try again */ - baro_init(); - } - } - break; - - case MS5611_ADC_D1: - /* read D1 (pressure) */ - ms5611_d1 = (ms5611_trans.input_buf[1] << 16) | - (ms5611_trans.input_buf[2] << 8) | - ms5611_trans.input_buf[3]; - /* start D2 conversion */ - ms5611_status = MS5611_CONV_D2; - ms5611_trans.output_buf[0] = MS5611_START_CONV_D2; - spi_submit(&(MS5611_SPI_DEV), &ms5611_trans); - break; - - case MS5611_ADC_D2: { - int64_t dt, baroms, tempms, off, sens, t2, off2, sens2; - /* read D2 (temperature) */ - ms5611_d2 = (ms5611_trans.input_buf[1] << 16) | - (ms5611_trans.input_buf[2] << 8) | - ms5611_trans.input_buf[3]; - ms5611_status = MS5611_IDLE; - ms5611_trans.status = SPITransDone; - - /* difference between actual and ref temperature */ - dt = ms5611_d2 - (int64_t)ms5611_c[5] * (1<<8); - /* actual temperature */ - tempms = 2000 + ((int64_t)dt * ms5611_c[6]) / (1<<23); - /* offset at actual temperature */ - off = ((int64_t)ms5611_c[2] * (1<<16)) + ((int64_t)ms5611_c[4] * dt) / (1<<7); - /* sensitivity at actual temperature */ - sens = ((int64_t)ms5611_c[1] * (1<<15)) + ((int64_t)ms5611_c[3] * dt) / (1<<8); - /* second order temperature compensation */ - if (tempms < 2000) { - t2 = (dt*dt) / (1<<31); - off2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<1); - sens2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<2); - if (tempms < -1500) { - off2 = off2 + 7 * (int64_t)(tempms+1500)*(tempms+1500); - sens2 = sens2 + 11 * ((int64_t)(tempms+1500)*(tempms+1500)) / (1<<1); - } - tempms = tempms - t2; - off = off - off2; - sens = sens - sens2; - } - /* temperature compensated pressure */ - baroms = (((int64_t)ms5611_d1 * sens) / (1<<21) - off) / (1<<15); - - /* Update baro structure */ - baro.absolute = (int32_t)baroms; - - b_abs_handler(); - b_diff_handler(); - - #ifdef DEBUG - ftempms = tempms / 100.; - fbaroms = baroms / 100.; - DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, - &ms5611_d1, &ms5611_d2, &fbaroms, &ftempms, &baro.status); - #endif - break; - } - - default: - ms5611_trans.status = SPITransDone; - break; - } - } -} diff --git a/sw/airborne/modules/sensors/baro_bmp.c b/sw/airborne/modules/sensors/baro_bmp.c index bdfce3a3af..5011b7d075 100644 --- a/sw/airborne/modules/sensors/baro_bmp.c +++ b/sw/airborne/modules/sensors/baro_bmp.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Martin Mueller + * Copyright (C) 2013 Felix Ruess * * This file is part of paparazzi. * @@ -20,14 +21,16 @@ * */ -/** \file baro_bmp.c - * \brief Bosch BMP085 I2C sensor interface +/** + * @file modules/sensors/baro_bmp.c + * Bosch BMP085 I2C sensor interface. * - * This reads the values for pressure and temperature from the Bosch BMP085 sensor through I2C. + * This reads the values for pressure and temperature from the Bosch BMP085 sensor through I2C. */ #include "baro_bmp.h" +#include "peripherals/bmp085_regs.h" #include "mcu_periph/sys_time.h" #include "mcu_periph/i2c.h" @@ -35,12 +38,6 @@ #include "mcu_periph/uart.h" #include "messages.h" #include "subsystems/datalink/downlink.h" -#include "state.h" -#include "subsystems/nav.h" - -#ifdef SITL -#include "subsystems/gps.h" -#endif #ifndef DOWNLINK_DEVICE #define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE @@ -54,196 +51,56 @@ #define BMP_I2C_DEV i2c0 #endif -#define BMP085_SLAVE_ADDR 0xEE -#define BARO_BMP_OFFSET_MAX 30000 -#define BARO_BMP_OFFSET_MIN 10 -#define BARO_BMP_OFFSET_NBSAMPLES_INIT 2 -#define BARO_BMP_OFFSET_NBSAMPLES_AVRG 4 #define BARO_BMP_R 0.5 #define BARO_BMP_SIGMA2 0.1 -struct i2c_transaction bmp_trans; + +struct Bmp085 baro_bmp; bool_t baro_bmp_enabled; float baro_bmp_r; float baro_bmp_sigma2; +int32_t baro_bmp_alt; -// Global variables -uint8_t baro_bmp_status; -bool_t baro_bmp_valid; -uint32_t baro_bmp_pressure; -uint16_t baro_bmp_temperature; -int32_t baro_bmp_altitude, baro_bmp,baro_bmp_temp,baro_bmp_offset; -double tmp_float; +void baro_bmp_init(void) { -int16_t bmp_ac1, bmp_ac2, bmp_ac3; -uint16_t bmp_ac4, bmp_ac5, bmp_ac6; -int16_t bmp_b1, bmp_b2; -int16_t bmp_mb, bmp_mc, bmp_md; -int32_t bmp_up, bmp_ut; + bmp085_init(&baro_bmp, &BMP_I2C_DEV, BMP085_SLAVE_ADDR); -// Local variables -bool_t baro_bmp_offset_init; -int32_t baro_bmp_offset_tmp; -uint16_t baro_bmp_cnt; - -void baro_bmp_init( void ) { - baro_bmp_status = BARO_BMP_UNINIT; - baro_bmp_valid = FALSE; baro_bmp_r = BARO_BMP_R; baro_bmp_sigma2 = BARO_BMP_SIGMA2; baro_bmp_enabled = TRUE; - baro_bmp_offset_init = FALSE; - baro_bmp_cnt = BARO_BMP_OFFSET_NBSAMPLES_INIT + BARO_BMP_OFFSET_NBSAMPLES_AVRG; - /* read calibration values */ - bmp_trans.buf[0] = BMP085_EEPROM_AC1; - i2c_transceive(&BMP_I2C_DEV, &bmp_trans, BMP085_SLAVE_ADDR, 1, 22); -} - -void baro_bmp_periodic( void ) { -#ifndef SITL - if (baro_bmp_status == BARO_BMP_IDLE) { - /* start temp measurement (once) */ - bmp_trans.buf[0] = BMP085_CTRL_REG; - bmp_trans.buf[1] = BMP085_START_TEMP; - i2c_transmit(&BMP_I2C_DEV, &bmp_trans, BMP085_SLAVE_ADDR, 2); - baro_bmp_status = BARO_BMP_START_TEMP; - } - else if (baro_bmp_status == BARO_BMP_START_TEMP) { - /* read temp measurement */ - bmp_trans.buf[0] = BMP085_DAT_MSB; - i2c_transceive(&BMP_I2C_DEV, &bmp_trans, BMP085_SLAVE_ADDR, 1, 2); - baro_bmp_status = BARO_BMP_READ_TEMP; - } - else if (baro_bmp_status == BARO_BMP_START_PRESS) { - /* read press measurement */ - bmp_trans.buf[0] = BMP085_DAT_MSB; - i2c_transceive(&BMP_I2C_DEV, &bmp_trans, BMP085_SLAVE_ADDR, 1, 3); - baro_bmp_status = BARO_BMP_READ_PRESS; - } -#else // SITL - baro_bmp_altitude = gps.hmsl / 1000.0; - baro_bmp_pressure = baro_bmp_altitude; //FIXME do a proper scaling here - baro_bmp_valid = TRUE; -#endif } -void baro_bmp_event( void ) { +void baro_bmp_periodic(void) { - if (bmp_trans.status == I2CTransSuccess) { + if (baro_bmp.initialized) + bmp085_periodic(&baro_bmp); + else + bmp085_read_eeprom_calib(&baro_bmp); - if (baro_bmp_status == BARO_BMP_UNINIT) { - /* get calibration data */ - bmp_ac1 = (bmp_trans.buf[0] << 8) | bmp_trans.buf[1]; - bmp_ac2 = (bmp_trans.buf[2] << 8) | bmp_trans.buf[3]; - bmp_ac3 = (bmp_trans.buf[4] << 8) | bmp_trans.buf[5]; - bmp_ac4 = (bmp_trans.buf[6] << 8) | bmp_trans.buf[7]; - bmp_ac5 = (bmp_trans.buf[8] << 8) | bmp_trans.buf[9]; - bmp_ac6 = (bmp_trans.buf[10] << 8) | bmp_trans.buf[11]; - bmp_b1 = (bmp_trans.buf[12] << 8) | bmp_trans.buf[13]; - bmp_b2 = (bmp_trans.buf[14] << 8) | bmp_trans.buf[15]; - bmp_mb = (bmp_trans.buf[16] << 8) | bmp_trans.buf[17]; - bmp_mc = (bmp_trans.buf[18] << 8) | bmp_trans.buf[19]; - bmp_md = (bmp_trans.buf[20] << 8) | bmp_trans.buf[21]; - baro_bmp_status = BARO_BMP_IDLE; - } - else if (baro_bmp_status == BARO_BMP_READ_TEMP) { - /* get uncompensated temperature */ - bmp_ut = (bmp_trans.buf[0] << 8) | bmp_trans.buf[1]; - /* start high res pressure measurement */ - bmp_trans.buf[0] = BMP085_CTRL_REG; - bmp_trans.buf[1] = BMP085_START_P3; - i2c_transmit(&BMP_I2C_DEV, &bmp_trans, BMP085_SLAVE_ADDR, 2); - baro_bmp_status = BARO_BMP_START_PRESS; - } - else if (baro_bmp_status == BARO_BMP_READ_PRESS) { - int32_t bmp_p, bmp_t; - int32_t bmp_x1, bmp_x2, bmp_x3; - int32_t bmp_b3, bmp_b5, bmp_b6; - uint32_t bmp_b4, bmp_b7; +} - /* get uncompensated pressure, oss=3 */ - bmp_up = (bmp_trans.buf[0] << 11) | - (bmp_trans.buf[1] << 3) | - (bmp_trans.buf[2] >> 5); - /* start temp measurement */ - bmp_trans.buf[0] = BMP085_CTRL_REG; - bmp_trans.buf[1] = BMP085_START_TEMP; - i2c_transmit(&BMP_I2C_DEV, &bmp_trans, BMP085_SLAVE_ADDR, 2); - baro_bmp_status = BARO_BMP_START_TEMP; +void baro_bmp_event(void) { - /* compensate temperature */ - bmp_x1 = (bmp_ut - bmp_ac6) * bmp_ac5 / (1<<15); - bmp_x2 = bmp_mc * (1<<11) / (bmp_x1 + bmp_md); - bmp_b5 = bmp_x1 + bmp_x2; - bmp_t = (bmp_b5 + 8) / (1<<4); + bmp085_event(&baro_bmp); - /* compensate pressure */ - bmp_b6 = bmp_b5 - 4000; - bmp_x1 = (bmp_b2 * (bmp_b6 * bmp_b6 / (1<<12))) / (1<<11); - bmp_x2 = bmp_ac2 *bmp_b6 / (1<<11); - bmp_x3 = bmp_x1 + bmp_x2; - bmp_b3 = (((bmp_ac1 * 4 + bmp_x3) << 3) + 2) / 4; - bmp_x1 = bmp_ac3 * bmp_b6 / (1<<13); - bmp_x2 = (bmp_b1 * (bmp_b6 * bmp_b6 / (1<<12))) / (1<<16); - bmp_x3 = ((bmp_x1 + bmp_x2) +2) / (1<<2); - bmp_b4 = bmp_ac4 * (uint32_t)(bmp_x3 + 32768) / (1<<15); - bmp_b7 = ((uint32_t)bmp_up - bmp_b3) * (50000>>3); - if (bmp_b7 < 0x80000000) - bmp_p = (bmp_b7 * 2) / bmp_b4; - else - bmp_p = (bmp_b7 / bmp_b4) * 2; - bmp_x1 = (bmp_p / (1<<8)) * (bmp_p / (1<<8)); - bmp_x1 = (bmp_x1 * 3038) / (1<<16); - bmp_x2 = (-7357 * bmp_p) / (1<<16); - bmp_p = bmp_p + (bmp_x1 + bmp_x2 + 3791) / (1<<4); + if (baro_bmp.data_available) { - baro_bmp_temperature = bmp_t; - baro_bmp_pressure = bmp_p; - - tmp_float = bmp_p/101325.0; //pressao nivel mar - tmp_float = pow(tmp_float,0.190295); //eleva pressao ao expoente - baro_bmp = 44330*(1.0-tmp_float); - - if (!baro_bmp_offset_init) { - baro_bmp_offset = baro_bmp; - baro_bmp_offset_init = TRUE; -#if 0 - --baro_bmp_cnt; - // Check if averaging completed - if (baro_bmp_cnt == 0) { - // Calculate average - baro_bmp_offset = (baro_bmp_offset_tmp / BARO_BMP_OFFSET_NBSAMPLES_AVRG); - // Limit offset - if (baro_bmp_offset < BARO_BMP_OFFSET_MIN) - baro_bmp_offset = BARO_BMP_OFFSET_MIN; - if (baro_bmp_offset > BARO_BMP_OFFSET_MAX) - baro_bmp_offset = BARO_BMP_OFFSET_MAX; - baro_bmp_offset_init = TRUE; - } - // Check if averaging needs to continue - else if (baro_bmp_cnt <= BARO_BMP_OFFSET_NBSAMPLES_AVRG) - baro_bmp_offset_tmp += baro_bmp; -#endif - } //baro offset init - - baro_bmp_temp = (baro_bmp - baro_bmp_offset); - - if (baro_bmp_offset_init) { - baro_bmp_altitude = ground_alt + baro_bmp_temp; - // New value available - baro_bmp_valid = TRUE; + float tmp = baro_bmp.pressure / 101325.0; // pressure at sea level + tmp = pow(tmp, 0.190295); + baro_bmp_alt = 44330 * (1.0 - tmp); #ifdef SENSOR_SYNC_SEND - DOWNLINK_SEND_BMP_STATUS(DefaultChannel, DefaultDevice, &bmp_up, &bmp_ut, &bmp_p, &bmp_t); + DOWNLINK_SEND_BMP_STATUS(DefaultChannel, DefaultDevice, &baro_bmp.up, + &baro_bmp.ut, &baro_bmp.pressure, + &baro_bmp.temperature); #else - RunOnceEvery(10, DOWNLINK_SEND_BMP_STATUS(DefaultChannel, DefaultDevice, &baro_bmp_temp, &bmp_ut, &bmp_p, &bmp_t)); + RunOnceEvery(10, DOWNLINK_SEND_BMP_STATUS(DefaultChannel, DefaultDevice, + &baro_bmp.up, &baro_bmp.ut, + &baro_bmp.pressure, + &baro_bmp.temperature)); #endif - } else { - baro_bmp_altitude = 0.0; - } - } } } diff --git a/sw/airborne/modules/sensors/baro_bmp.h b/sw/airborne/modules/sensors/baro_bmp.h index 860937bfe6..db1039e817 100644 --- a/sw/airborne/modules/sensors/baro_bmp.h +++ b/sw/airborne/modules/sensors/baro_bmp.h @@ -1,42 +1,43 @@ +/* + * Copyright (C) 2010 Martin Mueller + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * @file modules/sensors/baro_bmp.h + * Bosch BMP085 I2C sensor interface. + * + * This reads the values for pressure and temperature from the Bosch BMP085 sensor through I2C. + */ + #ifndef BARO_BMP_H #define BARO_BMP_H -#include "std.h" +#include "peripherals/bmp085.h" -#define BMP085_EEPROM_AC1 0xAA -#define BMP085_EEPROM_AC2 0xAC -#define BMP085_EEPROM_AC3 0xAE -#define BMP085_EEPROM_AC4 0xB0 -#define BMP085_EEPROM_AC5 0xB2 -#define BMP085_EEPROM_AC6 0xB4 -#define BMP085_EEPROM_B1 0xB6 -#define BMP085_EEPROM_B2 0xB8 -#define BMP085_EEPROM_MB 0xBA -#define BMP085_EEPROM_MC 0xBC -#define BMP085_EEPROM_MD 0xBE - -#define BMP085_CTRL_REG 0xF4 - -#define BMP085_START_TEMP 0x2E -#define BMP085_START_P0 0x34 -#define BMP085_START_P1 0x74 -#define BMP085_START_P2 0xB4 -#define BMP085_START_P3 0xF4 - -#define BMP085_DAT_MSB 0xF6 -#define BMP085_DAT_LSB 0xF7 -#define BMP085_DAT_XLSB 0xF8 - -#define BARO_BMP_UNINIT 0 -#define BARO_BMP_IDLE 1 -#define BARO_BMP_START_TEMP 2 -#define BARO_BMP_READ_TEMP 3 -#define BARO_BMP_START_PRESS 4 -#define BARO_BMP_READ_PRESS 5 +extern struct Bmp085 baro_bmp; /// new measurement every 3rd baro_bmp_periodic #ifndef SITL -#define BARO_BMP_DT (BARO_BMP_PERIODIC_PERIOID / 3) +#define BARO_BMP_DT (BARO_BMP_PERIODIC_PERIOD / 3) #else #define BARO_BMP_DT BARO_BMP_PERIODIC_PERIOID #endif @@ -44,19 +45,12 @@ extern bool_t baro_bmp_enabled; extern float baro_bmp_r; extern float baro_bmp_sigma2; - -extern uint8_t baro_bmp_status; -extern bool_t baro_bmp_valid; -extern uint32_t baro_bmp_pressure; -extern uint16_t baro_bmp_temperature; -extern int32_t baro_bmp_altitude; -extern int32_t baro_bmp; -extern int32_t baro_bmp_offset; +extern int32_t baro_bmp_alt; void baro_bmp_init(void); void baro_bmp_periodic(void); void baro_bmp_event(void); -#define BaroBmpUpdate(_b, _h) { if (baro_bmp_valid) { _b = baro_bmp_pressure; _h(); baro_bmp_valid = FALSE; } } +#define BaroBmpUpdate(_b, _h) { if (baro_bmp.data_available) { _b = baro_bmp.pressure; _h(); baro_bmp.data_available = FALSE; } } #endif diff --git a/sw/airborne/modules/sensors/baro_ms5611_i2c.c b/sw/airborne/modules/sensors/baro_ms5611_i2c.c index e7e2f1c423..d3b3a3d88c 100644 --- a/sw/airborne/modules/sensors/baro_ms5611_i2c.c +++ b/sw/airborne/modules/sensors/baro_ms5611_i2c.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Martin Mueller + * Copyright (C) 2011-2013 The Paparazzi Team * * This file is part of paparazzi. * @@ -30,11 +30,9 @@ #include "modules/sensors/baro_ms5611_i2c.h" #include "mcu_periph/sys_time.h" -#include "mcu_periph/i2c.h" #include "mcu_periph/uart.h" #include "messages.h" #include "subsystems/datalink/downlink.h" -#include "subsystems/nav.h" #ifndef DOWNLINK_DEVICE #define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE @@ -49,202 +47,66 @@ #define MS5611_SLAVE_ADDR 0xEE #endif +struct Ms5611_I2c baro_ms5611; -struct i2c_transaction ms5611_trans; -uint8_t ms5611_status; -uint16_t ms5611_c[PROM_NB]; -uint32_t ms5611_d1, ms5611_d2; -int32_t prom_cnt; -int64_t baroms; float fbaroms, ftempms; float baro_ms5611_alt; +bool_t baro_ms5611_alt_valid; bool_t baro_ms5611_enabled; -bool_t baro_ms5611_valid; + float baro_ms5611_r; float baro_ms5611_sigma2; -static int8_t baro_ms5611_crc(uint16_t* prom) { - int32_t i, j; - uint32_t res = 0; - uint8_t crc = prom[7] & 0xF; - prom[7] &= 0xFF00; - for (i = 0; i < 16; i++) { - if (i & 1) res ^= ((prom[i>>1]) & 0x00FF); - else res ^= (prom[i>>1]>>8); - for (j = 8; j > 0; j--) { - if (res & 0x8000) res ^= 0x1800; - res <<= 1; - } - } - prom[7] |= crc; - if (crc == ((res >> 12) & 0xF)) return 0; - else return -1; -} void baro_ms5611_init(void) { + ms5611_i2c_init(&baro_ms5611, &MS5611_I2C_DEV, MS5611_SLAVE_ADDR); + baro_ms5611_enabled = TRUE; - baro_ms5611_valid = FALSE; - ms5611_status = MS5611_UNINIT; + baro_ms5611_alt_valid = FALSE; + baro_ms5611_r = BARO_MS5611_R; baro_ms5611_sigma2 = BARO_MS5611_SIGMA2; - prom_cnt = 0; } -void baro_ms5611_periodic( void ) { - if (sys_time.nb_sec > 1) { - if (ms5611_status >= MS5611_IDLE) { - /* start D1 conversion */ - ms5611_status = MS5611_CONV_D1; - ms5611_trans.buf[0] = MS5611_START_CONV_D1; - i2c_transmit(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1); - RunOnceEvery((4*30), DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, - &ms5611_c[0], &ms5611_c[1], &ms5611_c[2], &ms5611_c[3], - &ms5611_c[4], &ms5611_c[5], &ms5611_c[6], &ms5611_c[7])); - } - else if (ms5611_status == MS5611_UNINIT) { - /* reset sensor */ - ms5611_status = MS5611_RESET; - ms5611_trans.buf[0] = MS5611_SOFT_RESET; - i2c_transmit(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1); - } - else if (ms5611_status == MS5611_RESET_OK) { - /* start getting prom data */ - ms5611_status = MS5611_PROM; - ms5611_trans.buf[0] = MS5611_PROM_READ | (prom_cnt << 1); - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 2); - } +void baro_ms5611_periodic_check( void ) { + + ms5611_i2c_periodic_check(&baro_ms5611); + + if (baro_ms5611.initialized) { + RunOnceEvery((4*30), DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, + &baro_ms5611.data.c[0], + &baro_ms5611.data.c[1], + &baro_ms5611.data.c[2], + &baro_ms5611.data.c[3], + &baro_ms5611.data.c[4], + &baro_ms5611.data.c[5], + &baro_ms5611.data.c[6], + &baro_ms5611.data.c[7])); } } -void baro_ms5611_d1( void ) { +/// trigger new measurement or initialize if needed +void baro_ms5611_read(void) { if (sys_time.nb_sec > 1) { - if (ms5611_status == MS5611_CONV_D1_OK) { - /* read D1 adc */ - ms5611_status = MS5611_ADC_D1; - ms5611_trans.buf[0] = MS5611_ADC_READ; - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 3); - } - } -} - -void baro_ms5611_d2( void ) { - if (sys_time.nb_sec > 1) { - if (ms5611_status == MS5611_CONV_D2_OK) { - /* read D2 adc */ - ms5611_status = MS5611_ADC_D2; - ms5611_trans.buf[0] = MS5611_ADC_READ; - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 3); - } + ms5611_i2c_read(&baro_ms5611); } } void baro_ms5611_event( void ) { - if (ms5611_trans.status == I2CTransSuccess) { - switch (ms5611_status) { - case MS5611_RESET: - ms5611_status = MS5611_RESET_OK; - ms5611_trans.status = I2CTransDone; - break; + ms5611_i2c_event(&baro_ms5611); - case MS5611_PROM: - /* read prom data */ - ms5611_c[prom_cnt++] = (ms5611_trans.buf[0] << 8) | ms5611_trans.buf[1]; - if (prom_cnt < PROM_NB) { - /* get next prom data */ - ms5611_trans.buf[0] = MS5611_PROM_READ | (prom_cnt << 1); - i2c_transceive(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1, 2); - } - else { - /* done reading prom */ - ms5611_trans.status = I2CTransDone; - /* check prom crc */ - if (baro_ms5611_crc(ms5611_c) == 0) { - DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, - &ms5611_c[0], &ms5611_c[1], &ms5611_c[2], &ms5611_c[3], - &ms5611_c[4], &ms5611_c[5], &ms5611_c[6], &ms5611_c[7]); - ms5611_status = MS5611_IDLE; - } - else { - /* checksum error, try again */ - baro_ms5611_init(); - } - } - break; - - case MS5611_CONV_D1: - ms5611_status = MS5611_CONV_D1_OK; - ms5611_trans.status = I2CTransDone; - break; - - case MS5611_ADC_D1: - /* read D1 (pressure) */ - ms5611_d1 = (ms5611_trans.buf[0] << 16) | - (ms5611_trans.buf[1] << 8) | - ms5611_trans.buf[2]; - /* start D2 conversion */ - ms5611_status = MS5611_CONV_D2; - ms5611_trans.buf[0] = MS5611_START_CONV_D2; - i2c_transmit(&MS5611_I2C_DEV, &ms5611_trans, MS5611_SLAVE_ADDR, 1); - break; - - case MS5611_CONV_D2: - ms5611_status = MS5611_CONV_D2_OK; - ms5611_trans.status = I2CTransDone; - break; - - case MS5611_ADC_D2: { - int64_t dt, tempms, off, sens, t2, off2, sens2; - /* read D2 (temperature) */ - ms5611_d2 = (ms5611_trans.buf[0] << 16) | - (ms5611_trans.buf[1] << 8) | - ms5611_trans.buf[2]; - ms5611_status = MS5611_IDLE; - ms5611_trans.status = I2CTransDone; - - /* difference between actual and ref temperature */ - dt = ms5611_d2 - (int64_t)ms5611_c[5] * (1<<8); - /* actual temperature */ - tempms = 2000 + ((int64_t)dt * ms5611_c[6]) / (1<<23); - /* offset at actual temperature */ - off = ((int64_t)ms5611_c[2] * (1<<16)) + ((int64_t)ms5611_c[4] * dt) / (1<<7); - /* sensitivity at actual temperature */ - sens = ((int64_t)ms5611_c[1] * (1<<15)) + ((int64_t)ms5611_c[3] * dt) / (1<<8); - /* second order temperature compensation */ - if (tempms < 2000) { - t2 = (dt*dt) / (1<<31); - off2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<1); - sens2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<2); - if (tempms < -1500) { - off2 = off2 + 7 * (int64_t)(tempms+1500)*(tempms+1500); - sens2 = sens2 + 11 * ((int64_t)(tempms+1500)*(tempms+1500)) / (1<<1); - } - tempms = tempms - t2; - off = off - off2; - sens = sens - sens2; - } - /* temperature compensated pressure */ - baroms = (((int64_t)ms5611_d1 * sens) / (1<<21) - off) / (1<<15); - - float tmp_float = baroms/101325.0; //pressure at sea level - tmp_float = pow(tmp_float,0.190295); //eleva pressao ao expoente - baro_ms5611_alt = 44330*(1.0-tmp_float); //altitude above MSL - - baro_ms5611_valid = TRUE; + if (baro_ms5611.data_available) { + float tmp_float = baro_ms5611.data.pressure / 101325.0; //pressure at sea level + tmp_float = pow(tmp_float, 0.190295); + baro_ms5611_alt = 44330 * (1.0 - tmp_float); //altitude above MSL + baro_ms5611_alt_valid = TRUE; #ifdef SENSOR_SYNC_SEND - ftempms = tempms / 100.; - fbaroms = baroms / 100.; - DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, - &ms5611_d1, &ms5611_d2, &fbaroms, &ftempms); + ftempms = baro_ms5611.data.temperature / 100.; + fbaroms = baro_ms5611.data.pressure / 100.; + DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, + &baro_ms5611.data.d1, &baro_ms5611.data.d2, &fbaroms, &ftempms); #endif - - break; - } - - default: - ms5611_trans.status = I2CTransDone; - break; - } } } diff --git a/sw/airborne/modules/sensors/baro_ms5611_i2c.h b/sw/airborne/modules/sensors/baro_ms5611_i2c.h index 2f34e8fcff..f30b28debc 100644 --- a/sw/airborne/modules/sensors/baro_ms5611_i2c.h +++ b/sw/airborne/modules/sensors/baro_ms5611_i2c.h @@ -2,48 +2,28 @@ #define BARO_MS56111_I2C_H #include "std.h" +#include "peripherals/ms5611_i2c.h" -/* we use OSR=4096 for maximum resolution */ -#define MS5611_SOFT_RESET 0x1E -#define MS5611_PROM_READ 0xA0 -#define MS5611_START_CONV_D1 0x48 -#define MS5611_START_CONV_D2 0x58 -#define MS5611_ADC_READ 0x00 - -#define PROM_NB 8 - -/// new measurement every baro_ms5611_periodic -#define BARO_MS5611_DT BARO_MS5611_PERIODIC_PERIOID - +/// new measurement with every baro_ms5611_read() call +#define BARO_MS5611_DT BARO_MS5611_READ_PERIOD #define BARO_MS5611_R 20 #define BARO_MS5611_SIGMA2 1 -extern float baro_ms5611_alt; -extern bool_t baro_ms5611_valid; -extern bool_t baro_ms5611_enabled; extern float baro_ms5611_r; extern float baro_ms5611_sigma2; -extern int64_t baroms; -enum ms5611_stat{ - MS5611_UNINIT, - MS5611_RESET, - MS5611_RESET_OK, - MS5611_PROM, - MS5611_IDLE, - MS5611_CONV_D1, - MS5611_CONV_D1_OK, - MS5611_ADC_D1, - MS5611_CONV_D2, - MS5611_CONV_D2_OK, - MS5611_ADC_D2 -}; +extern float baro_ms5611_alt; +extern bool_t baro_ms5611_alt_valid; +extern bool_t baro_ms5611_enabled; + +extern struct Ms5611_I2c baro_ms5611; extern void baro_ms5611_init(void); -extern void baro_ms5611_periodic(void); -extern void baro_ms5611_d1(void); -extern void baro_ms5611_d2(void); +extern void baro_ms5611_read(void); +extern void baro_ms5611_periodic_check(void); extern void baro_ms5611_event(void); -#define BaroMs5611Update(_b, _h) { if (baro_ms5611_valid) { _b = baro_ms5611_alt; _h(); baro_ms5611_valid = FALSE; } } +#define BaroMs5611UpdatePressure(_b, _h) { if (baro_ms5611.data_available) { _b = baro_ms5611.data.pressure; _h(); baro_ms5611.data_available = FALSE; } } + +#define BaroMs5611UpdateAlt(_b, _h) { if (baro_ms5611.data_available) { _b = baro_ms5611_alt; _h(); baro_ms5611.data_available = FALSE; } } #endif diff --git a/sw/airborne/modules/sensors/baro_ms5611_spi.c b/sw/airborne/modules/sensors/baro_ms5611_spi.c new file mode 100644 index 0000000000..c91d713153 --- /dev/null +++ b/sw/airborne/modules/sensors/baro_ms5611_spi.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2011-2013 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * @file modules/sensors/baro_ms5611_spi.c + * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for SPI. + * + */ + + +#include "modules/sensors/baro_ms5611_spi.h" + +#include "mcu_periph/sys_time.h" +#include "mcu_periph/uart.h" +#include "messages.h" +#include "subsystems/datalink/downlink.h" + +#ifndef DOWNLINK_DEVICE +#define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE +#endif + +#ifndef MS5611_SPI_DEV +#define MS5611_SPI_DEV spi1 +#endif + +#ifndef MS5611_SLAVE_DEV +#define MS5611_SLAVE_DEV SPI_SLAVE0 +#endif + + +struct Ms5611_Spi baro_ms5611; + +float fbaroms, ftempms; +float baro_ms5611_alt; +bool_t baro_ms5611_alt_valid; +bool_t baro_ms5611_enabled; + +float baro_ms5611_r; +float baro_ms5611_sigma2; + + +void baro_ms5611_init(void) { + ms5611_spi_init(&baro_ms5611, &MS5611_SPI_DEV, MS5611_SLAVE_DEV); + + baro_ms5611_enabled = TRUE; + baro_ms5611_alt_valid = FALSE; + + baro_ms5611_r = BARO_MS5611_R; + baro_ms5611_sigma2 = BARO_MS5611_SIGMA2; +} + +void baro_ms5611_periodic_check( void ) { + + ms5611_spi_periodic_check(&baro_ms5611); + + if (baro_ms5611.initialized) { + RunOnceEvery((4*30), DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, + &baro_ms5611.data.c[0], + &baro_ms5611.data.c[1], + &baro_ms5611.data.c[2], + &baro_ms5611.data.c[3], + &baro_ms5611.data.c[4], + &baro_ms5611.data.c[5], + &baro_ms5611.data.c[6], + &baro_ms5611.data.c[7])); + } +} + +/// trigger new measurement or initialize if needed +void baro_ms5611_read(void) { + if (sys_time.nb_sec > 1) { + ms5611_spi_read(&baro_ms5611); + } +} + +void baro_ms5611_event( void ) { + + ms5611_spi_event(&baro_ms5611); + + if (baro_ms5611.data_available) { + float tmp_float = baro_ms5611.data.pressure / 101325.0; //pressure at sea level + tmp_float = pow(tmp_float, 0.190295); + baro_ms5611_alt = 44330 * (1.0 - tmp_float); //altitude above MSL + baro_ms5611_alt_valid = TRUE; + +#ifdef SENSOR_SYNC_SEND + ftempms = baro_ms5611.data.temperature / 100.; + fbaroms = baro_ms5611.data.pressure / 100.; + DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, + &baro_ms5611.data.d1, &baro_ms5611.data.d2, &fbaroms, &ftempms); +#endif + } +} diff --git a/sw/airborne/modules/sensors/baro_ms5611_spi.h b/sw/airborne/modules/sensors/baro_ms5611_spi.h new file mode 100644 index 0000000000..7bab9d92e8 --- /dev/null +++ b/sw/airborne/modules/sensors/baro_ms5611_spi.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 Martin Mueller + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * @file modules/sensors/baro_ms5611_spi.h + * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for SPI. + * + */ + +#ifndef BARO_MS56111_SPI_H +#define BARO_MS56111_SPI_H + +#include "std.h" +#include "peripherals/ms5611_spi.h" + +/// new measurement with every baro_ms5611_read() call +#define BARO_MS5611_DT BARO_MS5611_READ_PERIOD +#define BARO_MS5611_R 20 +#define BARO_MS5611_SIGMA2 1 +extern float baro_ms5611_r; +extern float baro_ms5611_sigma2; + +extern float baro_ms5611_alt; +extern bool_t baro_ms5611_alt_valid; +extern bool_t baro_ms5611_enabled; + +extern struct Ms5611_Spi baro_ms5611; + +extern void baro_ms5611_init(void); +extern void baro_ms5611_read(void); +extern void baro_ms5611_periodic_check(void); +extern void baro_ms5611_event(void); + +#define BaroMs5611UpdatePressure(_b) { if (baro_ms5611.data_available) { _b = baro_ms5611.data.pressure; baro_ms5611.data_available = FALSE; } } + +#define BaroMs5611UpdateAlt(_b) { if (baro_ms5611.data_available) { _b = baro_ms5611_alt; baro_ms5611.data_available = FALSE; } } + +#endif diff --git a/sw/airborne/peripherals/bmp085.c b/sw/airborne/peripherals/bmp085.c new file mode 100644 index 0000000000..2c123ef592 --- /dev/null +++ b/sw/airborne/peripherals/bmp085.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2010 Martin Mueller + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** @file peripherals/bmp085.c + * Bosch BMP085 driver interface. + */ + +#include "peripherals/bmp085.h" +#include "peripherals/bmp085_regs.h" + + +static int32_t bmp085_compensated_temperature(struct Bmp085Calib* calib, int32_t raw) +{ + int32_t x1 = (raw - calib->ac6) * calib->ac5 / (1<<15); + int32_t x2 = (calib->mc << 11) / (x1 + calib->md); + calib->b5 = x1 + x2; + return (calib->b5 + 8) >> 4; +} + + + +/** Apply temp calibration and sensor calibration to raw measurement to get Pa + * (from BMP085 datasheet) + */ +static int32_t bmp085_compensated_pressure(struct Bmp085Calib* calib, int32_t raw) +{ + int32_t b6 = calib->b5 - 4000; + int32_t x1 = (calib->b2 * (b6 * b6 >> 12)) >> 11; + int32_t x2 = calib->ac2 * b6 >> 11; + int32_t x3 = x1 + x2; + int32_t b3 = (((calib->ac1 * 4 + x3) << BMP085_OSS) + 2)/4; + x1 = calib->ac3 * b6 >> 13; + x2 = (calib->b1 * (b6 * b6 >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + uint32_t b4 = (calib->ac4 * (uint32_t) (x3 + 32768)) >> 15; + uint32_t b7 = (raw - b3) * (50000 >> BMP085_OSS); + int32_t p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2; + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + return p + ((x1 + x2 + 3791) >> 4); +} + +/** + * Dummy function to always return TRUE on EndOfConversion check. + * Ensure proper timing trough frequency of bmp085_periodic instead! + */ +static bool_t bmp085_eoc_true(void) +{ + return TRUE; +} + + +void bmp085_read_eeprom_calib(struct Bmp085* bmp) +{ + if (bmp->status == BMP085_STATUS_UNINIT) { + bmp->initialized = FALSE; + bmp->i2c_trans.buf[0] = BMP085_EEPROM_AC1; + i2c_transceive(bmp->i2c_p, &(bmp->i2c_trans), bmp->i2c_trans.slave_addr, 1, 22); + } +} + + +void bmp085_init(struct Bmp085* bmp, struct i2c_periph *i2c_p, uint8_t addr) +{ + /* set i2c_peripheral */ + bmp->i2c_p = i2c_p; + + /* slave address */ + bmp->i2c_trans.slave_addr = addr; + /* set initial status: Success or Done */ + bmp->i2c_trans.status = I2CTransDone; + + bmp->data_available = FALSE; + bmp->initialized = FALSE; + bmp->status = BMP085_STATUS_UNINIT; + + /* by default assign EOC function that always returns TRUE + * ensure proper timing through frequeny of bmp_periodic! + */ + bmp->eoc = &bmp085_eoc_true; +} + +/** + * Start new measurement if idle or read temp/pressure. + * Should run at < 40Hz unless eoc check function is provided. + * At ultra high resolution (oss = 3) conversion time is max 25.5ms. + */ +void bmp085_periodic(struct Bmp085* bmp) +{ + switch (bmp->status) { + case BMP085_STATUS_IDLE: + /* start temp measurement */ + bmp->i2c_trans.buf[0] = BMP085_CTRL_REG; + bmp->i2c_trans.buf[1] = BMP085_START_TEMP; + i2c_transmit(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 2); + bmp->status = BMP085_STATUS_START_TEMP; + break; + + case BMP085_STATUS_START_TEMP: + /* read temp measurement */ + if (bmp->eoc()) { + bmp->i2c_trans.buf[0] = BMP085_DAT_MSB; + i2c_transceive(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 1, 2); + bmp->status = BMP085_STATUS_READ_TEMP; + } + break; + + case BMP085_STATUS_START_PRESS: + /* read press measurement */ + if (bmp->eoc()) { + bmp->i2c_trans.buf[0] = BMP085_DAT_MSB; + i2c_transceive(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 1, 3); + bmp->status = BMP085_STATUS_READ_PRESS; + } + break; + + default: + break; + } +} + +void bmp085_event(struct Bmp085* bmp) +{ + if (bmp->i2c_trans.status == I2CTransSuccess) { + switch (bmp->status) { + case BMP085_STATUS_UNINIT: + bmp->calib.ac1 = (bmp->i2c_trans.buf[0] << 8) | bmp->i2c_trans.buf[1]; + bmp->calib.ac2 = (bmp->i2c_trans.buf[2] << 8) | bmp->i2c_trans.buf[3]; + bmp->calib.ac3 = (bmp->i2c_trans.buf[4] << 8) | bmp->i2c_trans.buf[5]; + bmp->calib.ac4 = (bmp->i2c_trans.buf[6] << 8) | bmp->i2c_trans.buf[7]; + bmp->calib.ac5 = (bmp->i2c_trans.buf[8] << 8) | bmp->i2c_trans.buf[9]; + bmp->calib.ac6 = (bmp->i2c_trans.buf[10] << 8) | bmp->i2c_trans.buf[11]; + bmp->calib.b1 = (bmp->i2c_trans.buf[12] << 8) | bmp->i2c_trans.buf[13]; + bmp->calib.b2 = (bmp->i2c_trans.buf[14] << 8) | bmp->i2c_trans.buf[15]; + bmp->calib.mb = (bmp->i2c_trans.buf[16] << 8) | bmp->i2c_trans.buf[17]; + bmp->calib.mc = (bmp->i2c_trans.buf[18] << 8) | bmp->i2c_trans.buf[19]; + bmp->calib.md = (bmp->i2c_trans.buf[20] << 8) | bmp->i2c_trans.buf[21]; + bmp->status = BMP085_STATUS_IDLE; + bmp->initialized = TRUE; + break; + + case BMP085_STATUS_READ_TEMP: + /* get uncompensated temperature */ + bmp->ut = (bmp->i2c_trans.buf[0] << 8) | bmp->i2c_trans.buf[1]; + bmp->temperature = bmp085_compensated_temperature(&(bmp->calib), bmp->ut); + /* start high res pressure measurement */ + bmp->i2c_trans.buf[0] = BMP085_CTRL_REG; + bmp->i2c_trans.buf[1] = BMP085_START_P3; + i2c_transmit(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 2); + bmp->status = BMP085_STATUS_START_PRESS; + break; + + case BMP085_STATUS_READ_PRESS: + /* get uncompensated pressure */ + bmp->up = (bmp->i2c_trans.buf[0]<<16) | + (bmp->i2c_trans.buf[1] << 8) | + bmp->i2c_trans.buf[2]; + bmp->up = bmp->up >> (8 - BMP085_OSS); + bmp->pressure = bmp085_compensated_pressure(&(bmp->calib), bmp->up); + bmp->data_available = TRUE; + bmp->status = BMP085_STATUS_IDLE; + break; + + default: + break; + } + } + else if (bmp->i2c_trans.status == I2CTransFailed) { + /* try again */ + if (bmp->initialized) + bmp->status = BMP085_STATUS_IDLE; + else + bmp->status = BMP085_STATUS_UNINIT; + bmp->i2c_trans.status = I2CTransDone; + } +} diff --git a/sw/airborne/peripherals/bmp085.h b/sw/airborne/peripherals/bmp085.h new file mode 100644 index 0000000000..a335f1e3b5 --- /dev/null +++ b/sw/airborne/peripherals/bmp085.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Martin Mueller + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** @file peripherals/bmp085.h + * Bosch BMP085 driver interface. + */ + +#ifndef BMP085_H +#define BMP085_H + +#include "mcu_periph/i2c.h" +#include "std.h" + +enum Bmp085Status { + BMP085_STATUS_UNINIT, + BMP085_STATUS_IDLE, + BMP085_STATUS_START_TEMP, + BMP085_STATUS_READ_TEMP, + BMP085_STATUS_START_PRESS, + BMP085_STATUS_READ_PRESS +}; + +struct Bmp085Calib { + // These values come from EEPROM on sensor + int16_t ac1; + int16_t ac2; + int16_t ac3; + uint16_t ac4; + uint16_t ac5; + uint16_t ac6; + int16_t b1; + int16_t b2; + int16_t mb; + int16_t mc; + int16_t md; + + // These values are calculated + int32_t b5; +}; + +typedef bool_t (*Bmp085EOC)(void); + +struct Bmp085 { + struct i2c_periph *i2c_p; + struct i2c_transaction i2c_trans; + Bmp085EOC eoc; ///< function to check End Of Conversion + enum Bmp085Status status; ///< state machine status + bool_t initialized; ///< config done flag + volatile bool_t data_available; ///< data ready flag + struct Bmp085Calib calib; + int32_t ut; ///< uncompensated temperature + int32_t up; ///< uncompensated pressure + int32_t temperature; ///< temperature in 0.1 deg Celcius + int32_t pressure; ///< pressure in Pascal +}; + +extern void bmp085_read_eeprom_calib(struct Bmp085* bmp); +extern void bmp085_init(struct Bmp085* bmp, struct i2c_periph *i2c_p, uint8_t addr); +extern void bmp085_periodic(struct Bmp085* bmp); +extern void bmp085_event(struct Bmp085* bmp); + +#endif diff --git a/sw/airborne/peripherals/bmp085_regs.h b/sw/airborne/peripherals/bmp085_regs.h new file mode 100644 index 0000000000..fb94b6a67d --- /dev/null +++ b/sw/airborne/peripherals/bmp085_regs.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Martin Mueller + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** @file peripherals/bmp085_regs.h + * Bosch BMP085 register definitions. + */ + +#ifndef BMP085_REGS_H +#define BMP085_REGS_H + +#define BMP085_EEPROM_AC1 0xAA +#define BMP085_EEPROM_AC2 0xAC +#define BMP085_EEPROM_AC3 0xAE +#define BMP085_EEPROM_AC4 0xB0 +#define BMP085_EEPROM_AC5 0xB2 +#define BMP085_EEPROM_AC6 0xB4 +#define BMP085_EEPROM_B1 0xB6 +#define BMP085_EEPROM_B2 0xB8 +#define BMP085_EEPROM_MB 0xBA +#define BMP085_EEPROM_MC 0xBC +#define BMP085_EEPROM_MD 0xBE + +#define BMP085_CTRL_REG 0xF4 + +#define BMP085_START_TEMP 0x2E +#define BMP085_START_P0 0x34 +#define BMP085_START_P1 0x74 +#define BMP085_START_P2 0xB4 +#define BMP085_START_P3 0xF4 + +#define BMP085_DAT_MSB 0xF6 +#define BMP085_DAT_LSB 0xF7 +#define BMP085_DAT_XLSB 0xF8 + +/// Over sample setting (0-3) +#define BMP085_OSS 3 + +#define BMP085_SLAVE_ADDR 0xEE + +#endif diff --git a/sw/airborne/peripherals/ms5611.c b/sw/airborne/peripherals/ms5611.c new file mode 100644 index 0000000000..9956d6583b --- /dev/null +++ b/sw/airborne/peripherals/ms5611.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011 Martin Mueller + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file peripherals/ms5611.c + * + * MS5611 barometer driver common functions (I2C and SPI). + */ + +#include "peripherals/ms5611.h" +#include "std.h" + +/** + * Check if CRC of PROM data is OK. + * @return TRUE if OK, FALSE otherwise + */ +bool_t ms5611_prom_crc_ok(uint16_t* prom) { + int32_t i, j; + uint32_t res = 0; + uint8_t crc = prom[7] & 0xF; + prom[7] &= 0xFF00; + for (i = 0; i < 16; i++) { + if (i & 1) + res ^= ((prom[i>>1]) & 0x00FF); + else + res ^= (prom[i>>1]>>8); + for (j = 8; j > 0; j--) { + if (res & 0x8000) + res ^= 0x1800; + res <<= 1; + } + } + prom[7] |= crc; + if (crc == ((res >> 12) & 0xF)) + return TRUE; + else + return FALSE; +} + +/** + * Calculate temperature and compensated pressure. + */ +void ms5611_calc(struct Ms5611Data* ms) { + int64_t dt, tempms, off, sens, t2, off2, sens2; + + /* difference between actual and ref temperature */ + dt = ms->d2 - (int64_t)ms->c[5] * (1<<8); + /* actual temperature */ + tempms = 2000 + ((int64_t)dt * ms->c[6]) / (1<<23); + /* offset at actual temperature */ + off = ((int64_t)ms->c[2] * (1<<16)) + ((int64_t)ms->c[4] * dt) / (1<<7); + /* sensitivity at actual temperature */ + sens = ((int64_t)ms->c[1] * (1<<15)) + ((int64_t)ms->c[3] * dt) / (1<<8); + /* second order temperature compensation */ + if (tempms < 2000) { + t2 = (dt*dt) / (1<<31); + off2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<1); + sens2 = 5 * ((int64_t)(tempms-2000)*(tempms-2000)) / (1<<2); + if (tempms < -1500) { + off2 = off2 + 7 * (int64_t)(tempms+1500)*(tempms+1500); + sens2 = sens2 + 11 * ((int64_t)(tempms+1500)*(tempms+1500)) / (1<<1); + } + tempms = tempms - t2; + off = off - off2; + sens = sens - sens2; + } + + /* temperature in deg Celsius with 0.01 degC resolultion */ + ms->temperature = (int32_t)tempms; + /* temperature compensated pressure in Pascal (0.01mbar) */ + ms->pressure = (uint32_t)((((int64_t)ms->d1 * sens) / (1<<21) - off) / (1<<15)); +} diff --git a/sw/airborne/peripherals/ms5611.h b/sw/airborne/peripherals/ms5611.h index ad3054e776..85958d5ac5 100644 --- a/sw/airborne/peripherals/ms5611.h +++ b/sw/airborne/peripherals/ms5611.h @@ -1,6 +1,5 @@ /* - * - * Copyright (C) 2012 Piotr Esden-Tempski + * Copyright (C) 2013 Felix Ruess * * This file is part of paparazzi. * @@ -20,82 +19,44 @@ * Boston, MA 02111-1307, USA. */ -/* Register definition for MS5611 +/** + * @file peripherals/ms5611.h + * + * MS5611 barometer driver common interface (I2C and SPI). */ #ifndef MS5611_H #define MS5611_H -/* default i2c address - * when CSB is set to GND addr is 0xEE - * when CSB is set to VCC addr is 0xEC - * - * Note: Aspirin 2.1 has CSB bound to GND. - */ -#define MS5611_SLAVE_ADDR 0xEE +#include "std.h" -/* FIXME: For backwards compatibility with Aspirin driver (it doesnt talk to baro either) */ -#define MS5611_ADDR0 0x77 -#define MS5611_ADDR1 0x76 +/* Include address and register definition */ +#include "peripherals/ms5611_regs.h" -/* SPI SLAVE3 is on pin PC13 - * Aspirin 2.2 has ms5611 on SPI bus - */ -#ifndef MS5611_SLAVE_DEV -#define MS5611_SLAVE_DEV SPI_SLAVE3 -#endif -/* Number of 16bit calibration coefficients */ -#define PROM_NB 8 - -/* OSR definitions */ -#define MS5611_OSR256 0x02 -#define MS5611_OSR512 0x02 -#define MS5611_OSR1024 0x04 -#define MS5611_OSR2048 0x06 -#define MS5611_OSR4096 0x08 - -/* D1 Register defines */ -#define MS5611_REG_D1R 0x40 // Request D1 (pressure) conversion -#define MS5611_REG_D1(_osr) (MS5611_REG_D1R | _osr) -#define MS5611_REG_D1OSR256 MS5611_REG_D1(MS5611_ORS256) -#define MS5611_REG_D1OSR512 MS5611_REG_D1(MS5611_OSR512) -#define MS5611_REG_D1OSR1024 MS5611_REG_D1(MS5611_OSR1024) -#define MS5611_REG_D1OSR2048 MS5611_REG_D1(MS5611_OSR2048) -#define MS5611_REG_D1OSR4096 MS5611_REG_D1(MS5611_OSR4096) - -/* D2 register defines */ -#define MS5611_REG_D2R 0x50 // Request D2 (temperature) conversion -#define MS5611_REG_D2(_osr) (MS5611_REG_D2R | _osr) -#define MS5611_REG_D2OSR256 MS5611_REG_D2(MS5611_ORS256) -#define MS5611_REG_D2OSR512 MS5611_REG_D2(MS5611_OSR512) -#define MS5611_REG_D2OSR1024 MS5611_REG_D2(MS5611_OSR1024) -#define MS5611_REG_D2OSR2048 MS5611_REG_D2(MS5611_OSR2048) -#define MS5611_REG_D2OSR4096 MS5611_REG_D2(MS5611_OSR4096) - -/* Commands */ -#define MS5611_ADC_READ 0x00 // Read converted value -#define MS5611_SOFT_RESET 0x1E // Reset command -#define MS5611_PROM_READ 0xA0 // Start reading PROM -#define MS5611_START_CONV_D1 MS5611_REG_D1OSR4096 /* we use OSR=4096 for maximum resolution */ -#define MS5611_START_CONV_D2 MS5611_REG_D2OSR4096 /* we use OSR=4096 for maximum resolution */ - -/* FIXME: backwards compatibility with Aspirin driver */ -#define MS5611_REG_RESET MS5611_SOFT_RESET -#define MS5611_REG_ADCREAD MS5611_ADC_READ - -enum ms5611_stat{ - MS5611_UNINIT, - MS5611_RESET, - MS5611_RESET_OK, - MS5611_PROM, - MS5611_IDLE, - MS5611_CONV_D1, - MS5611_CONV_D1_OK, - MS5611_ADC_D1, - MS5611_CONV_D2, - MS5611_CONV_D2_OK, - MS5611_ADC_D2 +enum Ms5611Status { + MS5611_STATUS_UNINIT, + MS5611_STATUS_RESET, + MS5611_STATUS_RESET_OK, + MS5611_STATUS_PROM, + MS5611_STATUS_IDLE, + MS5611_STATUS_CONV_D1, + MS5611_STATUS_CONV_D1_OK, + MS5611_STATUS_ADC_D1, + MS5611_STATUS_CONV_D2, + MS5611_STATUS_CONV_D2_OK, + MS5611_STATUS_ADC_D2 }; +struct Ms5611Data { + uint32_t pressure; ///< pressure in Pascal (0.01mbar) + int32_t temperature; ///< temperature with 0.01 degrees Celsius resolution + uint16_t c[PROM_NB]; + uint32_t d1; + uint32_t d2; +}; + +extern bool_t ms5611_prom_crc_ok(uint16_t* prom); +extern void ms5611_calc(struct Ms5611Data* ms); + #endif /* MS5611_H */ diff --git a/sw/airborne/peripherals/ms5611_i2c.c b/sw/airborne/peripherals/ms5611_i2c.c new file mode 100644 index 0000000000..1ec14b4611 --- /dev/null +++ b/sw/airborne/peripherals/ms5611_i2c.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2011 Martin Mueller + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file peripherals/ms5611_i2c.c + * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for I2C. + * + */ + + +#include "peripherals/ms5611_i2c.h" + + +void ms5611_i2c_init(struct Ms5611_I2c *ms, struct i2c_periph *i2c_p, uint8_t addr) +{ + /* set i2c_peripheral */ + ms->i2c_p = i2c_p; + + /* slave address */ + ms->i2c_trans.slave_addr = addr; + /* set initial status: Success or Done */ + ms->i2c_trans.status = I2CTransDone; + + ms->data_available = FALSE; + ms->initialized = FALSE; + ms->status = MS5611_STATUS_UNINIT; + ms->prom_cnt = 0; +} + +void ms5611_i2c_start_configure(struct Ms5611_I2c *ms) +{ + if (ms->status == MS5611_STATUS_UNINIT) { + ms->initialized = FALSE; + ms->prom_cnt = 0; + ms->i2c_trans.buf[0] = MS5611_SOFT_RESET; + i2c_transmit(ms->i2c_p, &(ms->i2c_trans), ms->i2c_trans.slave_addr, 1); + ms->status = MS5611_STATUS_RESET; + } +} + +void ms5611_i2c_start_conversion(struct Ms5611_I2c *ms) +{ + if (ms->status == MS5611_STATUS_IDLE && + ms->i2c_trans.status == I2CTransDone) { + /* start D1 conversion */ + ms->i2c_trans.buf[0] = MS5611_START_CONV_D1; + i2c_transmit(ms->i2c_p, &(ms->i2c_trans), ms->i2c_trans.slave_addr, 1); + ms->status = MS5611_STATUS_CONV_D1; + } +} + +/** + * Periodic function to ensure proper delay after triggering reset or conversion. + * Should run at 100Hz max. + * Typical conversion time is 8.22ms at max resolution. + */ +void ms5611_i2c_periodic_check(struct Ms5611_I2c *ms) +{ + switch (ms->status) { + case MS5611_STATUS_RESET: + ms->status = MS5611_STATUS_RESET_OK; + break; + case MS5611_STATUS_RESET_OK: + if (ms->i2c_trans.status == I2CTransDone) { + /* start getting prom data */ + ms->i2c_trans.buf[0] = MS5611_PROM_READ | (ms->prom_cnt << 1); + i2c_transceive(ms->i2c_p, &(ms->i2c_trans), ms->i2c_trans.slave_addr, 1, 2); + ms->status = MS5611_STATUS_PROM; + } + break; + case MS5611_STATUS_CONV_D1: + ms->status = MS5611_STATUS_CONV_D1_OK; + break; + case MS5611_STATUS_CONV_D1_OK: + if (ms->i2c_trans.status == I2CTransDone) { + /* read D1 adc */ + ms->i2c_trans.buf[0] = MS5611_ADC_READ; + i2c_transceive(ms->i2c_p, &(ms->i2c_trans), ms->i2c_trans.slave_addr, 1, 3); + ms->status = MS5611_STATUS_ADC_D1; + } + break; + case MS5611_STATUS_CONV_D2: + ms->status = MS5611_STATUS_CONV_D2_OK; + break; + case MS5611_STATUS_CONV_D2_OK: + if (ms->i2c_trans.status == I2CTransDone) { + /* read D2 adc */ + ms->i2c_trans.buf[0] = MS5611_ADC_READ; + i2c_transceive(ms->i2c_p, &(ms->i2c_trans), ms->i2c_trans.slave_addr, 1, 3); + ms->status = MS5611_STATUS_ADC_D2; + } + break; + default: + break; + } +} + +void ms5611_i2c_event(struct Ms5611_I2c *ms) { + if (ms->initialized) { + if (ms->i2c_trans.status == I2CTransFailed) { + ms->status = MS5611_STATUS_IDLE; + ms->i2c_trans.status = I2CTransDone; + } + else if (ms->i2c_trans.status == I2CTransSuccess) { + // Successfull reading + switch (ms->status) { + + case MS5611_STATUS_ADC_D1: + /* read D1 (pressure) */ + ms->data.d1 = (ms->i2c_trans.buf[0] << 16) | + (ms->i2c_trans.buf[1] << 8) | + ms->i2c_trans.buf[2]; + if (ms->data.d1 == 0) { + /* if value is zero, it was read to soon and is invalid, back to idle */ + ms->status = MS5611_STATUS_IDLE; + } + else { + /* start D2 conversion */ + ms->i2c_trans.buf[0] = MS5611_START_CONV_D2; + i2c_transmit(ms->i2c_p, &(ms->i2c_trans), ms->i2c_trans.slave_addr, 1); + ms->status = MS5611_STATUS_CONV_D2; + } + break; + + case MS5611_STATUS_ADC_D2: + /* read D2 (temperature) */ + ms->data.d2 = (ms->i2c_trans.buf[0] << 16) | + (ms->i2c_trans.buf[1] << 8) | + ms->i2c_trans.buf[2]; + if (ms->data.d2 == 0) { + /* if value is zero, it was read to soon and is invalid, back to idle */ + ms->status = MS5611_STATUS_IDLE; + } + else { + /* calculate temp and pressure from measurements */ + ms5611_calc(&(ms->data)); + ms->status = MS5611_STATUS_IDLE; + ms->data_available = TRUE; + } + break; + + default: + break; + } + ms->i2c_trans.status = I2CTransDone; + } + } + else if (ms->status != MS5611_STATUS_UNINIT) { // Configuring but not yet initialized + switch (ms->i2c_trans.status) { + + case I2CTransFailed: + /* try again */ + ms->status = MS5611_STATUS_UNINIT; + ms->i2c_trans.status = I2CTransDone; + break; + + case I2CTransSuccess: + if (ms->status == MS5611_STATUS_PROM) { + /* read prom data */ + ms->data.c[ms->prom_cnt++] = (ms->i2c_trans.buf[0] << 8) | + ms->i2c_trans.buf[1]; + if (ms->prom_cnt < PROM_NB) { + /* get next prom data */ + ms->i2c_trans.buf[0] = MS5611_PROM_READ | (ms->prom_cnt << 1); + i2c_transceive(ms->i2c_p, &(ms->i2c_trans), ms->i2c_trans.slave_addr, 1, 2); + } + else { + /* done reading prom, check prom crc */ + if (ms5611_prom_crc_ok(ms->data.c)) { + ms->initialized = TRUE; + ms->status = MS5611_STATUS_IDLE; + } + else { + /* checksum error, try again */ + ms->status = MS5611_STATUS_UNINIT; + } + } + } + ms->i2c_trans.status = I2CTransDone; + break; + + default: + break; + } + } +} diff --git a/sw/airborne/peripherals/ms5611_i2c.h b/sw/airborne/peripherals/ms5611_i2c.h new file mode 100644 index 0000000000..149312ff36 --- /dev/null +++ b/sw/airborne/peripherals/ms5611_i2c.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file peripherals/ms5611_i2c.h + * + * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for I2C. + */ + +#ifndef MS5611_I2C_H +#define MS5611_I2C_H + +#include "mcu_periph/i2c.h" + +/* Include common MS5611 definitions */ +#include "peripherals/ms5611.h" + +struct Ms5611_I2c { + struct i2c_periph *i2c_p; + struct i2c_transaction i2c_trans; + enum Ms5611Status status; + bool_t initialized; ///< config done flag + volatile bool_t data_available; ///< data ready flag + struct Ms5611Data data; + int32_t prom_cnt; ///< number of bytes read from PROM +}; + +// Functions +extern void ms5611_i2c_init(struct Ms5611_I2c* ms, struct i2c_periph* i2c_p, uint8_t addr); +extern void ms5611_i2c_start_configure(struct Ms5611_I2c* ms); +extern void ms5611_i2c_start_conversion(struct Ms5611_I2c* ms); +extern void ms5611_i2c_periodic_check(struct Ms5611_I2c* ms); +extern void ms5611_i2c_event(struct Ms5611_I2c* ms); + +/** convenience function to trigger new measurement. + * (or start configuration if not already initialized) + * Still need to regularly run ms5611_i2c_periodic_check to complete the measurement. + */ +static inline void ms5611_i2c_read(struct Ms5611_I2c* ms) { + if (ms->initialized) + ms5611_i2c_start_conversion(ms); + else + ms5611_i2c_start_configure(ms); +} + +/// convenience function +static inline void ms5611_i2c_periodic(struct Ms5611_I2c* ms) { + ms5611_i2c_read(ms); + ms5611_i2c_periodic_check(ms); +} + + +#endif /* MS5611_I2C_H */ diff --git a/sw/airborne/peripherals/ms5611_regs.h b/sw/airborne/peripherals/ms5611_regs.h new file mode 100644 index 0000000000..6cd3eb1fe2 --- /dev/null +++ b/sw/airborne/peripherals/ms5611_regs.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2012 Piotr Esden-Tempski + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file peripherals/ms5611_regs.h + * Register definitions for MS5611 barometer. + */ + +#ifndef MS5611_REGS_H +#define MS5611_REGS_H + +/** default i2c address + * when CSB is set to GND addr is 0xEE + * when CSB is set to VCC addr is 0xEC + */ +#define MS5611_I2C_SLAVE_ADDR 0xEE +#define MS5611_I2C_SLAVE_ADDR_ALT 0xEC + +/* Number of 16bit calibration coefficients */ +#define PROM_NB 8 + +/* OSR definitions */ +#define MS5611_OSR256 0x02 +#define MS5611_OSR512 0x02 +#define MS5611_OSR1024 0x04 +#define MS5611_OSR2048 0x06 +#define MS5611_OSR4096 0x08 + +/* D1 Register defines */ +#define MS5611_REG_D1R 0x40 // Request D1 (pressure) conversion +#define MS5611_REG_D1(_osr) (MS5611_REG_D1R | _osr) +#define MS5611_REG_D1OSR256 MS5611_REG_D1(MS5611_ORS256) +#define MS5611_REG_D1OSR512 MS5611_REG_D1(MS5611_OSR512) +#define MS5611_REG_D1OSR1024 MS5611_REG_D1(MS5611_OSR1024) +#define MS5611_REG_D1OSR2048 MS5611_REG_D1(MS5611_OSR2048) +#define MS5611_REG_D1OSR4096 MS5611_REG_D1(MS5611_OSR4096) + +/* D2 register defines */ +#define MS5611_REG_D2R 0x50 // Request D2 (temperature) conversion +#define MS5611_REG_D2(_osr) (MS5611_REG_D2R | _osr) +#define MS5611_REG_D2OSR256 MS5611_REG_D2(MS5611_ORS256) +#define MS5611_REG_D2OSR512 MS5611_REG_D2(MS5611_OSR512) +#define MS5611_REG_D2OSR1024 MS5611_REG_D2(MS5611_OSR1024) +#define MS5611_REG_D2OSR2048 MS5611_REG_D2(MS5611_OSR2048) +#define MS5611_REG_D2OSR4096 MS5611_REG_D2(MS5611_OSR4096) + +/* Commands */ +#define MS5611_ADC_READ 0x00 // Read converted value +#define MS5611_SOFT_RESET 0x1E // Reset command +#define MS5611_PROM_READ 0xA0 // Start reading PROM +#define MS5611_START_CONV_D1 MS5611_REG_D1OSR4096 /* we use OSR=4096 for maximum resolution */ +#define MS5611_START_CONV_D2 MS5611_REG_D2OSR4096 /* we use OSR=4096 for maximum resolution */ + +#endif /* MS5611_REGS_H */ diff --git a/sw/airborne/peripherals/ms5611_spi.c b/sw/airborne/peripherals/ms5611_spi.c new file mode 100644 index 0000000000..d8e9293185 --- /dev/null +++ b/sw/airborne/peripherals/ms5611_spi.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2011 Martin Mueller + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file peripherals/ms5611_spi.c + * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for SPI. + * + */ + + +#include "peripherals/ms5611_spi.h" + + +void ms5611_spi_init(struct Ms5611_Spi *ms, struct spi_periph *spi_p, uint8_t slave_idx) +{ + /* set spi_peripheral */ + ms->spi_p = spi_p; + + /* configure spi transaction */ + ms->spi_trans.cpol = SPICpolIdleHigh; + ms->spi_trans.cpha = SPICphaEdge2; + ms->spi_trans.dss = SPIDss8bit; + ms->spi_trans.bitorder = SPIMSBFirst; + ms->spi_trans.cdiv = SPIDiv64; + + ms->spi_trans.select = SPISelectUnselect; + ms->spi_trans.slave_idx = slave_idx; + ms->spi_trans.output_length = 1; + ms->spi_trans.input_length = 4; + ms->spi_trans.before_cb = NULL; + ms->spi_trans.after_cb = NULL; + ms->spi_trans.input_buf = ms->rx_buf; + ms->spi_trans.output_buf = ms->tx_buf; + + /* set initial status: Success or Done */ + ms->spi_trans.status = SPITransDone; + + ms->data_available = FALSE; + ms->initialized = FALSE; + ms->status = MS5611_STATUS_UNINIT; + ms->prom_cnt = 0; +} + +void ms5611_spi_start_configure(struct Ms5611_Spi *ms) +{ + if (ms->status == MS5611_STATUS_UNINIT) { + ms->initialized = FALSE; + ms->prom_cnt = 0; + ms->tx_buf[0] = MS5611_SOFT_RESET; + spi_submit(ms->spi_p, &(ms->spi_trans)); + ms->status = MS5611_STATUS_RESET; + } +} + +void ms5611_spi_start_conversion(struct Ms5611_Spi *ms) +{ + if (ms->status == MS5611_STATUS_IDLE && + ms->spi_trans.status == SPITransDone) { + /* start D1 conversion */ + ms->tx_buf[0] = MS5611_START_CONV_D1; + spi_submit(ms->spi_p, &(ms->spi_trans)); + ms->status = MS5611_STATUS_CONV_D1; + } +} + +/** + * Periodic function to ensure proper delay after triggering reset or conversion. + * Should run at 100Hz max. + * Typical conversion time is 8.22ms at max resolution. + */ +void ms5611_spi_periodic_check(struct Ms5611_Spi *ms) +{ + switch (ms->status) { + case MS5611_STATUS_RESET: + ms->status = MS5611_STATUS_RESET_OK; + break; + case MS5611_STATUS_RESET_OK: + if (ms->spi_trans.status == SPITransDone) { + /* start getting prom data */ + ms->tx_buf[0] = MS5611_PROM_READ | (ms->prom_cnt << 1); + spi_submit(ms->spi_p, &(ms->spi_trans)); + ms->status = MS5611_STATUS_PROM; + } + break; + case MS5611_STATUS_CONV_D1: + ms->status = MS5611_STATUS_CONV_D1_OK; + break; + case MS5611_STATUS_CONV_D1_OK: + if (ms->spi_trans.status == SPITransDone) { + /* read D1 adc */ + ms->tx_buf[0] = MS5611_ADC_READ; + spi_submit(ms->spi_p, &(ms->spi_trans)); + ms->status = MS5611_STATUS_ADC_D1; + } + break; + case MS5611_STATUS_CONV_D2: + ms->status = MS5611_STATUS_CONV_D2_OK; + break; + case MS5611_STATUS_CONV_D2_OK: + if (ms->spi_trans.status == SPITransDone) { + /* read D2 adc */ + ms->tx_buf[0] = MS5611_ADC_READ; + spi_submit(ms->spi_p, &(ms->spi_trans)); + ms->status = MS5611_STATUS_ADC_D2; + } + break; + default: + break; + } +} + +void ms5611_spi_event(struct Ms5611_Spi *ms) { + if (ms->initialized) { + if (ms->spi_trans.status == SPITransFailed) { + ms->status = MS5611_STATUS_IDLE; + ms->spi_trans.status = SPITransDone; + } + else if (ms->spi_trans.status == SPITransSuccess) { + // Successfull reading + switch (ms->status) { + + case MS5611_STATUS_ADC_D1: + /* read D1 (pressure) */ + ms->data.d1 = (ms->rx_buf[1] << 16) | + (ms->rx_buf[2] << 8) | + ms->rx_buf[3]; + if (ms->data.d1 == 0) { + /* if value is zero, it was read to soon and is invalid, back to idle */ + ms->status = MS5611_STATUS_IDLE; + } + else { + /* start D2 conversion */ + ms->tx_buf[0] = MS5611_START_CONV_D2; + spi_submit(ms->spi_p, &(ms->spi_trans)); + ms->status = MS5611_STATUS_CONV_D2; + } + break; + + case MS5611_STATUS_ADC_D2: + /* read D2 (temperature) */ + ms->data.d2 = (ms->rx_buf[1] << 16) | + (ms->rx_buf[2] << 8) | + ms->rx_buf[3]; + if (ms->data.d2 == 0) { + /* if value is zero, it was read to soon and is invalid, back to idle */ + ms->status = MS5611_STATUS_IDLE; + } + else { + /* calculate temp and pressure from measurements */ + ms5611_calc(&(ms->data)); + ms->status = MS5611_STATUS_IDLE; + ms->data_available = TRUE; + } + break; + + default: + break; + } + ms->spi_trans.status = SPITransDone; + } + } + else if (ms->status != MS5611_STATUS_UNINIT) { // Configuring but not yet initialized + switch (ms->spi_trans.status) { + + case SPITransFailed: + /* try again */ + ms->status = MS5611_STATUS_UNINIT; + ms->spi_trans.status = SPITransDone; + break; + + case SPITransSuccess: + if (ms->status == MS5611_STATUS_PROM) { + /* read prom data */ + ms->data.c[ms->prom_cnt++] = (ms->rx_buf[1] << 8) | + ms->rx_buf[2]; + if (ms->prom_cnt < PROM_NB) { + /* get next prom data */ + ms->tx_buf[0] = MS5611_PROM_READ | (ms->prom_cnt << 1); + spi_submit(ms->spi_p, &(ms->spi_trans)); + } + else { + /* done reading prom, check prom crc */ + if (ms5611_prom_crc_ok(ms->data.c)) { + ms->initialized = TRUE; + ms->status = MS5611_STATUS_IDLE; + } + else { + /* checksum error, try again */ + ms->status = MS5611_STATUS_UNINIT; + } + } + } + ms->spi_trans.status = SPITransDone; + break; + + default: + break; + } + } +} diff --git a/sw/airborne/peripherals/ms5611_spi.h b/sw/airborne/peripherals/ms5611_spi.h new file mode 100644 index 0000000000..59f8f6e8e8 --- /dev/null +++ b/sw/airborne/peripherals/ms5611_spi.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file peripherals/ms5611_spi.h + * + * Measurement Specialties (Intersema) MS5611-01BA pressure/temperature sensor interface for SPI. + */ + +#ifndef MS5611_SPI_H +#define MS5611_SPI_H + +#include "mcu_periph/spi.h" + +/* Include common MS5611 definitions */ +#include "peripherals/ms5611.h" + +struct Ms5611_Spi { + struct spi_periph *spi_p; + struct spi_transaction spi_trans; + volatile uint8_t tx_buf[1]; + volatile uint8_t rx_buf[4]; + enum Ms5611Status status; + bool_t initialized; ///< config done flag + volatile bool_t data_available; ///< data ready flag + struct Ms5611Data data; + int32_t prom_cnt; ///< number of bytes read from PROM +}; + +// Functions +extern void ms5611_spi_init(struct Ms5611_Spi* ms, struct spi_periph* spi_p, uint8_t addr); +extern void ms5611_spi_start_configure(struct Ms5611_Spi* ms); +extern void ms5611_spi_start_conversion(struct Ms5611_Spi* ms); +extern void ms5611_spi_periodic_check(struct Ms5611_Spi* ms); +extern void ms5611_spi_event(struct Ms5611_Spi* ms); + +/** convenience function to trigger new measurement. + * (or start configuration if not already initialized) + * Still need to regularly run ms5611_spi_periodic_check to complete the measurement. + */ +static inline void ms5611_spi_read(struct Ms5611_Spi* ms) { + if (ms->initialized) + ms5611_spi_start_conversion(ms); + else + ms5611_spi_start_configure(ms); +} + +/// convenience function +static inline void ms5611_spi_periodic(struct Ms5611_Spi* ms) { + ms5611_spi_read(ms); + ms5611_spi_periodic_check(ms); +} + + +#endif /* MS5611_SPI_H */ diff --git a/sw/airborne/subsystems/sensors/baro_ms5611_i2c.c b/sw/airborne/subsystems/sensors/baro_ms5611_i2c.c new file mode 100644 index 0000000000..a996cee2dc --- /dev/null +++ b/sw/airborne/subsystems/sensors/baro_ms5611_i2c.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2011-2013 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * @file boards/lisa_m/baro_ms5611_i2c.c + * + * Driver for MS5611 baro via I2C. + * + */ + +#include "subsystems/sensors/baro.h" +#include "peripherals/ms5611_i2c.h" + +#include "mcu_periph/sys_time.h" +#include "led.h" +#include "std.h" + +#ifndef MS5611_I2C_DEV +#define MS5611_I2C_DEV i2c2 +#endif + +/* default i2c address + * when CSB is set to GND addr is 0xEE + * when CSB is set to VCC addr is 0xEC + * + * Note: Aspirin 2.1 has CSB bound to GND. + */ +#ifndef MS5611_SLAVE_ADDR +#define MS5611_SLAVE_ADDR 0xEE +#endif + +#ifdef DEBUG + +#ifndef DOWNLINK_DEVICE +#define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE +#endif +#include "mcu_periph/uart.h" +#include "messages.h" +#include "subsystems/datalink/downlink.h" + +float fbaroms, ftempms; +#endif + +struct Baro baro; +struct Ms5611_I2c baro_ms5611; + + +void baro_init(void) { + baro.status = BS_UNINITIALIZED; + baro.absolute = 0; + baro.differential = 0; + + ms5611_i2c_init(&baro_ms5611, &MS5611_I2C_DEV, MS5611_SLAVE_ADDR); +} + +void baro_periodic(void) { + if (sys_time.nb_sec > 1) { + + /* call the convenience periodic that initializes the sensor and starts reading*/ + ms5611_i2c_periodic(&baro_ms5611); + + if (baro_ms5611.initialized) { + baro.status = BS_RUNNING; +#if DEBUG + RunOnceEvery((4*30), DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, + &baro_ms5611.data.c[0], + &baro_ms5611.data.c[1], + &baro_ms5611.data.c[2], + &baro_ms5611.data.c[3], + &baro_ms5611.data.c[4], + &baro_ms5611.data.c[5], + &baro_ms5611.data.c[6], + &baro_ms5611.data.c[7])); +#endif + } + } +} + +void baro_event(void (*b_abs_handler)(void)){ + if (sys_time.nb_sec > 1) { + ms5611_i2c_event(&baro_ms5611); + + if (baro_ms5611.data_available) { + baro.absolute = baro_ms5611.data.pressure; + b_abs_handler(); + baro_ms5611.data_available = FALSE; + +#ifdef ROTORCRAFT_BARO_LED + RunOnceEvery(10,LED_TOGGLE(ROTORCRAFT_BARO_LED)); +#endif + +#if DEBUG + ftempms = baro_ms5611.data.temperature / 100.; + fbaroms = baro_ms5611.data.pressure / 100.; + DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, + &baro_ms5611.data.d1, &baro_ms5611.data.d2, + &fbaroms, &ftempms); +#endif + } + } +} diff --git a/sw/airborne/subsystems/sensors/baro_ms5611_spi.c b/sw/airborne/subsystems/sensors/baro_ms5611_spi.c new file mode 100644 index 0000000000..a86ab818f7 --- /dev/null +++ b/sw/airborne/subsystems/sensors/baro_ms5611_spi.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2011-2013 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * @file boards/lisa_m/baro_ms5611_spi.c + * + * Driver for MS5611 baro on LisaM/Aspirin2.2 via SPI. + * + */ + +#include "subsystems/sensors/baro.h" +#include "peripherals/ms5611_spi.h" + +#include "mcu_periph/sys_time.h" +#include "led.h" +#include "std.h" + +#ifndef MS5611_SPI_DEV +#define MS5611_SPI_DEV spi2 +#endif + +/* SPI SLAVE3 is on pin PC13 + * Aspirin 2.2 has ms5611 on SPI bus + */ +#ifndef MS5611_SLAVE_DEV +#define MS5611_SLAVE_DEV SPI_SLAVE3 +#endif + + +#ifdef DEBUG + +#ifndef DOWNLINK_DEVICE +#define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE +#endif +#include "mcu_periph/uart.h" +#include "messages.h" +#include "subsystems/datalink/downlink.h" + +float fbaroms, ftempms; +#endif + +struct Baro baro; +struct Ms5611_Spi baro_ms5611; + + +void baro_init(void) { + baro.status = BS_UNINITIALIZED; + baro.absolute = 0; + baro.differential = 0; + + ms5611_spi_init(&baro_ms5611, &MS5611_SPI_DEV, MS5611_SLAVE_DEV); +} + +void baro_periodic(void) { + if (sys_time.nb_sec > 1) { + + /* call the convenience periodic that initializes the sensor and starts reading*/ + ms5611_spi_periodic(&baro_ms5611); + + if (baro_ms5611.initialized) { + baro.status = BS_RUNNING; +#if DEBUG + RunOnceEvery((4*30), DOWNLINK_SEND_MS5611_COEFF(DefaultChannel, DefaultDevice, + &baro_ms5611.data.c[0], + &baro_ms5611.data.c[1], + &baro_ms5611.data.c[2], + &baro_ms5611.data.c[3], + &baro_ms5611.data.c[4], + &baro_ms5611.data.c[5], + &baro_ms5611.data.c[6], + &baro_ms5611.data.c[7])); +#endif + } + } +} + +void baro_event(void (*b_abs_handler)(void)){ + if (sys_time.nb_sec > 1) { + ms5611_spi_event(&baro_ms5611); + + if (baro_ms5611.data_available) { + baro.absolute = baro_ms5611.data.pressure; + b_abs_handler(); + baro_ms5611.data_available = FALSE; + +#ifdef ROTORCRAFT_BARO_LED + RunOnceEvery(10,LED_TOGGLE(ROTORCRAFT_BARO_LED)); +#endif + +#if DEBUG + ftempms = baro_ms5611.data.temperature / 100.; + fbaroms = baro_ms5611.data.pressure / 100.; + DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, + &baro_ms5611.data.d1, &baro_ms5611.data.d2, + &fbaroms, &ftempms); +#endif + } + } +}