bmpx8x: rewrite in C; FTI; C++ wraps C

This driver has been rewritten from scratch.

See docs/apichanges.md for a list of API compatibility changes
compared to the original driver.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2017-04-04 17:48:41 -06:00
parent 8d43c431f2
commit c57a0d2c30
17 changed files with 1346 additions and 424 deletions

View File

@ -6,6 +6,54 @@ compatibility between releases:
# current master
* **bmpx8x** This driver has been rewritten from scratch in C, with a
C++ wrapper.
All exported symbols have been renamed for consistancy and to
avoid symbol collisions by having a *BMPX8X_* prefix. As an example,
*ADDR* has been renamed to *BMPX8X_DEFAULT_I2C_ADDR*. Most C
ported drivers follow this rule.
The *getPressureRaw()* and *getTemperatureRaw()* functions have
been removed. This functionality was only needed internally to
the driver.
The constructor no longer accepts a mode argument. Only the I2C
bus and I2C address are accepted. By default, the device will be
configured for it's maximum resolution *BMPX8X_OSS_ULTRAHIGHRES*,
the previous default. You can use the new method
*setOversampling()* to change the mode to something else if
desired.
The methods related to calibration, like *computeB5()* are no
longer exposed.
New methods, *init()* and *reset()* have been added. *reset()*
resets the device to a freshly powered up state. *init()* can be
used to re-initialize the device after a reset (reload calibration
data) and set a default oversampling mode.
A new method, *update()* has been added. This method will update
all internal state from the device, and **must** be called before
querying the pressure, temperature, sealevel and altitude values.
The *getSeaLevelPressure()* method has been split into two
overloaded methods. One which **requires** an argument in meters
(previously, a default was provided), and another which does not
accept arguments at all and computes the sea level pressure based
on current altitude.
The *i2cReadReg_16()*, *i2CWriteReg()* and *i2cReadReg_8()* have
been replaced with *readReg()*, *readRegs()*, and *writeReg()*, in
line with other I2C/SPI drivers of this type. They are marked
protected (in C++) now as well. Please see the updated
documentation and examples for this driver.
* **mma7660** This driver has been rewritten in C. Some exported
symbols have been changed, for example, *MMA7660_I2C_BUS* was renamed
to *MMA7660_DEFAULT_I2C_BUS*. See updated documentation and examples
for other changes.
* **bmx055, bmi055, bmc150, bma250e, bmg160, bmm150** This driver has
been split up. The *bma250e*, *bmg160*, *bmm150* drivers have been
rewritten in C (with C++ wrappers) and now reside in their own
@ -15,14 +63,14 @@ compatibility between releases:
and *bmc150* are still contained within the *bmx055* library, and
also use the new libraries for their functionality.
In addition, for all of these drivers some private methods are no
longer exposed (such as the compensation routines).
In addition, for all of these drivers some private methods are no
longer exposed (such as the compensation routines).
The C++ driver methods that once returned pointers to a floating
point array now return *std::vectors* of the appropriate type. The
SWIG language examples for these drivers have been modified to use
these methods instead of the C pointer based SWIG methods previously
used.
The C++ driver methods that once returned pointers to a floating
point array now return *std::vectors* of the appropriate type.
The SWIG language examples for these drivers have been modified to
use these methods instead of the C pointer based SWIG methods
previously used.
* **sainsmartks** This driver has been renamed to *lcdks* (LCD Keypad
Shield) and moved into it's own library. It uses the *lcm1602*
@ -40,16 +88,16 @@ compatibility between releases:
*jhd1313m1* drivers had their C++ headers renamed to use a **.hxx**
suffix.
In this version of UPM, the *lcm1602* and *jhd1313m1* drivers have
been removed from the lcd/i2clcd library. In addition, the header
files for the new implementation have been renamed from their **.hxx**
suffix to the normal **.hpp** suffix.
In this version of UPM, the *lcm1602* and *jhd1313m1* drivers have
been removed from the lcd/i2clcd library. In addition, the header
files for the new implementation have been renamed from their
**.hxx** suffix to the normal **.hpp** suffix.
A change was also made to the new *lcm1602* and *jhd1313m1* C++
drivers. The *createChar()* function now accepts a byte vector
*std::vector<uint8_t>* rather than the *char ** pointer that was
used previously. This should make it easier to use with the SWIG
language bindings (Python, Javascript, and especially Java).
A change was also made to the new *lcm1602* and *jhd1313m1* C++
drivers. The *createChar()* function now accepts a byte vector
*std::vector<uint8_t>* rather than the *char ** pointer that was
used previously. This should make it easier to use with the SWIG
language bindings (Python, Javascript, and especially Java).
* **bmp280/bme280** Some private methods are no longer exposed (such
as the calibration and compensation routines). In addition,

View File

@ -1,6 +1,11 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 Intel Corporation.
*
* This driver was rewritten based on the original driver written by:
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
* Copyright (c) 2014 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,57 +29,50 @@
#include <unistd.h>
#include <iostream>
#include "bmpx8x.hpp"
#include <signal.h>
int doWork = 0;
upm::BMPX8X *sensor = NULL;
#include "bmpx8x.hpp"
void
sig_handler(int signo)
using namespace std;
bool shouldRun = true;
void sig_handler(int signo)
{
printf("got signal\n");
if (signo == SIGINT) {
printf("exiting application\n");
doWork = 1;
}
if (signo == SIGINT)
shouldRun = false;
}
int
main(int argc, char **argv)
int main(int argc, char **argv)
{
//! [Interesting]
uint32_t presure = 0;
float temperature = 0;
float altitude = 0;
uint32_t sealevel = 0;
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate a BMPX8X sensor on I2C
sensor = new upm::BMPX8X(0, ADDR);
// Instantiate a BMPX8X sensor on I2C using defaults.
upm::BMPX8X sensor;
// Print the pressure, altitude, sea level, and
// temperature values every 0.1 seconds
while (!doWork) {
presure = sensor->getPressure ();
temperature = sensor->getTemperature ();
altitude = sensor->getAltitude ();
sealevel = sensor->getSealevelPressure ();
// temperature values every 0.5 seconds
while (shouldRun)
{
sensor.update();
std::cout << "pressure value = " <<
presure <<
", altitude value = " <<
altitude <<
", sealevel value = " <<
sealevel <<
", temperature = " <<
temperature << std::endl;
usleep (100000);
cout << "Pressure: "
<< sensor.getPressure()
<< " Pa, Temperature: "
<< sensor.getTemperature()
<< " C, Altitude: "
<< sensor.getAltitude()
<< " m, Sea level: "
<< sensor.getSealevelPressure()
<< " Pa"
<< endl;
usleep(500000);
}
//! [Interesting]
std::cout << "exiting application" << std::endl;
delete sensor;
cout << "Exiting..." << endl;
//! [Interesting]
return 0;
}

View File

@ -157,6 +157,7 @@ add_example (bmg160)
add_example (bma250e)
add_example (bmm150)
add_example (rsc)
add_example (bmpx8x)
# Custom examples
add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps)

88
examples/c/bmpx8x.c Normal file
View File

@ -0,0 +1,88 @@
/*
* 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 "bmpx8x.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 BMPX8X instance using default i2c bus and address
bmpx8x_context sensor = bmpx8x_init(BMPX8X_DEFAULT_I2C_BUS,
BMPX8X_DEFAULT_I2C_ADDR);
if (!sensor)
{
printf("bmpx8x_init() failed.\n");
return 1;
}
// Print the pressure, altitude, sea level, and
// temperature values every 0.5 seconds
while (shouldRun)
{
if (bmpx8x_update(sensor))
{
printf("bmpx8x_update() failed\n");
bmpx8x_close(sensor);
return 1;
}
// assume sea level pressure is 101325 Pa.
float altitude = bmpx8x_get_altitude(sensor, 101325);
int sealevel = bmpx8x_get_sealevel_pressure(sensor, altitude);
printf("Pressure: %d Pa, Temperature: %f C, "
"Altitude %f m, Sea level %d Pa\n",
bmpx8x_get_pressure(sensor),
bmpx8x_get_temperature(sensor),
altitude,
sealevel);
upm_delay_ms(500);
}
printf("Exiting...\n");
bmpx8x_close(sensor);
//! [Interesting]
return 0;
}

View File

@ -1,6 +1,7 @@
/*
* Author: Stefan Andritoiu <stefan.andritoiu@intel.com>
* Copyright (c) 2015 Intel Corporation.
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2015-2017 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -22,27 +23,33 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
//NOT TESTED!!!
public class BMPX8XSample {
public static void main(String[] args) throws InterruptedException {
// ! [Interesting]
// Instantiate a BMPX8X sensor on I2C
upm_bmpx8x.BMPX8X sensor = new upm_bmpx8x.BMPX8X(0);
public static void main(String[] args) throws InterruptedException {
// ! [Interesting]
// Print the pressure, altitude, sea level, and
// temperature values every second
while (true) {
System.out.println("Pressure: " + sensor.getPressure());
System.out.println("Altitude: " + sensor.getAltitude());
System.out.println("Sealevel pressure: "
+ sensor.getSealevelPressure());
System.out.println("Temperature: " + sensor.getTemperature());
System.out.println();
// Instantiate a BMPX8X sensor on I2C using defaults.
upm_bmpx8x.BMPX8X sensor = new upm_bmpx8x.BMPX8X();
Thread.sleep(1000);
}
// ! [Interesting]
}
// Print the pressure, altitude, sea level, and
// temperature values every .5 seconds
while (true)
{
sensor.update();
}
System.out.println("Pressure: "
+ sensor.getPressure()
+ " Pa, Temperature: "
+ sensor.getTemperature()
+ " C, Altitude: "
+ sensor.getAltitude()
+ " m, Sea level: "
+ sensor.getSealevelPressure()
+ " Pa");
Thread.sleep(500);
}
// ! [Interesting]
}
}

View File

@ -1,6 +1,7 @@
/*
* Author: Zion Orent <zorent@ics.com>
* Copyright (c) 2014 Intel Corporation.
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014-2017 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -22,31 +23,34 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
//Load Barometer module
var bmpx8x = require('jsupm_bmpx8x');
// load this on i2c
var myBarometerObj = new bmpx8x.BMPX8X(0, bmpx8x.ADDR);
var pressure, temperature, altitude, sealevel;
var sensorObj = require('jsupm_bmpx8x');
// Instantiate a BMPX8X sensor on I2C using defaults.
var sensor = new sensorObj.BMPX8X();
// Print the pressure, altitude, sea level, and
// temperature values every 0.1 seconds
// temperature values every 0.5 seconds
setInterval(function()
{
var pressure = myBarometerObj.getPressure();
var temperature = myBarometerObj.getTemperature();
var altitude = myBarometerObj.getAltitude();
var sealevel = myBarometerObj.getSealevelPressure();
sensor.update();
var BMPX8Xresults = "pressure value = " + pressure;
BMPX8Xresults += ", altitude value = " + altitude;
BMPX8Xresults += ", sealevel value = " + sealevel;
BMPX8Xresults += ", temperature = " + temperature;
console.log(BMPX8Xresults);
}, 100);
console.log("Pressure: "
+ sensor.getPressure()
+ " Pa, Temperature: "
+ sensor.getTemperature()
+ " C, Altitude: "
+ sensor.getAltitude()
+ " m, Sea level: "
+ sensor.getSealevelPressure()
+ " Pa");
}, 500);
// Print message when exiting
// exit on ^C
process.on('SIGINT', function()
{
console.log("Exiting...");
process.exit(0);
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -1,6 +1,7 @@
#!/usr/bin/python
# Author: Zion Orent <zorent@ics.com>
# Copyright (c) 2015 Intel Corporation.
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2014-2017 Intel Corporation.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@ -26,15 +27,18 @@ import time, sys, signal, atexit
from upm import pyupm_bmpx8x as upmBmpx8x
def main():
# Load Barometer module on i2c
myBarometer = upmBmpx8x.BMPX8X(0, upmBmpx8x.ADDR);
# Load Barometer module on i2c using default values
sensor = upmBmpx8x.BMPX8X(0);
## Exit handlers ##
# This function stops python from printing a stacktrace when you hit control-C
# This function stops python from printing a stacktrace when you hit
# control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit, including functions from myBarometer
# This function lets you run code on exit, including functions
# from sensor
def exitHandler():
print("Exiting")
sys.exit(0)
@ -46,17 +50,19 @@ def main():
# Print the pressure, altitude, sea level, and
# temperature values every 0.1 seconds
while(1):
outputStr = ("pressure value = {0}"
", altitude value = {1}"
", sealevel value = {2}"
", temperature = {3}".format(
myBarometer.getPressure(),
myBarometer.getTemperature(),
myBarometer.getAltitude(),
myBarometer.getSealevelPressure()))
sensor.update()
outputStr = ("Pressure: {0}"
" Pa, Temperature: {1}"
" C, Altitude: {2}"
" m, Sea Level: {3} Pa".format(
sensor.getPressure(),
sensor.getTemperature(),
sensor.getAltitude(),
sensor.getSealevelPressure()))
print(outputStr)
time.sleep(.1)
time.sleep(.5)
if __name__ == '__main__':
main()

View File

@ -1,5 +1,10 @@
set (libname "bmpx8x")
set (libdescription "Bosch BMP & GY65 Atmospheric Pressure Sensor Library")
set (module_src ${libname}.cxx)
set (module_hpp ${libname}.hpp)
upm_module_init(mraa interfaces)
upm_mixed_module_init (NAME bmpx8x
DESCRIPTION "Pressure and temperature sensor"
C_HDR bmpx8x.h bmpx8x_defs.h
C_SRC bmpx8x.c
CPP_HDR bmpx8x.hpp
CPP_SRC bmpx8x.cxx
FTI_SRC bmpx8x_fti.c
CPP_WRAPS_C
REQUIRES mraa interfaces)
target_link_libraries(${libnamec} m)

360
src/bmpx8x/bmpx8x.c Normal file
View File

@ -0,0 +1,360 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 Intel Corporation.
*
* This driver was rewritten based on the original driver written by:
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
*
* 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 <assert.h>
#include "upm_utilities.h"
#include "upm_math.h"
#include "bmpx8x.h"
// UT is uncompensated temperature
static int32_t _bmpx8x_computeB5(const bmpx8x_context dev, int32_t UT)
{
assert(dev != NULL);
int32_t X1 = (UT - (int32_t)dev->ac6) * ((int32_t)dev->ac5) >> 15;
int32_t X2 = ((int32_t)dev->mc << 11) / (X1+(int32_t)dev->md);
return X1 + X2;
}
static upm_result_t _bmpx8x_read_calibration_data(const bmpx8x_context dev)
{
assert(dev != NULL);
const int dataLen = 22;
uint8_t calData[dataLen];
if (bmpx8x_read_regs(dev, BMPX8X_CAL_AC1, calData, dataLen) != dataLen)
return UPM_ERROR_OPERATION_FAILED;
dev->ac1 = (int16_t)( (calData[0] << 8) | calData[1] );
dev->ac2 = (int16_t)( (calData[2] << 8) | calData[3] );
dev->ac3 = (int16_t)( (calData[4] << 8) | calData[5] );
dev->ac4 = (uint16_t)( (calData[6] << 8) | calData[7] );
dev->ac5 = (uint16_t)( (calData[8] << 8) | calData[9] );
dev->ac6 = (uint16_t)( (calData[10] << 8) | calData[11] );
dev->b1 = (int16_t)( (calData[12] << 8) | calData[13] );
dev->b2 = (int16_t)( (calData[14] << 8) | calData[15] );
dev->mb = (int16_t)( (calData[16] << 8) | calData[17] );
dev->mc = (int16_t)( (calData[18] << 8) | calData[19] );
dev->md = (int16_t)( (calData[20] << 8) | calData[21] );
return UPM_SUCCESS;
}
// init
bmpx8x_context bmpx8x_init(int bus, int addr)
{
bmpx8x_context dev =
(bmpx8x_context)malloc(sizeof(struct _bmpx8x_context));
if (!dev)
return NULL;
// zero out context
memset((void *)dev, 0, sizeof(struct _bmpx8x_context));
// make sure MRAA is initialized
if (mraa_init() != MRAA_SUCCESS)
{
printf("%s: mraa_init() failed.\n", __FUNCTION__);
bmpx8x_close(dev);
return NULL;
}
if (!(dev->i2c = mraa_i2c_init(bus)))
{
printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__);
bmpx8x_close(dev);
return NULL;
}
if (mraa_i2c_address(dev->i2c, addr))
{
printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__);
bmpx8x_close(dev);
return NULL;
}
// check the chip id
uint8_t chipID = bmpx8x_get_chip_id(dev);
if (chipID != BMPX8X_DEFAULT_CHIPID)
{
printf("%s: invalid chip id: %02x. Expected %02x\n",
__FUNCTION__, chipID, BMPX8X_DEFAULT_CHIPID);
bmpx8x_close(dev);
return NULL;
}
// call devinit with a default ultrahigh resolution mode
if (bmpx8x_devinit(dev, BMPX8X_OSS_ULTRAHIGHRES))
{
printf("%s: bmpx8x_devinit() failed.\n", __FUNCTION__);
bmpx8x_close(dev);
return NULL;
}
return dev;
}
void bmpx8x_close(bmpx8x_context dev)
{
assert(dev != NULL);
if (dev->i2c)
mraa_i2c_stop(dev->i2c);
free(dev);
}
upm_result_t bmpx8x_devinit(const bmpx8x_context dev,
BMPX8X_OSS_T oss)
{
assert(dev != NULL);
// first read calibration data
if (_bmpx8x_read_calibration_data(dev))
{
printf("%s: _bmpx8x_read_calibration_data() failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
// now set our oversampling mode
bmpx8x_set_oversampling(dev, oss);
return UPM_SUCCESS;
}
uint8_t bmpx8x_get_chip_id(const bmpx8x_context dev)
{
assert(dev != NULL);
return bmpx8x_read_reg(dev, BMPX8X_CHIP_ID);
}
upm_result_t bmpx8x_reset(const bmpx8x_context dev)
{
assert(dev != NULL);
if (bmpx8x_write_reg(dev, BMPX8X_RESET, BMPX8X_RESET_BYTE))
return UPM_ERROR_OPERATION_FAILED;
upm_delay(1);
return UPM_SUCCESS;
}
void bmpx8x_set_oversampling(const bmpx8x_context dev,
BMPX8X_OSS_T oss)
{
assert(dev != NULL);
dev->oversampling = oss;
}
upm_result_t bmpx8x_update(const bmpx8x_context dev)
{
assert(dev != NULL);
const int maxLen = 3; // maximum number of bytes we will read
uint8_t buffer[maxLen];
// first we need to read the temperature
// send the measurement command, and sleep the required time
// before reading it
if (bmpx8x_write_reg(dev, BMPX8X_CTRL_MEAS, BMPX8X_CMD_READ_TEMP))
{
printf("%s: bmpx8x_write_reg(tempcmd) failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
upm_delay_ms(5);
if (bmpx8x_read_regs(dev, BMPX8X_OUTDATA_MSB, buffer, maxLen) != maxLen)
{
printf("%s: bmpx8x_read_regs(temp) failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
// we only need the first 2 bytes, uncompensated temperature
int32_t UT = (int32_t)( (buffer[0] << 8) | buffer[1] );
// now read in the uncompensated pressure - the delay time depends
// on the oversampling value
uint8_t reg = BMPX8X_CMD_READ_PRESSURE |
(dev->oversampling << _BMPX8X_CTRL_MEAS_OSS_SHIFT);
if (bmpx8x_write_reg(dev, BMPX8X_CTRL_MEAS, reg))
{
printf("%s: bmpx8x_write_reg(prescmd) failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
switch(dev->oversampling)
{
case BMPX8X_OSS_ULTRALOWPOWER:
upm_delay_ms(5);
break;
case BMPX8X_OSS_STANDARD:
upm_delay_ms(8);
break;
case BMPX8X_OSS_HIGHRES:
upm_delay_ms(14);
break;
case BMPX8X_OSS_ULTRAHIGHRES:
upm_delay_ms(26);
break;
}
if (bmpx8x_read_regs(dev, BMPX8X_OUTDATA_MSB, buffer, maxLen) != maxLen)
{
printf("%s: bmpx8x_read_regs(pres) failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
// uncompensated pressure
int32_t UP = ( (buffer[0] << 16) | (buffer[1] << 8) | buffer[2] );
UP >>= (8 - dev->oversampling);
// now, compensate and store
int32_t B3, B5, B6, X1, X2, X3, p;
uint32_t B4, B7;
// temperature
B5 = _bmpx8x_computeB5(dev, UT);
dev->temperature = (float)( (B5 + 8) >> 4 );
dev->temperature /= 10.0;
// pressure
B6 = B5 - 4000;
X1 = ((int32_t)dev->b2 * ( (B6 * B6)>>12 )) >> 11;
X2 = ((int32_t)dev->ac2 * B6) >> 11;
X3 = X1 + X2;
B3 = ((((int32_t)dev->ac1*4 + X3) << dev->oversampling) + 2) / 4;
X1 = ((int32_t)dev->ac3 * B6) >> 13;
X2 = ((int32_t)dev->b1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = ((uint32_t)dev->ac4 * (uint32_t)(X3 + 32768)) >> 15;
B7 = ((uint32_t)UP - B3) * (uint32_t)( 50000UL >> dev->oversampling );
if (B7 < 0x80000000)
p = (B7 * 2) / B4;
else
p = (B7 / B4) * 2;
X1 = (p >> 8) * (p >> 8);
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * p) >> 16;
dev->pressure = p + ((X1 + X2 + (int32_t)3791)>>4);
return UPM_SUCCESS;
}
int bmpx8x_get_pressure(const bmpx8x_context dev)
{
assert(dev != NULL);
return dev->pressure;
}
float bmpx8x_get_temperature(const bmpx8x_context dev)
{
assert(dev != NULL);
return dev->temperature;
}
int bmpx8x_get_sealevel_pressure(const bmpx8x_context dev,
float altitude)
{
assert(dev != NULL);
return ((float)dev->pressure / powf(1.0-altitude/44330.0, 5.255));
}
float bmpx8x_get_altitude(const bmpx8x_context dev, int sealevel)
{
assert(dev != NULL);
// avoid potential divide-by-0, and set the default to 101325 Pa
if (sealevel <= 0)
sealevel = 101325;
return 44307.69 * (1.0 - powf((float)dev->pressure / (float)sealevel,
0.190284));
}
uint8_t bmpx8x_read_reg(const bmpx8x_context dev, uint8_t reg)
{
assert(dev != NULL);
return (uint8_t)mraa_i2c_read_byte_data(dev->i2c, reg);
}
int bmpx8x_read_regs(const bmpx8x_context dev, uint8_t reg,
uint8_t *buffer, int len)
{
assert(dev != NULL);
if (mraa_i2c_read_bytes_data(dev->i2c, reg, buffer, len) != len)
return -1;
return len;
}
upm_result_t bmpx8x_write_reg(const bmpx8x_context dev,
uint8_t reg, uint8_t val)
{
assert(dev != NULL);
if (mraa_i2c_write_byte_data(dev->i2c, val, reg))
{
printf("%s: mraa_i2c_write_byte_data() failed.\n",
__FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
return UPM_SUCCESS;
}

View File

@ -1,6 +1,11 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 Intel Corporation.
*
* This driver was rewritten based on the original driver written by:
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
* Copyright (c) 2014 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,202 +36,85 @@
#include "bmpx8x.hpp"
using namespace upm;
using namespace std;
BMPX8X::BMPX8X (int bus, int devAddr, uint8_t mode) : m_controlAddr(devAddr), m_i2ControlCtx(bus) {
m_name = "BMPX8X";
mraa::Result ret = m_i2ControlCtx.address(m_controlAddr);
if (ret != mraa::SUCCESS) {
throw std::invalid_argument(std::string(__FUNCTION__) +
": mraa_i2c_address() failed");
return;
}
if (i2cReadReg_8 (0xD0) != 0x55) {
throw std::runtime_error(std::string(__FUNCTION__) +
": Invalid chip ID");
return;
}
if (mode > BMP085_ULTRAHIGHRES) {
mode = BMP085_ULTRAHIGHRES;
}
oversampling = mode;
/* read calibration data */
ac1 = i2cReadReg_16 (BMP085_CAL_AC1);
ac2 = i2cReadReg_16 (BMP085_CAL_AC2);
ac3 = i2cReadReg_16 (BMP085_CAL_AC3);
ac4 = i2cReadReg_16 (BMP085_CAL_AC4);
ac5 = i2cReadReg_16 (BMP085_CAL_AC5);
ac6 = i2cReadReg_16 (BMP085_CAL_AC6);
b1 = i2cReadReg_16 (BMP085_CAL_B1);
b2 = i2cReadReg_16 (BMP085_CAL_B2);
mb = i2cReadReg_16 (BMP085_CAL_MB);
mc = i2cReadReg_16 (BMP085_CAL_MC);
md = i2cReadReg_16 (BMP085_CAL_MD);
BMPX8X::BMPX8X (int bus, int addr) :
m_bmpx8x(bmpx8x_init(bus, addr))
{
if (!m_bmpx8x)
throw std::runtime_error(string(__FUNCTION__)
+ ": bmpx8x_init() failed");
}
int32_t
BMPX8X::getPressure () {
int32_t UT, UP, B3, B5, B6, X1, X2, X3, p;
uint32_t B4, B7;
UT = getTemperatureRaw();
UP = getPressureRaw();
B5 = computeB5(UT);
// do pressure calcs
B6 = B5 - 4000;
X1 = ((int32_t)b2 * ( (B6 * B6)>>12 )) >> 11;
X2 = ((int32_t)ac2 * B6) >> 11;
X3 = X1 + X2;
B3 = ((((int32_t)ac1*4 + X3) << oversampling) + 2) / 4;
X1 = ((int32_t)ac3 * B6) >> 13;
X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15;
B7 = ((uint32_t)UP - B3) * (uint32_t)( 50000UL >> oversampling );
if (B7 < 0x80000000) {
p = (B7 * 2) / B4
;
} else {
p = (B7 / B4) * 2;
}
X1 = (p >> 8) * (p >> 8);
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * p) >> 16;
p = p + ((X1 + X2 + (int32_t)3791)>>4);
return p;
BMPX8X::~BMPX8X()
{
bmpx8x_close(m_bmpx8x);
}
int32_t
BMPX8X::getPressureRaw () {
uint32_t raw;
i2cWriteReg (BMP085_CONTROL, BMP085_READPRESSURECMD + (oversampling << 6));
if (oversampling == BMP085_ULTRALOWPOWER) {
usleep(5000);
} else if (oversampling == BMP085_STANDARD) {
usleep(8000);
} else if (oversampling == BMP085_HIGHRES) {
usleep(14000);
} else {
usleep(26000);
}
raw = i2cReadReg_16 (BMP085_PRESSUREDATA);
raw <<= 8;
raw |= i2cReadReg_8 (BMP085_PRESSUREDATA + 2);
raw >>= (8 - oversampling);
return raw;
void BMPX8X::init(BMPX8X_OSS_T oss)
{
if (bmpx8x_devinit(m_bmpx8x, oss))
throw std::runtime_error(string(__FUNCTION__)
+ ": bmpx8x_devinit() failed");
}
int16_t
BMPX8X::getTemperatureRaw () {
i2cWriteReg (BMP085_CONTROL, BMP085_READTEMPCMD);
usleep(5000);
return i2cReadReg_16 (BMP085_TEMPDATA);
void BMPX8X::update()
{
if (bmpx8x_update(m_bmpx8x))
throw std::runtime_error(string(__FUNCTION__)
+ ": bmpx8x_update() failed");
}
float
BMPX8X::getTemperature () {
int32_t UT, B5; // following ds convention
float temp;
UT = getTemperatureRaw ();
B5 = computeB5 (UT);
temp = (B5 + 8) >> 4;
temp /= 10;
return temp;
void BMPX8X::reset()
{
if (bmpx8x_reset(m_bmpx8x))
throw std::runtime_error(string(__FUNCTION__)
+ ": bmpx8x_reset() failed");
}
int32_t
BMPX8X::getSealevelPressure(float altitudeMeters) {
float pressure = getPressure ();
return (int32_t)(pressure / pow(1.0-altitudeMeters/44330, 5.255));
void BMPX8X::setOversampling(BMPX8X_OSS_T oss)
{
bmpx8x_set_oversampling(m_bmpx8x, oss);
}
float
BMPX8X::getAltitude (float sealevelPressure) {
float altitude;
float pressure = getPressure ();
altitude = 44330 * (1.0 - pow(pressure /sealevelPressure,0.1903));
return altitude;
uint8_t BMPX8X::readReg(uint8_t reg)
{
return bmpx8x_read_reg(m_bmpx8x, reg);
}
int BMPX8X::readRegs(uint8_t reg, uint8_t *buffer, int len)
{
int rv = bmpx8x_read_regs(m_bmpx8x, reg, buffer, len);
if (rv < 0)
throw std::runtime_error(string(__FUNCTION__)
+ ": bmpx8x_read_regs() failed");
int
BMPX8X::getTemperatureCelsius() {
return static_cast<int>(getTemperature() + 0.5);
return rv;
}
const char*
BMPX8X::getModuleName() {
return m_name.c_str();
void BMPX8X::writeReg(uint8_t reg, uint8_t val)
{
if (bmpx8x_write_reg(m_bmpx8x, reg, val))
throw std::runtime_error(string(__FUNCTION__)
+ ": bmpx8x_write_reg() failed");
}
int32_t
BMPX8X::computeB5(int32_t UT) {
int32_t X1 = (UT - (int32_t)ac6) * ((int32_t)ac5) >> 15;
int32_t X2 = ((int32_t)mc << 11) / (X1+(int32_t)md);
return X1 + X2;
int BMPX8X::getPressure()
{
return bmpx8x_get_pressure(m_bmpx8x);
}
mraa::Result
BMPX8X::i2cWriteReg (uint8_t reg, uint8_t value) {
mraa::Result error = mraa::SUCCESS;
uint8_t data[2] = { reg, value };
error = m_i2ControlCtx.address (m_controlAddr);
error = m_i2ControlCtx.write (data, 2);
return error;
float BMPX8X::getTemperature()
{
return bmpx8x_get_temperature(m_bmpx8x);
}
uint16_t
BMPX8X::i2cReadReg_16 (int reg) {
uint16_t data;
m_i2ControlCtx.address(m_controlAddr);
m_i2ControlCtx.writeByte(reg);
m_i2ControlCtx.address(m_controlAddr);
m_i2ControlCtx.read((uint8_t *)&data, 0x2);
uint8_t high = (data & 0xFF00) >> 8;
data = (data << 8) & 0xFF00;
data |= high;
return data;
int BMPX8X::getSealevelPressure(float altitudeMeters)
{
return bmpx8x_get_sealevel_pressure(m_bmpx8x, altitudeMeters);
}
uint8_t
BMPX8X::i2cReadReg_8 (int reg) {
uint8_t data;
m_i2ControlCtx.address(m_controlAddr);
m_i2ControlCtx.writeByte(reg);
m_i2ControlCtx.address(m_controlAddr);
m_i2ControlCtx.read(&data, 0x1);
return data;
float BMPX8X::getAltitude(int sealevelPressure)
{
return bmpx8x_get_altitude(m_bmpx8x, sealevelPressure);
}

230
src/bmpx8x/bmpx8x.h Normal file
View File

@ -0,0 +1,230 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 Intel Corporation.
*
* This driver was rewritten based on the original driver written by:
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
*
* 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 <unistd.h>
#include <string.h>
#include <mraa/i2c.h>
#include "upm.h"
#include "bmpx8x_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file bmpx8x.h
* @library bmpx8x
* @brief C API for the bmpx8x driver
*
* @include bmpx8x.c
*/
/**
* Device context
*/
typedef struct _bmpx8x_context {
mraa_i2c_context i2c;
// our oversampling (precision)
BMPX8X_OSS_T oversampling;
// compensated temperature and pressure
float temperature;
int pressure;
// compensation coefficients
int16_t ac1;
int16_t ac2;
int16_t ac3;
uint16_t ac4;
uint16_t ac5;
uint16_t ac6;
int16_t b1;
int16_t b2;
int16_t mb;
int16_t mc;
int16_t md;
} *bmpx8x_context;
/**
* BMPX8X initialization.
*
* By default, the device is initialized to it's highest accuracy
* (BMP085_OSS_ULTRAHIGHRES).
*
* @param bus I2C bus number.
* @param addr I2C address of the device.
* @return Device context, or NULL if an error occurred.
*/
bmpx8x_context bmpx8x_init(int bus, int addr);
/**
* BMPX8X close function.
*
* @param dev Device context.
*/
void bmpx8x_close(bmpx8x_context dev);
/**
* Return the chip ID.
*
* @param dev The device context.
* @return The chip ID.
*/
uint8_t bmpx8x_get_chip_id(const bmpx8x_context dev);
/**
* Initialize the device, read calibration data, and start
* operation. This function is called from bmpx8x_init() so it
* will not typically need to be called by a user unless the
* device is reset. This method will call
* bmpx8x_set_oversampling() with the passed parameter.
*
* @param dev The device context.
* @param oss One of the BMPX8X_OSS_T values. The default set
* at bmpx8x_init() time is BMP085_OSS_ULTRAHIGHRES.
* @return UPM result.
*/
upm_result_t bmpx8x_devinit(const bmpx8x_context dev,
BMPX8X_OSS_T oss);
/**
* Perform a device reset. The device will be reset as if it was
* just powered on. All compensation values will be lost. You
* should call bmpx8x_devinit() afterward, or perform the same
* steps that bmpx8x_devinit() performs before attempting to use
* the device.
*
* @param dev The device context.
* @return UPM result.
*/
upm_result_t bmpx8x_reset(const bmpx8x_context dev);
/**
* Update the internal stored values from sensor data.
*
* @param dev The device context.
* @return UPM result.
*/
upm_result_t bmpx8x_update(const bmpx8x_context dev);
/**
* Set the oversampling (precision mode) of the device. Higher
* precision requires more time to complete.
*
* @param dev The device context.
* @param oss The desired oversampling mode, one of the
* BMPX8X_OSS_T values.
*/
void bmpx8x_set_oversampling(const bmpx8x_context dev,
BMPX8X_OSS_T oss);
/**
* Returns the pressure in Pascals. bmpx8x_update() must have
* been called prior to calling this function.
*
* @param dev Device context.
* @return The pressure in Pascals.
*/
int bmpx8x_get_pressure(const bmpx8x_context dev);
/**
* Returns the temperature in degrees Celsius. bmpx8x_update()
* must have been called prior to calling this function.
*
* @param dev Device context.
* @return The temperature in degrees Celsius.
*/
float bmpx8x_get_temperature(const bmpx8x_context dev);
/**
* With a given current altitude, calculate pressure at sea level.
* bmpx8x_update() must have been called prior to calling this
* function.
*
* @param dev Device context.
* @param altitude Current altitude in Meters.
* @return The pressure in Pascals at sea level.
*/
int bmpx8x_get_sealevel_pressure(const bmpx8x_context dev,
float altitude);
/**
* With a given sea level, calculate altitude in meters.
* bmpx8x_update() must have been called prior to calling this
* function.
*
* @param dev Device context.
* @param sealevel Sea level pressure in Pascals. If a negative
* number, or zero is supplied, a default sealevel of 101325 Pa
* will be used instead.
* @return The current altitude in Meters.
*/
float bmpx8x_get_altitude(const bmpx8x_context dev, int sealevel);
/**
* Read a register.
*
* @param dev The device context.
* @param reg The register to read.
* @return The value of the register.
*/
uint8_t bmpx8x_read_reg(const bmpx8x_context dev, uint8_t reg);
/**
* Read contiguous registers into a buffer.
*
* @param dev The 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 bmpx8x_read_regs(const bmpx8x_context dev, uint8_t reg,
uint8_t *buffer, int len);
/**
* Write to a register.
*
* @param dev The device context.
* @param reg The register to write to.
* @param val The value to write.
* @return UPM result.
*/
upm_result_t bmpx8x_write_reg(const bmpx8x_context dev,
uint8_t reg, uint8_t val);
#ifdef __cplusplus
}
#endif

View File

@ -1,10 +1,11 @@
/*
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
* Contributions: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation.
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 Intel Corporation.
*
* Credits to Adafruit.
* Based on Adafruit BMP085 library.
* This driver was rewritten based on the original driver written by:
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -28,182 +29,218 @@
#pragma once
#include <string>
#include <mraa/i2c.hpp>
#include <math.h>
#include "bmpx8x.h"
#include "interfaces/iPressureSensor.hpp"
#include "interfaces/iTemperatureSensor.hpp"
#define ADDR 0x77 // device address
// registers address
#define BMP085_ULTRALOWPOWER 0
#define BMP085_STANDARD 1
#define BMP085_HIGHRES 2
#define BMP085_ULTRAHIGHRES 3
#define BMP085_CAL_AC1 0xAA // R Calibration data (16 bits)
#define BMP085_CAL_AC2 0xAC // R Calibration data (16 bits)
#define BMP085_CAL_AC3 0xAE // R Calibration data (16 bits)
#define BMP085_CAL_AC4 0xB0 // R Calibration data (16 bits)
#define BMP085_CAL_AC5 0xB2 // R Calibration data (16 bits)
#define BMP085_CAL_AC6 0xB4 // R Calibration data (16 bits)
#define BMP085_CAL_B1 0xB6 // R Calibration data (16 bits)
#define BMP085_CAL_B2 0xB8 // R Calibration data (16 bits)
#define BMP085_CAL_MB 0xBA // R Calibration data (16 bits)
#define BMP085_CAL_MC 0xBC // R Calibration data (16 bits)
#define BMP085_CAL_MD 0xBE // R Calibration data (16 bits)
#define BMP085_CONTROL 0xF4
#define BMP085_TEMPDATA 0xF6
#define BMP085_PRESSUREDATA 0xF6
#define BMP085_READTEMPCMD 0x2E
#define BMP085_READPRESSURECMD 0x34
#define HIGH 1
#define LOW 0
namespace upm {
/**
* @brief Bosch BMP & GY65 Atmospheric Pressure Sensor library
* @defgroup bmpx8x libupm-bmpx8x
* @ingroup seeed adafruit sparkfun i2c pressure
*/
/**
* @brief Bosch BMP & GY65 Atmospheric Pressure Sensor library
* @defgroup bmpx8x libupm-bmpx8x @ingroup seeed adafruit sparkfun i2c
* pressure
*/
/**
* @library bmpx8x
* @sensor bmpx8x
* @comname BMP Atmospheric Pressure Sensor
* @altname GY65 BMP085 BMP180 BMP183
* @type pressure
* @man seeed adafruit sparkfun
* @con i2c
* @web https://www.sparkfun.com/datasheets/Components/General/BST-BMP085-DS000-05.pdf
* @web https://www.bosch-sensortec.com/bst/products/all_products/bmp180
* @web https://cdn-shop.adafruit.com/datasheets/1900_BMP183.pdf
*
* @brief API for the GY65/BMP085 and BMP180 Atmospheric Pressure Sensors
*
* Bosch GY65/BMP085 and BMP180 are high-precision, ultra-low
* power consumption pressure sensors. They operate in the range of
* 30,000-110,000 Pa.
*
* This module has been tested on the GY65/BMP085 and BMP180 sensors.
*
* @image html bmp085.jpeg
* @snippet bmpx8x.cxx Interesting
*/
/**
* @library bmpx8x
* @sensor bmpx8x
* @comname BMP Atmospheric Pressure Sensor
* @altname GY65 BMP085 BMP180 BMP183
* @type pressure
* @man seeed adafruit sparkfun
* @con i2c
* @web https://www.sparkfun.com/datasheets/Components/General/BST-BMP085-DS000-05.pdf
* @web https://www.bosch-sensortec.com/bst/products/all_products/bmp180
* @web https://cdn-shop.adafruit.com/datasheets/1900_BMP183.pdf
*
* @brief API for the GY65/BMP085 and BMP180 Atmospheric Pressure Sensors
*
* Bosch GY65/BMP085 and BMP180 are high-precision, ultra-low
* power consumption pressure sensors. They operate in the range of
* 30,000-110,000 Pa.
*
* This module has been tested on the GY65/BMP085 and BMP180 sensors.
*
* @image html bmp085.jpeg
* @snippet bmpx8x.cxx Interesting
*/
class BMPX8X : public IPressureSensor, public ITemperatureSensor {
class BMPX8X : public IPressureSensor, public ITemperatureSensor {
public:
/**
* Instantiates a BMPX8X object
*
* @param bus Number of the used bus
* @param devAddr Address of the used I2C device
* @param mode BMP085 mode
* @param bus I2C bus to use.
* @param addr The I2C address of the device.
* @throws std::runtime_error on failure.
*/
BMPX8X (int bus, int devAddr=0x77, uint8_t mode=BMP085_ULTRAHIGHRES);
BMPX8X(int bus=BMPX8X_DEFAULT_I2C_BUS,
int addr=BMPX8X_DEFAULT_I2C_ADDR);
/**
* BMPX8X object destructor; basically, it closes the I2C connection.
* ~BMPX8X ();
* LE: there is no need for the destructor, as the I2C connection
* will be closed when the m_i2ControlCtx variable will go out of
* scope (when all the BMPX8X objects will be destroyed)
* BMPX8X object destructor.
*/
/**
* Returns the calculated pressure
*/
int32_t getPressure ();
virtual ~BMPX8X();
/**
* Query the device and update the internal state. This
* method must be called before calling getPressure(),
* getTemperature(), getSealevelPressure(), and getAltitude()
* to retrieve values.
*
* Gets raw pressure data
* @throws std::runtime_error on failure.
*/
int32_t getPressureRaw ();
void update();
/**
* Gets raw temperature data from the sensor
*/
int16_t getTemperatureRaw ();
/**
* Returns the calculated temperature
*/
float getTemperature ();
/**
* With a given absolute altitude, sea level can be calculated
* Reset the device to power-on defaults. All calibration
* data is lost when the device is reset, so you should call
* init() before attempting to use the device.
*
* @param altitudeMeters Altitude
* @throws std::runtime_error on failure.
*/
int32_t getSealevelPressure(float altitudeMeters = 0);
void reset();
/**
* With a given sea level, altitude in meters can be calculated
* Initialize the device, read calibration data, and start
* operation. This function is called from the constructor,
* so it will not typically need to be called by a user unless
* the device is reset.
*
* @param sealevelPressure Sea level
* @param oss One of the BMPX8X_OSS_T values. The
* default is BMPX8X_OSS_ULTRAHIGHRES.
* @throws std::runtime_error on failure.
*/
float getAltitude (float sealevelPressure = 101325);
void init(BMPX8X_OSS_T oss=BMPX8X_OSS_ULTRAHIGHRES);
/**
* Return latest calculated temperature value in Celsius
* See ITemperatureSensor
*/
int getTemperatureCelsius();
/**
* Return latest calculated pressure value in Pascals
* See IPressureSensor
*/
int getPressurePa() { return getPressure(); };
/**
* Returns name of module. This is the string in library name
* after libupm_
* @return name of module
*/
const char* getModuleName();
/**
* Calculates B5 (check the spec for more information)
* Set the oversampling (precision mode) of the device.
* Higher precision requires more time to complete. This call
* takes effect the next time update() is called.
*
* @param UT
* @param oss One of the BMPX8X_OSS_T values. The
* default is BMPX8X_OSS_ULTRAHIGHRES.
*/
int32_t computeB5 (int32_t UT);
void setOversampling(BMPX8X_OSS_T oss=BMPX8X_OSS_ULTRAHIGHRES);
/**
* Reads a two-byte register
* Returns the calculated pressure in Pascals. update() must
* have been called prior to calling this function.
*
* @param reg Address of the register
* @returns The pressure in Pascals.
*/
uint16_t i2cReadReg_16 (int reg);
int getPressure();
/**
* Writes to a one-byte register
* Returns the calculated temperature in Celsius. update()
* must have been called prior to calling this function.
*
* @param reg Address of the register
* @param value Byte to be written
* @returns The temperature in Celsius.
*/
mraa::Result i2cWriteReg (uint8_t reg, uint8_t value);
float getTemperature();
/**
* Reads a one-byte register
* Using the supplied altitude in meters, compute the pressure
* at sea level in Pascals. update() must have been called
* prior to calling this function.
*
* @param reg Address of the register
* @param meters The altitude in meters.
* @returns The computed sea level pressure in Pascals.
*/
uint8_t i2cReadReg_8 (int reg);
int getSealevelPressure(float meters);
/**
* Using the current calculated altitude, compute the pressure
* at sea level in Pascals. update() must have been called
* prior to calling this function.
*
* @returns The computed sea level pressure in Pascals.
*/
int getSealevelPressure()
{
return getSealevelPressure(getAltitude());
}
/**
* Calculate the current altitude in meters, given a sea level
* pressure in Pascals. The default sea level pressure is
* 101325 Pascals. update() must have been called prior to
* calling this function.
*
* @param sealevelPressure The pressure at sea level in
* Pascals. The default is 101325 Pascals.
* @returns the computed altitude in meters.
*/
float getAltitude(int sealevelPressure = 101325);
/**
* Return latest calculated temperature value in Celsius. See
* ITemperatureSensor.
*
* @return The current temperature in Celsius.
*/
int getTemperatureCelsius()
{
update();
return (int)getTemperature();
}
/**
* Return latest calculated pressure value in Pascals. See
* IPressureSensor.
*
* @return The current pressure in Pascals.
*/
int getPressurePa()
{
update();
return getPressure();
}
/**
* Returns the name of module.
*
* @return The name of the module.
*/
const char *getModuleName()
{
return "BMPX8X";
}
protected:
// our underlying C context.
bmpx8x_context m_bmpx8x;
/**
* Read a register.
*
* @param reg The register to read.
* @return The value of the register.
*/
uint8_t readReg(uint8_t reg);
/**
* Read contiguous registers into a buffer.
*
* @param buffer The buffer to store the results.
* @param len The number of registers to read.
* @return The number of bytes read.
* @throws std::runtime_error on failure.
*/
int readRegs(uint8_t reg, uint8_t *buffer, int len);
/**
* Write to a register.
*
* @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);
private:
std::string m_name;
int m_controlAddr;
mraa::I2c m_i2ControlCtx;
uint8_t oversampling;
int16_t ac1, ac2, ac3, b1, b2, mb, mc, md;
uint16_t ac4, ac5, ac6;
};
};
}

110
src/bmpx8x/bmpx8x_defs.h Normal file
View File

@ -0,0 +1,110 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 Intel Corporation.
*
* This driver was rewritten based on the original driver written by:
* Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
*
* 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
#define BMPX8X_DEFAULT_I2C_BUS 0
#define BMPX8X_DEFAULT_I2C_ADDR 0x77
#define BMPX8X_DEFAULT_CHIPID 0x55
// special reset byte
#define BMPX8X_RESET_BYTE 0xb6
#ifdef __cplusplus
extern "C" {
#endif
/**
* BMPX8X registers.
*/
typedef enum {
BMPX8X_CAL_AC1 = 0xaa, // Calibration data (16
// bits, msb/lsb)
BMPX8X_CAL_AC2 = 0xac,
BMPX8X_CAL_AC3 = 0xae,
BMPX8X_CAL_AC4 = 0xb0,
BMPX8X_CAL_AC5 = 0xb2,
BMPX8X_CAL_AC6 = 0xb4,
BMPX8X_CAL_B1 = 0xb6,
BMPX8X_CAL_B2 = 0xb8,
BMPX8X_CAL_MB = 0xba,
BMPX8X_CAL_MC = 0xbc,
BMPX8X_CAL_MD = 0xbe,
BMPX8X_CTRL_MEAS = 0xf4, // command reg
BMPX8X_OUTDATA_MSB = 0xf6,
BMPX8X_OUTDATA_LSB = 0xf7,
BMPX8X_OUTDATA_XLSB = 0xf8,
BMPX8X_RESET = 0xe0,
BMPX8X_CHIP_ID = 0xd0
} BMPX8X_REGS_T;
/**
* BMPX8X_CTRL_MEAS register bits
*/
typedef enum {
BMPX8X_CTRL_MEAS_CMD0 = 0x01, // measurement command
BMPX8X_CTRL_MEAS_CMD1 = 0x02,
BMPX8X_CTRL_MEAS_CMD2 = 0x04,
BMPX8X_CTRL_MEAS_CMD3 = 0x08,
BMPX8X_CTRL_MEAS_CMD4 = 0x10,
_BMPX8X_CTRL_MEAS_CMD_MASK = 31,
_BMPX8X_CTRL_MEAS_CMD_SHIFT = 0,
BMPX8X_CTRL_MEAS_SCO = 0x20, // start conversion status
BMPX8X_CTRL_MEAS_OSS0 = 0x40, // oversampling (precision)
BMPX8X_CTRL_MEAS_OSS1 = 0x80,
_BMPX8X_CTRL_MEAS_OSS_MASK = 3,
_BMPX8X_CTRL_MEAS_OSS_SHIFT = 6,
} BMPX8X_CTRL_MEAS_BITS_T;
/**
* BMPX8X_CTRL_MEAS_CMD commands.
*/
typedef enum {
BMPX8X_CMD_READ_TEMP = 0x2e,
BMPX8X_CMD_READ_PRESSURE = 0x34
} BMPX8X_CMD_T;
/**
* BMPX8X_CTRL_MEAS_OSS, Oversampling ratio values.
*/
typedef enum {
BMPX8X_OSS_ULTRALOWPOWER = 0,
BMPX8X_OSS_STANDARD = 1,
BMPX8X_OSS_HIGHRES = 2,
BMPX8X_OSS_ULTRAHIGHRES = 3
} BMPX8X_OSS_T;
#ifdef __cplusplus
}
#endif

137
src/bmpx8x/bmpx8x_fti.c Normal file
View File

@ -0,0 +1,137 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2017 Intel Corporation.
*
* 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 "bmpx8x.h"
#include "upm_fti.h"
/**
* This file implements the Function Table Interface (FTI) for this sensor
*/
const char upm_bmpx8x_name[] = "BMPX8X";
const char upm_bmpx8x_description[] = "BMPX8X Pressure and Temperature Sensor";
const upm_protocol_t upm_bmpx8x_protocol[] = {UPM_I2C};
const upm_sensor_t upm_bmpx8x_category[] = {UPM_TEMPERATURE, UPM_PRESSURE};
// forward declarations
const void* upm_bmpx8x_get_ft(upm_sensor_t sensor_type);
void* upm_bmpx8x_init_name();
void upm_bmpx8x_close(void *dev);
upm_result_t upm_bmpx8x_get_pressure(void *dev, float *value);
upm_result_t upm_bmpx8x_get_temperature(void *dev, float *value,
upm_temperature_u unit);
const upm_sensor_descriptor_t upm_bmpx8x_get_descriptor()
{
upm_sensor_descriptor_t usd;
usd.name = upm_bmpx8x_name;
usd.description = upm_bmpx8x_description;
usd.protocol_size = 1;
usd.protocol = upm_bmpx8x_protocol;
usd.category_size = 2;
usd.category = upm_bmpx8x_category;
return usd;
}
static const upm_sensor_ft ft =
{
.upm_sensor_init_name = upm_bmpx8x_init_name,
.upm_sensor_close = upm_bmpx8x_close,
};
static const upm_temperature_ft tft =
{
.upm_temperature_get_value = upm_bmpx8x_get_temperature,
};
static const upm_pressure_ft pft =
{
.upm_pressure_get_value = upm_bmpx8x_get_pressure,
};
const void* upm_bmpx8x_get_ft(upm_sensor_t sensor_type)
{
switch(sensor_type)
{
case UPM_SENSOR:
return &ft;
case UPM_PRESSURE:
return &pft;
case UPM_TEMPERATURE:
return &tft;
default:
return NULL;
}
}
void* upm_bmpx8x_init_name()
{
return NULL;
}
void upm_bmpx8x_close(void *dev)
{
bmpx8x_close((bmpx8x_context)dev);
}
upm_result_t upm_bmpx8x_get_pressure(void *dev, float *value)
{
upm_result_t rv;
if ((rv = bmpx8x_update((bmpx8x_context)dev)))
return rv;
*value = bmpx8x_get_pressure((bmpx8x_context)dev);
return UPM_SUCCESS;
}
upm_result_t upm_bmpx8x_get_temperature(void *dev, float *value,
upm_temperature_u unit)
{
upm_result_t rv;
if ((rv = bmpx8x_update((bmpx8x_context)dev)))
return rv;
// always in C
float temp = bmpx8x_get_temperature((bmpx8x_context)dev);
switch (unit)
{
case CELSIUS:
*value = temp;
return UPM_SUCCESS;
case KELVIN:
*value = temp + 273.15;
return UPM_SUCCESS;
case FAHRENHEIT:
*value = temp * (9.0/5.0) + 32.0;
return UPM_SUCCESS;
}
return UPM_SUCCESS;
}

View File

@ -8,6 +8,7 @@
#include "bmpx8x.hpp"
%}
%include "bmpx8x_defs.h"
%include "bmpx8x.hpp"
%pragma(java) jniclasscode=%{

View File

@ -5,4 +5,5 @@
#include "bmpx8x.hpp"
%}
%include "bmpx8x_defs.h"
%include "bmpx8x.hpp"

View File

@ -5,6 +5,7 @@
%include "stdint.i"
%include "bmpx8x_defs.h"
%include "bmpx8x.hpp"
%{
#include "bmpx8x.hpp"