mirror of
https://github.com/eclipse/upm.git
synced 2025-03-15 04:57:30 +03:00
bmp280/bme280: C port, C++ wraps C
Some private methods (relating to calibration/compensation) are no longer exposed. In addition, the driver auto-detects the chip (BMP280 or BME280) and acts accordingly, rather than requiring the specification of a chip id in the ctor. The getHumidity() method no longer accepts an arguement representing pressure at sea level. A new method is provided to specify this. Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
parent
58cdfadf4e
commit
c4a506f5a3
@ -6,6 +6,11 @@ compatibility between releases:
|
||||
|
||||
# current master
|
||||
|
||||
* **bmp280/bme280** Some private methods are no longer exposed
|
||||
(such as the calibration and compensation routines). In addition,
|
||||
the *getHumidity()* method no longer accepts an argument representing
|
||||
pressure at sea level. A separate method is provided to set this now.
|
||||
|
||||
* **bno055** This module no longer uses std::strings to pass around
|
||||
binary data (*read/writeCalibrationData()*). Rather, now *std::vectors* of
|
||||
the appropriate type are used. In addition, methods that previously
|
||||
|
@ -31,7 +31,7 @@
|
||||
using namespace std;
|
||||
using namespace upm;
|
||||
|
||||
int shouldRun = true;
|
||||
bool shouldRun = true;
|
||||
|
||||
void sig_handler(int signo)
|
||||
{
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -31,7 +33,7 @@
|
||||
using namespace std;
|
||||
using namespace upm;
|
||||
|
||||
int shouldRun = true;
|
||||
bool shouldRun = true;
|
||||
|
||||
void sig_handler(int signo)
|
||||
{
|
||||
|
@ -150,6 +150,7 @@ add_example (wfs)
|
||||
add_example (enc03r)
|
||||
add_example (nunchuck)
|
||||
add_example (bno055)
|
||||
add_example (bmp280)
|
||||
|
||||
# Custom examples
|
||||
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)
|
||||
@ -161,3 +162,4 @@ add_custom_example (button_intr-example-c button_intr.c button)
|
||||
add_custom_example (mcp2515-txrx-example-c mcp2515-txrx.c mcp2515)
|
||||
add_custom_example (le910-example-c le910.c uartat)
|
||||
add_custom_example (speaker_pwm-example-c speaker_pwm.c speaker)
|
||||
add_custom_example (bme280-example-c bme280.c bmp280)
|
||||
|
89
examples/c/bme280.c
Normal file
89
examples/c/bme280.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "upm_utilities.h"
|
||||
#include "bmp280.h"
|
||||
|
||||
bool shouldRun = true;
|
||||
|
||||
void sig_handler(int signo)
|
||||
{
|
||||
if (signo == SIGINT)
|
||||
shouldRun = false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
signal(SIGINT, sig_handler);
|
||||
//! [Interesting]
|
||||
|
||||
// Instantiate a BME280 instance using default i2c bus and
|
||||
// address. We use the BMP280 driver to do all of our work, since
|
||||
// the BMP280 and the BME280 are identical except for the fact
|
||||
// that the BME280 includes a humidity sensor.
|
||||
bmp280_context sensor = bmp280_init(BME280_DEFAULT_I2C_BUS,
|
||||
BME280_DEFAULT_ADDR, -1);
|
||||
|
||||
if (!sensor)
|
||||
{
|
||||
printf("bmp280_init() failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
|
||||
// bmp280_init(BME280_DEFAULT_SPI_BUS,
|
||||
// -1, 10)
|
||||
|
||||
while (shouldRun)
|
||||
{
|
||||
// update our values from the sensor
|
||||
if (bmp280_update(sensor))
|
||||
{
|
||||
printf("bmp280_update() failed\n");
|
||||
bmp280_close(sensor);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Compensation Temperature: %f C\n",
|
||||
bmp280_get_temperature(sensor));
|
||||
printf("Pressure: %f Pa\n", bmp280_get_pressure(sensor));
|
||||
printf("Computed Altitude: %f m\n", bmp280_get_altitude(sensor));
|
||||
printf("Relative Humidity: %f %%\n\n", bmp280_get_humidity(sensor));
|
||||
|
||||
upm_delay(1);
|
||||
}
|
||||
//! [Interesting]
|
||||
|
||||
printf("Exiting...\n");
|
||||
|
||||
bmp280_close(sensor);
|
||||
|
||||
return 0;
|
||||
}
|
86
examples/c/bmp280.c
Normal file
86
examples/c/bmp280.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "upm_utilities.h"
|
||||
#include "bmp280.h"
|
||||
|
||||
bool shouldRun = true;
|
||||
|
||||
void sig_handler(int signo)
|
||||
{
|
||||
if (signo == SIGINT)
|
||||
shouldRun = false;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
signal(SIGINT, sig_handler);
|
||||
//! [Interesting]
|
||||
|
||||
// Instantiate a BMP280 instance using default i2c bus and address
|
||||
bmp280_context sensor = bmp280_init(BMP280_DEFAULT_I2C_BUS,
|
||||
BMP280_DEFAULT_ADDR, -1);
|
||||
|
||||
if (!sensor)
|
||||
{
|
||||
printf("bmp280_init() failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
|
||||
// bmp280_init(BMP280_DEFAULT_SPI_BUS,
|
||||
// -1, 10)
|
||||
|
||||
while (shouldRun)
|
||||
{
|
||||
// update our values from the sensor
|
||||
if (bmp280_update(sensor))
|
||||
{
|
||||
printf("bmp280_update() failed\n");
|
||||
bmp280_close(sensor);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Compensation Temperature: %f C\n",
|
||||
bmp280_get_temperature(sensor));
|
||||
printf("Pressure: %f Pa\n", bmp280_get_pressure(sensor));
|
||||
printf("Computed Altitude: %f m\n\n", bmp280_get_altitude(sensor));
|
||||
|
||||
upm_delay(1);
|
||||
}
|
||||
|
||||
printf("Exiting...\n");
|
||||
|
||||
bmp280_close(sensor);
|
||||
|
||||
//! [Interesting]
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
set (libname "bmp280")
|
||||
set (libdescription "Bosch Atmospheric Sensor Library (bmp280 and Bme280)")
|
||||
set (module_src ${libname}.cxx bme280.cxx)
|
||||
set (module_hpp ${libname}.hpp bme280.hpp)
|
||||
upm_module_init(interfaces mraa)
|
||||
upm_mixed_module_init (NAME bmp280
|
||||
DESCRIPTION "Bosch Atmospheric Sensor Library (BMP280 and BME280)"
|
||||
C_HDR bmp280.h bmp280_regs.h
|
||||
C_SRC bmp280.c
|
||||
CPP_HDR bmp280.hpp bme280.hpp
|
||||
CPP_SRC bmp280.cxx bme280.cxx
|
||||
CPP_WRAPS_C
|
||||
REQUIRES mraa interfaces)
|
||||
target_link_libraries(${libnamec} m)
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -34,141 +36,23 @@
|
||||
using namespace upm;
|
||||
using namespace std;
|
||||
|
||||
BME280::BME280(int bus, int addr, int cs, uint8_t theChipID) :
|
||||
BMP280(bus, addr, cs, theChipID)
|
||||
BME280::BME280(int bus, int addr, int cs) :
|
||||
BMP280(bus, addr, cs)
|
||||
{
|
||||
|
||||
m_humidity = 0;
|
||||
|
||||
m_dig_H1 = 0;
|
||||
m_dig_H2 = 0;
|
||||
m_dig_H3 = 0;
|
||||
m_dig_H4 = 0;
|
||||
m_dig_H5 = 0;
|
||||
m_dig_H6 = 0;
|
||||
|
||||
// set sleep mode for now
|
||||
setMeasureMode(MODE_SLEEP);
|
||||
|
||||
// read calibration data
|
||||
readCalibrationData();
|
||||
|
||||
// set the default mode to the highest resolution mode
|
||||
setUsageMode(USAGE_MODE_INDOOR_NAV);
|
||||
}
|
||||
|
||||
BME280::~BME280()
|
||||
{
|
||||
}
|
||||
|
||||
void BME280::update()
|
||||
{
|
||||
// call the base class method first. This will handle the details
|
||||
// WRT forced mode so that we can always be sure to read valid data
|
||||
// regardless of the underlying measurement mode.
|
||||
|
||||
BMP280::update();
|
||||
|
||||
int32_t hum = 0;
|
||||
|
||||
const int dataLen = 2;
|
||||
uint8_t data[dataLen];
|
||||
memset(data, 0, dataLen);
|
||||
|
||||
int rv;
|
||||
if ((rv = readRegs(REG_HUMIDITY_MSB, data, dataLen)) != dataLen)
|
||||
{
|
||||
throw std::runtime_error(std::string(__FUNCTION__)
|
||||
+ ": readRegs() failed, returned "
|
||||
+ std::to_string(rv));
|
||||
}
|
||||
|
||||
// 20 bits unsigned stored in a 32bit signed quanty
|
||||
|
||||
hum = ( (data[0] << 8) | data[1] );
|
||||
|
||||
m_humidity = float(bme280_compensate_H_int32(hum));
|
||||
m_humidity /= 1024.0;
|
||||
}
|
||||
|
||||
void BME280::readCalibrationData()
|
||||
{
|
||||
m_dig_H1 = readReg(REG_CALIB_DIG_H1);
|
||||
|
||||
const int calibLen = 7;
|
||||
uint8_t calibData[calibLen];
|
||||
readRegs(REG_CALIB_DIG_H2_LSB, calibData, calibLen);
|
||||
|
||||
m_dig_H2 = int16_t((calibData[1] << 8) | calibData[0]);
|
||||
|
||||
m_dig_H3 = calibData[2];
|
||||
|
||||
m_dig_H4 = int16_t( (calibData[3] << 4) |
|
||||
(calibData[4] & 0x0f) );
|
||||
|
||||
m_dig_H5 = int16_t( ((calibData[4] & 0xf0) >> 4) |
|
||||
(calibData[5] << 4) );
|
||||
|
||||
m_dig_H6 = int8_t(calibData[6]);
|
||||
|
||||
# if 0
|
||||
cerr << std::dec
|
||||
<< "H1: " << (int)m_dig_H1
|
||||
<< " H2: " << (int)m_dig_H2
|
||||
<< " H3: " << (int)m_dig_H3
|
||||
<< " H4: " << (int)m_dig_H4
|
||||
<< " H5: " << (int)m_dig_H5
|
||||
<< " H6: " << (int)m_dig_H5
|
||||
<< endl;
|
||||
# endif // 0
|
||||
|
||||
// The BMP280 ctor will call it's version of readCalibrationData
|
||||
}
|
||||
|
||||
float BME280::getHumidity()
|
||||
{
|
||||
return m_humidity;
|
||||
return bmp280_get_humidity(m_bmp280);
|
||||
}
|
||||
|
||||
void BME280::setOversampleRateHumidity(OSRS_H_T rate)
|
||||
void BME280::setOversampleRateHumidity(BME280_OSRS_H_T rate)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CTRL_HUM);
|
||||
|
||||
reg &= ~(_CTRL_HUM_OSRS_H_MASK << _CTRL_HUM_OSRS_H_SHIFT);
|
||||
reg |= (rate << _CTRL_HUM_OSRS_H_SHIFT);
|
||||
|
||||
writeReg(REG_CTRL_HUM, reg);
|
||||
bmp280_set_oversample_rate_humidity(m_bmp280, rate);
|
||||
}
|
||||
|
||||
|
||||
void BME280::setUsageMode(USAGE_MODE_T mode)
|
||||
{
|
||||
// Here, we just set the default humidity oversample to 1 and then
|
||||
// call the base method.
|
||||
|
||||
m_humidity = 0;
|
||||
|
||||
// set sleep mode first
|
||||
setMeasureMode(MODE_SLEEP);
|
||||
|
||||
setOversampleRateHumidity(OSRS_H_OVERSAMPLING_1);
|
||||
BMP280::setUsageMode(mode);
|
||||
}
|
||||
|
||||
// This function comes from the BMP180 datasheet, section 4.2.3
|
||||
|
||||
// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format
|
||||
// (22 integer and 10 fractional bits). Output value of “47445”
|
||||
// represents 47445/1024 = 46.333 %RH
|
||||
uint32_t BME280::bme280_compensate_H_int32(int32_t adc_H)
|
||||
{
|
||||
int32_t v_x1_u32r;
|
||||
v_x1_u32r = (m_t_fine - ((int32_t)76800));
|
||||
v_x1_u32r = (((((adc_H << 14) - (((int32_t)m_dig_H4) << 20) - (((int32_t)m_dig_H5) * v_x1_u32r)) +
|
||||
((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)m_dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)m_dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)m_dig_H2) + 8192) >> 14));
|
||||
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)m_dig_H1)) >> 4));
|
||||
v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
|
||||
v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
|
||||
return (int32_t)(v_x1_u32r>>12);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -24,19 +26,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <mraa/i2c.hpp>
|
||||
#include <mraa/spi.hpp>
|
||||
#include <mraa/gpio.hpp>
|
||||
|
||||
#include "interfaces/iHumiditySensor.hpp"
|
||||
|
||||
#include "bmp280.hpp"
|
||||
|
||||
#define BME280_DEFAULT_I2C_BUS 0
|
||||
#define BME280_DEFAULT_SPI_BUS 0
|
||||
#define BME280_DEFAULT_ADDR 0x77
|
||||
#define BME280_DEFAULT_CHIPID 0x60
|
||||
|
||||
namespace upm {
|
||||
|
||||
/**
|
||||
@ -52,13 +45,14 @@ namespace upm {
|
||||
* Temperature Sensor
|
||||
*
|
||||
* The BME280 is as combined digital humidity, pressure and
|
||||
* temperature sensor based on proven sensing principles. The sensor
|
||||
* module is housed in an extremely compact metal-lid LGA package
|
||||
* with a footprint of only 2.5 * 2.5 mm2 with a height of 0.93
|
||||
* mm. Its small dimensions and its low power consumption allow the
|
||||
* implementation in battery driven devices such as handsets, GPS
|
||||
* modules or watches. The BME280 is register and performance
|
||||
* compatible to the Bosch Sensortec BMP280 digital pressure sensor
|
||||
* temperature sensor based on proven sensing principles. The
|
||||
* sensor module is housed in an extremely compact metal-lid LGA
|
||||
* package with a footprint of only 2.5 * 2.5 mm2 with a height of
|
||||
* 0.93 mm. Its small dimensions and its low power consumption
|
||||
* allow the implementation in battery driven devices such as
|
||||
* handsets, GPS modules or watches. The BME280 is register and
|
||||
* performance compatible to the Bosch Sensortec BMP280 digital
|
||||
* pressure sensor.
|
||||
*
|
||||
* @snippet bme280.cxx Interesting
|
||||
*/
|
||||
@ -66,67 +60,13 @@ namespace upm {
|
||||
class BME280 : public BMP280, public IHumiditySensor {
|
||||
public:
|
||||
|
||||
/**
|
||||
* BMP280 registers
|
||||
*/
|
||||
typedef enum : uint8_t {
|
||||
// Do not write into reserved bits.
|
||||
|
||||
// We only specify those registers specific to the BME280. The
|
||||
// rest of them can be found in the BMP280 header file.
|
||||
|
||||
// read-only factory calibration data for humidity
|
||||
|
||||
REG_CALIB_DIG_H1 = 0xa1,
|
||||
|
||||
REG_CALIB_DIG_H2_LSB = 0xe1,
|
||||
REG_CALIB_DIG_H2_MSB = 0xe2,
|
||||
|
||||
REG_CALIB_DIG_H3 = 0xe3,
|
||||
|
||||
REG_CALIB_DIG_H4_0 = 0xe4, // bits 8 -> 11:4
|
||||
REG_CALIB_DIG_H4_1 = 0xe5, // bits 3:0 -> 3:0
|
||||
|
||||
REG_CALIB_DIG_H5_0 = 0xe5, // bits 7:4 -> 3:0
|
||||
REG_CALIB_DIG_H5_1 = 0xe6, // bits 8 -> 11:4
|
||||
|
||||
REG_CALIB_DIG_H6 = 0xe7,
|
||||
|
||||
REG_CTRL_HUM = 0xf2,
|
||||
|
||||
REG_HUMIDITY_MSB = 0xfd,
|
||||
REG_HUMIDITY_LSB = 0xfe
|
||||
} BME280_REGS_T;
|
||||
|
||||
/**
|
||||
* REG_CTRL_HUM bits
|
||||
*/
|
||||
typedef enum {
|
||||
CTRL_HUM_OSRS_H0 = 0x01,
|
||||
CTRL_HUM_OSRS_H1 = 0x02,
|
||||
CTRL_HUM_OSRS_H2 = 0x04,
|
||||
_CTRL_HUM_OSRS_H_MASK = 3,
|
||||
_CTRL_HUM_OSRS_H_SHIFT = 0
|
||||
|
||||
// 0x08-0x80 reserved
|
||||
} CTRL_HUM_T;
|
||||
|
||||
/**
|
||||
* CTRL_HUM_OSRS_H values
|
||||
*/
|
||||
typedef enum {
|
||||
OSRS_H_SKIPPED = 0,
|
||||
OSRS_H_OVERSAMPLING_1 = 1, // x1
|
||||
OSRS_H_OVERSAMPLING_2 = 2, // x2
|
||||
OSRS_H_OVERSAMPLING_4 = 3,
|
||||
OSRS_H_OVERSAMPLING_8 = 4,
|
||||
OSRS_H_OVERSAMPLING_16 = 5
|
||||
} OSRS_H_T;
|
||||
|
||||
|
||||
/**
|
||||
* BME280 constructor.
|
||||
*
|
||||
* This driver supports both the BMP280 and the BME280. The
|
||||
* BME280 adds a humidity sensor. The device type is detected
|
||||
* automatically by querying the chip id register.
|
||||
*
|
||||
* This device can support both I2C and SPI. For SPI, set the addr
|
||||
* to -1, and specify a positive integer representing the Chip
|
||||
* Select (CS) pin for the cs argument. If you are using a
|
||||
@ -135,13 +75,13 @@ namespace upm {
|
||||
* operating mode is I2C.
|
||||
*
|
||||
* @param bus I2C or SPI bus to use.
|
||||
* @param address The address for this device. -1 for SPI.
|
||||
* @param cs The gpio pin to use for the SPI Chip Select. -1 for
|
||||
* I2C or for SPI with a hardware controlled pin.
|
||||
* @param theChipID The chip ID used for validation
|
||||
* @param address The I2C address for this device. Use -1 for SPI.
|
||||
* @param cs The gpio pin to use for the SPI Chip Select. Use -1
|
||||
* for I2C, or for SPI with a hardware controlled pin.
|
||||
* @throws std::runtime_error on failure.
|
||||
*/
|
||||
BME280(int bus=BME280_DEFAULT_I2C_BUS, int addr=BME280_DEFAULT_ADDR,
|
||||
int cs=-1, uint8_t theChipID=BME280_DEFAULT_CHIPID);
|
||||
int cs=-1);
|
||||
|
||||
/**
|
||||
* BME280 Destructor.
|
||||
@ -149,28 +89,15 @@ namespace upm {
|
||||
virtual ~BME280();
|
||||
|
||||
/**
|
||||
* Update the internal stored values from sensor data.
|
||||
*/
|
||||
virtual void update();
|
||||
|
||||
/**
|
||||
* Return the current measured relative humidity. update() must
|
||||
* have been called prior to calling this method.
|
||||
* Return the current measured relative humidity. update()
|
||||
* must have been called prior to calling this method. If the
|
||||
* device is a bmp280 rather than a bme280, this method will
|
||||
* always return 0.
|
||||
*
|
||||
* @return The relative humidity in percent..
|
||||
* @return The relative humidity in percent.
|
||||
*/
|
||||
float getHumidity();
|
||||
|
||||
/**
|
||||
* Set a general usage mode. This function can be used to
|
||||
* configure the filters and oversampling for a particular use
|
||||
* case. These settings are documented in the BMP280 and BME280
|
||||
* datasheets.
|
||||
*
|
||||
* @param mode One of the USAGE_MODE_T values.
|
||||
*/
|
||||
virtual void setUsageMode(USAGE_MODE_T mode);
|
||||
|
||||
/**
|
||||
* Set the humidity sensor oversampling parameter. See the data
|
||||
* sheet for details. This value can be automatically set to a
|
||||
@ -179,7 +106,7 @@ namespace upm {
|
||||
*
|
||||
* @param mode One of the OSRS_H_T values.
|
||||
*/
|
||||
void setOversampleRateHumidity(OSRS_H_T rate);
|
||||
void setOversampleRateHumidity(BME280_OSRS_H_T rate);
|
||||
|
||||
// Interface support
|
||||
const char *getModuleName()
|
||||
@ -193,23 +120,7 @@ namespace upm {
|
||||
};
|
||||
|
||||
protected:
|
||||
// relative humidity
|
||||
float m_humidity;
|
||||
|
||||
// read the calibration data
|
||||
virtual void readCalibrationData();
|
||||
|
||||
private:
|
||||
// calibration data humidity
|
||||
uint8_t m_dig_H1;
|
||||
int16_t m_dig_H2;
|
||||
uint8_t m_dig_H3;
|
||||
int16_t m_dig_H4;
|
||||
int16_t m_dig_H5;
|
||||
int8_t m_dig_H6;
|
||||
|
||||
// Bosch supplied conversion/compensation functions from the
|
||||
// datasheet.
|
||||
uint32_t bme280_compensate_H_int32(int32_t adc_H);
|
||||
};
|
||||
}
|
||||
|
778
src/bmp280/bmp280.c
Normal file
778
src/bmp280/bmp280.c
Normal file
@ -0,0 +1,778 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <upm_utilities.h>
|
||||
|
||||
#include "bmp280.h"
|
||||
|
||||
// number of bytes of stored calibration data (bmp280)
|
||||
#define BMP280_CALIBRATION_BYTES (26)
|
||||
// BME280 has these additional calibration regs
|
||||
#define BME280_CALIBRATION_BYTES (7)
|
||||
|
||||
// Number of bytes to get bmp280 data
|
||||
#define BMP280_DATA_LEN (6)
|
||||
// Number of bytes to get bme280 data
|
||||
#define BME280_DATA_LEN (2)
|
||||
|
||||
// Uncomment the following to use test data as specified in the
|
||||
// datasheet, section 3.12. This really only tests the compensation
|
||||
// algorithm, and only for the bmp280 parts (temperature/pressure).
|
||||
|
||||
// #define BMP280_USE_TEST_DATA
|
||||
|
||||
// SPI CS on and off functions
|
||||
static void _csOn(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->gpio)
|
||||
mraa_gpio_write(dev->gpio, 0);
|
||||
}
|
||||
|
||||
static void _csOff(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->gpio)
|
||||
mraa_gpio_write(dev->gpio, 1);
|
||||
}
|
||||
|
||||
// These functions come from the BMP280 datasheet, section 3.11.3
|
||||
|
||||
// Returns temperature in DegC, resolution is 0.01 DegC. Output value
|
||||
// of "5123" equals 51.23 DegC. t_fine carries fine temperature as
|
||||
// global value
|
||||
static int32_t _bmp280_compensate_T_int32(const bmp280_context dev,
|
||||
int32_t adc_T)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
int32_t var1, var2, T;
|
||||
var1 = ((((adc_T>>3) - ((int32_t)dev->dig_T1<<1))) * ((int32_t)dev->dig_T2)) >> 11;
|
||||
var2 = (((((adc_T>>4) - ((int32_t)dev->dig_T1)) * ((adc_T>>4) - ((int32_t)dev->dig_T1))) >> 12) *
|
||||
((int32_t)dev->dig_T3)) >> 14;
|
||||
dev->t_fine = var1 + var2;
|
||||
T = (dev->t_fine * 5 + 128) >> 8;
|
||||
return T;
|
||||
}
|
||||
|
||||
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format
|
||||
// (24 integer bits and 8 fractional bits). Output value of
|
||||
// “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
|
||||
static uint32_t _bmp280_compensate_P_int64(const bmp280_context dev,
|
||||
int32_t adc_P)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
int64_t var1, var2, p;
|
||||
var1 = ((int64_t)dev->t_fine) - 128000;
|
||||
var2 = var1 * var1 * (int64_t)dev->dig_P6;
|
||||
var2 = var2 + ((var1*(int64_t)dev->dig_P5)<<17);
|
||||
var2 = var2 + (((int64_t)dev->dig_P4)<<35);
|
||||
var1 = ((var1 * var1 * (int64_t)dev->dig_P3)>>8) + ((var1 * (int64_t)dev->dig_P2)<<12);
|
||||
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)dev->dig_P1)>>33;
|
||||
if (var1 == 0)
|
||||
{
|
||||
return 0; // avoid exception caused by division by zero
|
||||
}
|
||||
p = 1048576-adc_P;
|
||||
p = (((p<<31)-var2)*3125)/var1;
|
||||
var1 = (((int64_t)dev->dig_P9) * (p>>13) * (p>>13)) >> 25;
|
||||
var2 = (((int64_t)dev->dig_P8) * p) >> 19;
|
||||
p = ((p + var1 + var2) >> 8) + (((int64_t)dev->dig_P7)<<4);
|
||||
return (uint32_t)p;
|
||||
}
|
||||
|
||||
// This function comes from the BME280 datasheet, section 4.2.3
|
||||
// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format
|
||||
// (22 integer and 10 fractional bits). Output value of “47445”
|
||||
// represents 47445/1024 = 46.333 %RH
|
||||
// BME280 only
|
||||
static uint32_t _bme280_compensate_H_int32(const bmp280_context dev,
|
||||
int32_t adc_H)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
int32_t v_x1_u32r;
|
||||
v_x1_u32r = (dev->t_fine - ((int32_t)76800));
|
||||
v_x1_u32r = (((((adc_H << 14) - (((int32_t)dev->dig_H4) << 20) - (((int32_t)dev->dig_H5) * v_x1_u32r)) +
|
||||
((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)dev->dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)dev->dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)dev->dig_H2) + 8192) >> 14));
|
||||
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)dev->dig_H1)) >> 4));
|
||||
v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
|
||||
v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
|
||||
return (int32_t)(v_x1_u32r>>12);
|
||||
}
|
||||
|
||||
// read the calibration data
|
||||
static upm_result_t _read_calibration_data(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
#if defined(BMP280_USE_TEST_DATA)
|
||||
printf("%s: WARNING: Test data is being used\n", __FUNCTIOM__);
|
||||
|
||||
// This data is taken from the datasheet, section 3.12
|
||||
dev->dig_T1 = 27504;
|
||||
dev->dig_T2 = 26435;
|
||||
dev->dig_T3 = -1000;
|
||||
|
||||
dev->dig_P1 = 36477;
|
||||
dev->dig_P2 = -10685;
|
||||
dev->dig_P3 = 3024;
|
||||
dev->dig_P4 = 2855;
|
||||
dev->dig_P5 = 140;
|
||||
dev->dig_P6 = -7;
|
||||
dev->dig_P7 = 15500;
|
||||
dev->dig_P8 = -14600;
|
||||
dev->dig_P9 = 6000;
|
||||
|
||||
// BME280 does not have any test data....
|
||||
dev->dig_H1 = 0;
|
||||
dev->dig_H2 = 0;
|
||||
dev->dig_H3 = 0;
|
||||
dev->dig_H4 = 0;
|
||||
dev->dig_H5 = 0;
|
||||
dev->dig_H6 = 0;
|
||||
|
||||
#else
|
||||
|
||||
// bmp280...
|
||||
uint8_t calibData[BMP280_CALIBRATION_BYTES];
|
||||
int rv;
|
||||
if ( (rv = bmp280_read_regs(dev, BMP280_REG_CALIB00, calibData,
|
||||
BMP280_CALIBRATION_BYTES))
|
||||
!= BMP280_CALIBRATION_BYTES)
|
||||
{
|
||||
printf("%s: bmp280_read_regs(BMP280) failed.",
|
||||
__FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
dev->dig_T1 = (uint16_t)((calibData[1] << 8) | calibData[0]);
|
||||
dev->dig_T2 = (int16_t)((calibData[3] << 8) | calibData[2]);
|
||||
dev->dig_T3 = (int16_t)((calibData[5] << 8) | calibData[4]);
|
||||
|
||||
dev->dig_P1 = (uint16_t)((calibData[7] << 8) | calibData[6]);
|
||||
dev->dig_P2 = (int16_t)((calibData[9] << 8) | calibData[8]);
|
||||
dev->dig_P3 = (int16_t)((calibData[11] << 8) | calibData[10]);
|
||||
dev->dig_P4 = (int16_t)((calibData[13] << 8) | calibData[12]);
|
||||
dev->dig_P5 = (int16_t)((calibData[15] << 8) | calibData[14]);
|
||||
dev->dig_P6 = (int16_t)((calibData[17] << 8) | calibData[16]);
|
||||
dev->dig_P7 = (int16_t)((calibData[19] << 8) | calibData[18]);
|
||||
dev->dig_P8 = (int16_t)((calibData[21] << 8) | calibData[20]);
|
||||
dev->dig_P9 = (int16_t)((calibData[23] << 8) | calibData[22]);
|
||||
|
||||
// bme280... (humidity calibration data)
|
||||
if (dev->isBME)
|
||||
{
|
||||
dev->dig_H1 = bmp280_read_reg(dev, BME280_REG_CALIB_DIG_H1);
|
||||
|
||||
uint8_t hCalibData[BME280_CALIBRATION_BYTES];
|
||||
if ( (rv = bmp280_read_regs(dev, BME280_REG_CALIB_DIG_H2_LSB,
|
||||
hCalibData,
|
||||
BME280_CALIBRATION_BYTES))
|
||||
!= BME280_CALIBRATION_BYTES)
|
||||
{
|
||||
printf("%s: bmp280_read_regs(BME280) failed.",
|
||||
__FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
dev->dig_H2 = (int16_t)((hCalibData[1] << 8) | hCalibData[0]);
|
||||
|
||||
dev->dig_H3 = hCalibData[2];
|
||||
|
||||
dev->dig_H4 = (int16_t)( (hCalibData[3] << 4) |
|
||||
(hCalibData[4] & 0x0f) );
|
||||
|
||||
dev->dig_H5 = (int16_t)( ((hCalibData[4] & 0xf0) >> 4) |
|
||||
(hCalibData[5] << 4) );
|
||||
|
||||
dev->dig_H6 = (int8_t)(hCalibData[6]);
|
||||
}
|
||||
#endif // defined(BMP280_USE_TEST_DATA)
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
bmp280_context bmp280_init(int bus, int addr, int cs)
|
||||
{
|
||||
bmp280_context dev =
|
||||
(bmp280_context)malloc(sizeof(struct _bmp280_context));
|
||||
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
// zero out context
|
||||
memset((void *)dev, 0, sizeof(struct _bmp280_context));
|
||||
|
||||
// make sure MRAA is initialized
|
||||
if (mraa_init() != MRAA_SUCCESS)
|
||||
{
|
||||
printf("%s: mraa_init() failed.\n", __FUNCTION__);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (addr < 0)
|
||||
dev->isSPI = true;
|
||||
|
||||
if (dev->isSPI)
|
||||
{
|
||||
if (!(dev->spi = mraa_spi_init(bus)))
|
||||
{
|
||||
printf("%s: mraa_spi_init() failed.\n", __FUNCTION__);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Only create cs context if we are actually using a valid pin.
|
||||
// A hardware controlled pin should specify cs as -1.
|
||||
if (cs >= 0)
|
||||
{
|
||||
if (!(dev->gpio = mraa_gpio_init(cs)))
|
||||
{
|
||||
printf("%s: mraa_gpio_init() failed.\n", __FUNCTION__);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
mraa_gpio_dir(dev->gpio, MRAA_GPIO_OUT);
|
||||
}
|
||||
|
||||
mraa_spi_mode(dev->spi, MRAA_SPI_MODE0);
|
||||
if (mraa_spi_frequency(dev->spi, 5000000))
|
||||
{
|
||||
printf("%s: mraa_spi_frequency() failed.\n", __FUNCTION__);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// toggle CS on/off so chip switches into SPI mode. For a hw
|
||||
// CS pin, the first SPI transaction should accomplish this.
|
||||
_csOn(dev);
|
||||
upm_delay_ms(10);
|
||||
_csOff(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
// I2C
|
||||
|
||||
if (!(dev->i2c = mraa_i2c_init(bus)))
|
||||
{
|
||||
printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mraa_i2c_address(dev->i2c, addr))
|
||||
{
|
||||
printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// check the chip id
|
||||
|
||||
uint8_t chipID = bmp280_read_reg(dev, BMP280_REG_CHIPID);
|
||||
|
||||
switch(chipID)
|
||||
{
|
||||
case BMP280_CHIPID: // BMP280
|
||||
dev->isBME = false;
|
||||
break;
|
||||
|
||||
case BME280_CHIPID: // BME280
|
||||
dev->isBME = true;
|
||||
break;
|
||||
|
||||
default: // ??
|
||||
printf("%s: invalid chip id: %02x. Expected either %02x "
|
||||
"(bmp280) or %02x (bme280)\n",
|
||||
__FUNCTION__, chipID, BMP280_CHIPID, BME280_CHIPID);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set sleep mode for now
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_SLEEP);
|
||||
|
||||
// read calibration data
|
||||
if (_read_calibration_data(dev))
|
||||
{
|
||||
printf("%s: _read_calibration_data() failed.", __FUNCTION__);
|
||||
bmp280_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set the default mode to the highest resolution mode
|
||||
bmp280_set_usage_mode(dev, BMP280_USAGE_MODE_INDOOR_NAV);
|
||||
|
||||
// set the default sea level pressure in hPA
|
||||
dev->sea_level_hPA = BMP280_SEA_LEVEL_HPA;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void bmp280_close(bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->i2c)
|
||||
mraa_i2c_stop(dev->i2c);
|
||||
|
||||
if (dev->spi)
|
||||
mraa_spi_stop(dev->spi);
|
||||
|
||||
if (dev->gpio)
|
||||
mraa_gpio_close(dev->gpio);
|
||||
}
|
||||
|
||||
upm_result_t bmp280_update(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
int32_t temp = 0;
|
||||
int32_t pres = 0;
|
||||
|
||||
uint8_t bmp_data[BMP280_DATA_LEN];
|
||||
memset(bmp_data, 0, BMP280_DATA_LEN);
|
||||
|
||||
// If we are using a forced mode, then we need to manually trigger
|
||||
// the measurement and wait for it to complete.
|
||||
|
||||
if (dev->mode == BMP280_MODE_FORCED)
|
||||
{
|
||||
// bmp280 measure mode will return to sleep after completion...
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_FORCED);
|
||||
|
||||
uint8_t stat;
|
||||
do
|
||||
{
|
||||
upm_delay_ms(10);
|
||||
stat = bmp280_get_status(dev);
|
||||
} while (stat & BMP280_STATUS_MEASURING);
|
||||
}
|
||||
|
||||
int rv;
|
||||
if ((rv = bmp280_read_regs(dev, BMP280_REG_PRESSURE_MSB,
|
||||
bmp_data, BMP280_DATA_LEN))
|
||||
!= BMP280_DATA_LEN)
|
||||
{
|
||||
printf("%s: bmp280_read_regs() failed.", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
// 20 bits unsigned stored in a 32bit signed quantity
|
||||
|
||||
#if defined(BMP280_USE_TEST_DATA)
|
||||
// taken from datasheet, section 3.12
|
||||
temp = 519888;
|
||||
pres = 415148;
|
||||
#else
|
||||
temp = ( (bmp_data[5] >> 4) | (bmp_data[4] << 4) | (bmp_data[3] << 12) );
|
||||
pres = ( (bmp_data[2] >> 4) | (bmp_data[1] << 4) | (bmp_data[0] << 12) );
|
||||
#endif
|
||||
|
||||
dev->temperature = (float)_bmp280_compensate_T_int32(dev, temp);
|
||||
dev->temperature /= 100.0;
|
||||
|
||||
dev->pressure = (float)_bmp280_compensate_P_int64(dev, pres);
|
||||
dev->pressure /= 256.0;
|
||||
|
||||
// BME280?
|
||||
if (dev->isBME)
|
||||
{
|
||||
uint8_t bme_data[BME280_DATA_LEN];
|
||||
|
||||
memset(bme_data, 0, BME280_DATA_LEN);
|
||||
|
||||
if ((rv = bmp280_read_regs(dev, BME280_REG_HUMIDITY_MSB,
|
||||
bme_data, BME280_DATA_LEN))
|
||||
!= BME280_DATA_LEN)
|
||||
{
|
||||
printf("%s: bmp280_read_regs(BME280) failed.",
|
||||
__FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
// 20 bits unsigned stored in a 32bit signed quantity
|
||||
int32_t hum = ( (bme_data[0] << 8) | bme_data[1] );
|
||||
|
||||
dev->humidity = (float)_bme280_compensate_H_int32(dev, hum);
|
||||
dev->humidity /= 1024.0;
|
||||
}
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
void bmp280_set_sea_level_pressure(const bmp280_context dev,
|
||||
float seaLevelhPA)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
dev->sea_level_hPA = seaLevelhPA;
|
||||
}
|
||||
|
||||
float bmp280_get_altitude(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
// adapted from the US NOAA pdf: pressureAltitude.pdf
|
||||
return 44307.69 * (1.0 - pow((dev->pressure/100.0)
|
||||
/ dev->sea_level_hPA, 0.190284));
|
||||
}
|
||||
|
||||
uint8_t bmp280_read_reg(const bmp280_context dev, uint8_t reg)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->isSPI)
|
||||
{
|
||||
reg |= 0x80; // needed for read
|
||||
uint8_t pkt[2] = {reg, 0};
|
||||
|
||||
_csOn(dev);
|
||||
if (mraa_spi_transfer_buf(dev->spi, pkt, pkt, 2))
|
||||
{
|
||||
_csOff(dev);
|
||||
printf("%s: mraa_spi_transfer_buf() failed.",
|
||||
__FUNCTION__);
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
_csOff(dev);
|
||||
|
||||
return pkt[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return (uint8_t)mraa_i2c_read_byte_data(dev->i2c, reg);
|
||||
}
|
||||
}
|
||||
|
||||
int bmp280_read_regs(const bmp280_context dev,
|
||||
uint8_t reg, uint8_t *buffer, int len)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->isSPI)
|
||||
{
|
||||
reg |= 0x80; // needed for read
|
||||
|
||||
uint8_t sbuf[len + 1];
|
||||
memset((char *)sbuf, 0, len + 1);
|
||||
sbuf[0] = reg;
|
||||
|
||||
// We need to do it this way for edison - ie: use a single
|
||||
// transfer rather than breaking it up into two like we used
|
||||
// to, since we have no control over CS. This means a buffer
|
||||
// copy is now required, but that's the way it goes.
|
||||
|
||||
_csOn(dev);
|
||||
if (mraa_spi_transfer_buf(dev->spi, sbuf, sbuf, len + 1))
|
||||
{
|
||||
_csOff(dev);
|
||||
printf("%s: mraa_spi_transfer_buf() failed.",
|
||||
__FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
_csOff(dev);
|
||||
|
||||
// now copy it into user buffer
|
||||
for (int i=0; i<len; i++)
|
||||
buffer[i] = sbuf[i + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mraa_i2c_read_bytes_data(dev->i2c, reg, buffer, len) != len)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
upm_result_t bmp280_write_reg(const bmp280_context dev,
|
||||
uint8_t reg, uint8_t val)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->isSPI)
|
||||
{
|
||||
reg &= 0x7f; // mask off 0x80 for writing
|
||||
uint8_t pkt[2] = {reg, val};
|
||||
|
||||
_csOn(dev);
|
||||
if (mraa_spi_transfer_buf(dev->spi, pkt, NULL, 2))
|
||||
{
|
||||
_csOff(dev);
|
||||
printf("%s: mraa_spi_transfer_buf() failed.",
|
||||
__FUNCTION__);
|
||||
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
_csOff(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mraa_i2c_write_byte_data(dev->i2c, val, reg))
|
||||
{
|
||||
printf("%s: mraa_i2c_write_byte_data() failed.",
|
||||
__FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t bmp280_get_chip_id(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
return bmp280_read_reg(dev, BMP280_REG_CHIPID);
|
||||
}
|
||||
|
||||
void bmp280_reset(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
bmp280_write_reg(dev, BMP280_REG_RESET, BMP280_RESET_BYTE);
|
||||
upm_delay(1);
|
||||
}
|
||||
|
||||
float bmp280_get_temperature(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
return dev->temperature;
|
||||
}
|
||||
|
||||
float bmp280_get_pressure(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
return dev->pressure;
|
||||
}
|
||||
|
||||
// BME280 only
|
||||
float bmp280_get_humidity(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->isBME)
|
||||
return dev->humidity;
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void bmp280_set_filter(const bmp280_context dev, BMP280_FILTER_T filter)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
uint8_t reg = bmp280_read_reg(dev, BMP280_REG_CONFIG);
|
||||
|
||||
reg &= ~(_BMP280_CONFIG_FILTER_MASK << _BMP280_CONFIG_FILTER_SHIFT);
|
||||
reg |= (filter << _BMP280_CONFIG_FILTER_SHIFT);
|
||||
|
||||
bmp280_write_reg(dev, BMP280_REG_CONFIG, reg);
|
||||
}
|
||||
|
||||
void bmp280_set_timer_standby(const bmp280_context dev,
|
||||
BMP280_T_SB_T tsb)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
uint8_t reg = bmp280_read_reg(dev, BMP280_REG_CONFIG);
|
||||
|
||||
reg &= ~(_BMP280_CONFIG_T_SB_MASK << _BMP280_CONFIG_T_SB_SHIFT);
|
||||
reg |= (tsb << _BMP280_CONFIG_T_SB_SHIFT);
|
||||
|
||||
bmp280_write_reg(dev, BMP280_REG_CONFIG, reg);
|
||||
}
|
||||
|
||||
void bmp280_set_measure_mode(const bmp280_context dev,
|
||||
BMP280_MODES_T mode)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
uint8_t reg = bmp280_read_reg(dev, BMP280_REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_BMP280_CTRL_MEAS_MODE_MASK << _BMP280_CTRL_MEAS_MODE_SHIFT);
|
||||
reg |= (mode << _BMP280_CTRL_MEAS_MODE_SHIFT);
|
||||
|
||||
bmp280_write_reg(dev, BMP280_REG_CTRL_MEAS, reg);
|
||||
dev->mode = mode;
|
||||
}
|
||||
|
||||
void bmp280_set_oversample_rate_pressure(const bmp280_context dev,
|
||||
BMP280_OSRS_P_T rate)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
uint8_t reg = bmp280_read_reg(dev, BMP280_REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_BMP280_CTRL_MEAS_OSRS_P_MASK << _BMP280_CTRL_MEAS_OSRS_P_SHIFT);
|
||||
reg |= (rate << _BMP280_CTRL_MEAS_OSRS_P_SHIFT);
|
||||
|
||||
bmp280_write_reg(dev, BMP280_REG_CTRL_MEAS, reg);
|
||||
}
|
||||
|
||||
void bmp280_set_oversample_rate_temperature(const bmp280_context dev,
|
||||
BMP280_OSRS_T_T rate)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
uint8_t reg = bmp280_read_reg(dev, BMP280_REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_BMP280_CTRL_MEAS_OSRS_T_MASK << _BMP280_CTRL_MEAS_OSRS_T_SHIFT);
|
||||
reg |= (rate << _BMP280_CTRL_MEAS_OSRS_T_SHIFT);
|
||||
|
||||
bmp280_write_reg(dev, BMP280_REG_CTRL_MEAS, reg);
|
||||
}
|
||||
|
||||
// bme280 only
|
||||
void bmp280_set_oversample_rate_humidity(const bmp280_context dev,
|
||||
BME280_OSRS_H_T rate)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
if (dev->isBME)
|
||||
{
|
||||
uint8_t reg = bmp280_read_reg(dev, BME280_REG_CTRL_HUM);
|
||||
|
||||
reg &= ~(_BME280_CTRL_HUM_OSRS_H_MASK << _BME280_CTRL_HUM_OSRS_H_SHIFT);
|
||||
reg |= (rate << _BME280_CTRL_HUM_OSRS_H_SHIFT);
|
||||
|
||||
bmp280_write_reg(dev, BME280_REG_CTRL_HUM, reg);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t bmp280_get_status(const bmp280_context dev)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
return bmp280_read_reg(dev, BMP280_REG_STATUS);
|
||||
}
|
||||
|
||||
void bmp280_set_usage_mode(const bmp280_context dev, BMP280_USAGE_MODE_T mode)
|
||||
{
|
||||
assert(dev != NULL);
|
||||
|
||||
// set up the regs for the given usage mode. These settings come
|
||||
// from the recomendations in the BMP280 datasheet, section 3.4
|
||||
// Filter Selection.
|
||||
|
||||
dev->temperature = 0;
|
||||
dev->pressure = 0;
|
||||
dev->humidity = 0;
|
||||
|
||||
// set sleep mode first
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_SLEEP);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case BMP280_USAGE_MODE_HANDHELD_LOW_POWER:
|
||||
bmp280_set_oversample_rate_pressure(dev,
|
||||
BMP280_OSRS_P_OVERSAMPLING_16);
|
||||
bmp280_set_oversample_rate_temperature(dev,
|
||||
BMP280_OSRS_T_OVERSAMPLING_2);
|
||||
bmp280_set_oversample_rate_humidity(dev,
|
||||
BME280_OSRS_H_OVERSAMPLING_1);
|
||||
bmp280_set_filter(dev, BMP280_FILTER_4);
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case BMP280_USAGE_MODE_HANDHELD_DYNAMIC:
|
||||
bmp280_set_oversample_rate_pressure(dev,
|
||||
BMP280_OSRS_P_OVERSAMPLING_4);
|
||||
bmp280_set_oversample_rate_temperature(dev,
|
||||
BMP280_OSRS_T_OVERSAMPLING_1);
|
||||
bmp280_set_oversample_rate_humidity(dev,
|
||||
BME280_OSRS_H_OVERSAMPLING_1);
|
||||
bmp280_set_filter(dev, BMP280_FILTER_16);
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case BMP280_USAGE_MODE_WEATHER_MONITOR:
|
||||
bmp280_set_oversample_rate_pressure(dev,
|
||||
BMP280_OSRS_P_OVERSAMPLING_1);
|
||||
bmp280_set_oversample_rate_temperature(dev,
|
||||
BMP280_OSRS_T_OVERSAMPLING_1);
|
||||
bmp280_set_oversample_rate_humidity(dev,
|
||||
BME280_OSRS_H_OVERSAMPLING_1);
|
||||
bmp280_set_filter(dev, BMP280_FILTER_OFF);
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_FORCED);
|
||||
|
||||
break;
|
||||
|
||||
case BMP280_USAGE_MODE_FLOOR_CHG_DETECT:
|
||||
bmp280_set_oversample_rate_pressure(dev,
|
||||
BMP280_OSRS_P_OVERSAMPLING_4);
|
||||
bmp280_set_oversample_rate_temperature(dev,
|
||||
BMP280_OSRS_T_OVERSAMPLING_1);
|
||||
bmp280_set_oversample_rate_humidity(dev,
|
||||
BME280_OSRS_H_OVERSAMPLING_1);
|
||||
bmp280_set_filter(dev, BMP280_FILTER_4);
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case BMP280_USAGE_MODE_DROP_DETECT:
|
||||
bmp280_set_oversample_rate_pressure(dev,
|
||||
BMP280_OSRS_P_OVERSAMPLING_2);
|
||||
bmp280_set_oversample_rate_temperature(dev,
|
||||
BMP280_OSRS_T_OVERSAMPLING_1);
|
||||
bmp280_set_oversample_rate_humidity(dev,
|
||||
BME280_OSRS_H_OVERSAMPLING_1);
|
||||
bmp280_set_filter(dev, BMP280_FILTER_OFF);
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case BMP280_USAGE_MODE_INDOOR_NAV:
|
||||
bmp280_set_oversample_rate_pressure(dev,
|
||||
BMP280_OSRS_P_OVERSAMPLING_16);
|
||||
bmp280_set_oversample_rate_temperature(dev,
|
||||
BMP280_OSRS_T_OVERSAMPLING_2);
|
||||
bmp280_set_oversample_rate_humidity(dev,
|
||||
BME280_OSRS_H_OVERSAMPLING_1);
|
||||
bmp280_set_filter(dev, BMP280_FILTER_16);
|
||||
bmp280_set_measure_mode(dev, BMP280_MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%s: invalid usage mode specified, mode unchanged.",
|
||||
__FUNCTION__);
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -26,546 +28,125 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bmp280.hpp"
|
||||
|
||||
using namespace upm;
|
||||
using namespace std;
|
||||
|
||||
// Uncomment the following to use test data as specified in the
|
||||
// datasheet, section 3.12. This really only tests the compensation
|
||||
// algorithm.
|
||||
|
||||
// #define BMP280_USE_TEST_DATA
|
||||
|
||||
// conversion from fahrenheit to celsius and back
|
||||
// conversion from Celsius to Fahrenheit.
|
||||
|
||||
static float c2f(float c)
|
||||
{
|
||||
return (c * (9.0 / 5.0) + 32.0);
|
||||
}
|
||||
|
||||
BMP280::BMP280(int bus, int addr, int cs, uint8_t theChipID) :
|
||||
m_i2c(0), m_spi(0), m_gpioCS(0)
|
||||
{
|
||||
|
||||
m_addr = addr;
|
||||
|
||||
m_temperature = 0;
|
||||
m_pressure = 0;
|
||||
m_isSPI = false;
|
||||
|
||||
clearData();
|
||||
|
||||
if (addr < 0)
|
||||
m_isSPI = true;
|
||||
|
||||
mraa::Result rv;
|
||||
|
||||
if (m_isSPI)
|
||||
{
|
||||
m_spi = new mraa::Spi(bus);
|
||||
|
||||
// Only create cs context if we are actually using a valid pin.
|
||||
// A hardware controlled pin should specify cs as -1.
|
||||
if (cs >= 0)
|
||||
{
|
||||
m_gpioCS = new mraa::Gpio(cs);
|
||||
m_gpioCS->dir(mraa::DIR_OUT);
|
||||
}
|
||||
|
||||
m_spi->mode(mraa::SPI_MODE0);
|
||||
m_spi->frequency(5000000);
|
||||
|
||||
// toggle it on/off so chip switches into SPI mode. For a hw CS
|
||||
// pin, the first SPI transaction should accomplish this.
|
||||
csOn();
|
||||
usleep(10000);
|
||||
csOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
// I2C
|
||||
m_i2c = new mraa::I2c(bus);
|
||||
|
||||
if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS)
|
||||
{
|
||||
throw std::runtime_error(string(__FUNCTION__) +
|
||||
": I2c.address() failed");
|
||||
}
|
||||
}
|
||||
|
||||
// check the chip id
|
||||
|
||||
uint8_t chipID = readReg(REG_CHIPID);
|
||||
if (chipID != theChipID)
|
||||
BMP280::BMP280(int bus, int addr, int cs) :
|
||||
m_bmp280(bmp280_init(bus, addr, cs))
|
||||
{
|
||||
if (!m_bmp280)
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": invalid chip ID. Expected "
|
||||
+ std::to_string(int(theChipID))
|
||||
+ ", got "
|
||||
+ std::to_string(int(chipID)));
|
||||
}
|
||||
|
||||
// set sleep mode for now
|
||||
setMeasureMode(MODE_SLEEP);
|
||||
|
||||
// read calibration data
|
||||
readCalibrationData();
|
||||
|
||||
// set the default mode to the highest resolution mode
|
||||
setUsageMode(USAGE_MODE_INDOOR_NAV);
|
||||
+ ": bmp280_init() failed");
|
||||
}
|
||||
|
||||
BMP280::~BMP280()
|
||||
{
|
||||
if (m_i2c)
|
||||
delete m_i2c;
|
||||
|
||||
if (m_spi)
|
||||
delete m_spi;
|
||||
|
||||
if (m_gpioCS)
|
||||
delete m_gpioCS;
|
||||
bmp280_close(m_bmp280);
|
||||
}
|
||||
|
||||
void BMP280::update()
|
||||
{
|
||||
int32_t temp = 0;
|
||||
int32_t pres = 0;
|
||||
|
||||
const int dataLen = 6;
|
||||
uint8_t data[dataLen];
|
||||
memset(data, 0, dataLen);
|
||||
|
||||
// If we are using a forced mode, then we need to manually trigger
|
||||
// the measurement, and wait for it to complete.
|
||||
|
||||
if (m_mode == MODE_FORCED)
|
||||
{
|
||||
// bmp280 measure mode will return to sleep after completion...
|
||||
setMeasureMode(MODE_FORCED);
|
||||
|
||||
uint8_t stat;
|
||||
do
|
||||
{
|
||||
usleep(10000); // 10ms
|
||||
stat = readReg(REG_STATUS);
|
||||
} while (stat & STATUS_MEASURING);
|
||||
if (bmp280_update(m_bmp280))
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": bmp280_update() failed");
|
||||
}
|
||||
|
||||
int rv;
|
||||
if ((rv = readRegs(REG_PRESSURE_MSB, data, dataLen)) != dataLen)
|
||||
void BMP280::setSeaLevelPreassure(float seaLevelhPA)
|
||||
{
|
||||
throw std::runtime_error(std::string(__FUNCTION__)
|
||||
+ ": readRegs() failed, returned "
|
||||
+ std::to_string(rv));
|
||||
bmp280_set_sea_level_pressure(m_bmp280, seaLevelhPA);
|
||||
}
|
||||
|
||||
// 20 bits unsigned stored in a 32bit signed quanty
|
||||
|
||||
#if defined(BMP280_USE_TEST_DATA)
|
||||
// taken from datasheet, section 3.12
|
||||
temp = 519888;
|
||||
pres = 415148;
|
||||
#else
|
||||
temp = ( (data[5] >> 4) | (data[4] << 4) | (data[3] << 12) );
|
||||
pres = ( (data[2] >> 4) | (data[1] << 4) | (data[0] << 12) );
|
||||
#endif
|
||||
|
||||
m_temperature = float(bmp280_compensate_T_int32(temp));
|
||||
m_temperature /= 100.0;
|
||||
|
||||
m_pressure = float(bmp280_compensate_P_int64(pres));
|
||||
m_pressure /= 256.0;
|
||||
}
|
||||
|
||||
float BMP280::getAltitude(float sealLevelhPA)
|
||||
float BMP280::getAltitude()
|
||||
{
|
||||
// adapted from the NOAA pdf: pressureAltitude.pdf
|
||||
return 44307.69 * (1.0 - pow((m_pressure/100.0) / sealLevelhPA, 0.190284));
|
||||
return bmp280_get_altitude(m_bmp280);
|
||||
}
|
||||
|
||||
uint8_t BMP280::readReg(uint8_t reg)
|
||||
{
|
||||
if (m_isSPI)
|
||||
{
|
||||
reg |= 0x80; // needed for read
|
||||
uint8_t pkt[2] = {reg, 0};
|
||||
|
||||
csOn();
|
||||
if (m_spi->transfer(pkt, pkt, 2))
|
||||
{
|
||||
csOff();
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": Spi.transfer() failed");
|
||||
}
|
||||
csOff();
|
||||
|
||||
#if 0
|
||||
cerr << "readReg: " << std::hex << "p0: " << (int)pkt[0] << " p1: "
|
||||
<< (int)pkt[1] << endl;
|
||||
#endif // 0
|
||||
|
||||
return pkt[1];
|
||||
}
|
||||
else
|
||||
return m_i2c->readReg(reg);
|
||||
return bmp280_read_reg(m_bmp280, reg);
|
||||
}
|
||||
|
||||
int BMP280::readRegs(uint8_t reg, uint8_t *buffer, int len)
|
||||
{
|
||||
if (m_isSPI)
|
||||
{
|
||||
reg |= 0x80; // needed for read
|
||||
|
||||
uint8_t sbuf[len + 1];
|
||||
memset((char *)sbuf, 0, len + 1);
|
||||
sbuf[0] = reg;
|
||||
|
||||
// We need to do it this way for edison - ie: use a single
|
||||
// transfer rather than breaking it up into two like we used to.
|
||||
// This means a buffer copy is now required, but that's the way
|
||||
// it goes.
|
||||
|
||||
csOn();
|
||||
if (m_spi->transfer(sbuf, sbuf, len + 1))
|
||||
{
|
||||
csOff();
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": Spi.transfer(buf) failed");
|
||||
}
|
||||
csOff();
|
||||
|
||||
// now copy it into user buffer
|
||||
for (int i=0; i<len; i++)
|
||||
buffer[i] = sbuf[i + 1];
|
||||
|
||||
// so... did this work on edison????
|
||||
|
||||
#if 0
|
||||
cerr << "readRegs(): " << std::hex;
|
||||
for (int i=0; i<len; i++)
|
||||
cerr << (int)buffer[i] << " ";
|
||||
cerr << endl;
|
||||
#endif // 0
|
||||
|
||||
return len;
|
||||
}
|
||||
else
|
||||
return m_i2c->readBytesReg(reg, buffer, len);
|
||||
return bmp280_read_regs(m_bmp280, reg, buffer, len);
|
||||
}
|
||||
|
||||
void BMP280::writeReg(uint8_t reg, uint8_t val)
|
||||
{
|
||||
if (m_isSPI)
|
||||
{
|
||||
reg &= 0x7f; // mask off 0x80 for writing
|
||||
uint8_t pkt[2] = {reg, val};
|
||||
|
||||
csOn();
|
||||
if (m_spi->transfer(pkt, NULL, 2))
|
||||
{
|
||||
csOff();
|
||||
if (bmp280_write_reg(m_bmp280, reg, val))
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": Spi.transfer() failed");
|
||||
}
|
||||
csOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
mraa::Result rv;
|
||||
if ((rv = m_i2c->writeReg(reg, val)) != mraa::SUCCESS)
|
||||
{
|
||||
throw std::runtime_error(std::string(__FUNCTION__)
|
||||
+ ": I2c.writeReg() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BMP280::clearData()
|
||||
{
|
||||
m_t_fine = 0;
|
||||
|
||||
m_dig_T1 = 0;
|
||||
m_dig_T2 = 0;
|
||||
m_dig_T3 = 0;
|
||||
|
||||
m_dig_P1 = 0;
|
||||
m_dig_P2 = 0;
|
||||
m_dig_P3 = 0;
|
||||
m_dig_P4 = 0;
|
||||
m_dig_P5 = 0;
|
||||
m_dig_P6 = 0;
|
||||
m_dig_P7 = 0;
|
||||
m_dig_P8 = 0;
|
||||
m_dig_P9 = 0;
|
||||
+ ": bmp280_write_reg() failed");
|
||||
}
|
||||
|
||||
uint8_t BMP280::getChipID()
|
||||
{
|
||||
|
||||
return readReg(REG_CHIPID);
|
||||
return bmp280_get_chip_id(m_bmp280);
|
||||
}
|
||||
|
||||
void BMP280::reset()
|
||||
{
|
||||
writeReg(REG_RESET, BMP280_RESET_BYTE);
|
||||
sleep(1);
|
||||
bmp280_reset(m_bmp280);
|
||||
}
|
||||
|
||||
|
||||
void BMP280::readCalibrationData()
|
||||
{
|
||||
#if defined(BMP280_USE_TEST_DATA)
|
||||
cerr << "WARNING: Test data is being used" << endl;
|
||||
// This data is taken from the datasheet, section 3.12
|
||||
m_dig_T1 = 27504;
|
||||
m_dig_T2 = 26435;
|
||||
m_dig_T3 = -1000;
|
||||
|
||||
m_dig_P1 = 36477;
|
||||
m_dig_P2 = -10685;
|
||||
m_dig_P3 = 3024;
|
||||
m_dig_P4 = 2855;
|
||||
m_dig_P5 = 140;
|
||||
m_dig_P6 = -7;
|
||||
m_dig_P7 = 15500;
|
||||
m_dig_P8 = -14600;
|
||||
m_dig_P9 = 6000;
|
||||
|
||||
#else
|
||||
|
||||
uint8_t calibData[CALIBRATION_BYTES];
|
||||
readRegs(REG_CALIB00, calibData, CALIBRATION_BYTES);
|
||||
|
||||
m_dig_T1 = uint16_t((calibData[1] << 8) | calibData[0]);
|
||||
m_dig_T2 = int16_t((calibData[3] << 8) | calibData[2]);
|
||||
m_dig_T3 = int16_t((calibData[5] << 8) | calibData[4]);
|
||||
|
||||
# if 0
|
||||
cerr << std::dec << "T1: " << (int)m_dig_T1
|
||||
<< " T2: " << (int)m_dig_T2
|
||||
<< " T3: " << (int)m_dig_T3
|
||||
<< endl;
|
||||
# endif // 0
|
||||
|
||||
m_dig_P1 = uint16_t((calibData[7] << 8) | calibData[6]);
|
||||
m_dig_P2 = int16_t((calibData[9] << 8) | calibData[8]);
|
||||
m_dig_P3 = int16_t((calibData[11] << 8) | calibData[10]);
|
||||
m_dig_P4 = int16_t((calibData[13] << 8) | calibData[12]);
|
||||
m_dig_P5 = int16_t((calibData[15] << 8) | calibData[14]);
|
||||
m_dig_P6 = int16_t((calibData[17] << 8) | calibData[16]);
|
||||
m_dig_P7 = int16_t((calibData[19] << 8) | calibData[18]);
|
||||
m_dig_P8 = int16_t((calibData[21] << 8) | calibData[20]);
|
||||
m_dig_P9 = int16_t((calibData[23] << 8) | calibData[22]);
|
||||
|
||||
# if 0
|
||||
cerr << std::dec << "P1: " << (int)m_dig_P1
|
||||
<< " P2: " << (int)m_dig_P2
|
||||
<< " P3: " << (int)m_dig_P3
|
||||
<< " P4: " << (int)m_dig_P4
|
||||
<< " P5: " << (int)m_dig_P5
|
||||
<< endl;
|
||||
cerr << std::dec << "P6: " << (int)m_dig_P6
|
||||
<< " P7: " << (int)m_dig_P7
|
||||
<< " P8: " << (int)m_dig_P8
|
||||
<< " P9: " << (int)m_dig_P9
|
||||
<< endl;
|
||||
# endif // 0
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
float BMP280::getTemperature(bool fahrenheit)
|
||||
{
|
||||
float temperature = bmp280_get_temperature(m_bmp280);
|
||||
|
||||
if (fahrenheit)
|
||||
return c2f(m_temperature);
|
||||
return c2f(temperature);
|
||||
else
|
||||
return m_temperature;
|
||||
return temperature;
|
||||
}
|
||||
|
||||
float BMP280::getPressure()
|
||||
{
|
||||
return m_pressure;
|
||||
return bmp280_get_pressure(m_bmp280);
|
||||
}
|
||||
|
||||
void BMP280::setFilter(FILTER_T filter)
|
||||
void BMP280::setFilter(BMP280_FILTER_T filter)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CONFIG);
|
||||
|
||||
reg &= ~(_CONFIG_FILTER_MASK << _CONFIG_FILTER_SHIFT);
|
||||
reg |= (filter << _CONFIG_FILTER_SHIFT);
|
||||
|
||||
writeReg(REG_CONFIG, reg);
|
||||
bmp280_set_filter(m_bmp280, filter);
|
||||
}
|
||||
|
||||
void BMP280::setTimerStandby(T_SB_T tsb)
|
||||
void BMP280::setTimerStandby(BMP280_T_SB_T tsb)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CONFIG);
|
||||
|
||||
reg &= ~(_CONFIG_T_SB_MASK << _CONFIG_T_SB_SHIFT);
|
||||
reg |= (tsb << _CONFIG_T_SB_SHIFT);
|
||||
|
||||
writeReg(REG_CONFIG, reg);
|
||||
bmp280_set_timer_standby(m_bmp280, tsb);
|
||||
}
|
||||
|
||||
void BMP280::setMeasureMode(MODES_T mode)
|
||||
void BMP280::setMeasureMode(BMP280_MODES_T mode)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_CTRL_MEAS_MODE_MASK << _CTRL_MEAS_MODE_SHIFT);
|
||||
reg |= (mode << _CTRL_MEAS_MODE_SHIFT);
|
||||
|
||||
writeReg(REG_CTRL_MEAS, reg);
|
||||
m_mode = mode;
|
||||
bmp280_set_measure_mode(m_bmp280, mode);
|
||||
}
|
||||
|
||||
void BMP280::setOversampleRatePressure(OSRS_P_T rate)
|
||||
void BMP280::setOversampleRatePressure(BMP280_OSRS_P_T rate)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_CTRL_MEAS_OSRS_P_MASK << _CTRL_MEAS_OSRS_P_SHIFT);
|
||||
reg |= (rate << _CTRL_MEAS_OSRS_P_SHIFT);
|
||||
|
||||
writeReg(REG_CTRL_MEAS, reg);
|
||||
bmp280_set_oversample_rate_pressure(m_bmp280, rate);
|
||||
}
|
||||
|
||||
void BMP280::setOversampleRateTemperature(OSRS_T_T rate)
|
||||
void BMP280::setOversampleRateTemperature(BMP280_OSRS_T_T rate)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_CTRL_MEAS_OSRS_T_MASK << _CTRL_MEAS_OSRS_T_SHIFT);
|
||||
reg |= (rate << _CTRL_MEAS_OSRS_T_SHIFT);
|
||||
|
||||
writeReg(REG_CTRL_MEAS, reg);
|
||||
bmp280_set_oversample_rate_temperature(m_bmp280, rate);
|
||||
}
|
||||
|
||||
uint8_t BMP280::getStatus()
|
||||
{
|
||||
return readReg(REG_STATUS);
|
||||
return bmp280_get_status(m_bmp280);
|
||||
}
|
||||
|
||||
void BMP280::setUsageMode(USAGE_MODE_T mode)
|
||||
void BMP280::setUsageMode(BMP280_USAGE_MODE_T mode)
|
||||
{
|
||||
// set up the regs for the given usage mode. These settings come
|
||||
// from the recomendations in the BMP280 datasheet, section 3.4
|
||||
// Filter Selection.
|
||||
|
||||
m_temperature = 0;
|
||||
m_pressure = 0;
|
||||
|
||||
// set sleep mode first
|
||||
setMeasureMode(MODE_SLEEP);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case USAGE_MODE_HANDHELD_LOW_POWER:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_16);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_2);
|
||||
setFilter(FILTER_4);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_HANDHELD_DYNAMIC:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_4);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_16);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_WEATHER_MONITOR:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_1);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_OFF);
|
||||
setMeasureMode(MODE_FORCED);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_FLOOR_CHG_DETECT:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_4);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_4);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_DROP_DETECT:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_2);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_OFF);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_INDOOR_NAV:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_16);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_2);
|
||||
setFilter(FILTER_16);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::logic_error(string(__FUNCTION__)
|
||||
+ ": invalid mode specified");
|
||||
}
|
||||
bmp280_set_usage_mode(m_bmp280, mode);
|
||||
}
|
||||
|
||||
void BMP280::csOn()
|
||||
{
|
||||
if (m_gpioCS)
|
||||
m_gpioCS->write(0);
|
||||
}
|
||||
|
||||
void BMP280::csOff()
|
||||
{
|
||||
if (m_gpioCS)
|
||||
m_gpioCS->write(1);
|
||||
}
|
||||
|
||||
// These functions come from the BMP280 datasheet, section 3.11.3
|
||||
|
||||
// Returns temperature in DegC, resolution is 0.01 DegC. Output value
|
||||
// of "5123" equals 51.23 DegC. t_fine carries fine temperature as
|
||||
// global value
|
||||
int32_t BMP280::bmp280_compensate_T_int32(int32_t adc_T)
|
||||
{
|
||||
int32_t var1, var2, T;
|
||||
var1 = ((((adc_T>>3) - ((int32_t)m_dig_T1<<1))) * ((int32_t)m_dig_T2)) >> 11;
|
||||
var2 = (((((adc_T>>4) - ((int32_t)m_dig_T1)) * ((adc_T>>4) - ((int32_t)m_dig_T1))) >> 12) *
|
||||
((int32_t)m_dig_T3)) >> 14;
|
||||
m_t_fine = var1 + var2;
|
||||
T = (m_t_fine * 5 + 128) >> 8;
|
||||
return T;
|
||||
}
|
||||
|
||||
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format
|
||||
// (24 integer bits and 8 fractional bits). Output value of
|
||||
// “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
|
||||
uint32_t BMP280::bmp280_compensate_P_int64(int32_t adc_P)
|
||||
{
|
||||
int64_t var1, var2, p;
|
||||
var1 = ((int64_t)m_t_fine) - 128000;
|
||||
var2 = var1 * var1 * (int64_t)m_dig_P6;
|
||||
var2 = var2 + ((var1*(int64_t)m_dig_P5)<<17);
|
||||
var2 = var2 + (((int64_t)m_dig_P4)<<35);
|
||||
var1 = ((var1 * var1 * (int64_t)m_dig_P3)>>8) + ((var1 * (int64_t)m_dig_P2)<<12);
|
||||
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)m_dig_P1)>>33;
|
||||
if (var1 == 0)
|
||||
{
|
||||
return 0; // avoid exception caused by division by zero
|
||||
}
|
||||
p = 1048576-adc_P;
|
||||
p = (((p<<31)-var2)*3125)/var1;
|
||||
var1 = (((int64_t)m_dig_P9) * (p>>13) * (p>>13)) >> 25;
|
||||
var2 = (((int64_t)m_dig_P8) * p) >> 19;
|
||||
p = ((p + var1 + var2) >> 8) + (((int64_t)m_dig_P7)<<4);
|
||||
return (uint32_t)p;
|
||||
}
|
||||
|
346
src/bmp280/bmp280.h
Normal file
346
src/bmp280/bmp280.h
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <upm.h>
|
||||
|
||||
#include <mraa/i2c.h>
|
||||
#include <mraa/spi.h>
|
||||
#include <mraa/gpio.h>
|
||||
|
||||
#include "bmp280_regs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file bmp280.h
|
||||
* @library bmp280
|
||||
* @brief C API for the bmp280 and bme280 driver
|
||||
*
|
||||
* @include bmp280.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* Device context
|
||||
*/
|
||||
typedef struct _bmp280_context {
|
||||
mraa_i2c_context i2c;
|
||||
mraa_gpio_context gpio;
|
||||
mraa_spi_context spi;
|
||||
|
||||
// are we doing SPI?
|
||||
bool isSPI;
|
||||
|
||||
// are we using a bme280?
|
||||
bool isBME;
|
||||
|
||||
// always stored in C
|
||||
float temperature;
|
||||
|
||||
// pressure in Pa
|
||||
float pressure;
|
||||
|
||||
// humidity (relative)
|
||||
float humidity;
|
||||
|
||||
// sea level pressure in hectoPascals (hPa)
|
||||
float sea_level_hPA;
|
||||
|
||||
// shared calibration data - set in temp conversion, used in
|
||||
// pressure conversion.
|
||||
int32_t t_fine;
|
||||
|
||||
// current operating mode. BMP280_MODE_FORCED requires
|
||||
// special attention in update()
|
||||
BMP280_MODES_T mode;
|
||||
|
||||
// calibration data temperature
|
||||
uint16_t dig_T1;
|
||||
int16_t dig_T2;
|
||||
int16_t dig_T3;
|
||||
|
||||
// calibration data pressure
|
||||
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;
|
||||
|
||||
// calibration data humidity (BME280 only)
|
||||
uint8_t dig_H1;
|
||||
int16_t dig_H2;
|
||||
uint8_t dig_H3;
|
||||
int16_t dig_H4;
|
||||
int16_t dig_H5;
|
||||
int8_t dig_H6;
|
||||
} *bmp280_context;
|
||||
|
||||
/**
|
||||
* BMP280 initialization.
|
||||
*
|
||||
* This driver supports both the BMP280 and the BME280. The
|
||||
* BME280 adds a humidity sensor. The device type is detected
|
||||
* automatically by querying the chip id register.
|
||||
*
|
||||
* Both I2C and SPI accesses are supported. For SPI, set the addr
|
||||
* to -1, and specify a positive integer representing the Chip
|
||||
* Select (CS) pin for the cs argument. If you are using a
|
||||
* hardware CS pin you cannot control (Intel Edison), then you can
|
||||
* connect the proper pin to the hardware CS pin on your MCU and
|
||||
* supply -1 for cs. The default operating mode is I2C.
|
||||
*
|
||||
* @param bus I2C or SPI bus to use.
|
||||
* @param address The I2C address for this device. Use -1 for SPI.
|
||||
* @param cs The gpio pin to use for the SPI Chip Select. Use -1
|
||||
* for I2C, or for SPI with a hardware controlled pin.
|
||||
* @return Device context, or NULL on error.
|
||||
*/
|
||||
bmp280_context bmp280_init(int bus, int addr, int cs);
|
||||
|
||||
/**
|
||||
* BMP280 close function.
|
||||
*
|
||||
* @param dev Device context.
|
||||
*/
|
||||
void bmp280_close(bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Update the internal stored values from sensor data.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @return UPM result.
|
||||
*/
|
||||
upm_result_t bmp280_update(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Return the chip ID.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @return The chip ID (BMP280_CHIPID).
|
||||
*/
|
||||
uint8_t bmp280_get_chip_id(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Reset the sensor, as if by a power-on-reset.
|
||||
*
|
||||
* @param dev Device context.
|
||||
*/
|
||||
void bmp280_reset(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Return the current measured temperature. Note, this is not
|
||||
* ambient temperature - this is the temperature used to fine tune
|
||||
* the pressure measurement. bmp280_update() must have been called prior
|
||||
* to calling this method.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @return The temperature in degrees Celsius.
|
||||
*/
|
||||
float bmp280_get_temperature(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Return the current measured relative humidity (bme280 only).
|
||||
* bmp280_update() must have been called prior to calling this
|
||||
* method. For a bmp280, the returned value will always be 0.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @return The relative humidity in percent.
|
||||
*/
|
||||
float bmp280_get_humidity(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Return the current measured pressure in Pascals (Pa).
|
||||
* bmp280_update() must have been called prior to calling this
|
||||
* method.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @return The pressure in Pascals (Pa).
|
||||
*/
|
||||
float bmp280_get_pressure(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Set the default Sea Level Pressure in hectoPascals (hPA). A
|
||||
* default of 1013.25 (101325 Pa) is set during bmp280_init().
|
||||
* This value is used for altitude computation.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param seaLevelhPA The pressure at sea level in hectoPascals
|
||||
* (hPa).
|
||||
*/
|
||||
void bmp280_set_sea_level_pressure(const bmp280_context dev,
|
||||
float seaLevelhPA);
|
||||
|
||||
/**
|
||||
* Return the current computed altitude in meters.
|
||||
* bmp280_update() must have been called prior to calling this
|
||||
* method.
|
||||
*
|
||||
* Computing this value requires knowing the pressure at sea
|
||||
* level. bmp280_init() sets this by default to 1013.25 hPA. Use
|
||||
* bmp280_set_sea_level_pressure() to change this value.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @return The computed altitude in meters.
|
||||
*/
|
||||
float bmp280_get_altitude(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Set a general usage mode. This function can be used to
|
||||
* configure the filters and oversampling for a particular use
|
||||
* case. These setting are documented in the BMP280 datasheet.
|
||||
* The default mode set in the bmp280_init() function is
|
||||
* BMP280_USAGE_MODE_INDOOR_NAV, the highest resolution mode.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param mode One of the BMP280_USAGE_MODE_T values.
|
||||
*/
|
||||
void bmp280_set_usage_mode(const bmp280_context dev,
|
||||
BMP280_USAGE_MODE_T mode);
|
||||
|
||||
/**
|
||||
* Set the temperature sensor oversampling parameter. See the
|
||||
* data sheet for details. This value can be automatically set to
|
||||
* a suitable value by using one of the predefined modes for
|
||||
* bmp280_set_usage_mode().
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param mode One of the BMP280_OSRS_T_T values.
|
||||
*/
|
||||
void bmp280_set_oversample_rate_temperature(const bmp280_context dev,
|
||||
BMP280_OSRS_T_T rate);
|
||||
|
||||
/**
|
||||
* Set the pressure sensor oversampling parameter. See the
|
||||
* data sheet for details. This value can be automatically set to
|
||||
* a suitable value by using one of the predefined modes for
|
||||
* bmp280_set_usage_mode().
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param mode One of the BMP280_OSRS_P_T values.
|
||||
*/
|
||||
void bmp280_set_oversample_rate_pressure(const bmp280_context dev,
|
||||
BMP280_OSRS_P_T rate);
|
||||
|
||||
/**
|
||||
* Set the humidity sensor oversampling parameter (BME280 only).
|
||||
* See the data sheet for details. This value can be
|
||||
* automatically set to a suitable value by using one of the
|
||||
* predefined modes for bmp280_set_usage_mode().
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param mode One of the BME280_OSRS_H_T values.
|
||||
*/
|
||||
void bmp280_set_oversample_rate_humidity(const bmp280_context dev,
|
||||
BME280_OSRS_H_T rate);
|
||||
|
||||
/**
|
||||
* Set the timer standby value. When in NORMAL operating mode,
|
||||
* this timer governs how long the chip will wait before
|
||||
* performing a measurement. See the data sheet for details.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param mode One of the BMP280_T_SB_T values.
|
||||
*/
|
||||
void bmp280_set_timer_standby(const bmp280_context dev,
|
||||
BMP280_T_SB_T tsb);
|
||||
|
||||
/**
|
||||
* Set the IIR filtering parameter. See the data sheet for
|
||||
* details. This value can be automatically set to a suitable
|
||||
* value by using one of the predefined modes for
|
||||
* bmp280_set_usage_mode().
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param mode One of the BMP280_FILTER_T values.
|
||||
*/
|
||||
void bmp280_set_filter(const bmp280_context dev, BMP280_FILTER_T filter);
|
||||
|
||||
/**
|
||||
* Set the default measuring mode. Basic values are forced,
|
||||
* sleep, and normal. See the data sheet for details. This value
|
||||
* can be automatically set to a suitable value by using one of
|
||||
* the predefined modes for bmp280_set_usage_mode().
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param mode One of the BMP280_MODES_T values.
|
||||
*/
|
||||
void bmp280_set_measure_mode(const bmp280_context dev,
|
||||
BMP280_MODES_T mode);
|
||||
|
||||
/**
|
||||
* Return the value of the BMP280_REG_STATUS register.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @return Contents of the status register.
|
||||
*/
|
||||
uint8_t bmp280_get_status(const bmp280_context dev);
|
||||
|
||||
/**
|
||||
* Read a register.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param reg The register to read
|
||||
* @return The value of the register
|
||||
*/
|
||||
uint8_t bmp280_read_reg(const bmp280_context dev, uint8_t reg);
|
||||
|
||||
/**
|
||||
* Read contiguous registers into a buffer. This is a low level
|
||||
* function, and should not be used unless you know what you are
|
||||
* doing.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param buffer The buffer to store the results
|
||||
* @param len The number of registers to read
|
||||
* @return The number of bytes read, or -1 on error
|
||||
*/
|
||||
int bmp280_read_regs(const bmp280_context dev,
|
||||
uint8_t reg, uint8_t *buffer, int len);
|
||||
|
||||
/**
|
||||
* Write to a register. This is a low level function, and should
|
||||
* not be used unless you know what you are doing.
|
||||
*
|
||||
* @param dev Device context.
|
||||
* @param reg The register to write to
|
||||
* @param val The value to write
|
||||
* @return UPM result.
|
||||
*/
|
||||
upm_result_t bmp280_write_reg(const bmp280_context dev,
|
||||
uint8_t reg, uint8_t val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -24,18 +26,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <mraa/i2c.hpp>
|
||||
#include <mraa/spi.hpp>
|
||||
#include <mraa/gpio.hpp>
|
||||
#include "bmp280.h"
|
||||
|
||||
#include "interfaces/iPressureSensor.hpp"
|
||||
#include "interfaces/iTemperatureSensor.hpp"
|
||||
|
||||
#define BMP280_DEFAULT_I2C_BUS 0
|
||||
#define BMP280_DEFAULT_SPI_BUS 0
|
||||
#define BMP280_DEFAULT_ADDR 0x77
|
||||
#define BMP280_DEFAULT_CHIPID 0x58
|
||||
|
||||
namespace upm {
|
||||
|
||||
/**
|
||||
@ -74,191 +69,14 @@ namespace upm {
|
||||
|
||||
class BMP280 : public ITemperatureSensor, public IPressureSensor {
|
||||
public:
|
||||
// special reset byte
|
||||
const uint8_t BMP280_RESET_BYTE = 0xb6;
|
||||
|
||||
// number of bytes of stored calibration data
|
||||
const int CALIBRATION_BYTES = 26;
|
||||
|
||||
/**
|
||||
* BMP280 registers
|
||||
*/
|
||||
typedef enum : uint8_t {
|
||||
// Do not write into reserved bits.
|
||||
|
||||
// read-only factory calibration data
|
||||
REG_CALIB00 = 0x88,
|
||||
REG_CALIB01 = 0x89,
|
||||
REG_CALIB02 = 0x8a,
|
||||
REG_CALIB03 = 0x8b,
|
||||
REG_CALIB04 = 0x8c,
|
||||
REG_CALIB05 = 0x8d,
|
||||
REG_CALIB06 = 0x8e,
|
||||
REG_CALIB07 = 0x8f,
|
||||
REG_CALIB08 = 0x90,
|
||||
REG_CALIB09 = 0x91,
|
||||
REG_CALIB10 = 0x92,
|
||||
REG_CALIB11 = 0x93,
|
||||
REG_CALIB12 = 0x94,
|
||||
REG_CALIB13 = 0x95,
|
||||
REG_CALIB14 = 0x96,
|
||||
REG_CALIB15 = 0x97,
|
||||
REG_CALIB16 = 0x98,
|
||||
REG_CALIB17 = 0x99,
|
||||
REG_CALIB18 = 0x9a,
|
||||
REG_CALIB19 = 0x9b,
|
||||
REG_CALIB20 = 0x9c,
|
||||
REG_CALIB21 = 0x9d,
|
||||
REG_CALIB22 = 0x9e,
|
||||
REG_CALIB23 = 0x9f,
|
||||
REG_CALIB24 = 0xa0,
|
||||
REG_CALIB25 = 0xa1,
|
||||
|
||||
REG_CHIPID = 0xd0,
|
||||
REG_RESET = 0xe0,
|
||||
REG_STATUS = 0xf3,
|
||||
REG_CTRL_MEAS = 0xf4,
|
||||
REG_CONFIG = 0xf5,
|
||||
|
||||
REG_PRESSURE_MSB = 0xf7,
|
||||
REG_PRESSURE_LSB = 0xf8,
|
||||
REG_PRESSURE_XLSB = 0xf9,
|
||||
|
||||
REG_TEMPERATURE_MSB = 0xfa,
|
||||
REG_TEMPERATURE_LSB = 0xfb,
|
||||
REG_TEMPERATURE_XLSB = 0xfc
|
||||
} BMP280_REGS_T;
|
||||
|
||||
/**
|
||||
* REG_CONFIG bits
|
||||
*/
|
||||
typedef enum {
|
||||
CONFIG_SPI3W_EN = 0x01,
|
||||
|
||||
// 0x02 reserved
|
||||
|
||||
CONFIG_FILTER0 = 0x04,
|
||||
CONFIG_FILTER1 = 0x08,
|
||||
CONFIG_FILTER2 = 0x10,
|
||||
_CONFIG_FILTER_MASK = 7,
|
||||
_CONFIG_FILTER_SHIFT = 2,
|
||||
|
||||
CONFIG_T_SB0 = 0x20,
|
||||
CONFIG_T_SB1 = 0x40,
|
||||
CONFIG_T_SB2 = 0x80,
|
||||
_CONFIG_T_SB_MASK = 7,
|
||||
_CONFIG_T_SB_SHIFT = 5
|
||||
} CONFIG_BITS_T;
|
||||
|
||||
/**
|
||||
* FILTER values (samples to reach >= 75% of step response)
|
||||
*/
|
||||
typedef enum {
|
||||
FILTER_OFF = 0, // 1 samples
|
||||
FILTER_2 = 1, // 2
|
||||
FILTER_4 = 2, // 5
|
||||
FILTER_8 = 3, // 11
|
||||
FILTER_16 = 4 // 22
|
||||
} FILTER_T;
|
||||
|
||||
/**
|
||||
* T_SB values (timer standby)
|
||||
*/
|
||||
typedef enum {
|
||||
T_SB_0_5 = 0, // 0.5ms
|
||||
T_SB_62_5 = 1, // 62.5ms
|
||||
T_SB_125 = 2, // 125ms
|
||||
T_SB_250 = 3,
|
||||
T_SB_500 = 4,
|
||||
T_SB_1000 = 5,
|
||||
T_SB_2000 = 6, // bme280 - 10ms
|
||||
T_SB_4000 = 7 // bme280 - 20ms
|
||||
} T_SB_T;
|
||||
|
||||
|
||||
/**
|
||||
* REG_CTRL_MEAS bits
|
||||
*/
|
||||
typedef enum {
|
||||
CTRL_MEAS_MODE0 = 0x01,
|
||||
CTRL_MEAS_MODE1 = 0x02,
|
||||
_CTRL_MEAS_MODE_MASK = 3,
|
||||
_CTRL_MEAS_MODE_SHIFT = 0,
|
||||
|
||||
CTRL_MEAS_OSRS_P0 = 0x04,
|
||||
CTRL_MEAS_OSRS_P1 = 0x08,
|
||||
CTRL_MEAS_OSRS_P2 = 0x10,
|
||||
_CTRL_MEAS_OSRS_P_MASK = 7,
|
||||
_CTRL_MEAS_OSRS_P_SHIFT = 2,
|
||||
|
||||
CTRL_MEAS_OSRS_T0 = 0x04,
|
||||
CTRL_MEAS_OSRS_T1 = 0x08,
|
||||
CTRL_MEAS_OSRS_T2 = 0x10,
|
||||
_CTRL_MEAS_OSRS_T_MASK = 7,
|
||||
_CTRL_MEAS_OSRS_T_SHIFT = 5
|
||||
} CTRL_MEAS_T;
|
||||
|
||||
/**
|
||||
* CTRL_MEAS_MODE values
|
||||
*/
|
||||
typedef enum {
|
||||
MODE_SLEEP = 0,
|
||||
MODE_FORCED = 1,
|
||||
// 2 is also FORCED mode
|
||||
MODE_NORMAL = 3
|
||||
} MODES_T;
|
||||
|
||||
/**
|
||||
* CTRL_MEAS_OSRS_P values
|
||||
*/
|
||||
typedef enum {
|
||||
OSRS_P_SKIPPED = 0,
|
||||
OSRS_P_OVERSAMPLING_1 = 1, // x1
|
||||
OSRS_P_OVERSAMPLING_2 = 2, // x2
|
||||
OSRS_P_OVERSAMPLING_4 = 3,
|
||||
OSRS_P_OVERSAMPLING_8 = 4,
|
||||
OSRS_P_OVERSAMPLING_16 = 5
|
||||
} OSRS_P_T;
|
||||
|
||||
/**
|
||||
* CTRL_MEAS_OSRS_T values
|
||||
*/
|
||||
typedef enum {
|
||||
OSRS_T_SKIPPED = 0,
|
||||
OSRS_T_OVERSAMPLING_1 = 1, // x1
|
||||
OSRS_T_OVERSAMPLING_2 = 2, // x2
|
||||
OSRS_T_OVERSAMPLING_4 = 3,
|
||||
OSRS_T_OVERSAMPLING_8 = 4,
|
||||
OSRS_T_OVERSAMPLING_16 = 5
|
||||
} OSRS_T_T;
|
||||
|
||||
/**
|
||||
* REG_STATUS bits
|
||||
*/
|
||||
typedef enum {
|
||||
STATUS_IM_UPDATE = 0x01,
|
||||
// 0x02-0x04 reserved
|
||||
STATUS_MEASURING = 0x08
|
||||
// 0x10-0x80 reserved
|
||||
} STATUS_T;
|
||||
|
||||
/**
|
||||
* USAGE_MODE values. This is a fake specification to configure
|
||||
* the various knobs based on their typical use modes, as
|
||||
* recommended by Bosch.
|
||||
*/
|
||||
typedef enum {
|
||||
USAGE_MODE_HANDHELD_LOW_POWER = 0,
|
||||
USAGE_MODE_HANDHELD_DYNAMIC = 1,
|
||||
USAGE_MODE_WEATHER_MONITOR = 2, // lowest power consumption
|
||||
USAGE_MODE_FLOOR_CHG_DETECT = 3,
|
||||
USAGE_MODE_DROP_DETECT = 4,
|
||||
USAGE_MODE_INDOOR_NAV = 5 // highest resolution
|
||||
} USAGE_MODE_T;
|
||||
|
||||
/**
|
||||
* BMP280 constructor.
|
||||
*
|
||||
* This driver supports both the BMP280 and the BME280. The
|
||||
* BME280 adds a humidity sensor. The device type is detected
|
||||
* automatically by querying the chip id register.
|
||||
*
|
||||
* This device can support both I2C and SPI. For SPI, set the addr
|
||||
* to -1, and specify a positive integer representing the Chip
|
||||
* Select (CS) pin for the cs argument. If you are using a
|
||||
@ -267,13 +85,13 @@ namespace upm {
|
||||
* operating mode is I2C.
|
||||
*
|
||||
* @param bus I2C or SPI bus to use.
|
||||
* @param address The address for this device. -1 for SPI.
|
||||
* @param cs The gpio pin to use for the SPI Chip Select. -1 for
|
||||
* I2C or for SPI with a hardware controlled pin.
|
||||
* @param theChipID The chip ID to use for validation
|
||||
* @param address The I2C address for this device. Use -1 for SPI.
|
||||
* @param cs The gpio pin to use for the SPI Chip Select. Use -1
|
||||
* for I2C, or for SPI with a hardware controlled pin.
|
||||
* @throws std::runtime_error on failure.
|
||||
*/
|
||||
BMP280(int bus=BMP280_DEFAULT_I2C_BUS, int addr=BMP280_DEFAULT_ADDR,
|
||||
int cs=-1, uint8_t theChipID=BMP280_DEFAULT_CHIPID);
|
||||
int cs=-1);
|
||||
|
||||
/**
|
||||
* BMP280 Destructor.
|
||||
@ -282,6 +100,8 @@ namespace upm {
|
||||
|
||||
/**
|
||||
* Update the internal stored values from sensor data.
|
||||
*
|
||||
* @throws std::runtime_error on failure.
|
||||
*/
|
||||
virtual void update();
|
||||
|
||||
@ -318,14 +138,24 @@ namespace upm {
|
||||
float getPressure();
|
||||
|
||||
/**
|
||||
* Return the current computed altitude in meters. update()
|
||||
* must have been called prior to calling this method.
|
||||
* Set the pressure at sea level in hecto-Pascals (hPA). This
|
||||
* value is used to compute the altitude based on the
|
||||
* pressure. At driver initialization time, this value is set
|
||||
* to 1013.25 hPA.
|
||||
*
|
||||
* @param seaLevelhPA The pressure at sea level in hectoPascals
|
||||
* (hPa). The default is 1013.25 hPA, (101325 Pa).
|
||||
* @return The computed altitude in meters.
|
||||
*/
|
||||
float getAltitude(float seaLevelhPA=1013.25);
|
||||
void setSeaLevelPreassure(float seaLevelhPA=1013.25);
|
||||
|
||||
/**
|
||||
* Return the current computed altitude in meters. update()
|
||||
* must have been called prior to calling this method.
|
||||
*
|
||||
* @return The computed altitude in meters.
|
||||
*/
|
||||
float getAltitude();
|
||||
|
||||
/**
|
||||
* Set a general usage mode. This function can be used to
|
||||
@ -334,9 +164,9 @@ namespace upm {
|
||||
* The default mode set in the constructor is
|
||||
* USAGE_MODE_INDOOR_NAV, the highest resolution mode.
|
||||
*
|
||||
* @param mode One of the USAGE_MODE_T values.
|
||||
* @param mode One of the BMP280_USAGE_MODE_T values.
|
||||
*/
|
||||
virtual void setUsageMode(USAGE_MODE_T mode);
|
||||
virtual void setUsageMode(BMP280_USAGE_MODE_T mode);
|
||||
|
||||
/**
|
||||
* Set the temperature sensor oversampling parameter. See the
|
||||
@ -344,9 +174,9 @@ namespace upm {
|
||||
* a suitable value by using one of the predefined modes for
|
||||
* setUsageMode().
|
||||
*
|
||||
* @param mode One of the OSRS_T_T values.
|
||||
* @param mode One of the BMP280_OSRS_T_T values.
|
||||
*/
|
||||
void setOversampleRateTemperature(OSRS_T_T rate);
|
||||
void setOversampleRateTemperature(BMP280_OSRS_T_T rate);
|
||||
|
||||
/**
|
||||
* Set the pressure sensor oversampling parameter. See the
|
||||
@ -354,27 +184,27 @@ namespace upm {
|
||||
* a suitable value by using one of the predefined modes for
|
||||
* setUsageMode().
|
||||
*
|
||||
* @param mode One of the OSRS_P_T values.
|
||||
* @param mode One of the BMP280_OSRS_P_T values.
|
||||
*/
|
||||
void setOversampleRatePressure(OSRS_P_T rate);
|
||||
void setOversampleRatePressure(BMP280_OSRS_P_T rate);
|
||||
|
||||
/**
|
||||
* Set the timer standby value. When in NORMAL operating mode,
|
||||
* this timer governs how long the chip will wait before
|
||||
* performing a measurement. See the data sheet for details.
|
||||
*
|
||||
* @param mode One of the T_SB_T values.
|
||||
* @param mode One of the BMP280_T_SB_T values.
|
||||
*/
|
||||
void setTimerStandby(T_SB_T tsb);
|
||||
void setTimerStandby(BMP280_T_SB_T tsb);
|
||||
|
||||
/**
|
||||
* Set the IIR filtering parameter. See the data sheet for
|
||||
* details. This value can be automatically set to a suitable
|
||||
* value by using one of the predefined modes for setUsageMode().
|
||||
*
|
||||
* @param mode One of the FILTER_T values.
|
||||
* @param mode One of the BMP280_FILTER_T values.
|
||||
*/
|
||||
void setFilter(FILTER_T filter);
|
||||
void setFilter(BMP280_FILTER_T filter);
|
||||
|
||||
/**
|
||||
* Set the default measuring mode. Basic values are forced,
|
||||
@ -382,9 +212,9 @@ namespace upm {
|
||||
* can be automatically set to a suitable value by using one of
|
||||
* the predefined modes for setUsageMode().
|
||||
*
|
||||
* @param mode One of the MODES_T values.
|
||||
* @param mode One of the BMP280_MODES_T values.
|
||||
*/
|
||||
void setMeasureMode(MODES_T mode);
|
||||
void setMeasureMode(BMP280_MODES_T mode);
|
||||
|
||||
|
||||
// Interface support
|
||||
@ -404,27 +234,13 @@ namespace upm {
|
||||
};
|
||||
|
||||
protected:
|
||||
mraa::I2c *m_i2c;
|
||||
mraa::Spi *m_spi;
|
||||
mraa::Gpio *m_gpioCS;
|
||||
bmp280_context m_bmp280;
|
||||
|
||||
uint8_t m_addr;
|
||||
|
||||
// always stored in C
|
||||
float m_temperature;
|
||||
|
||||
// pressure in Pa
|
||||
float m_pressure;
|
||||
|
||||
// shared calibration data - set in temp conversion, used in
|
||||
// pressure conversion.
|
||||
int32_t m_t_fine;
|
||||
|
||||
// current operating mode. MODE_FORCED requires special attention
|
||||
// in update()
|
||||
MODES_T m_mode;
|
||||
|
||||
// return the status register
|
||||
/**
|
||||
* Return the value of the BMP280_REG_STATUS register.
|
||||
*
|
||||
* @return Contents of the status register.
|
||||
*/
|
||||
uint8_t getStatus();
|
||||
|
||||
/**
|
||||
@ -449,42 +265,10 @@ namespace upm {
|
||||
*
|
||||
* @param reg The register to write to
|
||||
* @param val The value to write
|
||||
* @throws std::runtime_error on failure.
|
||||
*/
|
||||
void writeReg(uint8_t reg, uint8_t val);
|
||||
|
||||
// clear member data...
|
||||
void clearData();
|
||||
|
||||
// read the calibration data
|
||||
virtual void readCalibrationData();
|
||||
|
||||
// SPI chip select
|
||||
void csOn();
|
||||
void csOff();
|
||||
|
||||
private:
|
||||
// are we doing SPI?
|
||||
bool m_isSPI;
|
||||
|
||||
// calibration data temperature
|
||||
uint16_t m_dig_T1;
|
||||
int16_t m_dig_T2;
|
||||
int16_t m_dig_T3;
|
||||
|
||||
// calibration data pressure
|
||||
uint16_t m_dig_P1;
|
||||
int16_t m_dig_P2;
|
||||
int16_t m_dig_P3;
|
||||
int16_t m_dig_P4;
|
||||
int16_t m_dig_P5;
|
||||
int16_t m_dig_P6;
|
||||
int16_t m_dig_P7;
|
||||
int16_t m_dig_P8;
|
||||
int16_t m_dig_P9;
|
||||
|
||||
// Bosch supplied conversion/compensation functions from the
|
||||
// datasheet.
|
||||
int32_t bmp280_compensate_T_int32(int32_t adc_T);
|
||||
uint32_t bmp280_compensate_P_int64(int32_t adc_P);
|
||||
};
|
||||
}
|
||||
|
290
src/bmp280/bmp280_regs.h
Normal file
290
src/bmp280/bmp280_regs.h
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016-2017 Intel Corporation.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// BMP280
|
||||
#define BMP280_DEFAULT_I2C_BUS 0
|
||||
#define BMP280_DEFAULT_SPI_BUS 0
|
||||
#define BMP280_DEFAULT_ADDR 0x77
|
||||
#define BMP280_CHIPID 0x58
|
||||
|
||||
// BME280
|
||||
#define BME280_DEFAULT_I2C_BUS 0
|
||||
#define BME280_DEFAULT_SPI_BUS 0
|
||||
#define BME280_DEFAULT_ADDR 0x77
|
||||
#define BME280_CHIPID 0x60
|
||||
|
||||
// default sea level pressure in hPA
|
||||
#define BMP280_SEA_LEVEL_HPA (1013.25)
|
||||
|
||||
// special reset byte, same for bme280
|
||||
#define BMP280_RESET_BYTE 0xb6
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BMP280 registers
|
||||
*/
|
||||
typedef enum {
|
||||
// Do not write into reserved bits.
|
||||
|
||||
// read-only factory calibration data
|
||||
BMP280_REG_CALIB00 = 0x88,
|
||||
BMP280_REG_CALIB01 = 0x89,
|
||||
BMP280_REG_CALIB02 = 0x8a,
|
||||
BMP280_REG_CALIB03 = 0x8b,
|
||||
BMP280_REG_CALIB04 = 0x8c,
|
||||
BMP280_REG_CALIB05 = 0x8d,
|
||||
BMP280_REG_CALIB06 = 0x8e,
|
||||
BMP280_REG_CALIB07 = 0x8f,
|
||||
BMP280_REG_CALIB08 = 0x90,
|
||||
BMP280_REG_CALIB09 = 0x91,
|
||||
BMP280_REG_CALIB10 = 0x92,
|
||||
BMP280_REG_CALIB11 = 0x93,
|
||||
BMP280_REG_CALIB12 = 0x94,
|
||||
BMP280_REG_CALIB13 = 0x95,
|
||||
BMP280_REG_CALIB14 = 0x96,
|
||||
BMP280_REG_CALIB15 = 0x97,
|
||||
BMP280_REG_CALIB16 = 0x98,
|
||||
BMP280_REG_CALIB17 = 0x99,
|
||||
BMP280_REG_CALIB18 = 0x9a,
|
||||
BMP280_REG_CALIB19 = 0x9b,
|
||||
BMP280_REG_CALIB20 = 0x9c,
|
||||
BMP280_REG_CALIB21 = 0x9d,
|
||||
BMP280_REG_CALIB22 = 0x9e,
|
||||
BMP280_REG_CALIB23 = 0x9f,
|
||||
BMP280_REG_CALIB24 = 0xa0,
|
||||
BMP280_REG_CALIB25 = 0xa1,
|
||||
|
||||
BMP280_REG_CHIPID = 0xd0,
|
||||
BMP280_REG_RESET = 0xe0,
|
||||
BMP280_REG_STATUS = 0xf3,
|
||||
BMP280_REG_CTRL_MEAS = 0xf4,
|
||||
BMP280_REG_CONFIG = 0xf5,
|
||||
|
||||
BMP280_REG_PRESSURE_MSB = 0xf7,
|
||||
BMP280_REG_PRESSURE_LSB = 0xf8,
|
||||
BMP280_REG_PRESSURE_XLSB = 0xf9,
|
||||
|
||||
BMP280_REG_TEMPERATURE_MSB = 0xfa,
|
||||
BMP280_REG_TEMPERATURE_LSB = 0xfb,
|
||||
BMP280_REG_TEMPERATURE_XLSB = 0xfc
|
||||
} BMP280_REGS_T;
|
||||
|
||||
/**
|
||||
* BMP280_REG_CONFIG bits
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_CONFIG_SPI3W_EN = 0x01,
|
||||
|
||||
// 0x02 reserved
|
||||
|
||||
BMP280_CONFIG_FILTER0 = 0x04,
|
||||
BMP280_CONFIG_FILTER1 = 0x08,
|
||||
BMP280_CONFIG_FILTER2 = 0x10,
|
||||
_BMP280_CONFIG_FILTER_MASK = 7,
|
||||
_BMP280_CONFIG_FILTER_SHIFT = 2,
|
||||
|
||||
BMP280_CONFIG_T_SB0 = 0x20,
|
||||
BMP280_CONFIG_T_SB1 = 0x40,
|
||||
BMP280_CONFIG_T_SB2 = 0x80,
|
||||
_BMP280_CONFIG_T_SB_MASK = 7,
|
||||
_BMP280_CONFIG_T_SB_SHIFT = 5
|
||||
} BMP280_CONFIG_BITS_T;
|
||||
|
||||
/**
|
||||
* BMP280_FILTER values (samples to reach >= 75% of step response)
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_FILTER_OFF = 0, // 1 samples
|
||||
BMP280_FILTER_2 = 1, // 2
|
||||
BMP280_FILTER_4 = 2, // 5
|
||||
BMP280_FILTER_8 = 3, // 11
|
||||
BMP280_FILTER_16 = 4 // 22
|
||||
} BMP280_FILTER_T;
|
||||
|
||||
/**
|
||||
* BMP280_T_SB values (timer standby)
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_T_SB_0_5 = 0, // 0.5ms
|
||||
BMP280_T_SB_62_5 = 1, // 62.5ms
|
||||
BMP280_T_SB_125 = 2, // 125ms
|
||||
BMP280_T_SB_250 = 3,
|
||||
BMP280_T_SB_500 = 4,
|
||||
BMP280_T_SB_1000 = 5,
|
||||
BMP280_T_SB_2000 = 6, // bme280 - 10ms
|
||||
BMP280_T_SB_4000 = 7 // bme280 - 20ms
|
||||
} BMP280_T_SB_T;
|
||||
|
||||
|
||||
/**
|
||||
* BMP280_REG_CTRL_MEAS bits
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_CTRL_MEAS_MODE0 = 0x01,
|
||||
BMP280_CTRL_MEAS_MODE1 = 0x02,
|
||||
_BMP280_CTRL_MEAS_MODE_MASK = 3,
|
||||
_BMP280_CTRL_MEAS_MODE_SHIFT = 0,
|
||||
|
||||
BMP280_CTRL_MEAS_OSRS_P0 = 0x04,
|
||||
BMP280_CTRL_MEAS_OSRS_P1 = 0x08,
|
||||
BMP280_CTRL_MEAS_OSRS_P2 = 0x10,
|
||||
_BMP280_CTRL_MEAS_OSRS_P_MASK = 7,
|
||||
_BMP280_CTRL_MEAS_OSRS_P_SHIFT = 2,
|
||||
|
||||
BMP280_CTRL_MEAS_OSRS_T0 = 0x04,
|
||||
BMP280_CTRL_MEAS_OSRS_T1 = 0x08,
|
||||
BMP280_CTRL_MEAS_OSRS_T2 = 0x10,
|
||||
_BMP280_CTRL_MEAS_OSRS_T_MASK = 7,
|
||||
_BMP280_CTRL_MEAS_OSRS_T_SHIFT = 5
|
||||
} BMP280_CTRL_MEAS_T;
|
||||
|
||||
/**
|
||||
* BMP280_CTRL_MEAS_MODE values
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_MODE_SLEEP = 0,
|
||||
BMP280_MODE_FORCED = 1,
|
||||
// 2 is also FORCED mode
|
||||
BMP280_MODE_NORMAL = 3
|
||||
} BMP280_MODES_T;
|
||||
|
||||
/**
|
||||
* BMP280_CTRL_MEAS_OSRS_P values
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_OSRS_P_SKIPPED = 0,
|
||||
BMP280_OSRS_P_OVERSAMPLING_1 = 1, // x1
|
||||
BMP280_OSRS_P_OVERSAMPLING_2 = 2, // x2
|
||||
BMP280_OSRS_P_OVERSAMPLING_4 = 3,
|
||||
BMP280_OSRS_P_OVERSAMPLING_8 = 4,
|
||||
BMP280_OSRS_P_OVERSAMPLING_16 = 5
|
||||
} BMP280_OSRS_P_T;
|
||||
|
||||
/**
|
||||
* BMP280_CTRL_MEAS_OSRS_T values
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_OSRS_T_SKIPPED = 0,
|
||||
BMP280_OSRS_T_OVERSAMPLING_1 = 1, // x1
|
||||
BMP280_OSRS_T_OVERSAMPLING_2 = 2, // x2
|
||||
BMP280_OSRS_T_OVERSAMPLING_4 = 3,
|
||||
BMP280_OSRS_T_OVERSAMPLING_8 = 4,
|
||||
BMP280_OSRS_T_OVERSAMPLING_16 = 5
|
||||
} BMP280_OSRS_T_T;
|
||||
|
||||
/**
|
||||
* BMP280_REG_STATUS bits
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_STATUS_IM_UPDATE = 0x01,
|
||||
// 0x02-0x04 reserved
|
||||
BMP280_STATUS_MEASURING = 0x08
|
||||
// 0x10-0x80 reserved
|
||||
} BMP280_STATUS_T;
|
||||
|
||||
/**
|
||||
* BMP280_USAGE_MODE values. This is a fake specification to
|
||||
* configure the various knobs based on their typical use modes,
|
||||
* as recommended by Bosch.
|
||||
*/
|
||||
typedef enum {
|
||||
BMP280_USAGE_MODE_HANDHELD_LOW_POWER = 0,
|
||||
BMP280_USAGE_MODE_HANDHELD_DYNAMIC = 1,
|
||||
BMP280_USAGE_MODE_WEATHER_MONITOR = 2, // lowest power consumption
|
||||
BMP280_USAGE_MODE_FLOOR_CHG_DETECT = 3,
|
||||
BMP280_USAGE_MODE_DROP_DETECT = 4,
|
||||
BMP280_USAGE_MODE_INDOOR_NAV = 5 // highest resolution
|
||||
} BMP280_USAGE_MODE_T;
|
||||
|
||||
// The following are registers specific to the BME280. The BME280
|
||||
// is identical to the BMP280 with the exception of humidity
|
||||
// sensor support and the corresponding registers needed to
|
||||
// support it.
|
||||
|
||||
/**
|
||||
* BME280 registers
|
||||
*/
|
||||
typedef enum {
|
||||
// Do not write into reserved bits.
|
||||
|
||||
// We only specify those registers specific to the BME280. The
|
||||
// rest of them can be found in the BMP280 header file.
|
||||
|
||||
// read-only factory calibration data for humidity
|
||||
|
||||
BME280_REG_CALIB_DIG_H1 = 0xa1,
|
||||
|
||||
BME280_REG_CALIB_DIG_H2_LSB = 0xe1,
|
||||
BME280_REG_CALIB_DIG_H2_MSB = 0xe2,
|
||||
|
||||
BME280_REG_CALIB_DIG_H3 = 0xe3,
|
||||
|
||||
BME280_REG_CALIB_DIG_H4_0 = 0xe4, // bits 8 -> 11:4
|
||||
BME280_REG_CALIB_DIG_H4_1 = 0xe5, // bits 3:0 -> 3:0
|
||||
|
||||
BME280_REG_CALIB_DIG_H5_0 = 0xe5, // bits 7:4 -> 3:0
|
||||
BME280_REG_CALIB_DIG_H5_1 = 0xe6, // bits 8 -> 11:4
|
||||
|
||||
BME280_REG_CALIB_DIG_H6 = 0xe7,
|
||||
|
||||
BME280_REG_CTRL_HUM = 0xf2,
|
||||
|
||||
BME280_REG_HUMIDITY_MSB = 0xfd,
|
||||
BME280_REG_HUMIDITY_LSB = 0xfe
|
||||
} BME280_REGS_T;
|
||||
|
||||
/**
|
||||
* BME280_REG_CTRL_HUM bits
|
||||
*/
|
||||
typedef enum {
|
||||
BME280_CTRL_HUM_OSRS_H0 = 0x01,
|
||||
BME280_CTRL_HUM_OSRS_H1 = 0x02,
|
||||
BME280_CTRL_HUM_OSRS_H2 = 0x04,
|
||||
_BME280_CTRL_HUM_OSRS_H_MASK = 3,
|
||||
_BME280_CTRL_HUM_OSRS_H_SHIFT = 0
|
||||
|
||||
// 0x08-0x80 reserved
|
||||
} BME280_CTRL_HUM_T;
|
||||
|
||||
/**
|
||||
* BME280_CTRL_HUM_OSRS_H values
|
||||
*/
|
||||
typedef enum {
|
||||
BME280_OSRS_H_SKIPPED = 0,
|
||||
BME280_OSRS_H_OVERSAMPLING_1 = 1, // x1
|
||||
BME280_OSRS_H_OVERSAMPLING_2 = 2, // x2
|
||||
BME280_OSRS_H_OVERSAMPLING_4 = 3,
|
||||
BME280_OSRS_H_OVERSAMPLING_8 = 4,
|
||||
BME280_OSRS_H_OVERSAMPLING_16 = 5
|
||||
} BME280_OSRS_H_T;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -5,11 +5,7 @@
|
||||
%include "../interfaces/javaupm_iHumiditySensor.i"
|
||||
%include "../interfaces/javaupm_iPressureSensor.i"
|
||||
|
||||
%include "cpointer.i"
|
||||
%include "typemaps.i"
|
||||
%include "arrays_java.i";
|
||||
%include "../java_buffer.i"
|
||||
|
||||
%include "bmp280_regs.h"
|
||||
%include "bmp280.hpp"
|
||||
%{
|
||||
#include "bmp280.hpp"
|
||||
|
@ -6,6 +6,8 @@
|
||||
%include "iHumiditySensor.hpp"
|
||||
%include "iPressureSensor.hpp"
|
||||
%include "iTemperatureSensor.hpp"
|
||||
|
||||
%include "bmp280_regs.h"
|
||||
%include "bmp280.hpp"
|
||||
%{
|
||||
#include "bmp280.hpp"
|
||||
|
@ -16,6 +16,8 @@
|
||||
%include "iHumiditySensor.hpp"
|
||||
%include "iPressureSensor.hpp"
|
||||
%include "iTemperatureSensor.hpp"
|
||||
|
||||
%include "bmp280_regs.h"
|
||||
%include "bmp280.hpp"
|
||||
%{
|
||||
#include "bmp280.hpp"
|
||||
|
Loading…
x
Reference in New Issue
Block a user