Driver for MPU6500, HMC59xx and BMP280 (#3406)

* Enables MPU6500 with MPU60x0 spi driver, adds hmc59xx and enables BMP280 SPI and I2C

---------

Co-authored-by: Florian Sansou <florian.sansou@enac.fr>
This commit is contained in:
Florian Sansou
2024-11-25 22:53:33 +01:00
committed by GitHub
parent 45abdefc86
commit 6de702a144
22 changed files with 678 additions and 414 deletions
+1 -2
View File
@@ -31,7 +31,7 @@
<makefile target="ap|sim">
<file name="airspeed_adc.c"/>
<test arch="test">
<test>
<define name="AIRSPEED_ADC_QUADRATIC_SCALE" value="1"/>
<define name="AIRSPEED_ADC_BIAS" value="0"/>
<define name="ADC_CHANNEL_AIRSPEED" value="0"/>
@@ -43,4 +43,3 @@
</makefile>
</module>
+1 -3
View File
@@ -20,11 +20,9 @@
<define name="USE_BARO_DIFF"/>
<define name="USE_ADS1114_2"/>
<define name="ADS1114_2_PGA" value="0x1"/> <!-- PGA gain = 1 (+/- 4.096V) -->
<test arch="test">
<test>
<define name="USE_ADS1114_1"/>
<define name="BARO_DIFF_ADS" value="ads1114_1"/>
</test>
</makefile>
</module>
+51
View File
@@ -0,0 +1,51 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="baro_bmp280" dir="sensors" task="sensors">
<doc>
<description>
Bosch-Sensortech BMP280xx pressure sensor (I2C or SPI)
</description>
<configure name="BMP280_USE_SPI" default="FALSE" description="select which bus type use (default I2C -> FALSE, SPI -> TRUE)"/>
<configure name="BMP280_DEV" value="i2cX/spiX" description="select which i2c/spi peripheral to use (default i2c1/spi1)"/>
<configure name="BMP280_SLAVE_IDX" value="spi_slave0" description="select which slave peripheral to use when bus is spi (default spi_slave0)"/>
<define name="BMP280_SLAVE_ADDR" value="BMP280_I2C_ADDR|BMP280_I2C_ADDR_ALT" description="i2c slave address (default BMP280_I2C_ADDR)"/>
<define name="BMP280_SYNC_SEND" description="flag to transmit the data as it is acquired"/>
</doc>
<dep>
<depends>i2c|spi_master</depends>
<provides>baro</provides>
</dep>
<header>
<file name="baro_bmp280.h"/>
</header>
<init fun="baro_bmp280_init()"/>
<periodic fun="baro_bmp280_periodic()" freq="50"/>
<event fun="baro_bmp280_event()"/>
<makefile target="ap" >
<configure name="BMP280_USE_SPI" default="FALSE"/>
<define name="BMP280_USE_SPI" value="$(BMP280_USE_SPI)" />
<file name="baro_bmp280.c"/>
<file name="bmp280.c" dir="peripherals"/>
</makefile>
<makefile target="ap" cond="ifeq ($(BMP280_USE_SPI), TRUE)">
<configure name="BMP280_DEV" default="spi1" case="upper|lower"/>
<configure name="BMP280_SLAVE_IDX" default="spi_slave0" case="upper|lower"/>
<define name="USE_$(BMP280_DEV_UPPER)"/>
<define name="BMP280_DEV" value="$(BMP280_DEV_LOWER)"/>
<define name="BMP280_SLAVE_IDX" value="$(BMP280_SLAVE_IDX_UPPER)" />
<define name="USE_$(BMP280_SLAVE_IDX_UPPER)" />
<test>
<define name="BMP280_USE_SPI"/>
<define name="BMP280_DEV" value="spi1"/>
</test>
</makefile>
<makefile target="ap" cond="ifeq ($(BMP280_USE_SPI), FALSE)">
<configure name="BMP280_DEV" default="i2c1" case="upper|lower"/>
<configure name="BMP280_SLAVE_ADDR" default="BMP280_I2C_ADDR"/>
<define name="USE_$(BMP280_DEV_UPPER)"/>
<define name="BMP280_DEV" value="$(BMP280_DEV_LOWER)"/>
<test>
<define name="BMP280_DEV" value="i2c1"/>
</test>
</makefile>
</module>
-30
View File
@@ -1,30 +0,0 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="baro_bmp280_i2c" dir="sensors" task="sensors">
<doc>
<description>
Bosch-Sensortech BMP280xx pressure sensor
</description>
<configure name="BMP280_I2C_DEV" value="i2cX" description="select which i2c peripheral to use (default i2c1)"/>
<define name="BMP280_SLAVE_ADDR" value="BMP280_I2C_ADDR|BMP280_I2C_ADDR_ALT" description="i2c slave address (default BMP280_I2C_ADDR)"/>
<define name="BMP280_SYNC_SEND" description="flag to transmit the data as it is acquired"/>
</doc>
<dep>
<depends>i2c</depends>
<provides>baro</provides>
</dep>
<header>
<file name="baro_bmp280_i2c.h"/>
</header>
<init fun="baro_bmp280_init()"/>
<periodic fun="baro_bmp280_periodic()" freq="50"/>
<event fun="baro_bmp280_event()"/>
<makefile target="ap">
<configure name="BMP280_I2C_DEV" default="i2c1" case="upper|lower"/>
<define name="USE_$(BMP280_I2C_DEV_UPPER)"/>
<define name="BMP280_I2C_DEV" value="$(BMP280_I2C_DEV_LOWER)"/>
<file name="baro_bmp280_i2c.c"/>
<file name="bmp280_i2c.c" dir="peripherals"/>
</makefile>
</module>
+1 -2
View File
@@ -26,10 +26,9 @@
<define name="BMP3_I2C_DEV" value="$(BMP3_I2C_DEV_LOWER)"/>
<file name="baro_bmp3.c"/>
<file name="bmp3_i2c.c" dir="peripherals"/>
<test arch="test">
<test>
<define name="USE_I2C1"/>
<define name="BMP3_I2C_DEV" value="i2c1"/>
</test>
</makefile>
</module>
+2 -3
View File
@@ -13,7 +13,7 @@
</description>
</doc>
<dep>
<depends>spi_master,osd_max7456,baro_bmp280_i2c,imu_mpu6000</depends>
<depends>spi_master,osd_max7456,baro_bmp280,imu_mpu6000</depends>
</dep>
<makefile target="!sim|nps|fbw">
@@ -21,8 +21,7 @@
<configure name="IMU_MPU_SPI_DEV" value="spi1" case="upper|lower"/>
<configure name="IMU_MPU_SPI_SLAVE_IDX" value="SPI_SLAVE0"/>
<!-- BAROMETER BMP280 CONFIGURATION -->
<configure name="BMP280_I2C_DEV" value="i2c1" />
<configure name="BMP280_SLAVE_ADDR" value="BMP280_I2C_ADDR" />
<configure name="BMP280_DEV" value="i2c1" />
<!-- OSD CONFIGURATION -->
<configure name="MAX7456_SPI_DEV" value="spi2" />
<configure name="MAX7456_SLAVE_IDX" value="SPI_SLAVE1" />
+2 -2
View File
@@ -14,7 +14,7 @@
<configure name="BOARD_MATEK_ROTATED" value="FALSE|TRUE" description="if TRUE, the board is not using is default orientation and axis can be redefined by hand"/>
</doc>
<dep>
<depends>spi_master,baro_bmp280_i2c,current_sensor,imu_mpu6000</depends>
<depends>spi_master,baro_bmp280,current_sensor,imu_mpu6000</depends>
</dep>
<makefile target="!sim|nps|fbw">
@@ -27,7 +27,7 @@
<define name="IMU_MPU_CHAN_Y" value="0" cond="ifeq (,$(findstring $(BOARD_MATEK_ROTATED),1 TRUE))"/>
<define name="IMU_MPU_X_SIGN" value="-1" cond="ifeq (,$(findstring $(BOARD_MATEK_ROTATED),1 TRUE))"/>
<!-- BAROMETER BMP280 CONFIGURATION -->
<configure name="BMP280_I2C_DEV" value="i2c2"/>
<configure name="BMP280_DEV" value="i2c2"/>
<!-- OSD CONFIGURATION -->
<configure name="MAX7456_SPI_DEV" value="spi2"/>
<configure name="MAX7456_SLAVE_IDX" value="SPI_SLAVE5"/>
+2 -2
View File
@@ -14,7 +14,7 @@
<configure name="BOARD_MATEK_ROTATED" value="FALSE|TRUE" description="if TRUE, the board is not using is default orientation and axis can be redefined by hand"/>
</doc>
<dep>
<depends>spi_master,osd_max7456,baro_bmp280_i2c,current_sensor,imu_mpu6000</depends>
<depends>spi_master,osd_max7456,baro_bmp280,current_sensor,imu_mpu6000</depends>
</dep>
<makefile target="!sim|nps|fbw">
@@ -27,7 +27,7 @@
<define name="IMU_MPU_CHAN_Y" value="0" cond="ifeq (,$(findstring $(BOARD_MATEK_ROTATED),1 TRUE))"/>
<define name="IMU_MPU_X_SIGN" value="-1" cond="ifeq (,$(findstring $(BOARD_MATEK_ROTATED),1 TRUE))"/>
<!-- BAROMETER BMP280 CONFIGURATION -->
<configure name="BMP280_I2C_DEV" value="i2c2"/>
<configure name="BMP280_DEV" value="i2c2"/>
<!-- OSD CONFIGURATION -->
<configure name="MAX7456_SPI_DEV" value="spi2"/>
<configure name="MAX7456_SLAVE_IDX" value="SPI_SLAVE5"/>
+6
View File
@@ -21,6 +21,8 @@
<define name="MAG_TO_IMU_THETA" value="0.0" description="Rotation between sensor frame and IMU frame (theta angle)"/>
<define name="MAG_TO_IMU_PSI" value="0.0" description="Rotation between sensor frame and IMU frame (psi angle)"/>
</section>
<configure name="MAG_HMC58XX_SA" value="00|01|10|11" description="Number of samples averaged (default HMC5843 and HMC5983: 00, HMC5883: 11)"/>
<configure name="MAG_HMC58XX_TC" value="0|1" description="Automatic compensation of sensitivity over temperature (default 0)"/>
</doc>
<dep>
<depends>i2c,@imu</depends>
@@ -44,6 +46,10 @@
<configure name="MAG_HMC58XX_I2C_DEV" default="TRUE" case="upper|lower"/>
<define name="USE_$(MAG_HMC58XX_I2C_DEV_UPPER)"/>
<define name="MAG_HMC58XX_I2C_DEV" value="$(MAG_HMC58XX_I2C_DEV_LOWER)"/>
<configure name="MAG_HMC58XX_SA" default="0"/>
<configure name="MAG_HMC58XX_TC" default="0"/>
<define name="HMC58XX_DEFAULT_SA" value="$(MAG_HMC58XX_SA)"/>
<define name="HMC58XX_DEFAULT_TC" value="$(MAG_HMC58XX_SA)"/>
<test>
<define name="MAG_HMC58XX_I2C_DEV" value="i2c1"/>
<define name="USE_I2C1"/>
+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="mag_hmc59xx" dir="sensors" task="sensors">
<doc>
<description>
HMC59xx magnetometer with HMC58xx magnetometer driver.
</description>
</doc>
<dep>
<depends>mag_hmc58xx</depends>
<provides>mag</provides>
</dep>
<makefile target="ap">
<configure name="MAG_HMC58XX_SA" default="3"/>
<configure name="MAG_HMC58XX_TC" default="1"/>
</makefile>
</module>
@@ -1,5 +1,6 @@
/*
* Chris Efstathiou hendrixgr@gmail.com
* Florian Sansou florian.sansou@enac.fr
* This file is part of paparazzi.
*
* paparazzi is free software; you can redistribute it and/or modify
@@ -19,14 +20,14 @@
*/
/**
* @file modules/sensors/baro_bmp280_i2c.c
* Bosch BMP280 I2C sensor interface.
* @file modules/sensors/baro_bmp280.c
* Bosch BMP280 sensor interface.
*
* This reads the values for pressure and temperature from the Bosch BMP280 sensor through I2C.
* This reads the values for pressure and temperature from the Bosch BMP280 sensor.
*/
#include "baro_bmp280_i2c.h"
#include "baro_bmp280.h"
#include "modules/core/abi.h"
#include "mcu_periph/uart.h"
@@ -37,19 +38,31 @@
#if DOWNLINK && !defined(BMP280_SYNC_SEND)
#include "modules/datalink/telemetry.h"
#endif
PRINT_CONFIG_VAR(BMP280_SYNC_SEND)
#ifndef BMP280_USE_SPI
#define BMP280_USE_SPI FALSE
#endif
PRINT_CONFIG_VAR(BMP280_USE_SPI)
PRINT_CONFIG_VAR(BMP280_DEV)
/** default slave address */
#ifndef BMP280_SLAVE_ADDR
#define BMP280_SLAVE_ADDR BMP280_I2C_ADDR
#endif
#ifndef BMP280_SLAVE_IDX
#define BMP280_SLAVE_IDX SPI_SLAVE0
#endif
float baro_alt = 0;
float baro_temp = 0;
float baro_press = 0;
bool baro_alt_valid = 0;
struct Bmp280_I2c baro_bmp280;
struct bmp280_t baro_bmp280;
#if DOWNLINK && !defined(BMP280_SYNC_SEND)
static void send_baro_bmp_data(struct transport_tx *trans, struct link_device *dev)
@@ -67,8 +80,16 @@ static void send_baro_bmp_data(struct transport_tx *trans, struct link_device *d
void baro_bmp280_init(void)
{
bmp280_i2c_init(&baro_bmp280, &BMP280_I2C_DEV, BMP280_SLAVE_ADDR);
#if BMP280_USE_SPI
baro_bmp280.bus = BMP280_SPI;
baro_bmp280.spi.p = &BMP280_DEV;
baro_bmp280.spi.slave_idx = BMP280_SLAVE_IDX;
#else
baro_bmp280.bus = BMP280_I2C;
baro_bmp280.i2c.p = &BMP280_DEV;
baro_bmp280.i2c.slave_addr = BMP280_SLAVE_ADDR;
#endif
bmp280_init(&baro_bmp280);
#if DOWNLINK && !defined(BMP280_SYNC_SEND)
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_BMP_STATUS, send_baro_bmp_data);
#endif
@@ -76,12 +97,12 @@ void baro_bmp280_init(void)
void baro_bmp280_periodic(void)
{
bmp280_i2c_periodic(&baro_bmp280);
bmp280_periodic(&baro_bmp280);
}
void baro_bmp280_event(void)
{
bmp280_i2c_event(&baro_bmp280);
bmp280_event(&baro_bmp280);
if (baro_bmp280.data_available) {
uint32_t now_ts = get_sys_time_usec();
@@ -1,5 +1,6 @@
/*
* Chris Efstathiou hendrixgr@gmail.com
* Florian Sansou florian.sansou@enac.fr
*
* This file is part of paparazzi.
*
@@ -20,18 +21,18 @@
*/
/**
* @file modules/sensors/baro_bmp280_i2c.h
* Bosch BMP280 I2C sensor interface.
* @file modules/sensors/baro_bmp280.h
* Bosch BMP280 sensor interface.
*
* This reads the values for pressure and temperature from the Bosch BMP280 sensor through I2C.
* This reads the values for pressure and temperature from the Bosch BMP280 sensor.
*/
#ifndef BARO_BMP280_I2C_H
#define BARO_BMP280_I2C_H
#ifndef BARO_BMP280_H
#define BARO_BMP280_H
#include "peripherals/bmp280_i2c.h"
#include "peripherals/bmp280.h"
extern struct Bmp280_I2c baro_bmp280;
extern struct bmp280_t baro_bmp280;
extern float baro_alt;
extern bool baro_alt_valid;
+399
View File
@@ -0,0 +1,399 @@
/*
* Chris Efstathiou hendrixgr@gmail.com
* Florian Sansou florian.sansou@enac.fr
* 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, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file peripherals/bmp280.c
* @brief Sensor driver for BMP280 sensor
*
*
*/
#include "peripherals/bmp280.h"
/** local function to extract raw data from i2c buffer
* and compute compensation with selected precision
*/
static void parse_sensor_data(struct bmp280_t *bmp, uint8_t *data);
static void parse_calib_data(struct bmp280_t *bmp, uint8_t *data);
PRINT_CONFIG_MSG("BMP280 uses double precision compensation")
static double compensate_pressure(struct bmp280_t *bmp);
static double compensate_temperature(struct bmp280_t *bmp);
static bool bmp280_config(struct bmp280_t *bmp);
static void bmp280_register_write(struct bmp280_t *bmp, uint8_t reg, uint8_t value);
static void bmp280_register_read(struct bmp280_t *bmp, uint8_t reg, uint16_t size);
/**
* @brief Initialize the bmp280 sensor instance
*
* @param bmp The structure containing the configuration of the bmp280 instance
*/
void bmp280_init(struct bmp280_t *bmp)
{
bmp->data_available = false;
bmp->initialized = false;
bmp->status = BMP280_STATUS_UNINIT;
bmp->config_idx = 0;
/* SPI setup */
if(bmp->bus == BMP280_SPI) {
bmp->spi.trans.cpol = SPICpolIdleHigh;
bmp->spi.trans.cpha = SPICphaEdge2;
bmp->spi.trans.dss = SPIDss8bit;
bmp->spi.trans.bitorder = SPIMSBFirst;
bmp->spi.trans.cdiv = SPIDiv16;
bmp->spi.trans.select = SPISelectUnselect;
bmp->spi.trans.slave_idx = bmp->spi.slave_idx;
bmp->spi.trans.output_length = 0;
bmp->spi.trans.input_length = 0;
bmp->spi.trans.before_cb = NULL;
bmp->spi.trans.after_cb = NULL;
bmp->spi.trans.input_buf = bmp->spi.rx_buf;
bmp->spi.trans.output_buf = bmp->spi.tx_buf;
bmp->spi.trans.status = SPITransDone;
// in SPI read, the first byte is garbage because writing the register address
bmp->rx_buffer = &bmp->spi.rx_buf[1];
bmp->tx_buffer = bmp->spi.tx_buf;
bmp->rx_length = &bmp->spi.trans.input_length;
}
/* I2C setup */
else {
bmp->i2c.trans.slave_addr = bmp->i2c.slave_addr; // slave address
bmp->i2c.trans.status = I2CTransDone; // set initial status: Done
bmp->rx_buffer = (uint8_t *)bmp->i2c.trans.buf;
bmp->tx_buffer = (uint8_t *)bmp->i2c.trans.buf;
bmp->rx_length = &bmp->i2c.trans.len_r;
}
}
/**
* @brief Should be called periodically to request sensor readings
* - First detects the sensor using WHO_AM_I reading
* - Configures the sensor according the users requested configuration
* - Requests a sensor reading
*
* @param bmp The bmp280 instance
*/
void bmp280_periodic(struct bmp280_t *bmp)
{
/* Idle */
if((bmp->bus == BMP280_SPI && bmp->spi.trans.status == SPITransDone) ||
(bmp->bus == BMP280_I2C && bmp->i2c.trans.status == I2CTransDone)) {
switch (bmp->status) {
case BMP280_STATUS_UNINIT:
bmp->data_available = false;
bmp->initialized = false;
bmp->status = BMP280_STATUS_IDLE;
break;
case BMP280_STATUS_IDLE:
/* Request WHO_AM_I */
bmp280_register_read(bmp, BMP280_CHIP_ID_REG_ADDR, 1);
break;
case BMP280_STATUS_GET_CALIB:
// request calibration data
bmp280_register_read(bmp, BMP280_CALIB_LSB_DATA_ADDR, BMP280_CALIB_DATA_LEN);
//process in bmp280_event()
break;
case BMP280_STATUS_CONFIGURE:
/* Start configuring */
if(bmp280_config(bmp)) {
bmp->status = BMP280_STATUS_READ_STATUS_REG;
bmp->initialized = true;
}
break;
case BMP280_STATUS_READ_STATUS_REG:
// READ THE STATUS BYTE
bmp280_register_read(bmp, BMP280_STATUS_REG_ADDR, 1);
break;
case BMP280_STATUS_READ_DATA_REGS:
// READ ALL 6 DATA REGISTERS
bmp280_register_read(bmp, BMP280_DATA_START_REG_ADDR, BMP280_P_T_DATA_LEN);
break;
default:
break;
}
}
}
/**
* @brief Should be called in the event thread
* - Configures the sensor and reads the responses
* - Parse and request the sensor data
*
* @param bmp The bmp280 instance
*/
void bmp280_event(struct bmp280_t *bmp)
{
/* Successful transfer */
if((bmp->bus == BMP280_SPI && bmp->spi.trans.status == SPITransSuccess) ||
(bmp->bus == BMP280_I2C && bmp->i2c.trans.status == I2CTransSuccess)) {
switch (bmp->status) {
case BMP280_STATUS_IDLE:
/* WHO_AM_I */
if(bmp->rx_buffer[0] == BMP280_ID_NB) {
bmp->device = BMP_280;
bmp->status = BMP280_STATUS_GET_CALIB;
} else {
bmp->status = BMP280_STATUS_IDLE;
}
break;
case BMP280_STATUS_GET_CALIB:
// compute calib
parse_calib_data(bmp, &bmp->rx_buffer[0]);
bmp->status = BMP280_STATUS_CONFIGURE;
break;
case BMP280_STATUS_CONFIGURE:
if(bmp280_config(bmp)) {
bmp->status = BMP280_STATUS_READ_STATUS_REG;
bmp->initialized = true;
}
break;
case BMP280_STATUS_READ_STATUS_REG:
// check status byte
if ((bmp->rx_buffer[0] & (BMP280_EOC_BIT | BMP280_NVRAM_COPY_BIT)) == 0) {
bmp->status = BMP280_STATUS_READ_DATA_REGS;
}
break;
case BMP280_STATUS_READ_DATA_REGS:
// parse sensor data, compensate temperature first, then pressure
parse_sensor_data(bmp, &bmp->rx_buffer[0]);
compensate_temperature(bmp);
compensate_pressure(bmp);
bmp->data_available = true;
bmp->status = BMP280_STATUS_READ_STATUS_REG;
break;
default:
bmp->status = BMP280_STATUS_GET_CALIB; // just to avoid the compiler's warning message
break;
}
if(bmp->bus == BMP280_I2C){
bmp->i2c.trans.status = I2CTransDone;
}
else{
bmp->spi.trans.status = SPITransDone;
}
} else if ((bmp->bus == BMP280_SPI && bmp->spi.trans.status == SPITransFailed) ||
(bmp->bus == BMP280_I2C && bmp->i2c.trans.status == I2CTransFailed)) {
/* try again */
if (!bmp->initialized) {
bmp->status = BMP280_STATUS_UNINIT;
}
if(bmp->bus == BMP280_I2C){
bmp->i2c.trans.status = I2CTransDone;
}
else{
bmp->spi.trans.status = SPITransDone;
}
}
return;
}
static void parse_sensor_data(struct bmp280_t *bmp, uint8_t *data)
{
/* Temporary variables to store the sensor data */
uint32_t data_xlsb;
uint32_t data_lsb;
uint32_t data_msb;
// BMP280 HAS THE 6 DATA REGISTERS START AT F7 AND GOING UP TO FC MSB FIRST THEN LSB AND LAST THE XLSB BYTE.
// THE FIRST THREE BYTES ARE THE PRESSURE AND THE NEXT 3 THE TEMPERATURE.
/* Store the parsed register values for pressure data */
data_msb = (uint32_t)data[0] << 16;
data_lsb = (uint32_t)data[1] << 8;
data_xlsb = (uint32_t)data[2];
bmp->raw_pressure = (int32_t)((data_msb | data_lsb | data_xlsb) >> 4);
/* Store the parsed register values for temperature data */
data_msb = (uint32_t)data[3] << 16;
data_lsb = (uint32_t)data[4] << 8;
data_xlsb = (uint32_t)data[5];
bmp->raw_temperature = (int32_t)((data_msb | data_lsb | data_xlsb) >> 4);
}
/**
* @brief This internal API is used to parse the calibration data, compensates
* it and store it in device structure (float version)
*/
static void parse_calib_data(struct bmp280_t *bmp, uint8_t *data)
{
bmp->calib.dig_t1 = BMP280_CONCAT_BYTES(data[1], data[0]);
bmp->calib.dig_t2 = (int16_t)BMP280_CONCAT_BYTES(data[3], data[2]);
bmp->calib.dig_t3 = (int16_t)BMP280_CONCAT_BYTES(data[5], data[4]);
bmp->calib.dig_p1 = BMP280_CONCAT_BYTES(data[7], data[6]);
bmp->calib.dig_p2 = (int16_t)BMP280_CONCAT_BYTES(data[9], data[8]);
bmp->calib.dig_p3 = (int16_t)BMP280_CONCAT_BYTES(data[11], data[10]);
bmp->calib.dig_p4 = (int16_t)BMP280_CONCAT_BYTES(data[13], data[12]);
bmp->calib.dig_p5 = (int16_t)BMP280_CONCAT_BYTES(data[15], data[14]);
bmp->calib.dig_p6 = (int16_t)BMP280_CONCAT_BYTES(data[17], data[16]);
bmp->calib.dig_p7 = (int16_t)BMP280_CONCAT_BYTES(data[19], data[18]);
bmp->calib.dig_p8 = (int16_t)BMP280_CONCAT_BYTES(data[21], data[20]);
bmp->calib.dig_p9 = (int16_t)BMP280_CONCAT_BYTES(data[23], data[22]);
return;
}
/**
* @brief This internal API is used to compensate the raw temperature data and
* return the compensated temperature data in float data type.
*/
static double compensate_temperature(struct bmp280_t *bmp)
{
double var1 = (((double)bmp->raw_temperature / 16384.0) - ((double)bmp->calib.dig_t1 / 1024.0)) * ((double)bmp->calib.dig_t2);
double var2 = ((double)bmp->raw_temperature / 131072.0) - ((double)bmp->calib.dig_t1 / 8192.0);
var2 = (var2 * var2) * (double)bmp->calib.dig_t3;
int64_t t_fine = (int64_t)(var1 + var2);
/* Store t_lin in dev. structure for pressure calculation */
bmp->calib.t_fine = t_fine;
/* Store compensated temperature in float in structure */
bmp->temperature = (((var1 + var2) / 5120.f) * 100);
return (double)bmp->temperature;
}
/**
* @brief This internal API is used to compensate the raw pressure data and
* return the compensated pressure data in integer data type.
*/
static double compensate_pressure(struct bmp280_t *bmp)
{
double var1;
double var2;
double p;
var1 = ((double)bmp->calib.t_fine / 2) - 64000.0;
var2 = (var1 * var1 * (double)bmp->calib.dig_p5) / 32768.0;
var2 = var2 + (var1 * (double)bmp->calib.dig_p5 * 2.0);
var2 = (var2 / 4.0) + ((double)bmp->calib.dig_p4 * 65536.0);
var1 = (((double)bmp->calib.dig_p3 * var1 * (var1 / 524288.0)) + ((double)bmp->calib.dig_p2 * var1)) / 524288.0;
var1 = (1 + (var1 / 32768.0)) * (double)bmp->calib.dig_p1;
p = 1048576.0 - (double)bmp->raw_pressure;
p = (p - (var2 / 4096.0)) * (6250.0 / var1);
var1 = ((double)bmp->calib.dig_p9 * p) * (p / 2147483648.0);
var2 = (p * ((double)bmp->calib.dig_p8)) / 32768.0;
p = p + ((var1 + var2 + (double)bmp->calib.dig_p7) / 16.0);
bmp->pressure = p;
return (p);
}
/**
* @brief Configure the BMP280 device register by register
*
* @param bmp The bmp280 instance
* @return true When the configuration is completed
* @return false Still busy configuring
*/
static bool bmp280_config(struct bmp280_t *bmp) {
// Only one transaction can be made per call to the periodic function
switch(bmp->config_idx) {
case 0:
// From datasheet, recommended config for drone usecase:
// osrs_p = 16, osrs_t = 2
bmp280_register_write(bmp, BMP280_CTRL_MEAS_REG_ADDR, (BMP280_OVERSAMPLING_2X_T | BMP280_OVERSAMPLING_16X_P | BMP280_POWER_NORMAL_MODE));
bmp->config_idx++;
break;
case 1:
// IIR filter = 16
bmp280_register_write(bmp, BMP280_CONFIG_REG_ADDR, (BMP280_INACTIVITY_HALF_MS | BMP280_IIR_FILTER_COEFF_16));
bmp->config_idx++;
break;
default:
return true;
}
return false;
}
/**
* @brief Write a register with a value
*
* @param bmp The bmp280 instance
* @param reg The register address
* @param value The value to write to the register
*/
static void bmp280_register_write(struct bmp280_t *bmp, uint8_t reg, uint8_t value) {
bmp->tx_buffer[1] = value;
/* SPI transaction */
if(bmp->bus == BMP280_SPI) {
bmp->tx_buffer[0] = (reg & 0x7F); //write command (bit 7 = RW = '0')
bmp->spi.trans.output_length = 2;
bmp->spi.trans.input_length = 0;
spi_submit(bmp->spi.p, &(bmp->spi.trans));
}
/* I2C transaction */
else {
bmp->tx_buffer[0] = reg;
i2c_transmit(bmp->i2c.p, &(bmp->i2c.trans), bmp->i2c.slave_addr, 2);
}
}
/**
* @brief Read a register
*
* @param bmp The bmp280 instance
* @param reg The register address
* @param size The size to read (already 1 is added for the transmission of the register to read)
*/
static void bmp280_register_read(struct bmp280_t *bmp, uint8_t reg, uint16_t size) {
bmp->tx_buffer[0] = reg | BMP280_READ_FLAG;
/* SPI transaction */
if(bmp->bus == BMP280_SPI) {
bmp->spi.trans.output_length = 2;
bmp->spi.trans.input_length = size+1;
bmp->tx_buffer[1] = 0;
spi_submit(bmp->spi.p, &(bmp->spi.trans));
}
/* I2C transaction */
else {
i2c_transceive(bmp->i2c.p, &(bmp->i2c.trans), bmp->i2c.slave_addr, 1, size);
}
}
+118
View File
@@ -0,0 +1,118 @@
/*
* Chris Efstathiou hendrixgr@gmail.com
* Florian Sansou florian.sansou@enac.fr
* 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, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file peripherals/bmp280.h
* @brief Sensor driver for BMP280 sensor
*
*
*/
#ifndef BMP280_H
#define BMP280_H
/* Header includes */
#include "peripherals/bmp280_regs.h"
#include "mcu_periph/i2c.h"
#include "mcu_periph/spi.h"
struct bmp280_i2c_t {
struct i2c_periph *p; ///< Peripheral device for communication
struct i2c_transaction trans; ///< Transaction used during configuration and measurements
uint8_t slave_addr; ///< The I2C slave address on the bus
};
struct bmp280_spi_t {
struct spi_periph *p; ///< Peripheral device for communication
uint8_t slave_idx; ///< Slave index used for Slave Select
struct spi_transaction trans; ///< Transaction used during configuration and measurements
uint8_t tx_buf[50]; ///< Transmit buffer
uint8_t rx_buf[50]; //< Receive buffer
};
/* Possible communication busses for the bmp280 driver */
enum bmp280_bus_t {
BMP280_SPI,
BMP280_I2C
};
enum bmp_device_t{
BMP_UNKOWN,
BMP_280
};
/* Different states the bmp driver can be in */
enum bmp280_status_t {
BMP280_STATUS_UNINIT,
BMP280_STATUS_IDLE,
BMP280_STATUS_GET_CALIB,
BMP280_STATUS_CONFIGURE,
BMP280_STATUS_READ_STATUS_REG,
BMP280_STATUS_READ_DATA_REGS
};
// brief Register Trim Variables
struct bmp280_reg_calib_data_t {
uint16_t dig_t1;
int16_t dig_t2;
int16_t dig_t3;
uint16_t dig_p1;
int16_t dig_p2;
int16_t dig_p3;
int16_t dig_p4;
int16_t dig_p5;
int16_t dig_p6;
int16_t dig_p7;
int16_t dig_p8;
int16_t dig_p9;
int64_t t_fine;
};
struct bmp280_t {
enum bmp280_status_t status; ///< state machine status
enum bmp_device_t device; ///< The device type detected
bool initialized; ///< config done flag
volatile bool data_available; ///< data ready flag
struct bmp280_reg_calib_data_t calib; ///< calibration data
uint32_t raw_pressure; ///< uncompensated pressure
uint32_t raw_temperature; ///< uncompensated temperature
float pressure; ///< pressure in Pascal
float temperature; ///< temperature in deg Celcius
enum bmp280_bus_t bus; ///< The communication bus used to connect the device SPI/I2C
union {
struct bmp280_spi_t spi; ///< SPI specific configuration
struct bmp280_i2c_t i2c; ///< I2C specific configuration
};
uint8_t* rx_buffer;
uint8_t* tx_buffer;
uint16_t* rx_length;
uint8_t config_idx; ///< The current configuration index
};
extern void bmp280_read_eeprom_calib(struct bmp280_t *bmp);
extern void bmp280_init(struct bmp280_t *bmp);
extern void bmp280_periodic(struct bmp280_t *bmp);
extern void bmp280_event(struct bmp280_t *bmp);
#endif /* BMP280_H */
-248
View File
@@ -1,248 +0,0 @@
/*
* Chris Efstathiou hendrixgr@gmail.com
* 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, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file peripherals/bmp280_i2c.c
* @brief Sensor driver for BMP280 sensor via I2C
*
*
*/
#include "peripherals/bmp280_i2c.h"
/** local function to extract raw data from i2c buffer
* and compute compensation with selected precision
*/
static void parse_sensor_data(struct Bmp280_I2c *bmp);
static void parse_calib_data(struct Bmp280_I2c *bmp);
PRINT_CONFIG_MSG("BMP280 uses double precision compensation")
static double compensate_pressure(struct Bmp280_I2c *bmp);
static double compensate_temperature(struct Bmp280_I2c *bmp);
int64_t t_fine;
// init function
void bmp280_i2c_init(struct Bmp280_I2c *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: Done
bmp->i2c_trans.status = I2CTransDone;
bmp->data_available = false;
bmp->initialized = false;
bmp->status = BMP280_STATUS_UNINIT;
}
// Start new measurement if sensor ready
void bmp280_i2c_periodic(struct Bmp280_I2c *bmp)
{
if (bmp->i2c_trans.status != I2CTransDone) {
return; // transaction not finished
}
switch (bmp->status) {
case BMP280_STATUS_UNINIT:
bmp->data_available = false;
bmp->initialized = false;
bmp->status = BMP280_STATUS_GET_CALIB;
break;
case BMP280_STATUS_GET_CALIB:
// request calibration data
bmp->i2c_trans.buf[0] = BMP280_CALIB_LSB_DATA_ADDR;
i2c_transceive(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 1, BMP280_CALIB_DATA_LEN);
break;
case BMP280_STATUS_CONFIGURE:
// From datasheet, recommended config for drone usecase:
// osrs_p = 8, osrs_t = 1
// IIR filter = 2 (note: this one doesn't exist...)
bmp->i2c_trans.buf[0] = BMP280_CTRL_MEAS_REG_ADDR;
bmp->i2c_trans.buf[1] = (BMP280_OVERSAMPLING_1X_T | BMP280_OVERSAMPLING_8X_P | BMP280_POWER_NORMAL_MODE);
bmp->i2c_trans.buf[2] = BMP280_CONFIG_REG_ADDR;
bmp->i2c_trans.buf[3] = (BMP280_INACTIVITY_62_5_MS | BMP280_IIR_FILTER_COEFF_2);
i2c_transmit(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, (BMP280_CONFIG_LEN * 2));
break;
case BMP280_STATUS_READ_STATUS_REG:
// READ THE STATUS BYTE
bmp->i2c_trans.buf[0] = BMP280_STATUS_REG_ADDR;
i2c_transceive(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 1, 1);
break;
case BMP280_STATUS_READ_DATA_REGS:
// READ ALL 6 DATA REGISTERS
bmp->i2c_trans.buf[0] = BMP280_DATA_START_REG_ADDR;
i2c_transceive(bmp->i2c_p, &bmp->i2c_trans, bmp->i2c_trans.slave_addr, 1, BMP280_P_T_DATA_LEN);
break;
default:
break;
}
}
void bmp280_i2c_event(struct Bmp280_I2c *bmp)
{
if (bmp->i2c_trans.status == I2CTransSuccess) {
switch (bmp->status) {
case BMP280_STATUS_GET_CALIB:
// compute calib
parse_calib_data(bmp);
bmp->status = BMP280_STATUS_CONFIGURE;
break;
case BMP280_STATUS_CONFIGURE:
// nothing else to do, start reading
bmp->status = BMP280_STATUS_READ_STATUS_REG;
bmp->initialized = true;
break;
case BMP280_STATUS_READ_STATUS_REG:
// check status byte
if ((bmp->i2c_trans.buf[0] & (BMP280_EOC_BIT | BMP280_NVRAM_COPY_BIT)) == 0) {
bmp->status = BMP280_STATUS_READ_DATA_REGS;
}
break;
case BMP280_STATUS_READ_DATA_REGS:
// parse sensor data, compensate temperature first, then pressure
parse_sensor_data(bmp);
compensate_temperature(bmp);
compensate_pressure(bmp);
bmp->data_available = true;
bmp->status = BMP280_STATUS_READ_STATUS_REG;
break;
default:
bmp->status = BMP280_STATUS_GET_CALIB; // just to avoid the compiler's warning message
break;
}
bmp->i2c_trans.status = I2CTransDone;
} else if (bmp->i2c_trans.status == I2CTransFailed) {
/* try again */
if (!bmp->initialized) {
bmp->status = BMP280_STATUS_UNINIT;
}
bmp->i2c_trans.status = I2CTransDone;
}
return;
}
static void parse_sensor_data(struct Bmp280_I2c *bmp)
{
/* Temporary variables to store the sensor data */
uint32_t data_xlsb;
uint32_t data_lsb;
uint32_t data_msb;
// BMP280 HAS THE 6 DATA REGISTERS START AT F7 AND GOING UP TO FC MSB FIRST THEN LSB AND LAST THE XLSB BYTE.
// THE FIRST THREE BYTES ARE THE PRESSURE AND THE NEXT 3 THE TEMPERATURE.
/* Store the parsed register values for pressure data */
data_msb = (uint32_t)bmp->i2c_trans.buf[0] << 16;
data_lsb = (uint32_t)bmp->i2c_trans.buf[1] << 8;
data_xlsb = (uint32_t)bmp->i2c_trans.buf[2];
bmp->raw_pressure = (int32_t)((data_msb | data_lsb | data_xlsb) >> 4);
/* Store the parsed register values for temperature data */
data_msb = (uint32_t)bmp->i2c_trans.buf[3] << 16;
data_lsb = (uint32_t)bmp->i2c_trans.buf[4] << 8;
data_xlsb = (uint32_t)bmp->i2c_trans.buf[5];
bmp->raw_temperature = (int32_t)((data_msb | data_lsb | data_xlsb) >> 4);
}
/**
* @brief This internal API is used to parse the calibration data, compensates
* it and store it in device structure (float version)
*/
static void parse_calib_data(struct Bmp280_I2c *bmp)
{
uint8_t *data = (uint8_t *)bmp->i2c_trans.buf; // we know that this buffer will not be modified during this call
bmp->calib.dig_t1 = BMP280_CONCAT_BYTES(data[1], data[0]);
bmp->calib.dig_t2 = (int16_t)BMP280_CONCAT_BYTES(data[3], data[2]);
bmp->calib.dig_t3 = (int16_t)BMP280_CONCAT_BYTES(data[5], data[4]);
bmp->calib.dig_p1 = BMP280_CONCAT_BYTES(data[7], data[6]);
bmp->calib.dig_p2 = (int16_t)BMP280_CONCAT_BYTES(data[9], data[8]);
bmp->calib.dig_p3 = (int16_t)BMP280_CONCAT_BYTES(data[11], data[10]);
bmp->calib.dig_p4 = (int16_t)BMP280_CONCAT_BYTES(data[13], data[12]);
bmp->calib.dig_p5 = (int16_t)BMP280_CONCAT_BYTES(data[15], data[14]);
bmp->calib.dig_p6 = (int16_t)BMP280_CONCAT_BYTES(data[17], data[16]);
bmp->calib.dig_p7 = (int16_t)BMP280_CONCAT_BYTES(data[19], data[18]);
bmp->calib.dig_p8 = (int16_t)BMP280_CONCAT_BYTES(data[21], data[20]);
bmp->calib.dig_p9 = (int16_t)BMP280_CONCAT_BYTES(data[23], data[22]);
return;
}
/**
* @brief This internal API is used to compensate the raw temperature data and
* return the compensated temperature data in float data type.
*/
static double compensate_temperature(struct Bmp280_I2c *bmp)
{
double var1;
double var2;
var1 = (((double)bmp->raw_temperature / 16384.0) - ((double)bmp->calib.dig_t1 / 1024.0)) * ((double)bmp->calib.dig_t2);
var2 = ((double)bmp->raw_temperature / 131072.0) - ((double)bmp->calib.dig_t1 / 8192.0);
var2 = (var2 * var2) * (double)bmp->calib.dig_t3;
t_fine = (int64_t)(var1 + var2);
/* Store t_lin in dev. structure for pressure calculation */
bmp->calib.t_fine = t_fine;
/* Store compensated temperature in float in structure */
bmp->temperature = (((var1 + var2) / 5120.f) * 100);
return (double)bmp->temperature;
}
/**
* @brief This internal API is used to compensate the raw pressure data and
* return the compensated pressure data in integer data type.
*/
static double compensate_pressure(struct Bmp280_I2c *bmp)
{
double var1;
double var2;
double p;
var1 = ((double)t_fine / 2) - 64000.0;
var2 = (var1 * var1 * (double)bmp->calib.dig_p5) / 32768.0;
var2 = var2 + (var1 * (double)bmp->calib.dig_p5 * 2.0);
var2 = (var2 / 4.0) + ((double)bmp->calib.dig_p4 * 65536.0);
var1 = (((double)bmp->calib.dig_p3 * var1 * (var1 / 524288.0)) + ((double)bmp->calib.dig_p2 * var1)) / 524288.0;
var1 = (1 + (var1 / 32768.0)) * (double)bmp->calib.dig_p1;
p = 1048576.0 - (double)bmp->raw_pressure;
p = (p - (var2 / 4096.0)) * (6250.0 / var1);
var1 = ((double)bmp->calib.dig_p9 * p) * (p / 2147483648.0);
var2 = (p * ((double)bmp->calib.dig_p8)) / 32768.0;
p = p + ((var1 + var2 + (double)bmp->calib.dig_p7) / 16.0);
bmp->pressure = p;
return (p);
}
-53
View File
@@ -1,53 +0,0 @@
/*
* Chris Efstathiou hendrixgr@gmail.com
* 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, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file peripherals/bmp280_i2c.h
* @brief Sensor driver for BMP280 sensor via I2C
*
*
*/
#ifndef BMP280_I2C_H
#define BMP280_I2C_H
/* Header includes */
#include "peripherals/bmp280_regs.h"
#include "mcu_periph/i2c.h"
struct Bmp280_I2c {
struct i2c_periph *i2c_p;
struct i2c_transaction i2c_trans;
enum Bmp280Status status; ///< state machine status
bool initialized; ///< config done flag
volatile bool data_available; ///< data ready flag
struct bmp280_reg_calib_data calib; ///< calibration data
uint32_t raw_pressure; ///< uncompensated pressure
uint32_t raw_temperature; ///< uncompensated temperature
float pressure; ///< pressure in Pascal
float temperature; ///< temperature in deg Celcius
};
extern void bmp280_i2c_read_eeprom_calib(struct Bmp280_I2c *bmp);
extern void bmp280_i2c_init(struct Bmp280_I2c *bmp, struct i2c_periph *i2c_p, uint8_t addr);
extern void bmp280_i2c_periodic(struct Bmp280_I2c *bmp);
extern void bmp280_i2c_event(struct Bmp280_I2c *bmp);
#endif /* BMP280_I2C_H */
+17 -43
View File
@@ -33,33 +33,33 @@
#include "std.h"
#define BMP280_READ_FLAG 0x80
// I2C addresses (8 bits)
#define BMP280_I2C_ADDR 0xEC
#define BMP280_I2C_ADDR_ALT 0xEE
/**\name BMP280 chip identifier */
#define BMP280_CHIP_ID 0x50
// CALIBRATION REGISTER ADDRESSES
#define BMP280_CALIB_LSB_DATA_ADDR 0x88
#define BMP280_CALIB_DATA_LEN 24
#define BMP280_DIG_T1_UINT 0x88
#define BMP280_DIG_T2_INT 0x8A
#define BMP280_DIG_T3_INT 0x8C
#define BMP280_DIG_T2_INT 0x8A
#define BMP280_DIG_T3_INT 0x8C
#define BMP280_DIG_P1_UINT 0x8E
#define BMP280_DIG_P2_INT 0x90
#define BMP280_DIG_P3_INT 0x92
#define BMP280_DIG_P4_INT 0x94
#define BMP280_DIG_P3_INT 0x92
#define BMP280_DIG_P4_INT 0x94
#define BMP280_DIG_P5_INT 0x96
#define BMP280_DIG_P6_INT 0x98
#define BMP280_DIG_P7_INT 0x9A
#define BMP280_DIG_P8_INT 0x9C
#define BMP280_DIG_P7_INT 0x9A
#define BMP280_DIG_P8_INT 0x9C
#define BMP280_DIG_P9_INT 0x9E
// CONTROL AND VALUES REGISTER ADDRESSES
#define BMP280_CONFIG_ADDR 0xF4
#define BMP280_CONFIG_LEN 0x02
#define BMP280_CONFIG_ADDR 0xF4
#define BMP280_CONFIG_LEN 0x02
#define BMP280_DATA_START_REG_ADDR 0xF7
#define BMP280_P_T_DATA_LEN 6
#define BMP280_P_DATA_LEN 3
@@ -77,13 +77,14 @@
#define BMP280_T_LSB_REG_ADDR 0xFB
#define BMP280_T_XLSB_REG_ADDR 0xFC
// BMP280 ID
#define BMP280_ID_NB 0x58
//BMP280 RESET COMMAND VALUE
#define BMP280_RESET_VAL 0xB6
#define BMP280_EOC_BIT (1<<3)
#define BMP280_NVRAM_COPY_BIT (1<<0)
// BMP280 ID
#define BMP280_ID_NB 0x58
//BMP280 RESET COMMAND VALUE
#define BMP280_RESET_VAL 0xB6
#define BMP280_EOC_BIT (1<<3)
#define BMP280_NVRAM_COPY_BIT (1<<0)
// BMP280 CONTROL MEASUREMENT REGISTER BIT VALUES.
#define BMP280_NO_OVERSAMPLING_T (0x00<<5)
@@ -142,33 +143,6 @@
#define BMP280_COMPENSATION BMP280_DOUBLE_PRECISION_COMPENSATION
#endif
/**
* @brief Status enum
*/
enum Bmp280Status {
BMP280_STATUS_UNINIT,
BMP280_STATUS_GET_CALIB,
BMP280_STATUS_CONFIGURE,
BMP280_STATUS_READ_STATUS_REG,
BMP280_STATUS_READ_DATA_REGS
};
// brief Register Trim Variables
struct bmp280_reg_calib_data {
uint16_t dig_t1;
int16_t dig_t2;
int16_t dig_t3;
uint16_t dig_p1;
int16_t dig_p2;
int16_t dig_p3;
int16_t dig_p4;
int16_t dig_p5;
int16_t dig_p6;
int16_t dig_p7;
int16_t dig_p8;
int16_t dig_p9;
int32_t t_fine;
};
#endif /* BMP280_REGS_H */
+10 -2
View File
@@ -23,7 +23,7 @@
/**
* @file peripherals/hmc58xx.c
*
* Driver for Honeywell HMC5843 and HMC5883 magnetometers.
* Driver for Honeywell HMC5843, HMC5883 and HMC5983 magnetometers.
* @todo DRDY/IRQ handling
*/
@@ -45,6 +45,12 @@
#ifndef HMC58XX_DEFAULT_MD
#define HMC58XX_DEFAULT_MD 0x0 // Continious measurement mode
#endif
#ifndef HMC58XX_DEFAULT_SA
#define HMC58XX_DEFAULT_SA 0x0 // Number of samples averaged
#endif
#ifndef HMC58XX_DEFAULT_TC
#define HMC58XX_DEFAULT_TC 0x0 // Automatic compensation of sensitivity over temperature
#endif
/** HMC58XX startup delay
*
@@ -64,6 +70,8 @@ static void hmc58xx_set_default_config(struct Hmc58xxConfig *c)
c->meas = HMC58XX_DEFAULT_MS;
c->gain = HMC58XX_DEFAULT_GN;
c->mode = HMC58XX_DEFAULT_MD;
c->samples_averaged = HMC58XX_DEFAULT_SA;
c->temp_comp = HMC58XX_DEFAULT_TC;
}
/**
@@ -102,7 +110,7 @@ static void hmc58xx_send_config(struct Hmc58xx *hmc)
{
switch (hmc->init_status) {
case HMC_CONF_CRA:
hmc58xx_i2c_tx_reg(hmc, HMC58XX_REG_CFGA, (hmc->config.rate << 2) | (hmc->config.meas));
hmc58xx_i2c_tx_reg(hmc, HMC58XX_REG_CFGA, (hmc->config.temp_comp << 7) | (hmc->config.samples_averaged << 5) | (hmc->config.rate << 2) | (hmc->config.meas));
hmc->init_status++;
break;
case HMC_CONF_CRB:
+7 -5
View File
@@ -23,7 +23,7 @@
/**
* @file peripherals/hmc58xx.c
*
* Driver for Honeywell HMC5843 and HMC5883 magnetometers.
* Driver for Honeywell HMC5843, HMC5883 and HMC5983 magnetometers.
*/
#ifndef HMC58XX_H
@@ -37,10 +37,12 @@
#include "peripherals/hmc58xx_regs.h"
struct Hmc58xxConfig {
uint8_t rate; ///< Data Output Rate Bits(6 -> 50Hz with HMC5843, 75Hz with HMC5883)
uint8_t meas; ///< Measurement configuration
uint8_t gain; ///< Gain configuration (1 -> +- 1 Gauss)
uint8_t mode; ///< Measurement mode
uint8_t rate; ///< Data Output Rate Bits(6 -> 50Hz with HMC5843, 75Hz with HMC5883)
uint8_t meas; ///< Measurement configuration
uint8_t gain; ///< Gain configuration (1 -> +- 1 Gauss)
uint8_t mode; ///< Measurement mode
uint8_t samples_averaged; ///< Number of samples averaged per measurement output.
uint8_t temp_comp; ///< Enable temperature sensor (only on HMC5983)
};
/** config status states */
+1 -1
View File
@@ -21,7 +21,7 @@
/**
* @file peripherals/hmc58xx_regs.h
* Register defs for Honeywell HMC5843 and HMC5883 magnetometers.
* Register defs for Honeywell HMC5843, HMC5883 and HMC5983 magnetometers.
*/
#ifndef HMC58XX_REGS_H
+1
View File
@@ -117,6 +117,7 @@
// Different sensor WHOAMI replies
#define MPU60X0_REG_WHO_AM_I 0x75
#define MPU60X0_WHOAMI_REPLY 0x68
#define MPU6500_WHOAMI_REPLY 0x70
#define ICM20600_WHOAMI_REPLY 0x11
#define ICM20608_WHOAMI_REPLY 0xAF
#define ICM20602_WHOAMI_REPLY 0x12
+3 -2
View File
@@ -84,9 +84,10 @@ void mpu60x0_spi_start_configure(struct Mpu60x0_Spi *mpu)
mpu->rx_buf[1] == ICM20600_WHOAMI_REPLY ||
mpu->rx_buf[1] == ICM20608_WHOAMI_REPLY ||
mpu->rx_buf[1] == ICM20602_WHOAMI_REPLY ||
mpu->rx_buf[1] == ICM20689_WHOAMI_REPLY)) {
mpu->rx_buf[1] == ICM20689_WHOAMI_REPLY ||
mpu->rx_buf[1] == MPU6500_WHOAMI_REPLY)) {
if (mpu->rx_buf[1] == MPU60X0_WHOAMI_REPLY) {
if (mpu->rx_buf[1] == MPU60X0_WHOAMI_REPLY || mpu->rx_buf[1] == MPU6500_WHOAMI_REPLY) {
mpu->config.type = MPU60X0;
} else if (mpu->rx_buf[1] == ICM20600_WHOAMI_REPLY) {
mpu->config.type = ICM20600;