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
@ -19,10 +67,10 @@ compatibility between releases:
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.
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*
@ -42,8 +90,8 @@ compatibility between releases:
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.
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

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);
// ! [Interesting]
// Instantiate a BMPX8X sensor on I2C using defaults.
upm_bmpx8x.BMPX8X sensor = new upm_bmpx8x.BMPX8X();
// 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();
// temperature values every .5 seconds
while (true)
{
sensor.update();
Thread.sleep(1000);
System.out.println("Pressure: "
+ sensor.getPressure()
+ " Pa, Temperature: "
+ sensor.getTemperature()
+ " C, Altitude: "
+ sensor.getAltitude()
+ " m, Sea level: "
+ sensor.getSealevelPressure()
+ " Pa");
Thread.sleep(500);
}
// ! [Interesting]
// ! [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...");
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,48 +29,21 @@
#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
* @defgroup bmpx8x libupm-bmpx8x @ingroup seeed adafruit sparkfun i2c
* pressure
*/
/**
/**
* @library bmpx8x
* @sensor bmpx8x
* @comname BMP Atmospheric Pressure Sensor
@ -93,117 +67,180 @@ namespace upm {
* @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"