Compare commits

..

16 Commits

Author SHA1 Message Date
1849e22154 upm: v0.7.2
Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-06-30 16:28:44 -07:00
dec9b2096e mraa: Updated mraa dependecy to 1.1.1
There were api changes for iio kernel support on mraa which cascade to
UPM - setting the minimum version of mraa required.

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-06-30 15:15:50 -07:00
e1df8b5bf6 iio_core: Patches for IIO core kernel standard
Applying patches from Kuan Loon Lay.

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-06-30 14:57:19 -07:00
634208e3dc upm: v0.7.1
Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-06-28 11:37:42 -07:00
05ca452831 python: Removed exact from find_package
Failing on exact match for minor version.  Reverting back to
non-exact match.

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-06-24 23:01:25 -07:00
19b0b0c2f1 python: Fixes for building python modules
Moved src include AFTER setter for PYTHONBUILD_VERSION.  In this way,
the src CMakeLists has a valid PYTHONBUILD_VERSION str.
Call find_package on PythonInterp prior to finding the libs (recommended).

Signed-off-by: Noel Eck <noel.eck@intel.com>
2016-06-24 17:11:28 -07:00
9a74a3b4f5 LCD:jhd1313m1:HD44780 Setting number of rows and font size
Signed-off-by: Akira Tsukamoto <akira.tsukamoto@linaro.org>
Signed-off-by: Abhishek Malik <abhishek.malik@intel.com>
2016-06-17 14:24:36 -07:00
25c0f8ebb1 LCD:jhd1313m1:HD44780 Adding workaround of errata on init
HD44780 fails to initialize unsuccessfully without the workaround.

Adding workaround based on HD77480 datasheet for initialization
and software reset.

Signed-off-by: Akira Tsukamoto <akira.tsukamoto@linaro.org>
Signed-off-by: Abhishek Malik <abhishek.malik@intel.com>
2016-06-17 14:23:53 -07:00
33e2c03b48 tb7300: Initial implementation
This module implements support for the Honeywell TB7300 Communicating
Fan Coil Thermostat.  It may also support the TB7200, though only the
TB7300 was available for development of this driver.

The TB7200 Series PI thermostats are designed for zoning applications,
and the TB7300 Series PI thermostats are designed for fan coil
control. Both Series are communicating thermostats with models
available in BACnet® MS/TP protocol and can be easily integrated into
a WEBs-AX building automation system based on the NiagaraAX® platform.

TB7200 and TB7300 Series thermostats are compatible with the Honeywell
Occupancy Sensor Cover. Thermostats equipped with an occupancy sensor
cover provide advanced active occupancy logic, which will
automatically switch occupancy levels from Occupied to Stand-By and
Unoccupied as required by local activity being present or not. This
advanced occupancy functionality provides advantageous energy savings
during occupied hours without sacrificing occupant comfort. All
thermostats can be ordered with or without a factory installed PIR
cover.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-06-14 17:12:32 -06:00
3c5d498ae5 t8100: Initial implementation
This module implements support for the Amphenol Telaire Ventostat
T8100 Ventilation Controller with BACnet interface.  It may also
support the T8200 and T8300 models, but they have not been tested.

The Telaire Ventostat T8100 reports Temperature, Humidity and CO2
concentrations.  It supports an optional relay with a settable trigger
point.  The unit this driver was tested under did not support the
optional relay.  The temperature range supported is 0-50C, humidity is
0-100% non-condensing, and CO2 range is appoximately 0-2000 PPM for
the T8100.  Other sensors in this family support wider ranges.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-06-14 17:04:17 -06:00
93fea877e3 e50hx: use the new bacnetutil class
This commit removes functionality that is now present in the
bacnetutil class.  This simplifies the driver considerably.  The
examples were modified to reflect the renaming of some utility
functions in bacnetutil.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-06-14 17:00:00 -06:00
b7f038de3d bacnetmstp: add new bacnetutil class to bacnetmstp UPM library
There is some functionality that will always be needed for BACnet
drivers.  Here we create a new bacnetutil class, built as part of the
bacnetmstp library that can handle much of the data handling and setup
a BACnet driver will need.

The idea is that any BACnet functionality needed, that is not
device-specific, should be added to this class for all drivers to use.

The intent is that all BACnet drivers will inherit from this class.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-06-14 16:53:17 -06:00
f03696b7a5 bacnetmstp: Add array support and the ability to create BACnet enums
This reworks the data handling portion of bacnetmstp.  Instead of just
handling a single data element returned from a device, we can handle
more, as in the case of BACnet arrays.

Added the ability to create BACnet enum data elements.  This is needed
in order to set binary value objects.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-06-14 16:53:17 -06:00
8fb7907a4e bmx055, bmi055, bmc160, bma250e, bmg150, bmm150: Initial implementation
This module (bmx055) implements support for the following core Bosch
chipsets:

bma250e - accelerometer, 3 variants (chip id's 0x03, 0xf9, and 0xfa)
bmm150 - magnetometer
bmg160 - gyroscope

The other 3 devices are combinations of the above:

bmx055 - accel/gyro/mag
bmc160 - accel/mag
bmi055 - accel/gyro

...for 6 devices total.

For the combination devices, all of the sub-devices appear as
individual independent devices on the I2C/SPI bus.

The combination drivers provide basic configuration and data output.
For more detailed control as well as interrupt support, you should use
the core device drivers (accel/gyro/mag) directly.

These devices support both I2C and SPI communications.  They must be
powered at 3.3vdc.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-06-14 16:40:21 -06:00
66bd4ee8c8 readme: fixed broken link to MRAA in Readme.md
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
2016-05-13 17:25:15 -07:00
fd707242a9 node: bumped dependency for node modules to v4.4.x
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
2016-05-13 17:24:19 -07:00
92 changed files with 12004 additions and 888 deletions

View File

@ -10,7 +10,7 @@ find_package (PkgConfig REQUIRED)
# Force a libmraa search and minimum required version every time a config is generated
unset(MRAA_FOUND CACHE)
pkg_check_modules (MRAA REQUIRED mraa>=1.0.0)
pkg_check_modules (MRAA REQUIRED mraa>=1.1.1)
message (INFO " found mraa version: ${MRAA_VERSION}")
# Appends the cmake/modules path to MAKE_MODULE_PATH variable.
@ -25,7 +25,7 @@ include (GetGitRevisionDescription)
git_describe (VERSION "--tags")
if ("x_${VERSION}" STREQUAL "x_GIT-NOTFOUND" OR "x_${VERSION}" STREQUAL "x_-128-NOTFOUND")
message (WARNING " - Install git to compile a production UPM!")
set (VERSION "v0.7.0-dirty")
set (VERSION "v0.7.2-dirty")
endif ()
message (INFO " - UPM Version ${VERSION}")
@ -231,8 +231,6 @@ if (RPM)
include(CPack)
endif()
add_subdirectory (src)
if(BUILDEXAMPLES)
add_subdirectory (examples/c++)
endif()
@ -249,6 +247,8 @@ if (BUILDSWIGPYTHON OR BUILDTESTS)
endif ()
endif ()
add_subdirectory (src)
if (BUILDTESTS)
find_package (PythonInterp ${PYTHONBUILD_VERSION} REQUIRED)
enable_testing ()

View File

@ -4,7 +4,7 @@ UPM (Useful Packages & Modules) Sensor/Actuator repository for MRAA
The UPM repository provides software drivers for a wide variety of commonly
used sensors and actuators. These software drivers interact with the
underlying hardware platform (or microcontroller), as well as with the attached
sensors, through calls to [MRAA](github.com/intel-iot-devkit/mraa) APIs.
sensors, through calls to [MRAA](https://github.com/intel-iot-devkit/mraa) APIs.
Programmers can access the interfaces for each sensor by including the sensors
corresponding header file and instantiating the associated sensor class. In the

View File

@ -4,6 +4,19 @@ Changelog {#changelog}
Here's a list summarizing some of the key undergoing changes to our library
from earlier versions:
### v0.7.2
* Mraa 1.1.1 required changes to UPM drivers and examples for IIO core
kernel support
* Rev'ed libmraa requirement to 1.1.1
### v0.7.1
* Fix for building python2 vs python3 bindings
* Fixes for jhd1313m1 row/font size and reset
* Added bacnet utility class
* New sensors: bmx055, bmi055, bmc160, bma250e, bmg150, bmm150, t8100, tb7300
### v0.7.0
* C++ header files have been renamed from *.h to *.hpp along with all Intel

View File

@ -262,6 +262,8 @@ if (BACNET_FOUND)
# we need access to bacnetmstp headers too
include_directories(${PROJECT_SOURCE_DIR}/src/bacnetmstp)
add_example (e50hx)
add_example (t8100)
add_example (tb7300)
endif()
add_example (vcap)
add_example (ds2413)
@ -269,6 +271,7 @@ add_example (ds18b20)
add_example (bmp280)
add_example (bno055)
add_example (l3gd20)
add_example (bmx055)
# These are special cases where you specify example binary, source file and module(s)
include_directories (${PROJECT_SOURCE_DIR}/src)
@ -295,3 +298,8 @@ add_custom_example (adc-example adc-sensor.cxx "ads1x15")
add_custom_example (light-sensor-example light-sensor.cxx "si1132;max44009")
add_custom_example (light-controller-example light-controller.cxx "lp8860;ds1808lc;hlg150h")
add_custom_example (bme280-example bme280.cxx bmp280)
add_custom_example (bma250e-example bma250e.cxx bmx055)
add_custom_example (bmg160-example bmg160.cxx bmx055)
add_custom_example (bmm150-example bmm150.cxx bmx055)
add_custom_example (bmc150-example bmc150.cxx bmx055)
add_custom_example (bmi055-example bmi055.cxx bmx055)

83
examples/c++/bma250e.cxx Normal file
View File

@ -0,0 +1,83 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "bma250e.hpp"
using namespace std;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate an BMA250E using default I2C parameters
upm::BMA250E *sensor = new upm::BMA250E();
// For SPI, bus 0, you would pass -1 as the address, and a valid pin
// for CS: BMA250E(0, -1, 10);
// now output data every 250 milliseconds
while (shouldRun)
{
float x, y, z;
sensor->update();
sensor->getAccelerometer(&x, &y, &z);
cout << "Accelerometer x: " << x
<< " y: " << y
<< " z: " << z
<< " g"
<< endl;
// we show both C and F for temperature
cout << "Compensation Temperature: " << sensor->getTemperature()
<< " C / " << sensor->getTemperature(true) << " F"
<< endl;
cout << endl;
usleep(250000);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

82
examples/c++/bmc150.cxx Normal file
View File

@ -0,0 +1,82 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "bmc150.hpp"
using namespace std;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate an BMC150 using default I2C parameters
upm::BMC150 *sensor = new upm::BMC150();
// now output data every 250 milliseconds
while (shouldRun)
{
float x, y, z;
sensor->update();
sensor->getAccelerometer(&x, &y, &z);
cout << "Accelerometer x: " << x
<< " y: " << y
<< " z: " << z
<< " g"
<< endl;
sensor->getMagnetometer(&x, &y, &z);
cout << "Magnetometer x: " << x
<< " y: " << y
<< " z: " << z
<< " uT"
<< endl;
cout << endl;
usleep(250000);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

83
examples/c++/bmg160.cxx Normal file
View File

@ -0,0 +1,83 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "bmg160.hpp"
using namespace std;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate an BMG160 using default I2C parameters
upm::BMG160 *sensor = new upm::BMG160();
// For SPI, bus 0, you would pass -1 as the address, and a valid pin
// for CS: BMG160(0, -1, 10);
// now output data every 250 milliseconds
while (shouldRun)
{
float x, y, z;
sensor->update();
sensor->getGyroscope(&x, &y, &z);
cout << "Gyroscope x: " << x
<< " y: " << y
<< " z: " << z
<< " degrees/s"
<< endl;
// we show both C and F for temperature
cout << "Compensation Temperature: " << sensor->getTemperature()
<< " C / " << sensor->getTemperature(true) << " F"
<< endl;
cout << endl;
usleep(250000);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

82
examples/c++/bmi055.cxx Normal file
View File

@ -0,0 +1,82 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "bmi055.hpp"
using namespace std;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate an BMI055 using default I2C parameters
upm::BMI055 *sensor = new upm::BMI055();
// now output data every 250 milliseconds
while (shouldRun)
{
float x, y, z;
sensor->update();
sensor->getAccelerometer(&x, &y, &z);
cout << "Accelerometer x: " << x
<< " y: " << y
<< " z: " << z
<< " g"
<< endl;
sensor->getGyroscope(&x, &y, &z);
cout << "Gyroscope x: " << x
<< " y: " << y
<< " z: " << z
<< " degrees/s"
<< endl;
cout << endl;
usleep(250000);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

78
examples/c++/bmm150.cxx Normal file
View File

@ -0,0 +1,78 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "bmm150.hpp"
using namespace std;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate an BMM150 using default I2C parameters
upm::BMM150 *sensor = new upm::BMM150();
// For SPI, bus 0, you would pass -1 as the address, and a valid pin
// for CS: BMM150(0, -1, 10);
// now output data every 250 milliseconds
while (shouldRun)
{
float x, y, z;
sensor->update();
sensor->getMagnetometer(&x, &y, &z);
cout << "Magnetometer x: " << x
<< " y: " << y
<< " z: " << z
<< " uT"
<< endl;
cout << endl;
usleep(250000);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

89
examples/c++/bmx055.cxx Normal file
View File

@ -0,0 +1,89 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "bmx055.hpp"
using namespace std;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate an BMX055 using default I2C parameters
upm::BMX055 *sensor = new upm::BMX055();
// now output data every 250 milliseconds
while (shouldRun)
{
float x, y, z;
sensor->update();
sensor->getAccelerometer(&x, &y, &z);
cout << "Accelerometer x: " << x
<< " y: " << y
<< " z: " << z
<< " g"
<< endl;
sensor->getGyroscope(&x, &y, &z);
cout << "Gyroscope x: " << x
<< " y: " << y
<< " z: " << z
<< " degrees/s"
<< endl;
sensor->getMagnetometer(&x, &y, &z);
cout << "Magnetometer x: " << x
<< " y: " << y
<< " z: " << z
<< " uT"
<< endl;
cout << endl;
usleep(250000);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

View File

@ -74,8 +74,8 @@ int main(int argc, char **argv)
// sensor->setDebug(true);
cout << endl;
cout << "Device Description: " << sensor->getDescription() << endl;
cout << "Device Location: " << sensor->getLocation() << endl;
cout << "Device Description: " << sensor->getDeviceDescription() << endl;
cout << "Device Location: " << sensor->getDeviceLocation() << endl;
cout << endl;
// update and print a few values every 5 seconds

11
examples/c++/kxcjk1013.cxx Executable file → Normal file
View File

@ -1,6 +1,6 @@
/*
* Author: Lay, Kuan Loon <kuan.loon.lay@intel.com>
* Copyright (c) 2015 Intel Corporation.
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -22,8 +22,9 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <signal.h>
#include "kxcjk1013.hpp"
@ -44,7 +45,8 @@ data_callback(char* data)
{
float x, y, z;
accelerometer->extract3Axis(data, &x, &y, &z);
printf("% .1f % .1f % .1f\n", x, y, z);
cout << fixed << setprecision(1);
cout << x << '\t' << y << '\t' << z << "[m/s^2]" << endl;
}
int
@ -54,7 +56,10 @@ main()
//! [Interesting]
// Instantiate a KXCJK1013 Accelerometer Sensor on iio device 0
accelerometer = new upm::KXCJK1013(0);
// Available scales are 0.009582(2g), 0.019163(4g), and 0.038326(8g)
accelerometer->setScale(0.019163);
// Available sampling frequency are 0.781000, 1.563000, 3.125000, 6.250000, 12.500000, 25, 50,
// 100, 200, 400, 800, and 1600
accelerometer->setSamplingFrequency(25.0);
accelerometer->enable3AxisChannel();
accelerometer->installISR(data_callback, NULL);

View File

@ -1,6 +1,6 @@
/*
* Author: Lay, Kuan Loon <kuan.loon.lay@intel.com>
* Copyright (c) 2015 Intel Corporation.
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -22,8 +22,9 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <signal.h>
#include "l3gd20.hpp"
@ -43,8 +44,10 @@ void
data_callback(char* data)
{
float x, y, z;
if (gyroscope->extract3Axis(data, &x, &y, &z))
printf("% .2f % .2f % .2f\n", x, y, z);
if (gyroscope->extract3Axis(data, &x, &y, &z)) {
cout << fixed << setprecision(1);
cout << x << '\t' << y << '\t' << z << "[rad/sec]" << endl;
}
}
int
@ -54,7 +57,9 @@ main()
//! [Interesting]
// Instantiate a L3GD20 Gyroscope Sensor on iio device 3
gyroscope = new upm::L3GD20(3);
// Available scales are 0.000153(250dps), 0.000305(500dps), and 0.001222(2000dps)
gyroscope->setScale(0.001222);
// Available sampling frequency are 95, 190, 380, and 760
gyroscope->setSamplingFrequency(95.0);
gyroscope->enable3AxisChannel();
gyroscope->installISR(data_callback, NULL);

117
examples/c++/t8100.cxx Normal file
View File

@ -0,0 +1,117 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "t8100.hpp"
using namespace std;
using namespace upm;
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// You will need to edit this example to conform to your site and your
// devices, specifically the Device Object Instance ID passed to the
// constructor, and the arguments to initMaster() that are
// appropriate for your BACnet network.
string defaultDev = "/dev/ttyUSB0";
// if an argument was specified, use it as the device instead
if (argc > 1)
defaultDev = string(argv[1]);
cout << "Using device " << defaultDev << endl;
cout << "Initializing..." << endl;
// Instantiate an T8100 object for an T8100 device that has 568000
// as it's unique Device Object Instance ID. NOTE: You will
// certainly want to change this to the correct value for your
// device(s).
T8100 *sensor = new T8100(568000);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001 as
// our unique Device Object Instance ID, 2 as our MAC address and
// using default values for maxMaster and maxInfoFrames
sensor->initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor->setDebug(true);
cout << endl;
cout << "Device Description: " << sensor->getDeviceDescription() << endl;
cout << "Device Location: " << sensor->getDeviceLocation() << endl;
cout << endl;
// update and print a few values every 5 seconds
while (shouldRun)
{
// update our values
sensor->update();
cout << "CO2 Concentration: "
<< sensor->getCO2()
<< " ppm"
<< endl;
// we show both C and F for temperature
cout << "Temperature: " << sensor->getTemperature()
<< " C / "
<< sensor->getTemperature(true)
<< " F"
<< endl;
cout << "Humidity: " << sensor->getHumidity()
<< " %RH"
<< endl;
cout << "Relay State: " << sensor->getRelayState()
<< endl;
cout << endl;
sleep(5);
}
cout << "Exiting..." << endl;
delete sensor;
//! [Interesting]
return 0;
}

124
examples/c++/tb7300.cxx Normal file
View File

@ -0,0 +1,124 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <signal.h>
#include "tb7300.hpp"
using namespace std;
using namespace upm;
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// You will need to edit this example to conform to your site and your
// devices, specifically the Device Object Instance ID passed to the
// constructor, and the arguments to initMaster() that are
// appropriate for your BACnet network.
string defaultDev = "/dev/ttyUSB0";
// if an argument was specified, use it as the device instead
if (argc > 1)
defaultDev = string(argv[1]);
cout << "Using device " << defaultDev << endl;
cout << "Initializing..." << endl;
// Instantiate an TB7300 object for an TB7300 device that has 73001
// as it's unique Device Object Instance ID. NOTE: You will
// certainly want to change this to the correct value for your
// device(s).
TB7300 *sensor = new TB7300(73001);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001 as
// our unique Device Object Instance ID, 2 as our MAC address and
// using default values for maxMaster and maxInfoFrames
sensor->initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor->setDebug(true);
cout << endl;
cout << "Device Name: " << sensor->getDeviceName() << endl;
cout << "Device Description: " << sensor->getDeviceDescription() << endl;
cout << "Device Location: " << sensor->getDeviceLocation() << endl;
cout << endl;
cout << "Fan Mode: "
<< sensor->getMultiStateValueText(TB7300::MV_Fan_Mode)
<< endl;
cout << "Fan Status: "
<< sensor->getMultiStateValueText(TB7300::MV_Fan_Status)
<< endl;
cout << "System Mode: "
<< sensor->getMultiStateValueText(TB7300::MV_System_Mode)
<< endl;
cout << "Service Alarm: "
<< sensor->getBinaryInputText(TB7300::BI_Service_Alarm)
<< endl;
cout << endl;
// update and print the room temperature every 5 seconds
while (shouldRun)
{
// update our values
sensor->update();
// we show both C and F for temperature
cout << "Temperature: " << sensor->getTemperature()
<< " C / "
<< sensor->getTemperature(true)
<< " F"
<< endl;
cout << endl;
sleep(5);
}
cout << "Exiting..." << endl;
delete sensor;
//! [Interesting]
return 0;
}

View File

@ -0,0 +1,64 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_bmx055.BMA250E;
public class BMA250E_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a BMA250E instance using default i2c bus and address
BMA250E sensor = new BMA250E();
// For SPI, bus 0, you would pass -1 as the address, and a
// valid pin for CS:
// BMA250E(0, -1, 10);
while (true)
{
// update our values from the sensor
sensor.update();
float dataA[] = sensor.getAccelerometer();
System.out.println("Accelerometer x: " + dataA[0]
+ " y: " + dataA[1]
+ " z: " + dataA[2]
+ " g");
System.out.println("Compensation Temperature: "
+ sensor.getTemperature()
+ " C / "
+ sensor.getTemperature(true)
+ " F");
System.out.println();
Thread.sleep(250);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,61 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_bmx055.BMC150;
public class BMC150_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a BMC150 instance using default i2c bus and address
BMC150 sensor = new BMC150();
while (true)
{
// update our values from the sensor
sensor.update();
float data[] = sensor.getAccelerometer();
System.out.println("Accelerometer x: " + data[0]
+ " y: " + data[1]
+ " z: " + data[2]
+ " g");
data = sensor.getMagnetometer();
System.out.println("Magnetometer x: " + data[0]
+ " y: " + data[1]
+ " z: " + data[2]
+ " uT");
System.out.println();
Thread.sleep(250);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,64 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_bmx055.BMG160;
public class BMG160_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a BMG160 instance using default i2c bus and address
BMG160 sensor = new BMG160();
// For SPI, bus 0, you would pass -1 as the address, and a
// valid pin for CS:
// BMG160(0, -1, 10);
while (true)
{
// update our values from the sensor
sensor.update();
float dataA[] = sensor.getGyroscope();
System.out.println("Gyroscope x: " + dataA[0]
+ " y: " + dataA[1]
+ " z: " + dataA[2]
+ " degrees/s");
System.out.println("Compensation Temperature: "
+ sensor.getTemperature()
+ " C / "
+ sensor.getTemperature(true)
+ " F");
System.out.println();
Thread.sleep(250);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,61 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_bmx055.BMI055;
public class BMI055_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a BMI055 instance using default i2c bus and address
BMI055 sensor = new BMI055();
while (true)
{
// update our values from the sensor
sensor.update();
float data[] = sensor.getAccelerometer();
System.out.println("Accelerometer x: " + data[0]
+ " y: " + data[1]
+ " z: " + data[2]
+ " g");
data = sensor.getGyroscope();
System.out.println("Gyroscope x: " + data[0]
+ " y: " + data[1]
+ " z: " + data[2]
+ " degrees/s");
System.out.println();
Thread.sleep(250);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,58 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_bmx055.BMM150;
public class BMM150_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a BMM150 instance using default i2c bus and address
BMM150 sensor = new BMM150();
// For SPI, bus 0, you would pass -1 as the address, and a
// valid pin for CS:
// BMM150(0, -1, 10);
while (true)
{
// update our values from the sensor
sensor.update();
float dataA[] = sensor.getMagnetometer();
System.out.println("Magnetometer x: " + dataA[0]
+ " y: " + dataA[1]
+ " z: " + dataA[2]
+ " uT");
System.out.println();
Thread.sleep(250);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,69 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_bmx055.BMX055;
public class BMX055_Example
{
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// Instantiate a BMX055 instance using default i2c bus and address
BMX055 sensor = new BMX055();
while (true)
{
// update our values from the sensor
sensor.update();
float data[] = sensor.getAccelerometer();
System.out.println("Accelerometer x: " + data[0]
+ " y: " + data[1]
+ " z: " + data[2]
+ " g");
data = sensor.getGyroscope();
System.out.println("Gyroscope x: " + data[0]
+ " y: " + data[1]
+ " z: " + data[2]
+ " degrees/s");
data = sensor.getMagnetometer();
System.out.println("Magnetometer x: " + data[0]
+ " y: " + data[1]
+ " z: " + data[2]
+ " uT");
System.out.println();
Thread.sleep(250);
}
// ! [Interesting]
}
}

View File

@ -124,10 +124,13 @@ if (MODBUS_FOUND)
endif()
if (BACNET_FOUND)
add_example(E50HX_Example e50hx)
add_example(T8100_Example t8100)
add_example(TB7300_Example tb7300)
endif()
add_example(VCAP_Example vcap)
add_example(BMP280_Example bmp280)
add_example(BNO055_Example bno055)
add_example(BMX055_Example bmx055)
add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd)
add_example_with_path(Jhd1313m1Sample lcd i2clcd)
@ -136,4 +139,9 @@ add_example_with_path(Lcm1602_parallelSample lcd i2clcd)
add_example_with_path(SSD1308_oledSample lcd i2clcd)
add_example_with_path(SSD1327_oledSample lcd i2clcd)
add_example_with_path(BME280_Example bmp280 bmp280)
add_example_with_path(BMA250E_Example bmx055 bmx055)
add_example_with_path(BMG160_Example bmx055 bmx055)
add_example_with_path(BMM150_Example bmx055 bmx055)
add_example_with_path(BMC150_Example bmx055 bmx055)
add_example_with_path(BMI055_Example bmx055 bmx055)

View File

@ -58,8 +58,10 @@ public class E50HX_Example
// sensor.setDebug(true);
System.out.println();
System.out.println("Device Description: " + sensor.getDescription());
System.out.println("Device Location: " + sensor.getLocation());
System.out.println("Device Description: "
+ sensor.getDeviceDescription());
System.out.println("Device Location: "
+ sensor.getDeviceLocation());
System.out.println();
// update and print a few values every 5 seconds
@ -84,7 +86,6 @@ public class E50HX_Example
System.out.println();
Thread.sleep(5000);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,97 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_t8100.T8100;
public class T8100_Example
{
private static String defaultDev = "/dev/ttyUSB0";
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// You will need to edit this example to conform to your site
// and your devices, specifically the Device Object Instance
// ID passed to the constructor, and the arguments to
// initMaster() that are appropriate for your BACnet network.
if (args.length > 0)
defaultDev = args[0];
System.out.println("Using device " + defaultDev);
System.out.println("Initializing...");
// Instantiate an T8100 object for an T8100 device that has
// 568000 as it's unique Device Object Instance ID. NOTE: You
// will certainly want to change this to the correct value for
// your device(s).
T8100 sensor = new T8100(568000);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001
// as our unique Device Object Instance ID, 2 as our MAC
// address and using default values for maxMaster and
// maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor.setDebug(true);
System.out.println();
System.out.println("Device Description: "
+ sensor.getDeviceDescription());
System.out.println("Device Location: " + sensor.getDeviceLocation());
System.out.println();
// update and print a few values every 5 seconds
while (true)
{
// update our values
sensor.update();
System.out.println("CO2 Concentration: "
+ sensor.getCO2()
+ " ppm");
// we show both C and F for temperature
System.out.println("Temperature: "
+ sensor.getTemperature()
+ " C / "
+ sensor.getTemperature(true)
+ " F");
System.out.println("Humidity: "
+ sensor.getHumidity()
+ " %RH");
System.out.println("Relay State: "
+ sensor.getRelayState());
System.out.println();
Thread.sleep(5000);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,99 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
import upm_tb7300.TB7300;
public class TB7300_Example
{
private static String defaultDev = "/dev/ttyUSB0";
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// You will need to edit this example to conform to your site
// and your devices, specifically the Device Object Instance
// ID passed to the constructor, and the arguments to
// initMaster() that are appropriate for your BACnet network.
if (args.length > 0)
defaultDev = args[0];
System.out.println("Using device " + defaultDev);
System.out.println("Initializing...");
// Instantiate an TB7300 object for an TB7300 device that has
// 73001 as it's unique Device Object Instance ID. NOTE: You
// will certainly want to change this to the correct value for
// your device(s).
TB7300 sensor = new TB7300(73001);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001
// as our unique Device Object Instance ID, 2 as our MAC
// address and using default values for maxMaster and
// maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor.setDebug(true);
System.out.println();
System.out.println("Device Name: "
+ sensor.getDeviceName());
System.out.println("Device Description: "
+ sensor.getDeviceDescription());
System.out.println("Device Location: " + sensor.getDeviceLocation());
System.out.println();
System.out.println("Fan Mode: "
+ sensor.getMultiStateValueText(TB7300.MULTISTATE_VALUES_T.MV_Fan_Mode));
System.out.println("Fan Status: "
+ sensor.getMultiStateValueText(TB7300.MULTISTATE_VALUES_T.MV_Fan_Status));
System.out.println("System Mode: "
+ sensor.getMultiStateValueText(TB7300.MULTISTATE_VALUES_T.MV_System_Mode));
System.out.println("Service Alarm:"
+ sensor.getBinaryInputText(TB7300.BINARY_INPUTS_T.BI_Service_Alarm));
System.out.println();
// update and print the room temperature every 5 seconds
while (true)
{
// update our values
sensor.update();
// we show both C and F for temperature
System.out.println("Temperature: "
+ sensor.getTemperature()
+ " C / "
+ sensor.getTemperature(true)
+ " F");
System.out.println();
Thread.sleep(5000);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,72 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_bmx055');
// Instantiate a BMA250E instance using default i2c bus and address
var sensor = new sensorObj.BMA250E();
// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
// BMA250E(0, -1, 10);
var x = new sensorObj.new_floatp();
var y = new sensorObj.new_floatp();
var z = new sensorObj.new_floatp();
// now output data every 250 milliseconds
setInterval(function()
{
// update our values from the sensor
sensor.update();
sensor.getAccelerometer(x, y, z);
console.log("Accelerometer x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " g");
// we show both C and F for temperature
console.log("Compensation Temperature: "
+ sensor.getTemperature()
+ " C / "
+ sensor.getTemperature(true)
+ " F");
console.log();
}, 250);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,69 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_bmx055');
// Instantiate a BMC150 instance using default i2c bus and address
var sensor = new sensorObj.BMC150();
var x = new sensorObj.new_floatp();
var y = new sensorObj.new_floatp();
var z = new sensorObj.new_floatp();
// now output data every 250 milliseconds
setInterval(function()
{
// update our values from the sensor
sensor.update();
sensor.getAccelerometer(x, y, z);
console.log("Accelerometer x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " g");
sensor.getMagnetometer(x, y, z);
console.log("Magnetometer x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " uT");
console.log();
}, 250);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,72 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_bmx055');
// Instantiate a BMG160 instance using default i2c bus and address
var sensor = new sensorObj.BMG160();
// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
// BMG160(0, -1, 10);
var x = new sensorObj.new_floatp();
var y = new sensorObj.new_floatp();
var z = new sensorObj.new_floatp();
// now output data every 250 milliseconds
setInterval(function()
{
// update our values from the sensor
sensor.update();
sensor.getGyroscope(x, y, z);
console.log("Gyroscope x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " degrees/s");
// we show both C and F for temperature
console.log("Compensation Temperature: "
+ sensor.getTemperature()
+ " C / "
+ sensor.getTemperature(true)
+ " F");
console.log();
}, 250);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,69 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_bmx055');
// Instantiate a BMI055 instance using default i2c bus and address
var sensor = new sensorObj.BMI055();
var x = new sensorObj.new_floatp();
var y = new sensorObj.new_floatp();
var z = new sensorObj.new_floatp();
// now output data every 250 milliseconds
setInterval(function()
{
// update our values from the sensor
sensor.update();
sensor.getAccelerometer(x, y, z);
console.log("Accelerometer x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " g");
sensor.getGyroscope(x, y, z);
console.log("Gyroscope x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " degrees/s");
console.log();
}, 250);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,65 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_bmx055');
// Instantiate a BMM150 instance using default i2c bus and address
var sensor = new sensorObj.BMM150();
// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
// BMM150(0, -1, 10);
var x = new sensorObj.new_floatp();
var y = new sensorObj.new_floatp();
var z = new sensorObj.new_floatp();
// now output data every 250 milliseconds
setInterval(function()
{
// update our values from the sensor
sensor.update();
sensor.getMagnetometer(x, y, z);
console.log("Magnetometer x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " uT");
console.log();
}, 250);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,76 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_bmx055');
// Instantiate a BMX055 instance using default i2c bus and address
var sensor = new sensorObj.BMX055();
var x = new sensorObj.new_floatp();
var y = new sensorObj.new_floatp();
var z = new sensorObj.new_floatp();
// now output data every 250 milliseconds
setInterval(function()
{
// update our values from the sensor
sensor.update();
sensor.getAccelerometer(x, y, z);
console.log("Accelerometer x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " g");
sensor.getGyroscope(x, y, z);
console.log("Gyroscope x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " degrees/s");
sensor.getMagnetometer(x, y, z);
console.log("Magnetometer x: "
+ sensorObj.floatp_value(x)
+ " y: " + sensorObj.floatp_value(y)
+ " z: " + sensorObj.floatp_value(z)
+ " uT");
console.log();
}, 250);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -63,8 +63,8 @@ sensor.initMaster(defaultDev, 38400, 1000001, 2);
// sensor.setDebug(true);
console.log("");
console.log("Device Description:", sensor.getDescription());
console.log("Device Location:", sensor.getLocation());
console.log("Device Description:", sensor.getDeviceDescription());
console.log("Device Location:", sensor.getDeviceLocation());
console.log("");
// update and print a few values every 5 seconds

View File

@ -0,0 +1,98 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_t8100');
/************** Main code **************/
// You will need to edit this example to conform to your site and your
// devices, specifically the Device Object Instance ID passed to the
// constructor, and the arguments to initMaster() that are
// appropriate for your BACnet network.
var defaultDev = "/dev/ttyUSB0";
// if an argument was specified, use it as the device instead
if (process.argv.length > 2)
{
defaultDev = process.argv[2];
}
console.log("Using device " + defaultDev);
console.log("Initializing...");
// Instantiate an T8100 object for an T8100 device that has 568000
// as it's unique Device Object Instance ID. NOTE: You will
// certainly want to change this to the correct value for your
// device(s).
var sensor = new sensorObj.T8100(568000);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001 as
// our unique Device Object Instance ID, 2 as our MAC address and
// using default values for maxMaster and maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor.setDebug(true);
console.log("");
console.log("Device Description:", sensor.getDeviceDescription());
console.log("Device Location:", sensor.getDeviceLocation());
console.log("");
// update and print a few values every 5 seconds
setInterval(function()
{
// update our values
sensor.update();
console.log("CO2 Concentration:", sensor.getCO2(), "ppm");
// we show both C and F for temperature
console.log("Temperature:", sensor.getTemperature(),
"C /", sensor.getTemperature(true), "F");
console.log("Humidity:", sensor.getHumidity(), "%RH");
console.log("Relay State:", sensor.getRelayState());
console.log("");
}, 5000);
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting...");
process.exit(0);
});

View File

@ -0,0 +1,102 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
var sensorObj = require('jsupm_tb7300');
/************** Main code **************/
// You will need to edit this example to conform to your site and your
// devices, specifically the Device Object Instance ID passed to the
// constructor, and the arguments to initMaster() that are
// appropriate for your BACnet network.
var defaultDev = "/dev/ttyUSB0";
// if an argument was specified, use it as the device instead
if (process.argv.length > 2)
{
defaultDev = process.argv[2];
}
console.log("Using device " + defaultDev);
console.log("Initializing...");
// Instantiate an TB7300 object for an TB7300 device that has 73001
// as it's unique Device Object Instance ID. NOTE: You will
// certainly want to change this to the correct value for your
// device(s).
var sensor = new sensorObj.TB7300(73001);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001 as
// our unique Device Object Instance ID, 2 as our MAC address and
// using default values for maxMaster and maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor.setDebug(true);
console.log("");
console.log("Device Name:", sensor.getDeviceName());
console.log("Device Description:", sensor.getDeviceDescription());
console.log("Device Location:", sensor.getDeviceLocation());
console.log("");
console.log("Fan Mode:",
sensor.getMultiStateValueText(sensorObj.TB7300.MV_Fan_Mode));
console.log("Fan Status:",
sensor.getMultiStateValueText(sensorObj.TB7300.MV_Fan_Status));
console.log("System Mode:",
sensor.getMultiStateValueText(sensorObj.TB7300.MV_System_Mode));
console.log("Service Alarm:",
sensor.getBinaryInputText(sensorObj.TB7300.BI_Service_Alarm));
console.log("");
// update and print the room temperature every 5 seconds
setInterval(function()
{
// update our values
sensor.update();
// we show both C and F for temperature
console.log("Temperature:", sensor.getTemperature(),
"C /", sensor.getTemperature(true), "F");
console.log("");
}, 5000);
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting...");
process.exit(0);
});

View File

@ -0,0 +1,66 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_bmx055 as sensorObj
# Instantiate a BMP250E instance using default i2c bus and address
sensor = sensorObj.BMA250E()
# For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
# BMA250E(0, -1, 10);
## Exit handlers ##
# 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
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
x = sensorObj.new_floatp()
y = sensorObj.new_floatp()
z = sensorObj.new_floatp()
# now output data every 250 milliseconds
while (1):
sensor.update()
sensor.getAccelerometer(x, y, z)
print "Accelerometer x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " g"
# we show both C and F for temperature
print "Compensation Temperature:", sensor.getTemperature(), "C /",
print sensor.getTemperature(True), "F"
print
time.sleep(.250)

65
examples/python/bmc150.py Normal file
View File

@ -0,0 +1,65 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_bmx055 as sensorObj
# Instantiate a BMC150 instance using default i2c bus and address
sensor = sensorObj.BMC150()
## Exit handlers ##
# 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
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
x = sensorObj.new_floatp()
y = sensorObj.new_floatp()
z = sensorObj.new_floatp()
# now output data every 250 milliseconds
while (1):
sensor.update()
sensor.getAccelerometer(x, y, z)
print "Accelerometer x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " g"
sensor.getMagnetometer(x, y, z)
print "Magnetometer x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " uT"
print
time.sleep(.250)

66
examples/python/bmg160.py Normal file
View File

@ -0,0 +1,66 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_bmx055 as sensorObj
# Instantiate a BMP250E instance using default i2c bus and address
sensor = sensorObj.BMG160()
# For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
# BMG160(0, -1, 10);
## Exit handlers ##
# 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
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
x = sensorObj.new_floatp()
y = sensorObj.new_floatp()
z = sensorObj.new_floatp()
# now output data every 250 milliseconds
while (1):
sensor.update()
sensor.getGyroscope(x, y, z)
print "Gyroscope x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " degrees/s"
# we show both C and F for temperature
print "Compensation Temperature:", sensor.getTemperature(), "C /",
print sensor.getTemperature(True), "F"
print
time.sleep(.250)

65
examples/python/bmi055.py Normal file
View File

@ -0,0 +1,65 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_bmx055 as sensorObj
# Instantiate a BMI055 instance using default i2c bus and address
sensor = sensorObj.BMI055()
## Exit handlers ##
# 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
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
x = sensorObj.new_floatp()
y = sensorObj.new_floatp()
z = sensorObj.new_floatp()
# now output data every 250 milliseconds
while (1):
sensor.update()
sensor.getAccelerometer(x, y, z)
print "Accelerometer x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " g"
sensor.getGyroscope(x, y, z)
print "Gyroscope x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " degrees/s"
print
time.sleep(.250)

62
examples/python/bmm150.py Normal file
View File

@ -0,0 +1,62 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_bmx055 as sensorObj
# Instantiate a BMP250E instance using default i2c bus and address
sensor = sensorObj.BMM150()
# For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS:
# BMM150(0, -1, 10);
## Exit handlers ##
# 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
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
x = sensorObj.new_floatp()
y = sensorObj.new_floatp()
z = sensorObj.new_floatp()
# now output data every 250 milliseconds
while (1):
sensor.update()
sensor.getMagnetometer(x, y, z)
print "Magnetometer x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " uT"
print
time.sleep(.250)

71
examples/python/bmx055.py Normal file
View File

@ -0,0 +1,71 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_bmx055 as sensorObj
# Instantiate a BMX055 instance using default i2c bus and address
sensor = sensorObj.BMX055()
## Exit handlers ##
# 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
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
x = sensorObj.new_floatp()
y = sensorObj.new_floatp()
z = sensorObj.new_floatp()
# now output data every 250 milliseconds
while (1):
sensor.update()
sensor.getAccelerometer(x, y, z)
print "Accelerometer x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " g"
sensor.getGyroscope(x, y, z)
print "Gyroscope x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " degrees/s"
sensor.getMagnetometer(x, y, z)
print "Magnetometer x:", sensorObj.floatp_value(x),
print " y:", sensorObj.floatp_value(y),
print " z:", sensorObj.floatp_value(z),
print " uT"
print
time.sleep(.250)

View File

@ -69,8 +69,8 @@ sensor.initMaster(defaultDev, 38400, 1000001, 2)
# output the serial number and firmware revision
print
print "Device Description:", sensor.getDescription()
print "Device Location:", sensor.getLocation()
print "Device Description:", sensor.getDeviceDescription()
print "Device Location:", sensor.getDeviceLocation()
print
# update and print available values every second

97
examples/python/t8100.py Normal file
View File

@ -0,0 +1,97 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_t8100 as sensorObj
## Exit handlers ##
# 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
def exitHandler():
print "Exiting..."
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
# You will need to edit this example to conform to your site and your
# devices, specifically the Device Object Instance ID passed to the
# constructor, and the arguments to initMaster() that are
# appropriate for your BACnet network.
defaultDev = "/dev/ttyUSB0"
# if an argument was specified, use it as the device instead
if (len(sys.argv) > 1):
defaultDev = sys.argv[1]
print "Using device", defaultDev
print "Initializing..."
# Instantiate an T8100 object for an T8100 device that has 568000
# as it's unique Device Object Instance ID. NOTE: You will
# certainly want to change this to the correct value for your
# device(s).
sensor = sensorObj.T8100(568000)
# Initialize our BACnet master, if it has not already been
# initialized, with the device and baudrate, choosing 1000001 as
# our unique Device Object Instance ID, 2 as our MAC address and
# using default values for maxMaster and maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2)
# Uncomment to enable debugging output
# sensor.setDebug(True);
# output the serial number and firmware revision
print
print "Device Description:", sensor.getDeviceDescription()
print "Device Location:", sensor.getDeviceLocation()
print
# update and print available values every 5 seconds
while (1):
# update our values
sensor.update();
print "CO2 Concentration:",
print sensor.getCO2(),
print "ppm"
# we show both C and F for temperature
print "Temperature:", sensor.getTemperature(),
print "C /", sensor.getTemperature(True), "F"
print "Humidity:",
print sensor.getHumidity(),
print "%RH"
print "Relay State:",
print sensor.getRelayState()
print
time.sleep(5)

96
examples/python/tb7300.py Normal file
View File

@ -0,0 +1,96 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 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.
import time, sys, signal, atexit
import pyupm_tb7300 as sensorObj
## Exit handlers ##
# 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
def exitHandler():
print "Exiting..."
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
# You will need to edit this example to conform to your site and your
# devices, specifically the Device Object Instance ID passed to the
# constructor, and the arguments to initMaster() that are
# appropriate for your BACnet network.
defaultDev = "/dev/ttyUSB0"
# if an argument was specified, use it as the device instead
if (len(sys.argv) > 1):
defaultDev = sys.argv[1]
print "Using device", defaultDev
print "Initializing..."
# Instantiate an TB7300 object for an TB7300 device that has 73001
# as it's unique Device Object Instance ID. NOTE: You will
# certainly want to change this to the correct value for your
# device(s).
sensor = sensorObj.TB7300(73001)
# Initialize our BACnet master, if it has not already been
# initialized, with the device and baudrate, choosing 1000001 as
# our unique Device Object Instance ID, 2 as our MAC address and
# using default values for maxMaster and maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2)
# Uncomment to enable debugging output
# sensor.setDebug(True);
# output the serial number and firmware revision
print
print "Device Name:", sensor.getDeviceName()
print "Device Description:", sensor.getDeviceDescription()
print "Device Location:", sensor.getDeviceLocation()
print
print "Fan Mode:", sensor.getMultiStateValueText(sensorObj.TB7300.MV_Fan_Mode)
print "Fan Status:",
print sensor.getMultiStateValueText(sensorObj.TB7300.MV_Fan_Status)
print "System Mode:",
print sensor.getMultiStateValueText(sensorObj.TB7300.MV_System_Mode)
print "Service Alarm:",
print sensor.getBinaryInputText(sensorObj.TB7300.BI_Service_Alarm)
print
# update and print the room temperature every 5 seconds
while (1):
# update our values
sensor.update();
# we show both C and F for temperature
print "Temperature:", sensor.getTemperature(),
print "C /", sensor.getTemperature(True), "F"
print
time.sleep(5)

View File

@ -178,6 +178,7 @@ endmacro()
if (SWIG_FOUND)
if (BUILDSWIGPYTHON)
if(NOT PYTHONLIBS_FOUND)
find_package (PythonInterp ${PYTHONBUILD_VERSION} REQUIRED)
find_package (PythonLibs ${PYTHONBUILD_VERSION} REQUIRED)
string (REPLACE "." ";" PYTHON_VERSION_LIST ${PYTHONLIBS_VERSION_STRING})
list (GET PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)

View File

@ -1,7 +1,7 @@
set (libname "bacnetmstp")
set (libdescription "upm driver module for BACnet MS/TP devices")
set (module_src ${libname}.cxx device-client.c)
set (module_hpp ${libname}.hpp)
set (module_src ${libname}.cxx device-client.c bacnetutil.cxx)
set (module_hpp ${libname}.hpp bacnetutil.hpp)
pkg_check_modules(BACNET libbacnet)
if (BACNET_FOUND)

View File

@ -57,7 +57,7 @@ BACNETMSTP::BACNETMSTP()
memset(m_rxBuffer, 0, MAX_MPDU);
m_returnedValue = {0};
m_returnedValue.clear();
m_targetAddress = {0};
m_invokeID = 0;
m_errorDetected = false;
@ -165,6 +165,15 @@ void BACNETMSTP::handlerReadPropertyAck(uint8_t* service_request,
int len = 0;
BACNET_READ_PROPERTY_DATA data;
// clear our stored data
instance()->m_returnedValue.clear();
BACNET_APPLICATION_DATA_VALUE value;
memset((void *)&value, 0, sizeof(value));
uint8_t *application_data = 0;
int application_data_len = 0;
if (address_match(&(instance()->m_targetAddress), src) &&
(service_data->invoke_id == instance()->m_invokeID))
{
@ -173,19 +182,49 @@ void BACNETMSTP::handlerReadPropertyAck(uint8_t* service_request,
len = rp_ack_decode_service_request(service_request, service_len,
&data);
// FIXME: we don't currently handle arrays (len < service_len)
// store any delivered data elements
if (len > 0)
{
bacapp_decode_application_data(data.application_data,
data.application_data_len,
&(instance()->m_returnedValue));
}
else
{
// shouldn't happen?
cerr << __FUNCTION__ << ": decode app data failed" << endl;
application_data_len = data.application_data_len;
application_data = data.application_data;
while (true)
{
len = bacapp_decode_application_data(application_data,
application_data_len,
&value);
if (len > 0)
{
// store a copy
instance()->m_returnedValue.push_back(value);
if (len < application_data_len)
{
// there is more data
application_data += len;
application_data_len -= len;
}
else
{
// we are done
break;
}
}
else
{
// shouldn't happen?
cerr << __FUNCTION__ << ": decode app data failed" << endl;
break;
}
}
}
}
if (instance()->m_debugging)
cerr << __FUNCTION__ << ": STORED "
<< instance()->m_returnedValue.size()
<< " data elements." << endl;
}
void BACNETMSTP::handlerWritePropertyAck(BACNET_ADDRESS* src,
@ -553,7 +592,7 @@ bool BACNETMSTP::readProperty(uint32_t targetDeviceInstanceID,
m_command.readPropArgs.objType = objType;
m_command.readPropArgs.objInstance = objInstance;
m_command.readPropArgs.objProperty = objProperty;
m_command.readPropArgs.arrayIndex = arrayIndex; // not implemented in the ack handler!
m_command.readPropArgs.arrayIndex = arrayIndex;
if (m_debugging)
cerr << __FUNCTION__ << ": calling dispatchRequest()..." << endl;
@ -591,7 +630,7 @@ bool BACNETMSTP::writeProperty(uint32_t targetDeviceInstanceID,
m_command.writePropArgs.objProperty = objProperty;
m_command.writePropArgs.propValue = propValue;
m_command.writePropArgs.propPriority = propPriority;
m_command.writePropArgs.arrayIndex = arrayIndex; // not implemented!
m_command.writePropArgs.arrayIndex = arrayIndex;
if (m_debugging)
cerr << __FUNCTION__ << ": calling dispatchRequest()..." << endl;
@ -605,158 +644,163 @@ bool BACNETMSTP::writeProperty(uint32_t targetDeviceInstanceID,
return error;
}
BACNET_APPLICATION_DATA_VALUE BACNETMSTP::getData()
BACNET_APPLICATION_DATA_VALUE BACNETMSTP::getData(int index)
{
return m_returnedValue;
return m_returnedValue.at(index);
}
uint8_t BACNETMSTP::getDataType()
int BACNETMSTP::getDataNumElements()
{
return m_returnedValue.tag;
return m_returnedValue.size();
}
float BACNETMSTP::getDataTypeReal()
uint8_t BACNETMSTP::getDataType(int index)
{
if (getDataType() == BACNET_APPLICATION_TAG_REAL)
return m_returnedValue.type.Real;
return m_returnedValue.at(index).tag;
}
float BACNETMSTP::getDataTypeReal(int index)
{
if (getDataType(index) == BACNET_APPLICATION_TAG_REAL)
return m_returnedValue.at(index).type.Real;
else
{
if (m_debugging)
cerr << __FUNCTION__ << ": Not of Real type, trying to convert..." << endl;
// try to convert or throw
switch (getDataType())
switch (getDataType(index))
{
case BACNET_APPLICATION_TAG_BOOLEAN:
return (getDataTypeBoolean() ? 1.0 : 0.0);
return (getDataTypeBoolean(index) ? 1.0 : 0.0);
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
return float(getDataTypeUnsignedInt());
return float(getDataTypeUnsignedInt(index));
case BACNET_APPLICATION_TAG_SIGNED_INT:
return float(getDataTypeSignedInt());
return float(getDataTypeSignedInt(index));
default:
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type ("
+ std::to_string(int(getDataType()))
+ std::to_string(int(getDataType(index)))
+ ") is not convertible to Real");
}
}
}
bool BACNETMSTP::getDataTypeBoolean()
bool BACNETMSTP::getDataTypeBoolean(int index)
{
if (getDataType() == BACNET_APPLICATION_TAG_BOOLEAN)
return ((m_returnedValue.type.Boolean) ? true : false);
if (getDataType(index) == BACNET_APPLICATION_TAG_BOOLEAN)
return ((m_returnedValue.at(index).type.Boolean) ? true : false);
else
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type ("
+ std::to_string(int(getDataType()))
+ std::to_string(int(getDataType(index)))
+ ") is not convertible to Bool");
}
unsigned int BACNETMSTP::getDataTypeUnsignedInt()
unsigned int BACNETMSTP::getDataTypeUnsignedInt(int index)
{
if (getDataType() == BACNET_APPLICATION_TAG_UNSIGNED_INT)
return m_returnedValue.type.Unsigned_Int;
if (getDataType(index) == BACNET_APPLICATION_TAG_UNSIGNED_INT)
return m_returnedValue.at(index).type.Unsigned_Int;
else
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type ("
+ std::to_string(int(getDataType()))
+ std::to_string(int(getDataType(index)))
+ ") is not convertible to UnsignedInt");
}
int BACNETMSTP::getDataTypeSignedInt()
int BACNETMSTP::getDataTypeSignedInt(int index)
{
if (getDataType() == BACNET_APPLICATION_TAG_SIGNED_INT)
return m_returnedValue.type.Signed_Int;
if (getDataType(index) == BACNET_APPLICATION_TAG_SIGNED_INT)
return m_returnedValue.at(index).type.Signed_Int;
else
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type ("
+ std::to_string(int(getDataType()))
+ std::to_string(int(getDataType(index)))
+ ") is not convertible to SignedInt");
}
#if defined(BACAPP_DOUBLE)
double BACNETMSTP::getDataTypeDouble()
double BACNETMSTP::getDataTypeDouble(int index)
{
if (getDataType() == BACNET_APPLICATION_TAG_DOUBLE)
return m_returnedValue.type.Double;
return m_returnedValue.at(index).type.Double;
else
{
if (m_debugging)
cerr << __FUNCTION__ << ": Not of Double type, trying to convert..." << endl;
// try to convert or throw
switch (getDataType())
switch (getDataType(index))
{
case BACNET_APPLICATION_TAG_REAL:
return double(getDataTypeReal());
return double(getDataTypeReal(index));
case BACNET_APPLICATION_TAG_BOOLEAN:
return (getDataTypeBoolean() ? 1.0 : 0.0);
return (getDataTypeBoolean(index) ? 1.0 : 0.0);
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
return double(getDataTypeUnsignedInt());
return double(getDataTypeUnsignedInt(index));
case BACNET_APPLICATION_TAG_SIGNED_INT:
return double(getDataTypeSignedInt());
return double(getDataTypeSignedInt(index));
default:
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type ("
+ std::to_string(int(getDataType()))
+ std::to_string(int(getDataType(index)))
+ ") is not convertible to Double");
}
}
}
#endif // BACAPP_DOUBLE
unsigned int BACNETMSTP::getDataTypeEnum()
unsigned int BACNETMSTP::getDataTypeEnum(int index)
{
if (getDataType() == BACNET_APPLICATION_TAG_ENUMERATED)
return m_returnedValue.type.Enumerated;
if (getDataType(index) == BACNET_APPLICATION_TAG_ENUMERATED)
return m_returnedValue.at(index).type.Enumerated;
else
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type ("
+ std::to_string(int(getDataType()))
+ std::to_string(int(getDataType(index)))
+ ") is not convertible to Enum");
}
std::string BACNETMSTP::getDataTypeString()
std::string BACNETMSTP::getDataTypeString(int index)
{
string retval;
// Here, we can try to accomodate all the types
switch(getDataType())
switch(getDataType(index))
{
case BACNET_APPLICATION_TAG_REAL:
retval = std::to_string(getDataTypeReal());
retval = std::to_string(getDataTypeReal(index));
break;
#if defined(BACAPP_DOUBLE)
case BACNET_APPLICATION_TAG_DOUBLE:
retval = std::to_string(getDataTypeDouble());
retval = std::to_string(getDataTypeDouble(index));
break;
#endif // BACAPP_DOUBLE
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
retval = std::to_string(getDataTypeUnsignedInt());
retval = std::to_string(getDataTypeUnsignedInt(index));
break;
case BACNET_APPLICATION_TAG_SIGNED_INT:
retval = std::to_string(getDataTypeSignedInt());
retval = std::to_string(getDataTypeSignedInt(index));
break;
case BACNET_APPLICATION_TAG_BOOLEAN:
retval = (getDataTypeBoolean() ? string("true") : string("false"));
retval = (getDataTypeBoolean(index) ? string("true") : string("false"));
break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
retval = string(characterstring_value(&m_returnedValue.type.Character_String),
retval = string(characterstring_value(&m_returnedValue.at(index).type.Character_String),
characterstring_length(&m_returnedValue.type.Character_String));
characterstring_length(&m_returnedValue.at(index).type.Character_String));
break;
case BACNET_APPLICATION_TAG_OCTET_STRING:
{
string tmpstr((char *)octetstring_value(&m_returnedValue.type.Octet_String),
string tmpstr((char *)octetstring_value(&m_returnedValue.at(index).type.Octet_String),
octetstring_length(&m_returnedValue.type.Octet_String));
octetstring_length(&m_returnedValue.at(index).type.Octet_String));
retval = string2HexString(tmpstr);
}
@ -764,11 +808,12 @@ std::string BACNETMSTP::getDataTypeString()
case BACNET_APPLICATION_TAG_BIT_STRING:
{
int len = bitstring_bits_used(&m_returnedValue.type.Bit_String);
int len = bitstring_bits_used(&m_returnedValue.at(index).type.Bit_String);
for (int i=0; i<len; i++)
{
if (bitstring_bit(&m_returnedValue.type.Bit_String, uint8_t(i)))
if (bitstring_bit(&m_returnedValue.at(index).type.Bit_String,
uint8_t(i)))
retval += "1";
else
retval += "0";
@ -783,7 +828,7 @@ std::string BACNETMSTP::getDataTypeString()
default:
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type ("
+ std::to_string(int(getDataType()))
+ std::to_string(int(getDataType(index)))
+ ") is not convertible to String");
break;
}
@ -860,6 +905,17 @@ BACNET_APPLICATION_DATA_VALUE BACNETMSTP::createDataString(string value)
return data;
}
BACNET_APPLICATION_DATA_VALUE BACNETMSTP::createDataEnum(uint32_t value)
{
BACNET_APPLICATION_DATA_VALUE data;
memset(&data, 0, sizeof(BACNET_APPLICATION_DATA_VALUE));
data.tag = BACNET_APPLICATION_TAG_ENUMERATED;
data.type.Enumerated = value;
return data;
}
string BACNETMSTP::string2HexString(string input)
{

View File

@ -24,6 +24,7 @@
#pragma once
#include <string>
#include <vector>
// we only support a BACnet RS-485 MS/TP datalink
#define BACDL_MSTP 1
@ -185,8 +186,7 @@ namespace upm {
* instance you wish to access. It should be one of the
* BACNET_PROPERTY_ID values.
* @param arrayIndex This specifies the index number of an array
* property. This is not currently supported. Until it is, leave
* the default at BACNET_ARRAY_ALL.
* property. The default is BACNET_ARRAY_ALL.
* @return true if an error occurred, false otherwise.
*/
bool readProperty(uint32_t targetDeviceInstanceID,
@ -225,8 +225,7 @@ namespace upm {
* information in the bacnet-stack documentation as to whether
* this is even supported.
* @param arrayIndex This specifies the index number of an array
* property. This is not currently supported. Until it is, leave
* the default at BACNET_ARRAY_ALL.
* property. The default is BACNET_ARRAY_ALL.
* @return true if an error occurred, false otherwise.
*/
bool writeProperty(uint32_t targetDeviceInstanceID,
@ -242,19 +241,32 @@ namespace upm {
* to return a BACNET_APPLICATION_DATA_VALUE structure containing
* the returned data.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return a BACNET_APPLICATION_DATA_VALUE structure containing
* the returned data.
*/
BACNET_APPLICATION_DATA_VALUE getData();
BACNET_APPLICATION_DATA_VALUE getData(int index=0);
/**
* After a successful readProperty request, this method can be
* used to return the number of data elements returned. This will
* usually be 1, unless reading an array.
*
* @return The number of data elements received.
*/
int getDataNumElements();
/**
* After a successful readProperty request, this method can be
* used to return the BACnet data type of the returned data. It
* will be one of the BACNET_APPLICATION_TAG_* values.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A BACNET_APPLICATION_TAG_* value
*/
uint8_t getDataType();
uint8_t getDataType(int index=0);
/**
* After a successful readProperty request, this method can be
@ -263,9 +275,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_REAL, and the value returned cannot be
* safely converted, an exception is thrown.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A floating point value representing the returned data
*/
float getDataTypeReal();
float getDataTypeReal(int index=0);
/**
* After a successful readProperty request, this method can be
@ -274,9 +288,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_BOOLEAN, and the value returned cannot
* be safely converted, an exception is thrown.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A boolean value representing the returned data
*/
bool getDataTypeBoolean();
bool getDataTypeBoolean(int index=0);
/**
* After a successful readProperty request, this method can be
@ -285,9 +301,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_UNSIGNED_INT, and the value returned
* cannot be safely converted, an exception is thrown.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return An unsigned int value representing the returned data
*/
unsigned int getDataTypeUnsignedInt();
unsigned int getDataTypeUnsignedInt(int index=0);
/**
* After a successful readProperty request, this method can be
@ -296,9 +314,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_SIGNED_INT, and the value returned
* cannot be safely converted, an exception is thrown.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A signed int value representing the returned data
*/
int getDataTypeSignedInt();
int getDataTypeSignedInt(int index=0);
/**
* After a successful readProperty request, this method can be
@ -308,9 +328,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_CHARACTER_STRING, and the value returned
* cannot be safely converted, an exception is thrown.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A string value representing the returned data
*/
std::string getDataTypeString();
std::string getDataTypeString(int index=0);
/**
* After a successful readProperty request, this method can be
@ -318,9 +340,11 @@ namespace upm {
* enumeration. If the data type (getDataType()) is not a
* BACNET_APPLICATION_TAG_ENUMERATED an exception is thrown.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return An unsigned int representing a BACnet enumerant
*/
unsigned int getDataTypeEnum();
unsigned int getDataTypeEnum(int index=0);
#if defined(BACAPP_DOUBLE)
/**
@ -330,9 +354,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_DOUBLE, and the value returned cannot be
* safely converted, an exception is thrown.
*
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A double floating point value representing the returned data
*/
double getDataTypeDouble();
double getDataTypeDouble(int index=0);
#endif // BACAPP_DOUBLE
/**
@ -392,6 +418,18 @@ namespace upm {
*/
BACNET_APPLICATION_DATA_VALUE createDataString(std::string value);
/**
* This method is used to create and return an initialized
* BACNET_APPLICATION_DATA_VALUE containing an enumeration. A
* pointer to this returned structure can then be used with
* writeProperty().
*
* @param value The BACnet enumeration to initialize the
* structure to.
* @return An initialized structure containing the value
*/
BACNET_APPLICATION_DATA_VALUE createDataEnum(uint32_t value);
/**
* Return an enumration of the last error type to occur. The
* value returned will be one of the BACERR_TYPE_T values.
@ -664,7 +702,7 @@ namespace upm {
std::string m_upmErrorString;
// our returned data from readProperty()
BACNET_APPLICATION_DATA_VALUE m_returnedValue;
std::vector<BACNET_APPLICATION_DATA_VALUE> m_returnedValue;
// current bound target address of dispatched service request
// (read/write prop, etc)

View File

@ -0,0 +1,925 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <assert.h>
#include <errno.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "bacnetutil.hpp"
using namespace upm;
using namespace std;
BACNETUTIL::BACNETUTIL(uint32_t targetDeviceObjectID) :
m_instance(0)
{
// Save our device's ID
m_targetDeviceObjectID = targetDeviceObjectID;
// create the BACNETMSTP instance here if it does not already exist,
// and store the pointer in our class to save on some typing.
m_instance = BACNETMSTP::instance();
// now see if it has been initialized yet for init()
m_initialized = m_instance->isInitialized();
setDebug(false);
// we disable this by default for performance reasons
checkReliability(false);
// empty our unit caches
m_avUnitCache.clear();
m_aiUnitCache.clear();
// empty our msv info store
m_msvInfo.clear();
// empty our binary info stores
m_bvInfo.clear();
m_biInfo.clear();
}
BACNETUTIL::~BACNETUTIL()
{
}
void BACNETUTIL::initMaster(std::string port, int baudRate,
int deviceInstanceID, int macAddr, int maxMaster,
int maxInfoFrames)
{
// first we check to see if the bacnetmstp instance has already been
// initialized (determined in the ctor). If not, we will do so here
// with the arguments specified. If it has already been
// initialized, then we do not bother calling bacnetmstp's init
// again as it will just be ignored.
if (!m_initialized)
m_instance->initMaster(port, baudRate, deviceInstanceID,
macAddr, maxMaster, maxInfoFrames);
// either it threw an exception, was already initialized or it's
// initialized now...
m_initialized = true;
}
void BACNETUTIL::setDebug(bool enable)
{
m_debugging = enable;
// we also enable/disable debugging in BACNETMSTP
m_instance->setDebug(enable);
}
float BACNETUTIL::getAnalogValue(uint32_t objInstance)
{
// check reliability first, if enabled
if (m_checkReliability)
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
objInstance, PROP_RELIABILITY))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (reliability): " << getAllErrorString()
<< endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ getAllErrorString());
}
BACNET_RELIABILITY reliable =
static_cast<BACNET_RELIABILITY>(m_instance->getDataTypeEnum());
if (reliable != RELIABILITY_NO_FAULT_DETECTED)
{
if (m_debugging)
cerr << __FUNCTION__ << ": Reliability check failed" << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": Reliability check failed");
}
}
// now get the value
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
objInstance, PROP_PRESENT_VALUE))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (value): " << getAllErrorString()
<< endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
return m_instance->getDataTypeReal();
}
void BACNETUTIL::setAnalogValue(uint32_t objInstance,
float value)
{
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(value);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
objInstance, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
}
string BACNETUTIL::getAnalogValueUnits(uint32_t objInstance)
{
// see if it exists
if (m_avUnitCache.count(objInstance) == 0)
{
// then we need to fetch it
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
objInstance, PROP_UNITS))
{
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
// set to empty string
m_avUnitCache[objInstance] = string("");
}
else
{
// cache it for future calls
m_avUnitCache[objInstance] =
string(bactext_engineering_unit_name(m_instance->getDataTypeEnum()));
}
}
return m_avUnitCache[objInstance];
}
float BACNETUTIL::getAnalogInput(uint32_t objInstance)
{
// check reliability first, if enabled
if (m_checkReliability)
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_INPUT,
objInstance, PROP_RELIABILITY))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (reliability): "
<< getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ getAllErrorString());
}
BACNET_RELIABILITY reliable =
static_cast<BACNET_RELIABILITY>(m_instance->getDataTypeEnum());
if (reliable != RELIABILITY_NO_FAULT_DETECTED)
{
if (m_debugging)
cerr << __FUNCTION__ << ": Reliability check failed" << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": Reliability check failed");
}
}
// now get the value
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_INPUT,
objInstance, PROP_PRESENT_VALUE))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (value): " << getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
return m_instance->getDataTypeReal();
}
bool BACNETUTIL::getBinaryInput(uint32_t objInstance)
{
// check the BV info, and update/cache the data if needed
updateBinaryInputInfo(objInstance);
// check reliability first, if enabled
if (m_checkReliability)
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_BINARY_INPUT,
objInstance, PROP_RELIABILITY))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (reliability): "
<< getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ getAllErrorString());
}
BACNET_RELIABILITY reliable =
static_cast<BACNET_RELIABILITY>(m_instance->getDataTypeEnum());
if (reliable != RELIABILITY_NO_FAULT_DETECTED)
{
if (m_debugging)
cerr << __FUNCTION__ << ": Reliability check failed" << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": Reliability check failed");
}
}
// now get the value
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_BINARY_INPUT,
objInstance, PROP_PRESENT_VALUE))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (value): " << getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
BACNET_BINARY_PV bpv =
static_cast<BACNET_BINARY_PV>(m_instance->getDataTypeEnum());
return (bpv == BINARY_INACTIVE) ? false : true;
}
bool BACNETUTIL::getBinaryValue(uint32_t objInstance)
{
// check the BV info, and update/cache the data if needed
updateBinaryValueInfo(objInstance);
// check reliability first, if enabled
if (m_checkReliability)
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_BINARY_VALUE,
objInstance, PROP_RELIABILITY))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (reliability): "
<< getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ getAllErrorString());
}
BACNET_RELIABILITY reliable =
static_cast<BACNET_RELIABILITY>(m_instance->getDataTypeEnum());
if (reliable != RELIABILITY_NO_FAULT_DETECTED)
{
if (m_debugging)
cerr << __FUNCTION__ << ": Reliability check failed" << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": Reliability check failed");
}
}
// now get the value
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_BINARY_VALUE,
objInstance, PROP_PRESENT_VALUE))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (value): " << getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
BACNET_BINARY_PV bpv =
static_cast<BACNET_BINARY_PV>(m_instance->getDataTypeEnum());
return (bpv == BINARY_INACTIVE) ? false : true;
}
void BACNETUTIL::setBinaryValue(uint32_t objInstance,
bool value)
{
BACNET_BINARY_PV bpv = (value) ? BINARY_ACTIVE : BINARY_INACTIVE;
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataEnum(bpv);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_BINARY_VALUE,
objInstance, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
}
string BACNETUTIL::getAnalogInputUnits(uint32_t objInstance)
{
// see if it exists
if (m_aiUnitCache.count(objInstance) == 0)
{
// then we need to fetch it
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_INPUT,
objInstance, PROP_UNITS))
{
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
// set to empty string
m_aiUnitCache[objInstance] = string("");
}
else
{
// cache it for future calls
m_aiUnitCache[objInstance] =
string(bactext_engineering_unit_name(m_instance->getDataTypeEnum()));
}
}
return m_aiUnitCache[objInstance];
}
unsigned int BACNETUTIL::getMultiStateValue(uint32_t objInstance)
{
// check the MSV info, and update/cache the data if needed
updateMultiStateValueInfo(objInstance);
// check reliability first, if enabled
if (m_checkReliability)
{
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_MULTI_STATE_VALUE,
objInstance, PROP_RELIABILITY))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (reliability): "
<< getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ getAllErrorString());
}
BACNET_RELIABILITY reliable =
static_cast<BACNET_RELIABILITY>(m_instance->getDataTypeEnum());
if (reliable != RELIABILITY_NO_FAULT_DETECTED)
{
if (m_debugging)
cerr << __FUNCTION__ << ": Reliability check failed" << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": Reliability check failed");
}
}
// now get the value
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_MULTI_STATE_VALUE,
objInstance, PROP_PRESENT_VALUE))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (value): " << getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
return m_instance->getDataTypeUnsignedInt();
}
void BACNETUTIL::updateMultiStateValueInfo(uint32_t objInstance)
{
// bail if we already have information on this msv
if (m_msvInfo.count(objInstance) != 0)
return;
// we need to fetch information on MSV's - number of states, and
// possibly the state-text, if present
// get the number of values possible (required)
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_MULTI_STATE_VALUE,
objInstance, PROP_NUMBER_OF_STATES))
{
if (m_debugging)
cerr << __FUNCTION__
<< ": (number of states): "
<< getAllErrorString()
<< endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
// Add the entry...
m_msvInfo[objInstance].numStates = m_instance->getDataTypeUnsignedInt();
if (m_debugging)
cerr << __FUNCTION__
<< ": number of states: "
<< m_msvInfo[objInstance].numStates
<< endl;
// now get the state-text. This is optional, so we will not throw
// here.
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_MULTI_STATE_VALUE,
objInstance, PROP_STATE_TEXT))
{
if (m_debugging)
cerr << __FUNCTION__
<< ": (state-text): "
<< getAllErrorString()
<< endl;
}
// store them
int numElements = m_instance->getDataNumElements();
if (m_debugging)
cerr << __FUNCTION__ << ": numElements: " << numElements << endl;
if (numElements > 0)
{
for (int i=0; i<numElements; i++)
{
m_msvInfo[objInstance].stateList.push_back(m_instance->getDataTypeString(i));
if (m_debugging)
cerr << __FUNCTION__ << ": " << int(objInstance) << ", "
<< i << ": "
<< "added state text string: "
<< m_msvInfo[objInstance].stateList.at(i)
<< endl;
}
}
return;
}
void BACNETUTIL::deleteMultiStateValueInfo(uint32_t objInstance)
{
// if there is no data stored for this objInstance yet, then we do
// not need to do anything.
if (m_msvInfo.count(objInstance) == 0)
return;
// Now, we just erase the entry, and it will be updated the next
// time the MSV is accessed.
m_msvInfo.erase(objInstance);
return;
}
string BACNETUTIL::lookupMultiStateValueText(uint32_t objInstance,
unsigned int value)
{
// verify that we have the relevant object data cached. If not, go
// get it.
updateMultiStateValueInfo(objInstance);
// verify that value is valid for this object
if (value == 0 || value > m_msvInfo[objInstance].numStates)
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value supplied is invalid. Maximum "
+ "allowed values are 1 to "
+ std::to_string(m_msvInfo[objInstance].numStates)
+ " for this object");
// at this point either it failed or suceeded. If it suceeded, then
// we will see if any state text was retrieved. If no text is
// available (it is an optional property), then we will simply
// return the value itself as a string.
if (m_msvInfo[objInstance].stateList.size() > 0)
{
// we have state-text and a usable value.
// value should never be 0 at this point, so compensate for
// indexing into stateList which is 0-based.
value--;
return m_msvInfo[objInstance].stateList.at(value);
}
// no stateList text available, so just return value as a string
return std::to_string(value);
}
unsigned int BACNETUTIL::getMultiStateValueMaxStates(uint32_t objInstance)
{
// check the MSV info, and update/cache the data if needed
updateMultiStateValueInfo(objInstance);
return m_msvInfo[objInstance].numStates;
}
string BACNETUTIL::getMultiStateValueText(uint32_t objInstance)
{
unsigned int value = getMultiStateValue(objInstance);
return lookupMultiStateValueText(objInstance, value);
}
void BACNETUTIL::setMultiStateValue(uint32_t objInstance,
unsigned int value)
{
// check the MSV info, and update/cache the data if needed
updateMultiStateValueInfo(objInstance);
// Check value against the valid limits
if (value == 0 || value > m_msvInfo[objInstance].numStates)
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": value supplied is invalid. Maximum "
+ "allowed values are 1 to "
+ std::to_string(m_msvInfo[objInstance].numStates)
+ " for this object");
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataUnsignedInt(value);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID,
OBJECT_MULTI_STATE_VALUE,
objInstance, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
throw std::runtime_error(std::string(__FUNCTION__)
+ ": "
+ getAllErrorString());
}
}
void BACNETUTIL::updateBinaryValueInfo(uint32_t objInstance)
{
// bail if we already have information on this object
if (m_bvInfo.count(objInstance) != 0)
return;
// fetch inactive/active text. These are optional accordingto the
// spec, so we will not throw if they do not exist.
// get inactive text
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_BINARY_VALUE,
objInstance, PROP_INACTIVE_TEXT))
{
if (m_debugging)
cerr << __FUNCTION__
<< ": (inactive text): "
<< getAllErrorString()
<< endl;
m_bvInfo[objInstance].inactiveText = "inactive";
}
else
{
m_bvInfo[objInstance].inactiveText = m_instance->getDataTypeString();
}
// get active text
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_BINARY_VALUE,
objInstance, PROP_ACTIVE_TEXT))
{
if (m_debugging)
cerr << __FUNCTION__
<< ": (active text): "
<< getAllErrorString()
<< endl;
m_bvInfo[objInstance].activeText = "active";
}
else
{
m_bvInfo[objInstance].activeText = m_instance->getDataTypeString();
}
return;
}
void BACNETUTIL::deleteBinaryValueInfo(uint32_t objInstance)
{
// if there is no data stored for this objInstance yet, then we do
// not need to do anything.
if (m_bvInfo.count(objInstance) == 0)
return;
// Now, we just erase the entry, and it will be updated the next
// time it is accessed.
m_bvInfo.erase(objInstance);
return;
}
void BACNETUTIL::updateBinaryInputInfo(uint32_t objInstance)
{
// bail if we already have information on this object
if (m_biInfo.count(objInstance) != 0)
return;
// fetch inactive/active text. These are optional accordingto the
// spec, so we will not throw if they do not exist.
// get inactive text
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_BINARY_INPUT,
objInstance, PROP_INACTIVE_TEXT))
{
if (m_debugging)
cerr << __FUNCTION__
<< ": (inactive text): "
<< getAllErrorString()
<< endl;
m_biInfo[objInstance].inactiveText = "inactive";
}
else
{
m_biInfo[objInstance].inactiveText = m_instance->getDataTypeString();
}
// get active text
if (m_instance->readProperty(m_targetDeviceObjectID,
OBJECT_BINARY_INPUT,
objInstance, PROP_ACTIVE_TEXT))
{
if (m_debugging)
cerr << __FUNCTION__
<< ": (active text): "
<< getAllErrorString()
<< endl;
m_biInfo[objInstance].activeText = "active";
}
else
{
m_biInfo[objInstance].activeText = m_instance->getDataTypeString();
}
return;
}
void BACNETUTIL::deleteBinaryInputInfo(uint32_t objInstance)
{
// if there is no data stored for this objInstance yet, then we do
// not need to do anything.
if (m_biInfo.count(objInstance) == 0)
return;
// Now, we just erase the entry, and it will be updated the next
// time it is accessed.
m_biInfo.erase(objInstance);
return;
}
string BACNETUTIL::lookupBinaryInputText(uint32_t objInstance, bool value)
{
// cache relevant data if necessary
updateBinaryInputInfo(objInstance);
if (value)
return m_biInfo[objInstance].activeText;
else
return m_biInfo[objInstance].inactiveText;
}
string BACNETUTIL::getBinaryInputText(uint32_t objInstance)
{
bool value = getBinaryInput(objInstance);
return lookupBinaryInputText(objInstance, value);
}
string BACNETUTIL::lookupBinaryValueText(uint32_t objInstance, bool value)
{
// cache relevant data if necessary
updateBinaryValueInfo(objInstance);
if (value)
return m_bvInfo[objInstance].activeText;
else
return m_bvInfo[objInstance].inactiveText;
}
string BACNETUTIL::getBinaryValueText(uint32_t objInstance)
{
bool value = getBinaryValue(objInstance);
return lookupBinaryValueText(objInstance, value);
}
BACNETMSTP::BACERR_TYPE_T BACNETUTIL::getErrorType()
{
return m_instance->getErrorType();
}
uint8_t BACNETUTIL::getRejectReason()
{
return m_instance->getRejectReason();
}
std::string BACNETUTIL::getRejectString()
{
return m_instance->getRejectString();
}
uint8_t BACNETUTIL::getAbortReason()
{
return m_instance->getAbortReason();
}
std::string BACNETUTIL::getAbortString()
{
return m_instance->getAbortString();
}
BACNET_ERROR_CLASS BACNETUTIL::getErrorClass()
{
return m_instance->getErrorClass();
}
BACNET_ERROR_CODE BACNETUTIL::getErrorCode()
{
return m_instance->getErrorCode();
}
std::string BACNETUTIL::getUPMErrorString()
{
return m_instance->getUPMErrorString();
}
std::string BACNETUTIL::getErrorString()
{
return m_instance->getErrorString();
};
string BACNETUTIL::getAllErrorString()
{
switch (m_instance->getErrorType())
{
case BACNETMSTP::BACERR_TYPE_NONE:
return string("No Error");
break;
case BACNETMSTP::BACERR_TYPE_REJECT:
return string("Reject: ") + getRejectString();
break;
case BACNETMSTP::BACERR_TYPE_ABORT:
return string("Abort: ") + getAbortString();
break;
case BACNETMSTP::BACERR_TYPE_ERROR:
return string("Error: ") + getErrorString();
break;
case BACNETMSTP::BACERR_TYPE_UPM:
return string("UPM Error: ") + getUPMErrorString();
break;
}
}
string BACNETUTIL::getDeviceDescription()
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_DESCRIPTION))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return "";
}
return m_instance->getDataTypeString();
}
string BACNETUTIL::getDeviceLocation()
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_LOCATION))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return "";
}
return m_instance->getDataTypeString();
}
bool BACNETUTIL::setDeviceLocation(string location)
{
BACNET_APPLICATION_DATA_VALUE myLocation =
m_instance->createDataString(location);
// write the Device Object Location
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_LOCATION,
&myLocation))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
}
string BACNETUTIL::getDeviceName()
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_OBJECT_NAME))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return "";
}
return m_instance->getDataTypeString();
}
bool BACNETUTIL::setDeviceName(string name)
{
if (name.size() < 1)
{
throw std::invalid_argument(std::string(__FUNCTION__)
+ ": name must have at least one character");
}
BACNET_APPLICATION_DATA_VALUE myName =
m_instance->createDataString(name);
// write the Device Object Location
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_OBJECT_NAME,
&myName))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
}

View File

@ -0,0 +1,559 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include <map>
#include <vector>
#include "bacnetmstp.hpp"
namespace upm {
/**
* @library bacnetmstp
* @comname UPM Utility API for BACnet
* @con uart
*
* @brief UPM Utility API for BACnet
*
* This class implements some common access functions that are
* useful to any driver making use of the bacnetmstp driver.
*
* It provides some basic functionality for reading and writing a
* proprty (with and without relability checking) as well as access
* to error conditions. It is intended to be inherited by your
* driver class.
*/
class BACNETUTIL {
public:
/**
* BACNETUTIL constructor
*
*/
BACNETUTIL(uint32_t targetDeviceObjectID);
/**
* BACNETUTIL Destructor
*/
virtual ~BACNETUTIL();
/**
* This function initializes the underlying BACNETMSTP Master
* singleton in the event it has not already been initialized. If
* the BACNETMSTP Master singleton has already been initialized,
* then this call will be ignored.
*
* @param port The serial port that the RS-485 interface is
* connected to.
* @param baudRate The baudrate of the RS-485 interface. All
* devices on a BACnet RS-485 bus must run at the same baudrate.
* Valid values are 9600, 19200, 38400, 57600, 76800, and 115200.
* @param deviceInstanceNumber This is the unique Device Object
* Instance number that will be used for our BACnet Master in
* order to communicate over the BACnet interface. This number
* must be between 1-4194302 and must be unique on the BACnet
* network.
* @param macAddr This is the MAC address of our BACnet Master.
* It must be unique on the BACnet segment, and must be between
* 1-127.
* @param maxMaster This specifies to our Master the maximum MAC
* address used by any other Masters on the BACnet network. This
* must be between 1-127, the default is 127. Do not change this
* unless you know what you are doing or you could introduce
* token passing errors on the BACnet network.
* @param maxInfoFrames This number specifies the maximum number
* of transmissions (like requests for data) our Master is allowed
* to make before passing the token to the next Master. The
* default is 1.
*/
virtual void initMaster(std::string port, int baudRate,
int deviceInstanceNumber,
int macAddr, int maxMaster=DEFAULT_MAX_MASTER,
int maxInfoFrames=1);
/**
* Enable some debugging output in this module as well as the
* BACNETMSTP module. Debugging is disabled by default.
*
* @param enable true to enable, false to disable.
*/
virtual void setDebug(bool enable);
/**
* Retrieve the Present_Value property of an Analog Value object.
* If checkReliability() has been enabled, then the Reliability
* property of the object will be retrieved first. If the
* Reliability property is anything other than
* RELIABILITY_NO_FAULT_DETECTED, then the method will throw.
* Reliability checking is disabled by default for performance
* reasons.
*
* @param objInstance The Analog Value Object instance.
* @return The floating point value requested.
*/
virtual float getAnalogValue(uint32_t objInstance);
/**
* Set the Present_Value property of an Analog Value object. This
* method will throw on an error.
*
* @param objInstance The Analog Value Object instance.
* @param value The data value to write.
*/
virtual void setAnalogValue(uint32_t objInstance,
float value);
/**
* Retrieve the Present_Value property of an Analog Input object.
* If checkReliability() has been enabled, then the Reliability
* property of the object will be retrieved first. If the
* Reliability property is anything other than
* RELIABILITY_NO_FAULT_DETECTED, then the method will throw.
* Reliability checking is disabled by default for performance
* reasons.
*
* @param objInstance The Analog Input Object instance.
* @return the floating point value requested.
*/
virtual float getAnalogInput(uint32_t objInstance);
/**
* Query an Analog Value object for the unit code, translate it
* into a string and cache the result for future use. Return the
* BACnet text for the Unit enumeration. Unit enumerations are
* things like 'kilowatt-hours', 'volts', etc. For Objects which
* do not have a Units property defined for them, or for which
* Units has no meaning, 'no-units' will typically be returned and
* cached for the object.
*
* @param objInstance The Analog Value Object instance.
* @return A string representing the Object's Unit property.
*/
virtual std::string getAnalogValueUnits(uint32_t objInstance);
/**
* Query an Analog Input object for the unit code, translate it
* into a string and cache the result for future use. Return the
* BACnet text for the Unit enumeration. Unit enumerations are
* things like 'kilowatt-hours', 'volts', etc. For Objects which
* do not have a Units property defined for them, or for which
* Units has no meaning, 'no-units' will typically be returned and
* cached for the object.
*
* @param objInstance The Analog Input Object instance.
* @return A string representing the Object's Unit property.
*/
virtual std::string getAnalogInputUnits(uint32_t objInstance);
/**
* Retrieve the Present_Value property of a Binary Input object.
* If checkReliability() has been enabled, then the Reliability
* property of the object will be retrieved first. If the
* Reliability property is anything other than
* RELIABILITY_NO_FAULT_DETECTED, then the method will throw.
* Reliability checking is disabled by default for performance
* reasons.
*
* @param objInstance The Object Instance number to query
* @return the boolean point value requested
*/
virtual bool getBinaryInput(uint32_t objInstance);
/**
* Lookup (retrieve if necessary) the Inactive_Text and
* Active_Text properties of a Binary Input object. These text
* properties are optional and can provide a string representing a
* given state (true/false) that can be more informational than
* just the boolean value the object represents. This is useful
* in applications that display this data to a user for example.
* If this text is not present in the object (as it is not
* required), then a string representation of the value will be
* returned instead ("active" and "inactive").
*
* @param objInstance The Object Instance number of the object
* @param value The value you want to lookup the text
* representation for.
* @return The string representing the value.
*/
virtual std::string lookupBinaryInputText(uint32_t objInstance, bool value);
/**
* Return a string representation of the Present_Value property of
* a BinaryInput object. This method just calls getBinaryInput()
* on the object, uses lookupBinaryInputText() to lookup the
* corresponding text value, and returns the result.
*
* @param objInstance The Object Instance number of the object.
* @return The string representing the value.
*/
virtual std::string getBinaryInputText(uint32_t objInstance);
/**
* Retrieve the Present_Value property of a Binary Value object.
* If checkReliability() has been enabled, then the Reliability
* property of the object will be retrieved first. If the
* Reliability property is anything other than
* RELIABILITY_NO_FAULT_DETECTED, then the method will throw.
* Reliability checking is disabled by default for performance
* reasons.
*
* @param objInstance The Object Instance number to query
* @return the boolean point value requested
*/
virtual bool getBinaryValue(uint32_t objInstance);
/**
* Set the Present_Value property of a Binary Value object. This
* method will throw on an error.
*
* @param objInstance The Analog Value Object instance.
* @param value The data value to write
*/
virtual void setBinaryValue(uint32_t objInstance,
bool value);
/**
* Lookup (retrieve if necessary) the Inactive_Text and
* Active_Text properties of a Binary Value object. These text
* properties are optional and can provide a string representing a
* given state (true/false) that can be more informational than
* just the boolean value the object represents. This is useful
* in applications that display this data to a user for example.
* If this text is not present in the object (as it is not
* required), then a string representation of the value will be
* returned instead ("active" and "inactive").
*
* @param objInstance The Object Instance number of the object.
* @param value The value you want to lookup the text
* representation for.
* @return The string representing the value.
*/
virtual std::string lookupBinaryValueText(uint32_t objInstance, bool value);
/**
* Return a string representation of the Present_Value property of
* a Binary Value object. This method just calls getBinaryValue()
* on the object, uses lookupBinaryValueText() to lookup the
* corresponding text value, and returns the result.
*
* @param objInstance The Object Instance number of the object.
* @return The string representing the value.
*/
virtual std::string getBinaryValueText(uint32_t objInstance);
/**
* Retrieve the Present_Value property of a Multi State Value
* object. If checkReliability() has been enabled, then the
* Reliability property of the object will be retrieved first. If
* the Reliability property is anything other than
* RELIABILITY_NO_FAULT_DETECTED, then the method will throw.
* Reliability checking is disabled by default for performance
* reasons.
*
* @param objInstance The Object Instance number to query.
* @return The Present_Value property of the object.
*/
virtual unsigned int getMultiStateValue(uint32_t objInstance);
/**
* Lookup (retrieve if necessary) the State_Text strings
* corresponding to the supplied value of a MultiStateValue
* object. State_Text is an optional property that can provide
* strings representing a given state that can be more
* informational than just the unsigned integer the object
* represents. This is useful in applications that display this
* data to a user for example. If this text is not present in the
* object (as it is not required), then a string representation of
* the integer value will be returned instead.
*
* @param objInstance The Object Instance number of the object.
* @param value The value you want to lookup the text
* representation for.
* @return The string representing the value.
*/
virtual std::string lookupMultiStateValueText(uint32_t objInstance,
unsigned int value);
/**
* Return a string representation of the Present_Value property of
* a MultiStateValue object. This method just calls
* getMultiStateValue() on the object, uses
* lookupMultiStateValueText() to lookup the corresponding
* State_Text value, and returns the result.
*
* @param objInstance The Object Instance number of the object.
* @return The string representing the value.
*/
virtual std::string getMultiStateValueText(uint32_t objInstance);
/**
* Return the maximum legal value of a Multi State Value Object.
* The value represents the highest value the Present_Value
* porperty of the object will allow.
*
* @param objInstance The Object Instance number of the object.
* @return The highest Present_Value the object supports.
*/
virtual unsigned int getMultiStateValueMaxStates(uint32_t objInstance);
/**
* Set the Present_Value property of a Multi State Value object.
* The value provided must not be 0, and must not exceed the
* object's Number_Of_States property. Use
* getMultiStateValueMaxStates() to determine the maximum value
* the object supports. This method will throw on an error.
*
* @param objInstance The MultiStateValue Object instance.
* @param value The data value to write.
*/
virtual void setMultiStateValue(uint32_t objInstance,
unsigned int value);
/**
* Enable or disable reliability checking. When retrieving data,
* the Present_Value property is returned. There is also an
* optional property called Reliability that can be checked to
* ensure that the Present_Value property is currently valid.
*
* Enabling Reliability Checking has the data retrieval functions
* check for a RELIABILITY_NO_FAULT_DETECTED value for the
* Reliability property before querying the Present_Value
* property. If anything other than RELIABILITY_NO_FAULT_DETECTED
* is set, then the method will throw.
*
* This checking is disabled by default since it will double the
* number of queries needed to retrieve a given value. In
* addition, since it is an optional property, calling it for an
* object that does not support it will also throw. However, if
* you need to ensure that the values returned are always
* completely valid as determined by the device firmware, and the
* objects you are querying support the reliability property, you
* can enable this.
*
* @param enable true to check Reliability before returning a
* value, false otherwise.
*/
virtual void checkReliability(bool enable)
{
m_checkReliability = enable;
};
/**
* Query the Device Object of the device and return it's
* Description property. This typically contains information like
* the Vendor, model and serial number of a device.
*
* @return A string containing the Device Object's Description property.
*/
virtual std::string getDeviceDescription();
/**
* Query the Device Object of the device and return it's Location
* property. This typically contains a string indication of a
* customer specific value. Use setLocation() to change.
*
* @return A string containing the Device Object's Location property.
*/
virtual std::string getDeviceLocation();
/**
* Set the Device Object's Location property. This must be a
* string containing no more than 63 characters. Not all devices
* allow setting the location.
*
* @param location The new location to set, if supported.
* @return true if the operation succeeded, otherwise false.
*/
virtual bool setDeviceLocation(std::string location);
/**
* Query the Device Object of the device and return it's Name
* property. This should contain a unique string value. Use
* setName() to change. Note, according to the spec, the Device
* Object Name must be unique within a given BACnet network.
*
* @return A string containing the Object's Name property.
*/
virtual std::string getDeviceName();
/**
* Set the Device Object's Name property. This must be a string
* containing at least one character and no more than 63
* characters. Note, according to the spec, the Device Object
* Name must be unique within a given BACnet network.
*
* @param name The name to set.
* @return true if the operation succeeded, false otherwise
*/
virtual bool setDeviceName(std::string name);
/**
* This is a utility function that will return a string reporting
* on the various types of errors that can occur in BACnet
* operation.
*
* @return A string containing the last error message.
*/
virtual std::string getAllErrorString();
/**
* Return an enumration of the last error type to occur. The
* value returned will be one of the BACNETMSTP::BACERR_TYPE_T
* values.
*
* @return The last error type to occur, one of the
* BACNETMSTP::BACERR_TYPE_T values.
*/
virtual BACNETMSTP::BACERR_TYPE_T getErrorType();
/**
* In the event of a BACnet Reject error, return the error code.
*
* @return The Reject error code.
*/
virtual uint8_t getRejectReason();
/**
* In the event of a BACnet Reject error, return the error string.
*
* @return The Reject error string.
*/
virtual std::string getRejectString();
/**
* In the event of a BACnet Abort error, return the Abort reason code.
*
* @return The Abort reason code.
*/
virtual uint8_t getAbortReason();
/**
* In the event of a BACnet Abort error, return the Abort string.
*
* @return The Abort error string.
*/
virtual std::string getAbortString();
/**
* In the event of a general BACnet error, return the BACnet error class.
*
* @return One of the BACNET_ERROR_CLASS error class codes
*/
virtual BACNET_ERROR_CLASS getErrorClass();
/**
* In the event of a general BACnet error, return the BACnet error code.
*
* @return One of the BACNET_ERROR_CODE error codes
*/
virtual BACNET_ERROR_CODE getErrorCode();
/**
* In the event of a general BACnet error, return the BACnet error
* string.
*
* @return A string representing the BACnet error class and code.
*/
virtual std::string getErrorString();
/**
* In the event of a non-BACnet UPM error, return a string
* describing the error.
*
* @return A string representing the UPM error.
*/
virtual std::string getUPMErrorString();
protected:
// update our stored info for an MSV
virtual void updateMultiStateValueInfo(uint32_t objInstance);
// delete our stored info for an MSV
virtual void deleteMultiStateValueInfo(uint32_t objInstance);
// update our stored info for a BV
virtual void updateBinaryValueInfo(uint32_t objInstance);
// delete our stored info for a BV
virtual void deleteBinaryValueInfo(uint32_t objInstance);
// update our stored info for a BI
virtual void updateBinaryInputInfo(uint32_t objInstance);
// delete our stored info for a BI
virtual void deleteBinaryInputInfo(uint32_t objInstance);
// also enable mstp debugging in BACNETMSTP
bool m_debugging;
// whether or not to verify reliability before reading a value.
bool m_checkReliability;
// our target Device Object ID
uint32_t m_targetDeviceObjectID;
// a copy of the BACNETMSTP singleton instance pointer
BACNETMSTP* m_instance;
// are we initialized?
bool m_initialized;
// storage for Binary Input and Binary Value Data. This will
// generate SWIG warnings which can be ignored as we do not expose
// this struct outside the class.
typedef struct {
std::string inactiveText;
std::string activeText;
} binaryData_t;
typedef std::map<uint32_t, binaryData_t> binaryInfo_t;
// storage for binary input/value information
binaryInfo_t m_bvInfo;
binaryInfo_t m_biInfo;
// storage for multi-state data. This will generate SWIG
// warnings which can be ignored as we do not expose this struct
// outside the class.
typedef struct {
unsigned int numStates;
std::vector<std::string>stateList;
} multiStateData_t;
// our information storage for MSV's
typedef std::map<uint32_t, multiStateData_t> multiStateInfo_t;
multiStateInfo_t m_msvInfo;
// Unit cache for AV
typedef std::map<uint32_t, std::string> avCacheMap_t;
avCacheMap_t m_avUnitCache;
// Unit cache for AI
typedef std::map<uint32_t, std::string> aiCacheMap_t;
aiCacheMap_t m_aiUnitCache;
private:
};
}

View File

@ -1,15 +1,15 @@
%module javaupm_bacnetmstp
%include "../upm.i"
%include "typemaps.i"
%include "cpointer.i"
%include "arrays_java.i";
%include "../java_buffer.i"
%include "carrays_uint32_t.i"
%{
#include "bacnetmstp.hpp"
#include "bacnetutil.hpp"
%}
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%pragma(java) jniclasscode=%{
static {

View File

@ -0,0 +1,5 @@
set (libname "bmx055")
set (libdescription "Bosch bmx055, bmi055, bma250e, bmc150, bmg160, bmm150")
set (module_src ${libname}.cxx bma250e.cxx bmg160.cxx bmm150.cxx bmc150.cxx bmi055.cxx)
set (module_hpp ${libname}.hpp bma250e.hpp bmg160.hpp bmm150.hpp bmc150.cxx bmi055.hpp)
upm_module_init()

735
src/bmx055/bma250e.cxx Normal file
View File

@ -0,0 +1,735 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string.h>
#include "bma250e.hpp"
using namespace upm;
using namespace std;
// conversion from celcius to fahrenheit
static float c2f(float c)
{
return (c * (9.0 / 5.0) + 32.0);
}
BMA250E::BMA250E(int bus, uint8_t addr, int cs) :
m_i2c(0), m_spi(0), m_gpioIntr1(0), m_gpioIntr2(0), m_gpioCS(0)
{
m_addr = addr;
m_isSPI = false;
m_accX = 0;
m_accY = 0;
m_accZ = 0;
m_accScale = 0;
m_temperature = 0.0;
if (addr < 0)
m_isSPI = true;
if (m_isSPI)
{
m_spi = new mraa::Spi(bus);
// Only create cs context if we are actually using a valid pin.
// A hardware controlled pin should specify cs as -1.
if (cs >= 0)
{
m_gpioCS = new mraa::Gpio(cs);
m_gpioCS->dir(mraa::DIR_OUT);
}
m_spi->mode(mraa::SPI_MODE0);
m_spi->frequency(5000000);
}
else
{
// I2C
m_i2c = new mraa::I2c(bus);
mraa::Result rv;
if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS)
{
throw std::runtime_error(string(__FUNCTION__) +
": I2c.address() failed");
}
}
// check the chip id
uint8_t chipID = getChipID();
m_useFIFO = false;
// check the various chips id's and set appropriate capabilities.
// Bail if the chip id is unknown.
switch (chipID)
{
case 0xf9: // standalone bma250e
m_resolution = RESOLUTION_10BITS;
m_fifoAvailable = true;
break;
case 0xfa: // bmx055, bmi055 variants, 12b resolution
m_resolution = RESOLUTION_12BITS;
m_fifoAvailable = true;
break;
case 0x03: // bmc050 variant, no FIFO, 12b resolution
m_resolution = RESOLUTION_12BITS;
m_fifoAvailable = false;
break;
default:
throw std::runtime_error(string(__FUNCTION__)
+ ": invalid chip ID. Expected "
+ "3, 249, or 250 "
+ ", got "
+ std::to_string(int(chipID)));
}
// call init with default options
init();
}
BMA250E::~BMA250E()
{
uninstallISR(INTERRUPT_INT1);
uninstallISR(INTERRUPT_INT2);
}
void BMA250E::init(POWER_MODE_T pwr, RANGE_T range, BW_T bw)
{
setPowerMode(pwr);
usleep(50000); // 50ms, in case we are waking up
// set our range and bandwidth
setRange(range);
setBandwidth(bw);
// make sure register shadowing is enabled
enableRegisterShadowing(true);
// enable output filtering
enableOutputFiltering(true);
// use the FIFO by default, if we have one
fifoConfig(FIFO_MODE_BYPASS, FIFO_DATA_SEL_XYZ);
enableFIFO(true);
// make sure low power mode LPM2 is enabled in case we go to low
// power or suspend mode. LPM1 mode (the default) requires register
// writes to be drastically slowed down when enabled, which we
// cannot handle.
setLowPowerMode2();
// settle
usleep(50000);
}
void BMA250E::update()
{
int bufLen = 0;
uint8_t startReg = 0;
if (m_useFIFO)
{
bufLen = 6;
startReg = REG_FIFO_DATA;
}
else
{
// non FIFO, read acc regs directly (including temp)
bufLen = 7;
startReg = REG_ACCD_X_LSB;
}
uint8_t buf[bufLen];
if (readRegs(startReg, buf, bufLen) != bufLen)
{
throw std::runtime_error(string(__FUNCTION__)
+ ": readRegs() failed to read "
+ std::to_string(bufLen)
+ " bytes");
}
uint8_t mask, shift;
float divisor;
switch (m_resolution)
{
case RESOLUTION_10BITS:
mask = _ACCD10_LSB_MASK;
shift = _ACCD10_LSB_SHIFT;
divisor = 64.0;
break;
case RESOLUTION_12BITS:
mask = _ACCD12_LSB_MASK;
shift = _ACCD12_LSB_SHIFT;
divisor = 16.0;
break;
default:
throw std::logic_error(string(__FUNCTION__)
+ ": internal error: invalid resolution "
+ std::to_string(int(m_resolution)));
}
int16_t val;
// x
val = int16_t(buf[1] << 8 | (buf[0] & (mask << shift)));
m_accX = float(val / divisor);
// y
val = int16_t(buf[3] << 8 | (buf[2] & (mask << shift)));
m_accY = float(val / divisor);
// z
val = int16_t(buf[5] << 8 | (buf[4] & (mask << shift)));
m_accZ = float(val / divisor);
// get the temperature...
uint8_t temp = 0;
if (m_useFIFO)
{
// we have to read temperature separately...
temp = readReg(REG_TEMP);
}
else
{
// we've already got it
temp = buf[6];
}
// .5K/LSB, 23C center point
m_temperature = (float(temp) / 2.0) + 23.0;
}
void BMA250E::enableFIFO(bool useFIFO)
{
if (m_fifoAvailable)
m_useFIFO = useFIFO;
}
uint8_t BMA250E::readReg(uint8_t reg)
{
if (m_isSPI)
{
reg |= 0x80; // needed for read
uint8_t pkt[2] = {reg, 0};
csOn();
if (m_spi->transfer(pkt, pkt, 2))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer() failed");
}
csOff();
return pkt[1];
}
else
return m_i2c->readReg(reg);
}
int BMA250E::readRegs(uint8_t reg, uint8_t *buffer, int len)
{
if (m_isSPI)
{
reg |= 0x80; // needed for read
uint8_t sbuf[len + 1];
memset((char *)sbuf, 0, len + 1);
sbuf[0] = reg;
// We need to do it this way for edison - ie: use a single
// transfer rather than breaking it up into two like we used to.
// This means a buffer copy is now required, but that's the way
// it goes.
csOn();
if (m_spi->transfer(sbuf, sbuf, len + 1))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer(buf) failed");
}
csOff();
// now copy it into user buffer
for (int i=0; i<len; i++)
buffer[i] = sbuf[i + 1];
return len;
}
else
return m_i2c->readBytesReg(reg, buffer, len);
}
void BMA250E::writeReg(uint8_t reg, uint8_t val)
{
if (m_isSPI)
{
reg &= 0x7f; // mask off 0x80 for writing
uint8_t pkt[2] = {reg, val};
csOn();
if (m_spi->transfer(pkt, NULL, 2))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer() failed");
}
csOff();
}
else
{
if (m_i2c->writeReg(reg, val) != mraa::SUCCESS)
{
throw std::runtime_error(std::string(__FUNCTION__)
+ ": I2c.writeReg() failed");
}
}
}
void BMA250E::csOn()
{
if (m_gpioCS)
m_gpioCS->write(0);
}
void BMA250E::csOff()
{
if (m_gpioCS)
m_gpioCS->write(1);
}
uint8_t BMA250E::getChipID()
{
return readReg(REG_CHIP_ID);
}
void BMA250E::getAccelerometer(float *x, float *y, float *z)
{
if (x)
*x = (m_accX * m_accScale) / 1000.0;
if (y)
*y = (m_accY * m_accScale) / 1000.0;
if (z)
*z = (m_accZ * m_accScale) / 1000.0;
}
float *BMA250E::getAccelerometer()
{
static float v[3];
getAccelerometer(&v[0], &v[1], &v[2]);
return v;
}
float BMA250E::getTemperature(bool fahrenheit)
{
if (fahrenheit)
return c2f(m_temperature);
else
return m_temperature;
}
void BMA250E::reset()
{
writeReg(REG_SOFTRESET, BMA250E_RESET_BYTE);
sleep(1);
}
void BMA250E::setRange(RANGE_T range)
{
switch (m_resolution)
{
case RESOLUTION_10BITS:
switch(range)
{
case RANGE_2G:
m_accScale = 3.91; // milli-gravities
break;
case RANGE_4G:
m_accScale = 7.81;
break;
case RANGE_8G:
m_accScale = 15.63;
break;
case RANGE_16G:
m_accScale = 31.25;
break;
}
break;
case RESOLUTION_12BITS:
switch(range)
{
case RANGE_2G:
m_accScale = 0.98; // milli-gravities
break;
case RANGE_4G:
m_accScale = 1.95;
break;
case RANGE_8G:
m_accScale = 3.91;
break;
case RANGE_16G:
m_accScale = 7.81;
break;
}
break;
}
writeReg(REG_PMU_RANGE, range);
}
void BMA250E::setBandwidth(BW_T bw)
{
writeReg(REG_PMU_BW, bw);
}
void BMA250E::setPowerMode(POWER_MODE_T power)
{
// mask off reserved bits
uint8_t reg = readReg(REG_PMU_LPW) & ~_PMU_LPW_RESERVED_MASK;
reg &= ~(_PMU_LPW_POWER_MODE_MASK << _PMU_LPW_POWER_MODE_SHIFT);
reg |= (power << _PMU_LPW_POWER_MODE_SHIFT);
writeReg(REG_PMU_LPW, power);
}
void BMA250E::fifoSetWatermark(int wm)
{
// do nothing if we don't have a FIFO
if (!m_fifoAvailable)
return;
// mask off illegal values
uint8_t reg = uint8_t(wm) & _FIFO_CONFIG_0_WATER_MARK_MASK;
writeReg(REG_FIFO_CONFIG_0, reg);
}
void BMA250E::fifoConfig(FIFO_MODE_T mode, FIFO_DATA_SEL_T axes)
{
// do nothing if we don't have a FIFO
if (!m_fifoAvailable)
return;
uint8_t reg = ( (mode << _FIFO_CONFIG_1_FIFO_MODE_SHIFT) |
(axes << _FIFO_CONFIG_1_FIFO_DATA_SHIFT) );
writeReg(REG_FIFO_CONFIG_1, reg);
}
void BMA250E::setSelfTest(bool sign, bool amp, SELFTTEST_AXIS_T axis)
{
uint8_t reg = (axis << _PMU_SELFTTEST_AXIS_SHIFT);
if (amp)
reg |= PMU_SELFTTEST_AMP;
if (sign)
reg |= PMU_SELFTTEST_SIGN;
writeReg(REG_PMU_SELFTEST, reg);
}
uint8_t BMA250E::getInterruptEnable0()
{
return readReg(REG_INT_EN_0) & ~_INT_EN_0_RESERVED_BITS;
}
void BMA250E::setInterruptEnable0(uint8_t bits)
{
uint8_t reg = bits & ~_INT_EN_0_RESERVED_BITS;
writeReg(REG_INT_EN_0, reg);
}
uint8_t BMA250E::getInterruptEnable1()
{
return readReg(REG_INT_EN_1) & ~_INT_EN_1_RESERVED_BITS;
}
void BMA250E::setInterruptEnable1(uint8_t bits)
{
uint8_t reg = bits & ~_INT_EN_1_RESERVED_BITS;
writeReg(REG_INT_EN_1, reg);
}
uint8_t BMA250E::getInterruptEnable2()
{
return readReg(REG_INT_EN_2) & ~_INT_EN_2_RESERVED_BITS;
}
void BMA250E::setInterruptEnable2(uint8_t bits)
{
uint8_t reg = bits & ~_INT_EN_2_RESERVED_BITS;
writeReg(REG_INT_EN_2, reg);
}
uint8_t BMA250E::getInterruptMap0()
{
return readReg(REG_INT_MAP_0);
}
void BMA250E::setInterruptMap0(uint8_t bits)
{
writeReg(REG_INT_MAP_0, bits);
}
uint8_t BMA250E::getInterruptMap1()
{
return readReg(REG_INT_MAP_1) & ~_INT_MAP_1_INT1_RESERVED_BITS;
}
void BMA250E::setInterruptMap1(uint8_t bits)
{
uint8_t reg = bits & ~_INT_MAP_1_INT1_RESERVED_BITS;
writeReg(REG_INT_MAP_1, reg);
}
uint8_t BMA250E::getInterruptMap2()
{
return readReg(REG_INT_MAP_2);
}
void BMA250E::setInterruptMap2(uint8_t bits)
{
writeReg(REG_INT_MAP_2, bits);
}
uint8_t BMA250E::getInterruptSrc()
{
return readReg(REG_INT_SRC) & ~_INT_SRC_RESERVED_BITS;
}
void BMA250E::setInterruptSrc(uint8_t bits)
{
uint8_t reg = bits & ~_INT_SRC_RESERVED_BITS;
writeReg(REG_INT_SRC, reg);
}
uint8_t BMA250E::getInterruptOutputControl()
{
return readReg(REG_INT_OUT_CTRL) & ~_INT_OUT_CTRL_INT1_RESERVED_BITS;
}
void BMA250E::setInterruptOutputControl(uint8_t bits)
{
uint8_t reg = bits & ~_INT_OUT_CTRL_INT1_RESERVED_BITS;
writeReg(REG_INT_OUT_CTRL, reg);
}
void BMA250E::clearInterruptLatches()
{
uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS;
reg |= INT_RST_LATCH_RESET_INT;
writeReg(REG_INT_RST_LATCH, reg);
}
BMA250E::RST_LATCH_T BMA250E::getInterruptLatchBehavior()
{
uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS;
reg &= (_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT);
return static_cast<RST_LATCH_T>(reg);
}
void BMA250E::setInterruptLatchBehavior(RST_LATCH_T latch)
{
uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS;
reg &= ~(_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT);
reg |= (latch << _INT_RST_LATCH_SHIFT);
writeReg(REG_INT_RST_LATCH, reg);
}
void BMA250E::enableRegisterShadowing(bool shadow)
{
uint8_t reg = readReg(REG_ACC_HBW) & ~_ACC_HBW_RESERVED_BITS;
if (shadow)
reg &= ~ACC_HBW_SHADOW_DIS;
else
reg |= ACC_HBW_SHADOW_DIS;
writeReg(REG_ACC_HBW, reg);
}
void BMA250E::enableOutputFiltering(bool filter)
{
uint8_t reg = readReg(REG_ACC_HBW) & ~_ACC_HBW_RESERVED_BITS;
if (filter)
reg &= ~ACC_HBW_DATA_HIGH_BW;
else
reg |= ACC_HBW_DATA_HIGH_BW;
writeReg(REG_ACC_HBW, reg);
}
uint8_t BMA250E::getInterruptStatus0()
{
return readReg(REG_INT_STATUS_0);
}
uint8_t BMA250E::getInterruptStatus1()
{
return readReg(REG_INT_STATUS_1) & ~_INT_STATUS_1_RESERVED_BITS;
}
uint8_t BMA250E::getInterruptStatus2()
{
return readReg(REG_INT_STATUS_2);
}
uint8_t BMA250E::getInterruptStatus3Bits()
{
// filter out the orientation bitfield..
return readReg(REG_INT_STATUS_3) &
~(_INT_STATUS_3_ORIENT_MASK << _INT_STATUS_3_ORIENT_SHIFT);
}
BMA250E::ORIENT_T BMA250E::getInterruptStatus3Orientation()
{
// grab just the orientation bitfield
uint8_t reg = readReg(REG_INT_STATUS_3) &
(_INT_STATUS_3_ORIENT_MASK << _INT_STATUS_3_ORIENT_SHIFT);
reg >>= _INT_STATUS_3_ORIENT_SHIFT;
return static_cast<ORIENT_T>(reg);
}
void BMA250E::setLowPowerMode2()
{
uint8_t reg = readReg(REG_PMU_LOW_POWER) & ~_LOW_POWER_RESERVED_BITS;
// we simply set the low power mode to 2. Low power mode 1 slows
// down register write accesses, and we can't handle that. In the
// words of the late Admiral Akbar: "We cannot handle firepower of
// that magnitude!" :(
reg |= LOW_POWER_LOWPOWER_MODE;
writeReg(REG_PMU_LOW_POWER, reg);
}
#if defined(SWIGJAVA) || (JAVACALLBACK)
void BMA250E::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
jobject runnable)
{
// delete any existing ISR and GPIO context
uninstallISR(intr);
// create gpio context
getPin(intr) = new mraa::Gpio(gpio);
getPin(intr)->dir(mraa::DIR_IN);
getPin(intr)->isr(level, runnable);
}
#else
void BMA250E::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
void (*isr)(void *), void *arg)
{
// delete any existing ISR and GPIO context
uninstallISR(intr);
// create gpio context
getPin(intr) = new mraa::Gpio(gpio);
getPin(intr)->dir(mraa::DIR_IN);
getPin(intr)->isr(level, isr, arg);
}
#endif
void BMA250E::uninstallISR(INTERRUPT_PINS_T intr)
{
if (getPin(intr))
{
getPin(intr)->isrExit();
delete getPin(intr);
getPin(intr) = 0;
}
}
mraa::Gpio*& BMA250E::getPin(INTERRUPT_PINS_T intr)
{
switch(intr)
{
case INTERRUPT_INT1:
return m_gpioIntr1;
break;
case INTERRUPT_INT2:
return m_gpioIntr2;
break;
default:
throw std::out_of_range(string(__FUNCTION__) +
": Invalid interrupt enum passed");
}
}

1461
src/bmx055/bma250e.hpp Normal file

File diff suppressed because it is too large Load Diff

120
src/bmx055/bmc150.cxx Normal file
View File

@ -0,0 +1,120 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "bmc150.hpp"
using namespace upm;
using namespace std;
BMC150::BMC150(int accelBus, uint8_t accelAddr, int accelCS,
int magBus, uint8_t magAddr, int magCS) :
m_accel(0), m_mag(0)
{
// if -1 is supplied as a bus for any of these, we will not
// instantiate them
if (accelBus >= 0)
m_accel = new BMA250E(accelBus, accelAddr, accelCS);
if (magBus >= 0)
m_mag = new BMM150(magBus, magAddr, magCS);
// now initialize them...
if (m_accel)
m_accel->init();
if (m_mag)
m_mag->init();
}
BMC150::~BMC150()
{
if (m_accel)
delete m_accel;
if (m_mag)
delete m_mag;
}
void BMC150::initAccelerometer(BMA250E::POWER_MODE_T pwr,
BMA250E::RANGE_T range,
BMA250E::BW_T bw)
{
if (m_accel)
m_accel->init(pwr, range, bw);
}
void BMC150::initMagnetometer(BMM150::USAGE_PRESETS_T usage)
{
if (m_mag)
m_mag->init(usage);
}
void BMC150::update()
{
if (m_accel)
m_accel->update();
if (m_mag)
m_mag->update();
}
void BMC150::getAccelerometer(float *x, float *y, float *z)
{
if (m_accel)
m_accel->getAccelerometer(x, y, z);
}
float *BMC150::getAccelerometer()
{
if (m_accel)
return m_accel->getAccelerometer();
else
{
static float v[3] = {0.0f, 0.0f, 0.0f};
return v;
}
}
void BMC150::getMagnetometer(float *x, float *y, float *z)
{
if (m_mag)
m_mag->getMagnetometer(x, y, z);
}
float *BMC150::getMagnetometer()
{
if (m_mag)
return m_mag->getMagnetometer();
else
{
static float v[3] = {0.0f, 0.0f, 0.0f};
return v;
}
}

196
src/bmx055/bmc150.hpp Normal file
View File

@ -0,0 +1,196 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include "bma250e.hpp"
#include "bmm150.hpp"
#define BMC150_DEFAULT_BUS 0
#define BMC150_DEFAULT_ACC_ADDR 0x10
#define BMC150_DEFAULT_MAG_ADDR 0x12
namespace upm {
/**
* @library bmx055
* @sensor bmc150
* @comname BMC150 6-axis eCompass
* @type accelerometer compass
* @man mouser
* @con i2c gpio spi
* @web http://www.mouser.com/ProductDetail/Bosch-Sensortec/0330SB0156/?qs=sGAEpiMZZMsrChSOYEGTCd8nwjostN1SWavW0HYOOXw%3d
*
* @brief API for the BMC150 6-axis eCompass
*
*
* The BMC150 is an integrated electronic compass solution for
* consumer market applications. It comprises a 12bit leading edge
* triaxial, low-g acceleration sensor and an ultra-low power, high
* precision triaxial magnetic field sensor. It allows measurements
* of acceleration and magnetic field in three perpendicular
* axes. Performance and features of both sensing technologies are
* carefully tuned and perfectly match the demanding requirements of
* all 6-axis mobile applications such as electronic compass,
* navigation or augmented reality.
* The BMC150 is essentially 2 separate devices in one: the BMA250E
* Accelerometer and the BMM150 Magnetometer. They are completely
* independant of each other.
*
* This driver provides a very simple interface to these 2 devices.
* If finer control is desired, you should just use the separate
* BMA25E and BMM150 device classes directly. This driver simply
* initializes both devices, and provides a mechanism to read
* accelerometer and magnetometer data from them.
*
* @snippet bmc150.cxx Interesting
*/
class BMC150 {
public:
/**
* BMC150 constructor.
*
* This device can support both I2C and SPI. For SPI, set the addr
* to -1, and specify a positive integer representing the Chip
* Select (CS) pin for the cs argument. If you are using a
* hardware CS pin (like edison with arduino breakout), then you
* can connect the proper pin to the hardware CS pin on your MCU
* and supply -1 for cs. The default operating mode is I2C.
*
* @param accelBus I2C or SPI bus to use. -1 to skip initializing
* this device.
* @param accelAddr The address for this device. -1 for SPI.
* @param accelCS The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
* @param magBus I2C or SPI bus to use. -1 to skip initializing
* this device.
* @param magAddr The address for this device. -1 for SPI.
* @param magCS The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
*/
BMC150(int accelBus=BMC150_DEFAULT_BUS,
uint8_t accelAddr=BMC150_DEFAULT_ACC_ADDR,
int accelCS=-1,
int magBus=BMC150_DEFAULT_BUS,
uint8_t magAddr=BMC150_DEFAULT_MAG_ADDR,
int magCS=-1);
/**
* BMC150 Destructor.
*/
~BMC150();
/**
* Update the internal stored values from sensor data.
*/
void update();
/**
* Initialize the accelerometer and start operation. This
* function is called from the constructor so will not typically
* need to be called by a user unless the device is reset or you
* want to change these values.
*
* @param pwr One of the BMA250E::POWER_MODE_T values. The default is
* BMA250E::POWER_MODE_NORMAL.
* @param range One of the BMA250E::RANGE_T values. The default is
* BMA250E::RANGE_2G.
* @param bw One of the filtering BMA250E::BW_T values. The default is
* BMA250E::BW_250.
*/
void initAccelerometer(BMA250E::POWER_MODE_T pwr=BMA250E::POWER_MODE_NORMAL,
BMA250E::RANGE_T range=BMA250E::RANGE_2G,
BMA250E::BW_T bw=BMA250E::BW_250);
/**
* Initialize the magnetometer and start operation. This function
* is called from the constructor so will not typically need to be
* called by a user unless the device is reset or you want to
* change these values. This method will call
* BMM150::setPresetMode() with the passed parameter.
*
* @param usage One of the BMM150::USAGE_PRESETS_T values. The default is
* BMM150::USAGE_HIGH_ACCURACY.
*/
void initMagnetometer(BMM150::USAGE_PRESETS_T usage=BMM150::USAGE_HIGH_ACCURACY);
/**
* Return accelerometer data in gravities. update() must have
* been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getAccelerometer(float *x, float *y, float *z);
/**
* Return accelerometer data in gravities in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getAccelerometer();
/**
* Return magnetometer data in micro-Teslas (uT). update() must
* have been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getMagnetometer(float *x, float *y, float *z);
/**
* Return magnetometer data in micro-Teslas (uT) in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getMagnetometer();
protected:
BMA250E *m_accel;
BMM150 *m_mag;
private:
};
}

581
src/bmx055/bmg160.cxx Normal file
View File

@ -0,0 +1,581 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string.h>
#include "bmg160.hpp"
using namespace upm;
using namespace std;
#define BMG160_DEFAULT_CHIPID 0x0f
// conversion from celcius to fahrenheit
static float c2f(float c)
{
return (c * (9.0 / 5.0) + 32.0);
}
BMG160::BMG160(int bus, uint8_t addr, int cs) :
m_i2c(0), m_spi(0), m_gpioIntr1(0), m_gpioIntr2(0), m_gpioCS(0)
{
m_addr = addr;
m_isSPI = false;
m_gyrX = 0;
m_gyrY = 0;
m_gyrZ = 0;
m_gyrScale = 0;
m_temperature = 0.0;
if (addr < 0)
m_isSPI = true;
if (m_isSPI)
{
m_spi = new mraa::Spi(bus);
// Only create cs context if we are actually using a valid pin.
// A hardware controlled pin should specify cs as -1.
if (cs >= 0)
{
m_gpioCS = new mraa::Gpio(cs);
m_gpioCS->dir(mraa::DIR_OUT);
}
m_spi->mode(mraa::SPI_MODE0);
m_spi->frequency(5000000);
}
else
{
// I2C
m_i2c = new mraa::I2c(bus);
mraa::Result rv;
if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS)
{
throw std::runtime_error(string(__FUNCTION__) +
": I2c.address() failed");
}
}
// check the chip id
uint8_t chipID = getChipID();
if (chipID != BMG160_DEFAULT_CHIPID)
{
throw std::runtime_error(string(__FUNCTION__)
+ ": invalid chip ID. Expected "
+ std::to_string(int(BMG160_DEFAULT_CHIPID))
+ ", got "
+ std::to_string(int(chipID)));
}
// call init with default options
init();
}
BMG160::~BMG160()
{
uninstallISR(INTERRUPT_INT1);
uninstallISR(INTERRUPT_INT2);
}
void BMG160::init(POWER_MODE_T pwr, RANGE_T range, BW_T bw)
{
setPowerMode(pwr);
usleep(50000); // 50ms, in case we are waking up
// set our range and bandwidth
setRange(range);
setBandwidth(bw);
// make sure register shadowing is enabled
enableRegisterShadowing(true);
// enable output filtering
enableOutputFiltering(true);
// use the FIFO by default
fifoConfig(FIFO_MODE_BYPASS, FIFO_DATA_SEL_XYZ);
enableFIFO(true);
// settle
usleep(50000);
}
void BMG160::update()
{
int bufLen = 0;
uint8_t startReg = 0;
if (m_useFIFO)
{
bufLen = 6;
startReg = REG_FIFO_DATA;
}
else
{
// non FIFO, read acc regs directly (including temp)
bufLen = 7;
startReg = REG_RATE_X_LSB;
}
uint8_t buf[bufLen];
if (readRegs(startReg, buf, bufLen) != bufLen)
{
throw std::runtime_error(string(__FUNCTION__)
+ ": readRegs() failed to read "
+ std::to_string(bufLen)
+ " bytes");
}
int16_t val;
// x
val = int16_t(buf[1] << 8 | buf[0]);
m_gyrX = float(val);
// y
val = int16_t(buf[3] << 8 | buf[2]);
m_gyrY = float(val);
// z
val = int16_t(buf[5] << 8 | buf[4]);
m_gyrZ = float(val);
// get the temperature...
uint8_t temp = 0;
if (m_useFIFO)
{
// we have to read temperature separately...
temp = readReg(REG_TEMP);
}
else
{
// we already got it
temp = buf[6];
}
// .5K/LSB, 23C center point
m_temperature = (float(temp) / 2.0) + 23.0;
}
void BMG160::enableFIFO(bool useFIFO)
{
m_useFIFO = useFIFO;
}
uint8_t BMG160::readReg(uint8_t reg)
{
if (m_isSPI)
{
reg |= 0x80; // needed for read
uint8_t pkt[2] = {reg, 0};
csOn();
if (m_spi->transfer(pkt, pkt, 2))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer() failed");
}
csOff();
return pkt[1];
}
else
return m_i2c->readReg(reg);
}
int BMG160::readRegs(uint8_t reg, uint8_t *buffer, int len)
{
if (m_isSPI)
{
reg |= 0x80; // needed for read
uint8_t sbuf[len + 1];
memset((char *)sbuf, 0, len + 1);
sbuf[0] = reg;
// We need to do it this way for edison - ie: use a single
// transfer rather than breaking it up into two like we used to.
// This means a buffer copy is now required, but that's the way
// it goes.
csOn();
if (m_spi->transfer(sbuf, sbuf, len + 1))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer(buf) failed");
}
csOff();
// now copy it into user buffer
for (int i=0; i<len; i++)
buffer[i] = sbuf[i + 1];
return len;
}
else
return m_i2c->readBytesReg(reg, buffer, len);
}
void BMG160::writeReg(uint8_t reg, uint8_t val)
{
if (m_isSPI)
{
reg &= 0x7f; // mask off 0x80 for writing
uint8_t pkt[2] = {reg, val};
csOn();
if (m_spi->transfer(pkt, NULL, 2))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer() failed");
}
csOff();
}
else
{
mraa::Result rv;
if ((rv = m_i2c->writeReg(reg, val)) != mraa::SUCCESS)
{
throw std::runtime_error(std::string(__FUNCTION__)
+ ": I2c.writeReg() failed");
}
}
}
void BMG160::csOn()
{
if (m_gpioCS)
m_gpioCS->write(0);
}
void BMG160::csOff()
{
if (m_gpioCS)
m_gpioCS->write(1);
}
uint8_t BMG160::getChipID()
{
return readReg(REG_CHIP_ID);
}
void BMG160::getGyroscope(float *x, float *y, float *z)
{
if (x)
*x = (m_gyrX * m_gyrScale) / 1000.0;
if (y)
*y = (m_gyrY * m_gyrScale) / 1000.0;
if (z)
*z = (m_gyrZ * m_gyrScale) / 1000.0;
}
float *BMG160::getGyroscope()
{
static float v[3];
getGyroscope(&v[0], &v[1], &v[2]);
return v;
}
float BMG160::getTemperature(bool fahrenheit)
{
if (fahrenheit)
return c2f(m_temperature);
else
return m_temperature;
}
void BMG160::reset()
{
writeReg(REG_SOFTRESET, BMG160_RESET_BYTE);
sleep(1);
}
void BMG160::setRange(RANGE_T range)
{
switch(range)
{
case RANGE_125:
m_gyrScale = 3.8; // milli-degrees
break;
case RANGE_250:
m_gyrScale = 7.6;
break;
case RANGE_500:
m_gyrScale = 15.3;
break;
case RANGE_1000:
m_gyrScale = 30.5;
break;
case RANGE_2000:
m_gyrScale = 61.0;
break;
}
// we also have to write a fixed '0x10' to the high-order bits for
// some reason (according to datasheet)
uint8_t reg = range | (_GYR_RANGE_FIXED_VALUE << _GYR_RANGE_FIXED_SHIFT);
writeReg(REG_GYR_RANGE, reg);
}
void BMG160::setBandwidth(BW_T bw)
{
writeReg(REG_GYR_BW, bw);
}
void BMG160::setPowerMode(POWER_MODE_T power)
{
// mask off reserved bits
uint8_t reg = readReg(REG_LPM1) & ~_LPM1_RESERVED_MASK;
reg &= ~(_LPM1_POWER_MODE_MASK << _LPM1_POWER_MODE_SHIFT);
reg |= (power << _LPM1_POWER_MODE_SHIFT);
writeReg(REG_LPM1, power);
}
void BMG160::fifoSetWatermark(int wm)
{
// mask off illegal values
uint8_t reg = uint8_t(wm) & _FIFO_CONFIG_0_WATER_MARK_MASK;
writeReg(REG_FIFO_CONFIG_0, reg);
}
void BMG160::fifoConfig(FIFO_MODE_T mode, FIFO_DATA_SEL_T axes)
{
uint8_t reg = ( (mode << _FIFO_CONFIG_1_FIFO_MODE_SHIFT) |
(axes << _FIFO_CONFIG_1_FIFO_DATA_SHIFT) );
writeReg(REG_FIFO_CONFIG_1, reg);
}
uint8_t BMG160::getInterruptEnable0()
{
return readReg(REG_INT_EN_0) & ~_INT_EN_0_RESERVED_BITS;
}
void BMG160::setInterruptEnable0(uint8_t bits)
{
uint8_t reg = bits & ~_INT_EN_0_RESERVED_BITS;
writeReg(REG_INT_EN_0, reg);
}
uint8_t BMG160::getInterruptMap0()
{
return readReg(REG_INT_MAP_0) & ~_INT_MAP_0_RESERVED_BITS;
}
void BMG160::setInterruptMap0(uint8_t bits)
{
uint8_t reg = bits & ~_INT_MAP_0_RESERVED_BITS;
writeReg(REG_INT_MAP_0, reg);
}
uint8_t BMG160::getInterruptMap1()
{
return readReg(REG_INT_MAP_1);
}
void BMG160::setInterruptMap1(uint8_t bits)
{
writeReg(REG_INT_MAP_1, bits);
}
// REG_INT_EN1, for some strange reason
uint8_t BMG160::getInterruptSrc()
{
return readReg(REG_INT_EN_1) & ~_INT_EN_1_INT1_RESERVED_BITS;
}
void BMG160::setInterruptSrc(uint8_t bits)
{
uint8_t reg = bits & ~_INT_EN_1_INT1_RESERVED_BITS;
writeReg(REG_INT_EN_1, reg);
}
uint8_t BMG160::getInterruptOutputControl()
{
return readReg(REG_INT_EN_1) & ~_INT_EN_1_INT1_RESERVED_BITS;
}
void BMG160::setInterruptOutputControl(uint8_t bits)
{
uint8_t reg = bits & ~_INT_EN_1_INT1_RESERVED_BITS;
writeReg(REG_INT_EN_1, reg);
}
void BMG160::clearInterruptLatches()
{
uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS;
reg |= INT_RST_LATCH_RESET_INT;
writeReg(REG_INT_RST_LATCH, reg);
}
BMG160::RST_LATCH_T BMG160::getInterruptLatchBehavior()
{
uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS;
reg &= (_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT);
return static_cast<RST_LATCH_T>(reg);
}
void BMG160::setInterruptLatchBehavior(RST_LATCH_T latch)
{
uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS;
reg &= ~(_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT);
reg |= (latch << _INT_RST_LATCH_SHIFT);
writeReg(REG_INT_RST_LATCH, reg);
}
void BMG160::enableRegisterShadowing(bool shadow)
{
uint8_t reg = readReg(REG_RATE_HBW) & ~_RATE_HBW_RESERVED_BITS;
if (shadow)
reg &= ~RATE_HBW_SHADOW_DIS;
else
reg |= RATE_HBW_SHADOW_DIS;
writeReg(REG_RATE_HBW, reg);
}
void BMG160::enableOutputFiltering(bool filter)
{
uint8_t reg = readReg(REG_RATE_HBW) & ~_RATE_HBW_RESERVED_BITS;
if (filter)
reg &= ~RATE_HBW_DATA_HIGH_BW;
else
reg |= RATE_HBW_DATA_HIGH_BW;
writeReg(REG_RATE_HBW, reg);
}
uint8_t BMG160::getInterruptStatus0()
{
return readReg(REG_INT_STATUS_0) & ~_INT_STATUS_0_RESERVED_BITS;
}
uint8_t BMG160::getInterruptStatus1()
{
return readReg(REG_INT_STATUS_1) & ~_INT_STATUS_1_RESERVED_BITS;
}
uint8_t BMG160::getInterruptStatus2()
{
return readReg(REG_INT_STATUS_2) & ~_INT_STATUS_2_RESERVED_BITS;
}
uint8_t BMG160::getInterruptStatus3()
{
return readReg(REG_INT_STATUS_3) & ~_INT_STATUS_3_RESERVED_BITS;
}
#if defined(SWIGJAVA) || (JAVACALLBACK)
void BMG160::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
jobject runnable)
{
// delete any existing ISR and GPIO context
uninstallISR(intr);
// create gpio context
getPin(intr) = new mraa::Gpio(gpio);
getPin(intr)->dir(mraa::DIR_IN);
getPin(intr)->isr(level, runnable);
}
#else
void BMG160::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
void (*isr)(void *), void *arg)
{
// delete any existing ISR and GPIO context
uninstallISR(intr);
// create gpio context
getPin(intr) = new mraa::Gpio(gpio);
getPin(intr)->dir(mraa::DIR_IN);
getPin(intr)->isr(level, isr, arg);
}
#endif
void BMG160::uninstallISR(INTERRUPT_PINS_T intr)
{
if (getPin(intr))
{
getPin(intr)->isrExit();
delete getPin(intr);
getPin(intr) = 0;
}
}
mraa::Gpio*& BMG160::getPin(INTERRUPT_PINS_T intr)
{
switch(intr)
{
case INTERRUPT_INT1:
return m_gpioIntr1;
break;
case INTERRUPT_INT2:
return m_gpioIntr2;
break;
default:
throw std::out_of_range(string(__FUNCTION__) +
": Invalid interrupt enum passed");
}
}

1223
src/bmx055/bmg160.hpp Normal file

File diff suppressed because it is too large Load Diff

122
src/bmx055/bmi055.cxx Normal file
View File

@ -0,0 +1,122 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "bmi055.hpp"
using namespace upm;
using namespace std;
BMI055::BMI055(int accelBus, uint8_t accelAddr, int accelCS,
int gyroBus, uint8_t gyroAddr, int gyroCS) :
m_accel(0), m_gyro(0)
{
// if -1 is supplied as a bus for any of these, we will not
// instantiate them
if (accelBus >= 0)
m_accel = new BMA250E(accelBus, accelAddr, accelCS);
if (gyroBus >= 0)
m_gyro = new BMG160(gyroBus, gyroAddr, gyroCS);
// now initialize them...
if (m_accel)
m_accel->init();
if (m_gyro)
m_gyro->init();
}
BMI055::~BMI055()
{
if (m_accel)
delete m_accel;
if (m_gyro)
delete m_gyro;
}
void BMI055::initAccelerometer(BMA250E::POWER_MODE_T pwr,
BMA250E::RANGE_T range,
BMA250E::BW_T bw)
{
if (m_accel)
m_accel->init(pwr, range, bw);
}
void BMI055::initGyroscope(BMG160::POWER_MODE_T pwr,
BMG160::RANGE_T range,
BMG160::BW_T bw)
{
if (m_gyro)
m_gyro->init(pwr, range, bw);
}
void BMI055::update()
{
if (m_accel)
m_accel->update();
if (m_gyro)
m_gyro->update();
}
void BMI055::getAccelerometer(float *x, float *y, float *z)
{
if (m_accel)
m_accel->getAccelerometer(x, y, z);
}
float *BMI055::getAccelerometer()
{
if (m_accel)
return m_accel->getAccelerometer();
else
{
static float v[3] = {0.0f, 0.0f, 0.0f};
return v;
}
}
void BMI055::getGyroscope(float *x, float *y, float *z)
{
if (m_gyro)
m_gyro->getGyroscope(x, y, z);
}
float *BMI055::getGyroscope()
{
if (m_gyro)
return m_gyro->getGyroscope();
else
{
static float v[3] = {0.0f, 0.0f, 0.0f};
return v;
}
}

193
src/bmx055/bmi055.hpp Normal file
View File

@ -0,0 +1,193 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include "bma250e.hpp"
#include "bmg160.hpp"
namespace upm {
/**
* @library bmx055
* @sensor bmi055
* @comname BMI055 6-axis Sensor Module
* @type accelerometer compass
* @man mouser
* @con i2c gpio spi
* @web http://www.mouser.com/ProductDetail/Bosch-Sensortec/0330SB0134/?qs=sGAEpiMZZMsrChSOYEGTCVIRbo47L7ys6GxSnxRPEhU%3d
*
* @brief API for the BMI055 6-axis Sensor Module
*
* The BMI055 is an inertial measurement unit (IMU) for the
* detection of movements and rotations in 6 degrees of freedom
* (6DoF). It reflects the full functionality of a triaxial, low-g
* acceleration sensor and at the same time it is capable to measure
* angular rates. Both acceleration and angular rate in three
* perpendicular room dimensions, the x-, y- and z-axis.
*
* The BMI055 is essentially 2 separate devices in one: the BMA250E
* Accelerometer and the BMG160 Gyroscope. They are completely
* independant of each other.
*
* This driver provides a very simple interface to these two devices.
* If finer control is desired, you should just use the separate
* BMA25E and BMG160 device classes directly. This driver
* simply initializes both devices, and provides a mechanism to
* read accelerometer and gyroscope data from them.
*
* @snippet bmi055.cxx Interesting
*/
class BMI055 {
public:
/**
* BMI055 constructor.
*
* This device can support both I2C and SPI. For SPI, set the addr
* to -1, and specify a positive integer representing the Chip
* Select (CS) pin for the cs argument. If you are using a
* hardware CS pin (like edison with arduino breakout), then you
* can connect the proper pin to the hardware CS pin on your MCU
* and supply -1 for cs. The default operating mode is I2C.
*
* @param accelBus I2C or SPI bus to use. -1 to skip initializing
* this device.
* @param accelAddr The address for this device. -1 for SPI.
* @param accelCS The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
* @param gyroBus I2C or SPI bus to use. -1 to skip initializing
* this device.
* @param gyroAddr The address for this device. -1 for SPI.
* @param gyroCS The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
*/
BMI055(int accelBus=BMA250E_I2C_BUS,
uint8_t accelAddr=BMA250E_DEFAULT_ADDR,
int accelCS=-1,
int gyroBus=BMG160_I2C_BUS,
uint8_t gyroAddr=BMG160_DEFAULT_ADDR,
int gyroCS=-1);
/**
* BMI055 Destructor.
*/
~BMI055();
/**
* Update the internal stored values from sensor data.
*/
void update();
/**
* Initialize the accelerometer and start operation. This
* function is called from the constructor so will not typically
* need to be called by a user unless the device is reset or you
* want to change these values.
*
* @param pwr One of the BMA250E::POWER_MODE_T values. The default is
* BMA250E::POWER_MODE_NORMAL.
* @param range One of the BMA250E::RANGE_T values. The default is
* BMA250E::RANGE_2G.
* @param bw One of the filtering BMA250E::BW_T values. The default is
* BMA250E::BW_250.
*/
void initAccelerometer(BMA250E::POWER_MODE_T pwr=BMA250E::POWER_MODE_NORMAL,
BMA250E::RANGE_T range=BMA250E::RANGE_2G,
BMA250E::BW_T bw=BMA250E::BW_250);
/**
* Initialize the gyroscope and start operation. This function is
* called from the constructor so will not typically need to be
* called by a user unless the device is reset or you want to
* change these values.
*
* @param pwr One of the BMG160::POWER_MODE_T values. The default is
* BMG160::POWER_MODE_NORMAL.
* @param range One of the BMG160::RANGE_T values. The default is
* BMG160::RANGE_250.
* @param bw One of the filtering BMG160::BW_T values. The default is
* BMG160::BW_400_47.
*/
void initGyroscope(BMG160::POWER_MODE_T pwr=BMG160::POWER_MODE_NORMAL,
BMG160::RANGE_T range=BMG160::RANGE_250,
BMG160::BW_T bw=BMG160::BW_400_47);
/**
* Return accelerometer data in gravities. update() must have
* been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getAccelerometer(float *x, float *y, float *z);
/**
* Return accelerometer data in gravities in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getAccelerometer();
/**
* Return gyroscope data in degrees per second. update() must
* have been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getGyroscope(float *x, float *y, float *z);
/**
* Return gyroscope data in degrees per second in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getGyroscope();
protected:
BMA250E *m_accel;
BMG160 *m_gyro;
private:
};
}

675
src/bmx055/bmm150.cxx Normal file
View File

@ -0,0 +1,675 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
// The trimming algorithms are taken from the Bosch BMM050 driver code
/****************************************************************************
* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
*
* File : bmm050.h
*
* Date : 2016/03/17
*
* Revision : 2.0.5 $
*
* Usage: Sensor Driver for BMM050 and BMM150 sensor
*
****************************************************************************
*
* section License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
* The information provided is believed to be accurate and reliable.
* The copyright holder assumes no responsibility
* for the consequences of use
* of such information nor for any infringement of patents or
* other rights of third parties which may result from its use.
* No license is granted by implication or otherwise under any patent or
* patent rights of the copyright holder.
**************************************************************************/
#include <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string.h>
#include "bmm150.hpp"
#define BMM150_DEFAULT_CHIPID 0x32
using namespace upm;
using namespace std;
BMM150::BMM150(int bus, uint8_t addr, int cs) :
m_i2c(0), m_spi(0), m_gpioIntr(0), m_gpioDR(0), m_gpioCS(0)
{
m_addr = addr;
m_isSPI = false;
m_magX = 0;
m_magY = 0;
m_magZ = 0;
m_hall = 0;
m_dig_x1 = 0;
m_dig_y1 = 0;
m_dig_z4 = 0;
m_dig_x2 = 0;
m_dig_y2 = 0;
m_dig_z2 = 0;
m_dig_z1 = 0;
m_dig_xyz1 = 0;
m_dig_z3 = 0;
m_dig_xy2 = 0;
m_dig_xy1 = 0;
if (addr < 0)
m_isSPI = true;
if (m_isSPI)
{
m_spi = new mraa::Spi(bus);
// Only create cs context if we are actually using a valid pin.
// A hardware controlled pin should specify cs as -1.
if (cs >= 0)
{
m_gpioCS = new mraa::Gpio(cs);
m_gpioCS->dir(mraa::DIR_OUT);
}
m_spi->mode(mraa::SPI_MODE0);
m_spi->frequency(5000000);
}
else
{
// I2C
m_i2c = new mraa::I2c(bus);
mraa::Result rv;
if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS)
{
throw std::runtime_error(string(__FUNCTION__) +
": I2c.address() failed");
}
}
// power bit must be on for chip ID to be accessable
setPowerBit(true);
m_opmode = OPERATION_MODE_SLEEP;
usleep(50000);
// check the chip id
uint8_t chipID = getChipID();
if (chipID != BMM150_DEFAULT_CHIPID)
{
throw std::runtime_error(string(__FUNCTION__)
+ ": invalid chip ID. Expected "
+ std::to_string(int(BMM150_DEFAULT_CHIPID))
+ ", got "
+ std::to_string(int(chipID)));
}
// get trim data
readTrimData();
// call init with default options
init();
}
BMM150::~BMM150()
{
uninstallISR(INTERRUPT_INT);
uninstallISR(INTERRUPT_DR);
}
void BMM150::init(USAGE_PRESETS_T usage)
{
setPowerBit(true);
setOpmode(OPERATION_MODE_NORMAL);
usleep(50000); // 50ms, in case we are waking up
setPresetMode(usage);
// settle
usleep(50000);
}
void BMM150::update()
{
// special care when in a forced mode - need to trigger a
// measurement, and wait for the opmode to return to OPMODE_SLEEP,
// then we can read the values.
if (m_opmode == OPERATION_MODE_FORCED)
{
// trigger measurement
setOpmode(OPERATION_MODE_FORCED);
// opmode will return to sleep after measurement is complete
do {
usleep(5000);
} while (getOpmode() == OPERATION_MODE_FORCED);
}
const int bufLen = 8;
uint8_t buf[bufLen];
if (readRegs(REG_MAG_X_LSB, buf, bufLen) != bufLen)
{
throw std::runtime_error(string(__FUNCTION__)
+ ": readRegs() failed to read "
+ std::to_string(bufLen)
+ " bytes");
}
// we need to get the hall data first, since it's needed for the
// bosch compensation functions for each of the xyz axes
m_hall = uint16_t(buf[7] << 8 | (buf[6] &
(_MAG_RHALL_LSB_LSB_MASK <<
_MAG_RHALL_LSB_LSB_SHIFT)));
m_hall /= 4;
int16_t val;
// x
val = int16_t(buf[1] << 8 | (buf[0] & (_MAG_XY_LSB_LSB_MASK <<
_MAG_XY_LSB_LSB_SHIFT)));
val /= 8;
m_magX = bmm050_compensate_X_float(val, m_hall);
// y
val = int16_t(buf[3] << 8 | (buf[2] & (_MAG_XY_LSB_LSB_MASK <<
_MAG_XY_LSB_LSB_SHIFT)));
val /= 8;
m_magY = bmm050_compensate_Y_float(val, m_hall);
// z
val = int16_t(buf[5] << 8 | (buf[4] & (_MAG_Z_LSB_LSB_MASK <<
_MAG_Z_LSB_LSB_SHIFT)));
val /= 2;
m_magZ = bmm050_compensate_Z_float(val, m_hall);
}
uint8_t BMM150::readReg(uint8_t reg)
{
if (m_isSPI)
{
reg |= 0x80; // needed for read
uint8_t pkt[2] = {reg, 0};
csOn();
if (m_spi->transfer(pkt, pkt, 2))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer() failed");
}
csOff();
return pkt[1];
}
else
return m_i2c->readReg(reg);
}
int BMM150::readRegs(uint8_t reg, uint8_t *buffer, int len)
{
if (m_isSPI)
{
reg |= 0x80; // needed for read
uint8_t sbuf[len + 1];
memset((char *)sbuf, 0, len + 1);
sbuf[0] = reg;
// We need to do it this way for edison - ie: use a single
// transfer rather than breaking it up into two like we used to.
// This means a buffer copy is now required, but that's the way
// it goes.
csOn();
if (m_spi->transfer(sbuf, sbuf, len + 1))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer(buf) failed");
}
csOff();
// now copy it into user buffer
for (int i=0; i<len; i++)
buffer[i] = sbuf[i + 1];
return len;
}
else
return m_i2c->readBytesReg(reg, buffer, len);
}
void BMM150::writeReg(uint8_t reg, uint8_t val)
{
if (m_isSPI)
{
reg &= 0x7f; // mask off 0x80 for writing
uint8_t pkt[2] = {reg, val};
csOn();
if (m_spi->transfer(pkt, NULL, 2))
{
csOff();
throw std::runtime_error(string(__FUNCTION__)
+ ": Spi.transfer() failed");
}
csOff();
}
else
{
mraa::Result rv;
if ((rv = m_i2c->writeReg(reg, val)) != mraa::SUCCESS)
{
throw std::runtime_error(std::string(__FUNCTION__)
+ ": I2c.writeReg() failed");
}
}
}
void BMM150::csOn()
{
if (m_gpioCS)
m_gpioCS->write(0);
}
void BMM150::csOff()
{
if (m_gpioCS)
m_gpioCS->write(1);
}
uint8_t BMM150::getChipID()
{
return readReg(REG_CHIP_ID);
}
void BMM150::getMagnetometer(float *x, float *y, float *z)
{
if (x)
*x = m_magX;
if (y)
*y = m_magY;
if (z)
*z = m_magZ;
}
float *BMM150::getMagnetometer()
{
static float v[3];
getMagnetometer(&v[0], &v[1], &v[2]);
return v;
}
void BMM150::reset()
{
// mask off reserved bits
uint8_t reg = readReg(REG_POWER_CTRL) & ~_POWER_CTRL_RESERVED_BITS;
reg |= POWER_CTRL_SOFT_RESET0 | POWER_CTRL_SOFT_RESET1;
writeReg(REG_POWER_CTRL, reg);
sleep(1);
// device will return to SLEEP mode...
}
void BMM150::setOutputDataRate(DATA_RATE_T odr)
{
uint8_t reg = readReg(REG_OPMODE);
reg &= ~(_OPMODE_DATA_RATE_MASK << _OPMODE_DATA_RATE_SHIFT);
reg |= (odr << _OPMODE_DATA_RATE_SHIFT);
writeReg(REG_OPMODE, reg);
}
void BMM150::setPowerBit(bool power)
{
// mask off reserved bits
uint8_t reg = readReg(REG_POWER_CTRL) & ~_POWER_CTRL_RESERVED_BITS;
if (power)
reg |= POWER_CTRL_POWER_CTRL_BIT;
else
reg &= ~POWER_CTRL_POWER_CTRL_BIT;
writeReg(REG_POWER_CTRL, reg);
}
void BMM150::setOpmode(OPERATION_MODE_T opmode)
{
uint8_t reg = readReg(REG_OPMODE);
reg &= ~(_OPMODE_OPERATION_MODE_MASK << _OPMODE_OPERATION_MODE_SHIFT);
reg |= (opmode << _OPMODE_OPERATION_MODE_SHIFT);
writeReg(REG_OPMODE, reg);
m_opmode = opmode;
}
BMM150::OPERATION_MODE_T BMM150::getOpmode()
{
uint8_t reg = readReg(REG_OPMODE);
reg &= (_OPMODE_OPERATION_MODE_MASK << _OPMODE_OPERATION_MODE_SHIFT);
reg >>= _OPMODE_OPERATION_MODE_SHIFT;
return static_cast<OPERATION_MODE_T>(reg);
}
uint8_t BMM150::getInterruptEnable()
{
return readReg(REG_INT_EN);
}
void BMM150::setInterruptEnable(uint8_t bits)
{
writeReg(REG_INT_EN, bits);
}
uint8_t BMM150::getInterruptConfig()
{
return readReg(REG_INT_CONFIG);
}
void BMM150::setInterruptConfig(uint8_t bits)
{
writeReg(REG_INT_CONFIG, bits);
}
uint8_t BMM150::getInterruptStatus()
{
return readReg(REG_INT_STATUS);
}
void BMM150::readTrimData()
{
int bufLen = 10;
uint8_t calibData[bufLen];
// 2 bytes first
readRegs(REG_TRIM_DIG_X1, calibData, 2);
m_dig_x1 = int8_t(calibData[0]);
m_dig_y1 = int8_t(calibData[1]);
// next block of 4 bytes
readRegs(REG_TRIM_DIG_Z4_LSB, calibData, 4);
m_dig_z4 = int16_t((calibData[1] << 8) | calibData[0]);
m_dig_x2 = int8_t(calibData[2]);
m_dig_y2 = int8_t(calibData[3]);
// final block of 10 bytes
readRegs(REG_TRIM_DIG_Z2_LSB, calibData, 10);
m_dig_z2 = int16_t((calibData[1] << 8) | calibData[0]);
m_dig_z1 = uint16_t((calibData[3] << 8) | calibData[2]);
m_dig_xyz1 = uint16_t((calibData[5] << 8) | calibData[4]);
m_dig_z3 = int16_t((calibData[7] << 8) | calibData[6]);
m_dig_xy2 = int8_t(calibData[8]);
m_dig_xy1 = calibData[9];
}
void BMM150::setRepetitionsXY(uint8_t reps)
{
writeReg(REG_REP_XY, reps);
}
void BMM150::setRepetitionsZ(uint8_t reps)
{
writeReg(REG_REP_Z, reps);
}
void BMM150::setPresetMode(USAGE_PRESETS_T usage)
{
// these recommended presets come from the datasheet, Table 3,
// Section 4.2
switch (usage)
{
case USAGE_LOW_POWER:
setRepetitionsXY(3);
setRepetitionsZ(3);
setOutputDataRate(DATA_RATE_10HZ);
break;
case USAGE_REGULAR:
setRepetitionsXY(9);
setRepetitionsZ(15);
setOutputDataRate(DATA_RATE_10HZ);
break;
case USAGE_ENHANCED_REGULAR:
setRepetitionsXY(15);
setRepetitionsZ(27);
setOutputDataRate(DATA_RATE_10HZ);
break;
case USAGE_HIGH_ACCURACY:
setRepetitionsXY(47);
setRepetitionsZ(83);
setOutputDataRate(DATA_RATE_20HZ);
break;
default:
throw std::out_of_range(string(__FUNCTION__) +
": Invalid usage enum passed");
}
}
#if defined(SWIGJAVA) || (JAVACALLBACK)
void BMM150::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
jobject runnable)
{
// delete any existing ISR and GPIO context
uninstallISR(intr);
// create gpio context
getPin(intr) = new mraa::Gpio(gpio);
getPin(intr)->dir(mraa::DIR_IN);
getPin(intr)->isr(level, runnable);
}
#else
void BMM150::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
void (*isr)(void *), void *arg)
{
// delete any existing ISR and GPIO context
uninstallISR(intr);
// create gpio context
getPin(intr) = new mraa::Gpio(gpio);
getPin(intr)->dir(mraa::DIR_IN);
getPin(intr)->isr(level, isr, arg);
}
#endif
void BMM150::uninstallISR(INTERRUPT_PINS_T intr)
{
if (getPin(intr))
{
getPin(intr)->isrExit();
delete getPin(intr);
getPin(intr) = 0;
}
}
mraa::Gpio*& BMM150::getPin(INTERRUPT_PINS_T intr)
{
switch(intr)
{
case INTERRUPT_INT:
return m_gpioIntr;
break;
case INTERRUPT_DR:
return m_gpioDR;
break;
default:
throw std::out_of_range(string(__FUNCTION__) +
": Invalid interrupt enum passed");
}
}
// Bosch compensation functions
float BMM150::bmm050_compensate_X_float(int16_t mag_data_x, uint16_t data_r)
{
float inter_retval = 0;
if (mag_data_x != -4096 /* no overflow */
) {
if ((data_r != 0)
&& (m_dig_xyz1 != 0)) {
inter_retval = ((((float)m_dig_xyz1)
* 16384.0 / data_r) - 16384.0);
} else {
inter_retval = 0.0f;
return inter_retval;
}
inter_retval = (((mag_data_x * ((((((float)m_dig_xy2) *
(inter_retval*inter_retval /
268435456.0) +
inter_retval * ((float)m_dig_xy1)
/ 16384.0)) + 256.0) *
(((float)m_dig_x2) + 160.0)))
/ 8192.0)
+ (((float)m_dig_x1) *
8.0)) / 16.0;
} else {
inter_retval = 0.0f;
}
return inter_retval;
}
float BMM150::bmm050_compensate_Y_float(int16_t mag_data_y, uint16_t data_r)
{
float inter_retval = 0;
if (mag_data_y != -4096 /* no overflow */
) {
if ((data_r != 0)
&& (m_dig_xyz1 != 0)) {
inter_retval = ((((float)m_dig_xyz1)
* 16384.0
/data_r) - 16384.0);
} else {
inter_retval = 0.0f;
return inter_retval;
}
inter_retval = (((mag_data_y * ((((((float)m_dig_xy2) *
(inter_retval*inter_retval
/ 268435456.0) +
inter_retval * ((float)m_dig_xy1)
/ 16384.0)) +
256.0) *
(((float)m_dig_y2) + 160.0)))
/ 8192.0) +
(((float)m_dig_y1) * 8.0))
/ 16.0;
} else {
/* overflow, set output to 0.0f */
inter_retval = 0.0f;
}
return inter_retval;
}
float BMM150::bmm050_compensate_Z_float(int16_t mag_data_z, uint16_t data_r)
{
float inter_retval = 0;
/* no overflow */
if (mag_data_z != -16384) {
if ((m_dig_z2 != 0)
&& (m_dig_z1 != 0)
&& (m_dig_xyz1 != 0)
&& (data_r != 0)) {
inter_retval = ((((((float)mag_data_z)-
((float)m_dig_z4)) * 131072.0)-
(((float)m_dig_z3)*(((float)data_r)
-((float)m_dig_xyz1))))
/((((float)m_dig_z2)+
((float)m_dig_z1)*((float)data_r) /
32768.0) * 4.0)) / 16.0;
}
} else {
/* overflow, set output to 0.0f */
inter_retval = 0.0f;
}
return inter_retval;
}

614
src/bmx055/bmm150.hpp Normal file
View File

@ -0,0 +1,614 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include <mraa/i2c.hpp>
#include <mraa/spi.hpp>
#include <mraa/gpio.hpp>
#define BMM150_I2C_BUS 0
#define BMM150_SPI_BUS 0
#define BMM150_DEFAULT_ADDR 0x10
namespace upm {
/**
* @library bmx050
* @sensor bmm150
* @comname BMM150 3-Axis Geomagnetic Sensor
* @altname bmm050
* @type compass
* @man bosch
* @con i2c spi gpio
*
* @brief API for the BMM150 3-Axis Geomagnetic Sensor
*
* The BMM150 is a standalone geomagnetic sensor for consumer market
* applications. It allows measurements of the magnetic field in
* three perpendicular axes. Based on Boschs proprietary FlipCore
* technology, performance and features of BMM150 are carefully
* tuned and perfectly match the demanding requirements of all
* 3-axis mobile applications such as electronic compass, navigation
* or augmented reality.
*
* An evaluation circuitry (ASIC) converts the output of the
* geomagnetic sensor to digital results which can be read out over
* the industry standard digital interfaces (SPI and I2C).
*
* Not all functionality of this chip has been implemented in this
* driver, however all the pieces are present to add any desired
* functionality. This driver supports both I2C (default) and SPI
* operation.
*
* This device requires 3.3v operation.
*
* @snippet bmm150.cxx Interesting
*/
class BMM150 {
public:
// NOTE: Reserved registers must not be written into. Reading
// from them may return indeterminate values. Registers
// containing reserved bitfields must be written as 0. Reading
// reserved bitfields may return indeterminate values.
/**
* BMM150 registers
*/
typedef enum : uint8_t {
REG_CHIP_ID = 0x40,
// 0x41 reserved
REG_MAG_X_LSB = 0x42,
REG_MAG_X_MSB = 0x43,
REG_MAG_Y_LSB = 0x44,
REG_MAG_Y_MSB = 0x45,
REG_MAG_Z_LSB = 0x46,
REG_MAG_Z_MSB = 0x47,
REG_RHALL_LSB = 0x48,
REG_RHALL_MSB = 0x49,
REG_INT_STATUS = 0x4a,
REG_POWER_CTRL = 0x4b,
REG_OPMODE = 0x4c,
REG_INT_EN = 0x4d,
REG_INT_CONFIG = 0x4e,
REG_LOW_THRES = 0x4f,
REG_HIGH_THRES = 0x50,
REG_REP_XY = 0x51,
REG_REP_Z = 0x52,
// 0x53-0x71 reserved (mostly)
// TRIM registers from Bosch BMM050 driver
REG_TRIM_DIG_X1 = 0x5d,
REG_TRIM_DIG_Y1 = 0x5e,
REG_TRIM_DIG_Z4_LSB = 0x62,
REG_TRIM_DIG_Z4_MSB = 0x63,
REG_TRIM_DIG_X2 = 0x64,
REG_TRIM_DIG_Y2 = 0x65,
REG_TRIM_DIG_Z2_LSB = 0x68,
REG_TRIM_DIG_Z2_MSB = 0x69,
REG_TRIM_DIG_Z1_LSB = 0x6a,
REG_TRIM_DIG_Z1_MSB = 0x6b,
REG_TRIM_DIG_XYZ1_LSB = 0x6c,
REG_TRIM_DIG_XYZ1_MSB = 0x6d,
REG_TRIM_DIG_Z3_LSB = 0x6e,
REG_TRIM_DIG_Z3_MSB = 0x6f,
REG_TRIM_DIG_XY2 = 0x70,
REG_TRIM_DIG_XY1 = 0x71
} BMM150_REGS_T;
/**
* REG_MAG_XY_LSB bits (for X and Y mag data LSB's only)
*/
typedef enum {
_MAG_XY_LSB_RESERVED_BITS = 0x02 | 0x04,
MAG_XY_LSB_SELFTEST_XY = 0x01,
MAG_XY_LSB_LSB0 = 0x08,
MAG_XY_LSB_LSB1 = 0x10,
MAG_XY_LSB_LSB2 = 0x20,
MAG_XY_LSB_LSB3 = 0x40,
MAG_XY_LSB_LSB4 = 0x80,
_MAG_XY_LSB_LSB_MASK = 31,
_MAG_XY_LSB_LSB_SHIFT = 3
} MAG_XY_LSB_BITS_T;
/**
* REG_MAG_Z_LSB bits (for Z LSB only)
*/
typedef enum {
MAG_Z_LSB_SELFTEST_Z = 0x01,
MAG_Z_LSB_LSB0 = 0x02,
MAG_Z_LSB_LSB1 = 0x04,
MAG_Z_LSB_LSB2 = 0x08,
MAG_Z_LSB_LSB3 = 0x10,
MAG_Z_LSB_LSB4 = 0x20,
MAG_Z_LSB_LSB5 = 0x40,
MAG_Z_LSB_LSB6 = 0x80,
_MAG_Z_LSB_LSB_MASK = 127,
_MAG_Z_LSB_LSB_SHIFT = 1
} MAG_Z_LSB_BITS_T;
/**
* REG_MAG_RHALL_LSB bits (for RHALL LSB only)
*/
typedef enum {
_MAG_RHALL_LSB_RESERVED_BITS = 0x02,
MAG_RHALL_LSB_DATA_READY_STATUS = 0x01,
MAG_RHALL_LSB_LSB0 = 0x04,
MAG_RHALL_LSB_LSB1 = 0x08,
MAG_RHALL_LSB_LSB2 = 0x10,
MAG_RHALL_LSB_LSB3 = 0x20,
MAG_RHALL_LSB_LSB4 = 0x40,
MAG_RHALL_LSB_LSB5 = 0x80,
_MAG_RHALL_LSB_LSB_MASK = 63,
_MAG_RHALL_LSB_LSB_SHIFT = 2
} MAG_RHALL_LSB_BITS_T;
/**
* REG_INT_STATUS bits
*/
typedef enum {
INT_STATUS_LOW_INT_X = 0x01,
INT_STATUS_LOW_INT_Y = 0x02,
INT_STATUS_LOW_INT_Z = 0x04,
INT_STATUS_HIGH_INT_X = 0x08,
INT_STATUS_HIGH_INT_Y = 0x10,
INT_STATUS_HIGH_INT_Z = 0x20,
INT_STATUS_OVERFLOW = 0x40,
INT_STATUS_DATA_OVERRUN = 0x80
} INT_STATUS_BITS_T;
/**
* REG_POWER_CTRL bits
*/
typedef enum {
_POWER_CTRL_RESERVED_BITS = 0x40 | 0x20 | 0x10 | 0x08,
POWER_CTRL_POWER_CTRL_BIT = 0x01,
POWER_CTRL_SOFT_RESET0 = 0x02,
POWER_CTRL_SPI3EN = 0x04, // not supported
POWER_CTRL_SOFT_RESET1 = 0x80
} POWER_CTRL_BITS_T;
/**
* REG_OPMODE bits
*/
typedef enum {
OPMODE_SELFTTEST = 0x01,
OPMODE_OPERATION_MODE0 = 0x02,
OPMODE_OPERATION_MODE1 = 0x04,
_OPMODE_OPERATION_MODE_MASK = 3,
_OPMODE_OPERATION_MODE_SHIFT = 1,
OPMODE_DATA_RATE0 = 0x08,
OPMODE_DATA_RATE1 = 0x10,
OPMODE_DATA_RATE2 = 0x20,
_OPMODE_DATA_RATE_MASK = 7,
_OPMODE_DATA_RATE_SHIFT = 3,
OPMODE_ADV_SELFTEST0 = 0x40,
OPMODE_ADV_SELFTEST1 = 0x80,
_OPMODE_ADV_SELFTEST_MASK = 3,
_OPMODE_ADV_SELFTEST_SHIFT = 6
} OPMODE_BITS_T;
/**
* OPMODE_OPERATION_MODE values
*/
typedef enum {
OPERATION_MODE_NORMAL = 0,
OPERATION_MODE_FORCED = 1,
OPERATION_MODE_SLEEP = 3
} OPERATION_MODE_T;
/**
* OPMODE_DATA_RATE values
*/
typedef enum {
DATA_RATE_10HZ = 0,
DATA_RATE_2HZ = 1,
DATA_RATE_6HZ = 2,
DATA_RATE_8HZ = 3,
DATA_RATE_15HZ = 4,
DATA_RATE_20HZ = 5,
DATA_RATE_25HZ = 6,
DATA_RATE_30HZ = 7
} DATA_RATE_T;
/**
* REG_INT_EN bits
*/
typedef enum {
INT_EN_LOW_INT_X_EN = 0x01,
INT_EN_LOW_INT_Y_EN = 0x02,
INT_EN_LOW_INT_Z_EN = 0x04,
INT_EN_HIGH_INT_X_EN = 0x08,
INT_EN_HIGH_INT_Y_EN = 0x10,
INT_EN_HIGH_INT_Z_EN = 0x20,
INT_EN_OVERFLOW_INT_EN = 0x40,
INT_EN_DATA_OVERRUN_INT_EN = 0x80
} INT_EN_T;
/**
* REG_INT_CONFIG bits
*/
typedef enum {
INT_CONFIG_INT_POLARITY = 0x01,
INT_CONFIG_INT_LATCH = 0x02,
INT_CONFIG_DR_POLARITY = 0x04,
INT_CONFIG_CHANNEL_X = 0x08,
INT_CONFIG_CHANNEL_Y = 0x10,
INT_CONFIG_CHANNEL_Z = 0x20,
INT_CONFIG_INT_PIN_EN = 0x40,
INT_CONFIG_DR_PIN_EN = 0x80
} INT_CONFIG_T;
/**
* Interrupt selection for installISR() and uninstallISR()
*/
typedef enum {
INTERRUPT_INT,
INTERRUPT_DR
} INTERRUPT_PINS_T;
/**
* Bosch recommended usage preset modes
*/
typedef enum {
USAGE_LOW_POWER,
USAGE_REGULAR,
USAGE_ENHANCED_REGULAR,
USAGE_HIGH_ACCURACY
} USAGE_PRESETS_T;
/**
* BMM150 constructor.
*
* This device can support both I2C and SPI. For SPI, set the addr
* to -1, and specify a positive integer representing the Chip
* Select (CS) pin for the cs argument. If you are using a
* hardware CS pin (like edison with arduino breakout), then you
* can connect the proper pin to the hardware CS pin on your MCU
* and supply -1 for cs. The default operating mode is I2C.
*
* @param bus I2C or SPI bus to use.
* @param addr The address for this device. -1 for SPI.
* @param cs The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
* @param theChipID The chip ID to use for validation
*/
BMM150(int bus=BMM150_I2C_BUS, uint8_t addr=BMM150_DEFAULT_ADDR,
int cs=-1);
/**
* BMM150 Destructor.
*/
~BMM150();
/**
* Update the internal stored values from sensor data.
*/
void update();
/**
* Return the chip ID.
*
* @return The chip ID (BMM150_CHIPID).
*/
uint8_t getChipID();
/**
* Return magnetometer data in micro-Teslas (uT). update() must
* have been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getMagnetometer(float *x, float *y, float *z);
/**
* Return magnetometer data in micro-Teslas (uT) in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getMagnetometer();
/**
* Initialize the device and start operation. This function is
* called from the constructor so will not typically need to be
* called by a user unless the device is reset. This method will
* call setPresetMode() with the passed parameter.
*
* @param usage One of the USAGE_PRESETS_T values. The default is
* USAGE_HIGH_ACCURACY.
*/
void init(USAGE_PRESETS_T usage=USAGE_HIGH_ACCURACY);
/**
* Set one of the Bosch recommended preset modes. These modes
* configure the sensor for varying use cases.
*
* @param usage One of the USAGE_PRESETS_T values. The default is
* USAGE_HIGH_ACCURACY.
*/
void setPresetMode(USAGE_PRESETS_T usage);
/**
* Perform a device soft-reset. The device will be placed in
* SUSPEND mode afterward with all configured setting lost, so
* some re-initialization will be required to get data from the
* sensor. Calling init() will get everything running again.
*/
void reset();
/**
* Set the magnetometer Output Data Rate. See the datasheet for
* details.
*
* @param odr One of the DATA_RATE_T values.
*/
void setOutputDataRate(DATA_RATE_T odr);
/**
* Set or clear the Power bit. When the power bit is cleared, the
* device enters a deep suspend mode where only the REG_POWER_CTRL
* register can be accessed. This bit needs to be enabled for the
* device to operate. See the datasheet for details. The
* constructor enables this by default. After a deep suspend mode
* has been entered, all configured data is lost and the device
* must be reconfigured (as via init()).
*
* @param power true to enable the bit, false otherwise.
*/
void setPowerBit(bool power);
/**
* Set the operating mode of the device. See the datasheet for
* details.
*
* @param power One of the POWER_MODE_T values.
*/
void setOpmode(OPERATION_MODE_T opmode);
/**
* Get the current operating mode of the device. See the datasheet for
* details. The power bit must be one for this method to succeed.
*
* @return One of the OPERATION_MODE_T values.
*/
OPERATION_MODE_T getOpmode();
/**
* Return the Interrupt Enables register. This resgister
* allows you to enable various interrupt conditions. See the
* datasheet for details.
*
* @return A bitmask of INT_EN_BITS_T bits.
*/
uint8_t getInterruptEnable();
/**
* Set the Interrupt Enables register. See the datasheet for
* details.
*
* @param bits A bitmask of INT_EN_BITS_T bits.
*/
void setInterruptEnable(uint8_t bits);
/**
* Return the Interrupt Config register. This register allows
* determining the electrical characteristics of the 2 interrupt
* pins (open-drain/push-pull and level/edge triggering) as well
* as other options. See the datasheet for details.
*
* @return A bitmask of INT_CONFIG_BITS_T bits.
*/
uint8_t getInterruptConfig();
/**
* Set the Interrupt Config register. This register
* allows determining the electrical characteristics of the 2
* interrupt pins (open-drain/push-pull and level/edge
* triggering). See the datasheet for details.
*
* @param bits A bitmask of INT_CONFIG_BITS_T bits.
*/
void setInterruptConfig(uint8_t bits);
/**
* Return the interrupt status register. This register
* indicates which interrupts have been triggered. See the
* datasheet for details.
*
* @return a bitmask of INT_STATUS_BITS_T bits.
*/
uint8_t getInterruptStatus();
/**
* Set the repetion counter for the X and Y axes. This allows the
* device to average a number of measurements for a more stable
* output. See the datasheet for details.
*
* @param reps A coefficient for specifying the number of
* repititions to perform. (1 + 2(reps))
*/
void setRepetitionsXY(uint8_t reps);
/**
* Set the repetion counter for the Z axis. This allows the
* device to average a number of measurements for a more stable
* output. See the datasheet for details.
*
* @param reps A coefficient for specifying the number of
* repititions to perform. (1 + (reps))
*/
void setRepetitionsZ(uint8_t reps);
#if defined(SWIGJAVA) || defined(JAVACALLBACK)
void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
jobject runnable);
#else
/**
* install an interrupt handler.
*
* @param intr one of the INTERRUPT_PINS_T values specifying which
* interrupt pin you are installing.
* @param gpio gpio pin to use as interrupt pin
* @param level the interrupt trigger level (one of mraa::Edge
* values). Make sure that you have configured the interrupt pin
* properly for whatever level you choose.
* @param isr the interrupt handler, accepting a void * argument
* @param arg the argument to pass the the interrupt handler
*/
void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
void (*isr)(void *), void *arg);
#endif
/**
* uninstall a previously installed interrupt handler
*
* @param intr one of the INTERRUPT_PINS_T values specifying which
* interrupt pin you are removing.
*/
void uninstallISR(INTERRUPT_PINS_T intr);
/**
* 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.
*/
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.
*/
void writeReg(uint8_t reg, uint8_t val);
protected:
mraa::I2c *m_i2c;
mraa::Spi *m_spi;
// spi chip select
mraa::Gpio *m_gpioCS;
mraa::Gpio *m_gpioIntr;
mraa::Gpio *m_gpioDR;
uint8_t m_addr;
OPERATION_MODE_T m_opmode;
// SPI chip select
void csOn();
void csOff();
// acc data
float m_magX;
float m_magY;
float m_magZ;
// hall resistance
uint16_t m_hall;
// trimming data
int8_t m_dig_x1;
int8_t m_dig_y1;
int16_t m_dig_z4;
int8_t m_dig_x2;
int8_t m_dig_y2;
int16_t m_dig_z2;
uint16_t m_dig_z1;
uint16_t m_dig_xyz1;
int16_t m_dig_z3;
int8_t m_dig_xy2;
uint8_t m_dig_xy1;
// read trim data for compensation
void readTrimData();
private:
bool m_isSPI;
// use the FIFO by default?
bool m_useFIFO;
// return a reference to a gpio pin pointer depending on intr
mraa::Gpio*& getPin(INTERRUPT_PINS_T intr);
// Adding a private function definition for java bindings
#if defined(SWIGJAVA) || defined(JAVACALLBACK)
void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
void (*isr)(void *), void *arg);
#endif
// bosch compensation algorithms
float bmm050_compensate_X_float(int16_t mag_data_x, uint16_t data_r);
float bmm050_compensate_Y_float(int16_t mag_data_y, uint16_t data_r);
float bmm050_compensate_Z_float(int16_t mag_data_z, uint16_t data_r);
};
}

158
src/bmx055/bmx055.cxx Normal file
View File

@ -0,0 +1,158 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "bmx055.hpp"
using namespace upm;
using namespace std;
BMX055::BMX055(int accelBus, uint8_t accelAddr, int accelCS,
int gyroBus, uint8_t gyroAddr, int gyroCS,
int magBus, uint8_t magAddr, int magCS) :
m_accel(0), m_gyro(0), m_mag(0)
{
// if -1 is supplied as a bus for any of these, we will not
// instantiate them
if (accelBus >= 0)
m_accel = new BMA250E(accelBus, accelAddr, accelCS);
if (gyroBus >= 0)
m_gyro = new BMG160(gyroBus, gyroAddr, gyroCS);
if (magBus >= 0)
m_mag = new BMM150(magBus, magAddr, magCS);
// now initialize them...
if (m_accel)
m_accel->init();
if (m_gyro)
m_gyro->init();
if (m_mag)
m_mag->init();
}
BMX055::~BMX055()
{
if (m_accel)
delete m_accel;
if (m_gyro)
delete m_gyro;
if (m_mag)
delete m_mag;
}
void BMX055::initAccelerometer(BMA250E::POWER_MODE_T pwr,
BMA250E::RANGE_T range,
BMA250E::BW_T bw)
{
if (m_accel)
m_accel->init(pwr, range, bw);
}
void BMX055::initGyroscope(BMG160::POWER_MODE_T pwr,
BMG160::RANGE_T range,
BMG160::BW_T bw)
{
if (m_gyro)
m_gyro->init(pwr, range, bw);
}
void BMX055::initMagnetometer(BMM150::USAGE_PRESETS_T usage)
{
if (m_mag)
m_mag->init(usage);
}
void BMX055::update()
{
if (m_accel)
m_accel->update();
if (m_gyro)
m_gyro->update();
if (m_mag)
m_mag->update();
}
void BMX055::getAccelerometer(float *x, float *y, float *z)
{
if (m_accel)
m_accel->getAccelerometer(x, y, z);
}
float *BMX055::getAccelerometer()
{
if (m_accel)
return m_accel->getAccelerometer();
else
{
static float v[3] = {0.0f, 0.0f, 0.0f};
return v;
}
}
void BMX055::getGyroscope(float *x, float *y, float *z)
{
if (m_gyro)
m_gyro->getGyroscope(x, y, z);
}
float *BMX055::getGyroscope()
{
if (m_gyro)
return m_gyro->getGyroscope();
else
{
static float v[3] = {0.0f, 0.0f, 0.0f};
return v;
}
}
void BMX055::getMagnetometer(float *x, float *y, float *z)
{
if (m_mag)
m_mag->getMagnetometer(x, y, z);
}
float *BMX055::getMagnetometer()
{
if (m_mag)
return m_mag->getMagnetometer();
else
{
static float v[3] = {0.0f, 0.0f, 0.0f};
return v;
}
}

248
src/bmx055/bmx055.hpp Normal file
View File

@ -0,0 +1,248 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include "bma250e.hpp"
#include "bmg160.hpp"
#include "bmm150.hpp"
namespace upm {
/**
* @brief BMX055 9-axis Sensor Module
* @defgroup bmx055 libupm-bmx055
* @ingroup i2c spi accelerometer compass
*/
/**
* @library bmx055
* @sensor bmx055
* @comname BMX055 9-axis Sensor Module
* @type accelerometer compass
* @man mouser
* @con i2c gpio spi
* @web http://www.mouser.com/ProductDetail/Bosch-Sensortec/0330SB0179/?qs=sGAEpiMZZMsrChSOYEGTCZo8d3KRE6KPUk8gVuWS2Ho%3d
*
* @brief API for the BMX055 9-axis Sensor Module
*
* The BMX055 is an integrated 9-axis sensor for the detection of
* movements and rotations and magnetic heading. It comprises the
* full functionality of a triaxial, low-g acceleration sensor, a
* triaxial angular rate sensor and a triaxial geomagnetic sensor.
*
* The BMX055 senses orientation, tilt, motion, acceleration,
* rotation, shock, vibration and heading in cell phones, handhelds,
* computer peripherals, man-machine interfaces, virtual reality
* features and game controllers.
*
* The BMX055 is essentially 3 separate devices in one: the BMA250E
* Accelerometer, the BMG160 Gyroscope, and the BMM150 Magnetometer.
* They are completely independant of each other.
*
* This driver provides a very simple interface to these 3 devices.
* If finer control is desired, you should just use the separate
* BMA25E, BMG160, and BMM150 device classes directly. This driver
* simply initializes all three devices, and provides a mechanism to
* read accelerometer, gyroscope and magnetometer data from them.
*
* @snippet bmx055.cxx Interesting
*/
class BMX055 {
public:
/**
* BMX055 constructor.
*
* This device can support both I2C and SPI. For SPI, set the addr
* to -1, and specify a positive integer representing the Chip
* Select (CS) pin for the cs argument. If you are using a
* hardware CS pin (like edison with arduino breakout), then you
* can connect the proper pin to the hardware CS pin on your MCU
* and supply -1 for cs. The default operating mode is I2C.
*
* @param accelBus I2C or SPI bus to use. -1 to skip initializing
* this device.
* @param accelAddr The address for this device. -1 for SPI.
* @param accelCS The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
* @param gyroBus I2C or SPI bus to use. -1 to skip initializing
* this device.
* @param gyroAddr The address for this device. -1 for SPI.
* @param gyroCS The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
* @param magBus I2C or SPI bus to use. -1 to skip initializing
* this device.
* @param magAddr The address for this device. -1 for SPI.
* @param magCS The gpio pin to use for the SPI Chip Select. -1 for
* I2C or for SPI with a hardware controlled pin.
*/
BMX055(int accelBus=BMA250E_I2C_BUS,
uint8_t accelAddr=BMA250E_DEFAULT_ADDR,
int accelCS=-1,
int gyroBus=BMG160_I2C_BUS,
uint8_t gyroAddr=BMG160_DEFAULT_ADDR,
int gyroCS=-1,
int magBus=BMM150_I2C_BUS,
uint8_t magAddr=BMM150_DEFAULT_ADDR,
int magCS=-1);
/**
* BMX055 Destructor.
*/
~BMX055();
/**
* Update the internal stored values from sensor data.
*/
void update();
/**
* Initialize the accelerometer and start operation. This
* function is called from the constructor so will not typically
* need to be called by a user unless the device is reset or you
* want to change these values.
*
* @param pwr One of the BMA250E::POWER_MODE_T values. The default is
* BMA250E::POWER_MODE_NORMAL.
* @param range One of the BMA250E::RANGE_T values. The default is
* BMA250E::RANGE_2G.
* @param bw One of the filtering BMA250E::BW_T values. The default is
* BMA250E::BW_250.
*/
void initAccelerometer(BMA250E::POWER_MODE_T pwr=BMA250E::POWER_MODE_NORMAL,
BMA250E::RANGE_T range=BMA250E::RANGE_2G,
BMA250E::BW_T bw=BMA250E::BW_250);
/**
* Initialize the gyroscope and start operation. This function is
* called from the constructor so will not typically need to be
* called by a user unless the device is reset or you want to
* change these values.
*
* @param pwr One of the BMG160::POWER_MODE_T values. The default is
* BMG160::POWER_MODE_NORMAL.
* @param range One of the BMG160::RANGE_T values. The default is
* BMG160::RANGE_250.
* @param bw One of the filtering BMG160::BW_T values. The default is
* BMG160::BW_400_47.
*/
void initGyroscope(BMG160::POWER_MODE_T pwr=BMG160::POWER_MODE_NORMAL,
BMG160::RANGE_T range=BMG160::RANGE_250,
BMG160::BW_T bw=BMG160::BW_400_47);
/**
* Initialize the magnetometer and start operation. This function
* is called from the constructor so will not typically need to be
* called by a user unless the device is reset or you want to
* change these values. This method will call
* BMM150::setPresetMode() with the passed parameter.
*
* @param usage One of the BMM150::USAGE_PRESETS_T values. The default is
* BMM150::USAGE_HIGH_ACCURACY.
*/
void initMagnetometer(BMM150::USAGE_PRESETS_T usage=BMM150::USAGE_HIGH_ACCURACY);
/**
* Return accelerometer data in gravities. update() must have
* been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getAccelerometer(float *x, float *y, float *z);
/**
* Return accelerometer data in gravities in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getAccelerometer();
/**
* Return gyroscope data in degrees per second. update() must
* have been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getGyroscope(float *x, float *y, float *z);
/**
* Return gyroscope data in degrees per second in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getGyroscope();
/**
* Return magnetometer data in micro-Teslas (uT). update() must
* have been called prior to calling this method.
*
* @param x Pointer to a floating point value that will have the
* current x component placed into it.
* @param y Pointer to a floating point value that will have the
* current y component placed into it.
* @param z Pointer to a floating point value that will have the
* current z component placed into it.
*/
void getMagnetometer(float *x, float *y, float *z);
/**
* Return magnetometer data in micro-Teslas (uT) in the form of a
* floating point array. The pointer returned by this function is
* statically allocated and will be rewritten on each call.
* update() must have been called prior to calling this method.
*
* @return A floating point array containing x, y, and z in
* that order.
*/
float *getMagnetometer();
protected:
BMA250E *m_accel;
BMG160 *m_gyro;
BMM150 *m_mag;
private:
};
}

View File

@ -0,0 +1,77 @@
%module javaupm_bmx055
%include "../upm.i"
%include "cpointer.i"
%include "typemaps.i"
%include "arrays_java.i";
%include "../java_buffer.i"
%apply int {mraa::Edge};
%apply float *INOUT { float *x, float *y, float *z };
%typemap(jni) float* "jfloatArray"
%typemap(jstype) float* "float[]"
%typemap(jtype) float* "float[]"
%typemap(javaout) float* {
return $jnicall;
}
%typemap(out) float *getAccelerometer {
$result = JCALL1(NewFloatArray, jenv, 3);
JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1);
}
%typemap(out) float *getGyroscope {
$result = JCALL1(NewFloatArray, jenv, 3);
JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1);
}
%typemap(out) float *getMagnetometer {
$result = JCALL1(NewFloatArray, jenv, 3);
JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1);
}
%ignore getAccelerometer(float *, float *, float *);
%ignore getGyroscope(float *, float *, float *);
%ignore getMagnetometer(float *, float *, float *);
%include "bma250e.hpp"
%{
#include "bma250e.hpp"
%}
%include "bmg160.hpp"
%{
#include "bmg160.hpp"
%}
%include "bmm150.hpp"
%{
#include "bmm150.hpp"
%}
%include "bmx055.hpp"
%{
#include "bmx055.hpp"
%}
%include "bmc150.hpp"
%{
#include "bmc150.hpp"
%}
%include "bmi055.hpp"
%{
#include "bmi055.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_bmx055");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

37
src/bmx055/jsupm_bmx055.i Normal file
View File

@ -0,0 +1,37 @@
%module jsupm_bmx055
%include "../upm.i"
%include "cpointer.i"
/* Send "int *" and "float *" to JavaScript as intp and floatp */
%pointer_functions(int, intp);
%pointer_functions(float, floatp);
%include "bma250e.hpp"
%{
#include "bma250e.hpp"
%}
%include "bmg160.hpp"
%{
#include "bmg160.hpp"
%}
%include "bmm150.hpp"
%{
#include "bmm150.hpp"
%}
%include "bmx055.hpp"
%{
#include "bmx055.hpp"
%}
%include "bmc150.hpp"
%{
#include "bmc150.hpp"
%}
%include "bmi055.hpp"
%{
#include "bmi055.hpp"
%}

47
src/bmx055/pyupm_bmx055.i Normal file
View File

@ -0,0 +1,47 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_bmx055
%include "../upm.i"
%include "cpointer.i"
%include "stdint.i"
/* Send "int *" and "float *" to python as intp and floatp */
%pointer_functions(int, intp);
%pointer_functions(float, floatp);
%feature("autodoc", "3");
#ifdef DOXYGEN
%include "bmx055_doc.i"
#endif
%include "bma250e.hpp"
%{
#include "bma250e.hpp"
%}
%include "bmg160.hpp"
%{
#include "bmg160.hpp"
%}
%include "bmm150.hpp"
%{
#include "bmm150.hpp"
%}
%include "bmx055.hpp"
%{
#include "bmx055.hpp"
%}
%include "bmc150.hpp"
%{
#include "bmc150.hpp"
%}
%include "bmi055.hpp"
%{
#include "bmi055.hpp"
%}

View File

@ -36,359 +36,34 @@ using namespace std;
E50HX::E50HX(uint32_t targetDeviceObjectID) :
m_instance(0)
BACNETUTIL(targetDeviceObjectID)
{
// Save our device's ID
m_targetDeviceObjectID = targetDeviceObjectID;
// create the BACNETMSTP instance here if it does not already exist,
// and store the pointer in our class to save on some typing.
m_instance = BACNETMSTP::instance();
// now see if it has been initialized yet for init()
m_initialized = m_instance->isInitialized();
setDebug(false);
// we disable this by default for performance reasons
checkReliability(false);
// empty our unit caches
m_avUnitCache.clear();
m_aiUnitCache.clear();
}
E50HX::~E50HX()
{
}
void E50HX::initMaster(std::string port, int baudRate,
int deviceInstanceID, int macAddr, int maxMaster,
int maxInfoFrames)
{
// first we check to see if the bacnetmstp instance has already been
// initialized (determined in the ctor). If not, we will do so here
// with the arguments specified. If it has already been
// initialized, then we do not bother calling bacnetmstp's init
// again as it will just be ignored.
if (!m_initialized)
m_instance->initMaster(port, baudRate, deviceInstanceID,
macAddr, maxMaster, maxInfoFrames);
// either it threw an exception, was already initialized or it's
// initialized now...
m_initialized = true;
}
void E50HX::setDebug(bool enable)
{
m_debugging = enable;
// we also enable/disable debugging in BACNETMSTP
m_instance->setDebug(enable);
}
float E50HX::getAnalogValue(ANALOG_VALUES_T objInstance)
{
// check reliability first, if enabled
if (m_checkReliability)
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
objInstance, PROP_RELIABILITY))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (reliability): " << getAllErrorString()
<< endl;
return RETURN_ERROR;
}
BACNET_RELIABILITY reliable =
static_cast<BACNET_RELIABILITY>(m_instance->getDataTypeEnum());
if (reliable != RELIABILITY_NO_FAULT_DETECTED)
{
if (m_debugging)
cerr << __FUNCTION__ << ": Reliability check failed" << endl;
return RETURN_UNRELIABLE;
}
}
// now get the value
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
objInstance, PROP_PRESENT_VALUE))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (value): " << getAllErrorString()
<< endl;
return RETURN_ERROR;
}
return m_instance->getDataTypeReal();
}
string E50HX::getAnalogValueUnits(ANALOG_VALUES_T objInstance)
{
// see if it exists
if (m_avUnitCache.count(objInstance) == 0)
{
// then we need to fetch it
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
objInstance, PROP_UNITS))
{
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
// set to empty string
m_avUnitCache[objInstance] = string("");
}
else
{
// cache it for future calls
m_avUnitCache[objInstance] =
string(bactext_engineering_unit_name(m_instance->getDataTypeEnum()));
}
}
return m_avUnitCache[objInstance];
}
float E50HX::getAnalogInput(ANALOG_INPUTS_T objInstance)
{
// check reliability first, if enabled
if (m_checkReliability)
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_INPUT,
objInstance, PROP_RELIABILITY))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (reliability): "
<< getAllErrorString() << endl;
return RETURN_ERROR;
}
BACNET_RELIABILITY reliable =
static_cast<BACNET_RELIABILITY>(m_instance->getDataTypeEnum());
if (reliable != RELIABILITY_NO_FAULT_DETECTED)
{
if (m_debugging)
cerr << __FUNCTION__ << ": Reliability check failed" << endl;
return RETURN_UNRELIABLE;
}
}
// now get the value
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_INPUT,
objInstance, PROP_PRESENT_VALUE))
{
if (m_debugging)
cerr << __FUNCTION__ << ": (value): " << getAllErrorString() << endl;
return RETURN_ERROR;
}
return m_instance->getDataTypeReal();
}
string E50HX::getAnalogInputUnits(ANALOG_INPUTS_T objInstance)
{
// see if it exists
if (m_aiUnitCache.count(objInstance) == 0)
{
// then we need to fetch it
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_ANALOG_INPUT,
objInstance, PROP_UNITS))
{
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
// set to empty string
m_aiUnitCache[objInstance] = string("");
}
else
{
// cache it for future calls
m_aiUnitCache[objInstance] =
string(bactext_engineering_unit_name(m_instance->getDataTypeEnum()));
}
}
return m_aiUnitCache[objInstance];
}
uint16_t E50HX::getAlarmBits()
{
return uint16_t(getAnalogInput(AI_Alarm_Bitmap));
}
BACNETMSTP::BACERR_TYPE_T E50HX::getErrorType()
void E50HX::writeConfig(CFG_VALUES_T config)
{
return m_instance->getErrorType();
setAnalogValue(AV_Config, float(config));
}
uint8_t E50HX::getRejectReason()
void E50HX::writeSystemType(SYSTEM_TYPES_T systype)
{
return m_instance->getRejectReason();
setAnalogValue(AV_System_Type, float(systype));
}
std::string E50HX::getRejectString()
{
return m_instance->getRejectString();
}
uint8_t E50HX::getAbortReason()
{
return m_instance->getAbortReason();
}
std::string E50HX::getAbortString()
{
return m_instance->getAbortString();
}
BACNET_ERROR_CLASS E50HX::getErrorClass()
{
return m_instance->getErrorClass();
}
BACNET_ERROR_CODE E50HX::getErrorCode()
{
return m_instance->getErrorCode();
}
std::string E50HX::getUPMErrorString()
{
return m_instance->getUPMErrorString();
}
std::string E50HX::getErrorString()
{
return m_instance->getErrorString();
};
string E50HX::getAllErrorString()
{
switch (m_instance->getErrorType())
{
case BACNETMSTP::BACERR_TYPE_NONE:
return string("No Error");
break;
case BACNETMSTP::BACERR_TYPE_REJECT:
return string("Reject: ") + getRejectString();
break;
case BACNETMSTP::BACERR_TYPE_ABORT:
return string("Abort: ") + getAbortString();
break;
case BACNETMSTP::BACERR_TYPE_ERROR:
return string("Error: ") + getErrorString();
break;
case BACNETMSTP::BACERR_TYPE_UPM:
return string("UPM Error: ") + getUPMErrorString();
break;
}
}
string E50HX::getDescription()
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_DESCRIPTION))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return "";
}
return m_instance->getDataTypeString();
}
string E50HX::getLocation()
{
if (m_instance->readProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_LOCATION))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return "";
}
return m_instance->getDataTypeString();
}
bool E50HX::setLocation(string location)
{
BACNET_APPLICATION_DATA_VALUE myLocation =
m_instance->createDataString(location);
// write the Device Object Location
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_DEVICE,
m_targetDeviceObjectID, PROP_LOCATION,
&myLocation))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
}
bool E50HX::writeConfig(CFG_VALUES_T config)
{
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(float(config));
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_Config, PROP_PRESENT_VALUE, &myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
}
bool E50HX::writeSystemType(SYSTEM_TYPES_T systype)
{
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(float(systype));
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_System_Type, PROP_PRESENT_VALUE, &myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
}
bool E50HX::writeCTRatioPrimary(float ctRatio)
void E50HX::writeCTRatioPrimary(float ctRatio)
{
if (ctRatio < 5 || ctRatio > 32000)
{
@ -396,47 +71,15 @@ bool E50HX::writeCTRatioPrimary(float ctRatio)
+ ": ctRatio must be between 5-32000");
}
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(ctRatio);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_CT_Ratio_Primary, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
setAnalogValue(AV_CT_Ratio_Primary, ctRatio);
}
bool E50HX::writeCTRatioSecondary(CT_SECONDARY_T ctRatio)
void E50HX::writeCTRatioSecondary(CT_SECONDARY_T ctRatio)
{
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(float(ctRatio));
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_CT_Ratio_Secondary, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
setAnalogValue(AV_CT_Ratio_Secondary, ctRatio);
}
bool E50HX::writePTRatio(float ptRatio)
void E50HX::writePTRatio(float ptRatio)
{
if (ptRatio < 0.01 || ptRatio > 320.0)
{
@ -444,26 +87,10 @@ bool E50HX::writePTRatio(float ptRatio)
+ ": ptRatio must be between 0.01-320.0");
}
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(ptRatio);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_PT_Ratio, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
setAnalogValue(AV_PT_Ratio, ptRatio);
}
bool E50HX::writeSystemVoltage(float sysVolts)
void E50HX::writeSystemVoltage(float sysVolts)
{
if (sysVolts < 82.0 || sysVolts > 32000.0)
{
@ -471,47 +98,15 @@ bool E50HX::writeSystemVoltage(float sysVolts)
+ ": sysVolts must be between 82.0-32000.0");
}
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(sysVolts);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_System_Voltage, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
setAnalogValue(AV_System_Voltage, sysVolts);
}
bool E50HX::writeDisplayUnits(DISP_UNITS_T dispUnits)
void E50HX::writeDisplayUnits(DISP_UNITS_T dispUnits)
{
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(float(dispUnits));
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_Display_Units, PROP_PRESENT_VALUE,
&myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
setAnalogValue(AV_Display_Units, dispUnits);
}
bool E50HX::writePhaseLossVT(float phaseLoss)
void E50HX::writePhaseLossVT(float phaseLoss)
{
if (phaseLoss < 1.0 || phaseLoss > 99.0)
{
@ -519,26 +114,10 @@ bool E50HX::writePhaseLossVT(float phaseLoss)
+ ": phaseLoss must be between 1.0-99.0");
}
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(phaseLoss);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_Phase_Loss_Voltage_Threshold,
PROP_PRESENT_VALUE, &myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
setAnalogValue(AV_Phase_Loss_Voltage_Threshold, phaseLoss);
}
bool E50HX::writePhaseLossIT(float phaseLoss)
void E50HX::writePhaseLossIT(float phaseLoss)
{
if (phaseLoss < 1.0 || phaseLoss > 99.0)
{
@ -546,21 +125,5 @@ bool E50HX::writePhaseLossIT(float phaseLoss)
+ ": phaseLoss must be between 1.0-99.0");
}
// Write the value
BACNET_APPLICATION_DATA_VALUE myData =
m_instance->createDataReal(phaseLoss);
// write it
if (m_instance->writeProperty(m_targetDeviceObjectID, OBJECT_ANALOG_VALUE,
AV_Phase_Loss_Imbalance_Threshold,
PROP_PRESENT_VALUE, &myData))
{
// error occurred
if (m_debugging)
cerr << __FUNCTION__ << ": " << getAllErrorString() << endl;
return false;
}
return true;
setAnalogValue(AV_Phase_Loss_Imbalance_Threshold, phaseLoss);
}

View File

@ -27,6 +27,7 @@
#include <map>
#include "bacnetmstp.hpp"
#include "bacnetutil.hpp"
namespace upm {
@ -81,7 +82,7 @@ namespace upm {
* @snippet e50hx.cxx Interesting
*/
class E50HX {
class E50HX : public BACNETUTIL {
public:
// Supported Analog Value Objects. These are readable and writable.
@ -209,14 +210,6 @@ namespace upm {
DISP_UNITS_IEEE = 1 // IEEE display units
} DISP_UNITS_T;
// Since none of the legal values returned by getAnalogValue() or
// getAnalogInput() will ever be negative, we use these two values
// to indicate either an error (BACnet or UPM), or to indicate
// that the value is unreliable if checkReliability() has been
// enabled.
const float RETURN_ERROR = -1.0;
const float RETURN_UNRELIABLE = -2.0;
/**
* E50HX constructor
*
@ -236,353 +229,93 @@ namespace upm {
*/
~E50HX();
/**
* This function initializes the underlying BACNETMSTP Master
* singleton in the event it has not already been initialized. If
* the BACNETMSTP Master singleton has already been initialized,
* then this call will be ignored.
*
* @param port The serial port that the RS-485 interface is
* connected to.
* @param baudRate The baudrate of the RS-485 interface. All
* devices on a BACnet RS-485 bus must run at the same baudrate.
* Valid values are 9600, 19200, 38400, 57600, 76800, and 115200.
* @param deviceInstanceNumber This is the unique Device Object
* Instance number that will be used for our BACnet Master in
* order to communicate over the BACnet interface. This number
* must be between 1-4194302 and must be unique on the BACnet
* network.
* @param macAddr This is the MAC address of our BACnet Master.
* It must be unique on the BACnet segment, and must be between
* 1-127.
* @param maxMaster This specifies to our Master the maximum MAC
* address used by any other Masters on the BACnet network. This
* must be between 1-127, the default is 127. Do not change this
* unless you know what you are doing or you could introduce
* token passing errors on the BACnet network.
* @param maxInfoFrames This number specifies the maximum number
* of transmissions (like requests for data) our Master is allowed
* to make before passing the token to the next Master. The
* default is 1.
*/
void initMaster(std::string port, int baudRate, int deviceInstanceNumber,
int macAddr, int maxMaster=DEFAULT_MAX_MASTER,
int maxInfoFrames=1);
/**
* Enable some debugging output in this module as well as the
* BACNETMSTP module. Debugging is disabled by default.
*
* @param enable true to enable, false to disable.
*/
void setDebug(bool enable);
/**
* Retrieve the Present_Value property of an Analog Value object.
* If checkReliability() has been enabled, then the Reliability
* property of the object will be retrieved first. If the
* Reliability property is anything other than
* RELIABILITY_NO_FAULT_DETECTED, then the RETURN_UNRELIABLE value
* will be returned. Reliability checking is disabled by default
* for performance reasons.
*
* @param objInstance One of the ANALOG_VALUES_T values.
* @return the floating point value requested
*/
float getAnalogValue(ANALOG_VALUES_T objInstance);
/**
* Retrieve the Present_Value property of an Analog Input object.
* If checkReliability() has been enabled, then the Reliability
* property of the object will be retrieved first. If the
* Reliability property is anything other than
* RELIABILITY_NO_FAULT_DETECTED, then the RETURN_UNRELIABLE value
* will be returned. Reliability checking is disabled by default
* for performance reasons.
*
* @param objInstance One of the ANALOG_INPUTS_T values.
* @return the floating point value requested
*/
float getAnalogInput(ANALOG_INPUTS_T objInstance);
/**
* Write one of several 'magic' numbers to the configuration
* object (AV1). This is used to clear certain counters, reset
* the accumulated Energy consumption values, etc.
* the accumulated Energy consumption values, etc. This method
* will throw on error.
*
* @param config One of the CFG_VALUES_T values
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writeConfig(CFG_VALUES_T config);
void writeConfig(CFG_VALUES_T config);
/**
* Set the System Type of the device. This defines the voltage
* lines you have connected.
* lines you have connected. This method will throw on error.
*
* @param systype One of the SYSTEM_TYPES_T values.
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writeSystemType(SYSTEM_TYPES_T systype);
void writeSystemType(SYSTEM_TYPES_T systype);
/**
* Set the Primary CT ratio. See the datasheet for details.
* Set the Primary CT ratio. See the datasheet for details. This
* method will throw on error.
*
* @param ctRatio A floating point value between 5-32000
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writeCTRatioPrimary(float ctRatio);
void writeCTRatioPrimary(float ctRatio);
/**
* Set the Secondary CT ratio. See the datasheet for details.
* This method will throw on error.
*
* @param ctRatio One of the CT_SECONDARY_T values.
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writeCTRatioSecondary(CT_SECONDARY_T ctRatio);
void writeCTRatioSecondary(CT_SECONDARY_T ctRatio);
/**
* Set the PT ratio. See the datasheet for details.
* Set the PT ratio. See the datasheet for details. This method
* will throw on error.
*
* @param ptRatio A floating point value between 0.01-320.0
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writePTRatio(float ptRatio);
void writePTRatio(float ptRatio);
/**
* Set the System Voltage parmeter. See the datasheet for details.
* Set the System Voltage parmeter. See the datasheet for
* details. This method will throw on error.
*
* @param sysVolts A floating point value between 82.0-32000.0
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writeSystemVoltage(float sysVolts);
void writeSystemVoltage(float sysVolts);
/**
* Set the LCD Display Units in IEC or IEEE format.
* Set the LCD Display Units in IEC or IEEE format. This method
* will throw on error.
*
* @param dispUnits One of the DISP_UNITS_T values.
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writeDisplayUnits(DISP_UNITS_T dispUnits);
void writeDisplayUnits(DISP_UNITS_T dispUnits);
/**
* Set the Phase Loss Voltage Threshold. See the datasheet for
* details.
* details. This method will throw on error.
*
* @param dispUnits A floating point value between 1.0-99.0
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writePhaseLossVT(float phaseLoss);
void writePhaseLossVT(float phaseLoss);
/**
* Set the Phase Loss Imbalance Threshold. See the datasheet for
* details.
* details. This method will throw on error.
*
* @param dispUnits A floating point value between 1.0-99.0
* @return true if the operation suceeded, false if there was an
* error.
*/
bool writePhaseLossIT(float phaseLoss);
/**
* Query an Analog Value object for the unit code, translate it
* into a string and cache the result for future use. Return the
* BACnet text for the Unit enumeration. Unit enumerations are
* things like 'kilowatt-hours', 'volts', etc. For Objects which
* do not have a Units property defined for them, or for which
* Units has no meaning, 'no-units' will typically be returned and
* cached.
*
* @param objInstance One of the ANALOG_VALUES_T values.
* @return A string representing the Object's Unit property.
*/
std::string getAnalogValueUnits(ANALOG_VALUES_T objInstance);
/**
* Query an Analog Input object for the unit code, translate it
* into a string and cache the result for future use. Return the
* BACnet text for the Unit enumeration. Unit enumerations are
* things like 'kilowatt-hours', 'volts', etc. For Objects which
* do not have a Units property defined for them, or for which
* Units has no meaning, 'no-units' will typically be returned and
* cached.
*
* @param objInstance One of the ANALOG_INPUTS_T values.
* @return A string representing the Object's Unit property.
*/
std::string getAnalogInputUnits(ANALOG_INPUTS_T objInstance);
void writePhaseLossIT(float phaseLoss);
/**
* Query the AI52 Object and return a bitmask of current Alarms.
* Compare against ALARM_BITS_T to determine what conditions are
* signaling an alarm. Alarm conditions will clear on their own
* as soon as the cause is rectified.
* as soon as the cause is rectified. This method will throw on
* error.
*
* @return A bitmask of values from ALARM_BITS_T indicating
* current alarm conditions.
*/
uint16_t getAlarmBits();
/**
* Enable or disable reliability checking. By default, when using
* getAnalogValue() or getAnalogInput() the Present_Value property
* is returned. There is also a property called Reliability that
* can be checked to ensure that the Present_Value property is
* currently valid.
*
* Enabling Reliability Checking has these functions check for a
* RELIABILITY_NO_FAULT_DETECTED value for the Reliability
* property before querying the Present_Value property. If
* anything other than RELIABILITY_NO_FAULT_DETECTED is set, then
* these functions will return RETURN_UNRELIABLE rather than the
* Present_Value.
*
* This checking is disabled by default since it will double the
* number of queries needed to retrieve a given value. However,
* if you need to ensure that the values returned are always
* completely valid as determined by the device firmware, you
* should enable this.
*
* @param enable true to check Reliability before returning a
* value, false otherwise.
*/
void checkReliability(bool enable)
{
m_checkReliability = enable;
};
/**
* Query the Device Object of the device and return it's
* Description property. This typically contains information like
* the Vendor, model and serial number of a device.
*
* @return A string containing the Device Object's Description property.
*/
std::string getDescription();
/**
* Query the Device Object of the device and return it's Location
* property. This typically contains a string indication a
* customer specific value. Use setLocation() to change.
*
* @return A string containing the Device Object's Location property.
*/
std::string getLocation();
/**
* Set the Device Object's Location property. This must be a
* string containing no more than 63 characters.
*
* @return true if the operation succeeded, false otherwise
*/
bool setLocation(std::string location);
/**
* This is a utility function that will return a string reporting
* on the various types of errors that can occur in BACnet
* operation.
*
* @return A string containing the last error message.
*/
std::string getAllErrorString();
/**
* Return an enumration of the last error type to occur. The
* value returned will be one of the BACNETMSTP::BACERR_TYPE_T
* values.
*
* @return The last error type to occur, one of the
* BACNETMSTP::BACERR_TYPE_T values.
*/
BACNETMSTP::BACERR_TYPE_T getErrorType();
/**
* In the event of a BACnet Reject error, return the error code.
*
* @return The Reject error code.
*/
uint8_t getRejectReason();
/**
* In the event of a BACnet Reject error, return the error string.
*
* @return The Reject error string.
*/
std::string getRejectString();
/**
* In the event of a BACnet Abort error, return the Abort reason code.
*
* @return The Abort reason code.
*/
uint8_t getAbortReason();
/**
* In the event of a BACnet Abort error, return the Abort string.
*
* @return The Abort error string.
*/
std::string getAbortString();
/**
* In the event of a general BACnet error, return the BACnet error class.
*
* @return One of the BACNET_ERROR_CLASS error class codes
*/
BACNET_ERROR_CLASS getErrorClass();
/**
* In the event of a general BACnet error, return the BACnet error code.
*
* @return One of the BACNET_ERROR_CODE error codes
*/
BACNET_ERROR_CODE getErrorCode();
/**
* In the event of a general BACnet error, return the BACnet error
* string.
*
* @return A string representing the BACnet error class and code.
*/
std::string getErrorString();
/**
* In the event of a non-BACnet UPM error, return a string
* describing the error.
*
* @return A string representing the UPM error.
*/
std::string getUPMErrorString();
protected:
// a copy of the BACNETMSTP singleton instance pointer
BACNETMSTP* m_instance;
// unique device object ID of e50hx
uint32_t m_targetDeviceObjectID;
// are we initialized?
bool m_initialized;
private:
bool m_debugging;
// whether or not to verify reliability before reading a value.
bool m_checkReliability;
// Unit cache for AV
typedef std::map<ANALOG_VALUES_T, std::string> avCacheMap_t;
avCacheMap_t m_avUnitCache;
// Unit cache for AI
typedef std::map<ANALOG_INPUTS_T, std::string> aiCacheMap_t;
aiCacheMap_t m_aiUnitCache;
};
}

View File

@ -1,10 +1,23 @@
%module javaupm_e50hx
%include "../upm.i"
%include "typemaps.i"
%include "carrays_uint32_t.i"
// We need to use this method for enum wrapping since the enum typedefs used
// by the derived classes (like ANALOG_VALUES_T) are passed to methods
// in the base class which expect a uint32_t. This is fine, and
// works everywhere except Java. It's type safety is a little too
// stringent in these cases. %javaconst(1) is generally recommended
// as it avoids JNI calls to determine the enumerant values at
// runtime.
%include "enumtypeunsafe.swg"
%javaconst(1);
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "e50hx.hpp"
%{
#include "bacnetutil.hpp"
#include "e50hx.hpp"
%}

View File

@ -3,6 +3,7 @@
%include "stdint.i"
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "e50hx.hpp"
%{
#include "e50hx.hpp"

View File

@ -7,6 +7,7 @@
%feature("autodoc", "3");
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "e50hx.hpp"
%{
#include "e50hx.hpp"

0
src/kxcjk1013/CMakeLists.txt Executable file → Normal file
View File

0
src/kxcjk1013/jsupm_kxcjk1013.i Executable file → Normal file
View File

View File

@ -1,6 +1,6 @@
/*
* Author: Lay, Kuan Loon <kuan.loon.lay@intel.com>
* Copyright (c) 2015 Intel Corporation.
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -30,8 +30,6 @@
#define NUMBER_OF_BITS_IN_BYTE 8
#define NUMBER_OF_BITS_IN_BYTE 8
using namespace upm;
KXCJK1013::KXCJK1013(int device)
@ -51,7 +49,7 @@ KXCJK1013::KXCJK1013(int device)
if (mraa_iio_create_trigger(m_iio, trigger) != MRAA_SUCCESS)
fprintf(stderr, "Create trigger %s failed\n", trigger);
if (mraa_iio_get_mounting_matrix(m_iio, m_mount_matrix) == MRAA_SUCCESS)
if (mraa_iio_get_mount_matrix(m_iio, "in_mount_matrix", m_mount_matrix) == MRAA_SUCCESS)
m_mount_matrix_exist = true;
else
m_mount_matrix_exist = false;
@ -62,7 +60,7 @@ KXCJK1013::KXCJK1013(int device)
KXCJK1013::~KXCJK1013()
{
if(m_iio)
if (m_iio)
mraa_iio_close(m_iio);
}
@ -146,6 +144,7 @@ KXCJK1013::disableBuffer()
bool
KXCJK1013::setScale(float scale)
{
m_scale = scale;
mraa_iio_write_float(m_iio, "in_accel_scale", scale);
return true;
@ -187,6 +186,7 @@ KXCJK1013::extract3Axis(char* data, float* x, float* y, float* z)
iio_y = getChannelValue((unsigned char*) (data + channels[1].location), &channels[1]);
iio_z = getChannelValue((unsigned char*) (data + channels[2].location), &channels[2]);
// Raw data is acceleration in direction. Units after application of scale are m/s^2
*x = (iio_x * m_scale);
*y = (iio_y * m_scale);
*z = (iio_z * m_scale);

17
src/kxcjk1013/kxcjk1013.hpp Executable file → Normal file
View File

@ -1,6 +1,6 @@
/*
* Author: Lay, Kuan Loon <kuan.loon.lay@intel.com>
* Copyright (c) 2015 Intel Corporation.
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -85,7 +85,7 @@ class KXCJK1013
/**
* Enable trigger buffer
* @param trigger buffer length in string
* @param trigger buffer length in integer
*/
bool enableBuffer(int length);
@ -96,13 +96,18 @@ class KXCJK1013
/**
* Set scale
* @param scale in string
* @param scale in float
* Available scales are 0.009582(2g), 0.019163(4g), and 0.038326(8g)
* Default scale is 0.019163
*/
bool setScale(const float scale);
/**
* Set sampling frequency
* @param sampling frequency in string
* @param sampling frequency in float
* Available sampling frequency are 0.781000, 1.563000, 3.125000, 6.250000, 12.500000, 25, 50,
* 100, 200, 400, 800, and 1600
* Default sampling frequency is 25
*/
bool setSamplingFrequency(const float sampling_frequency);
@ -124,7 +129,7 @@ class KXCJK1013
mraa_iio_context m_iio;
int m_iio_device_num;
bool m_mount_matrix_exist; // is mount matrix exist
float m_mount_matrix[9]; // mount matrix
float m_scale; // accelerometer data scale
float m_mount_matrix[9]; // mount matrix
float m_scale; // accelerometer data scale
};
}

0
src/kxcjk1013/pyupm_kxcjk1013.i Executable file → Normal file
View File

18
src/l3gd20/l3gd20.cxx Normal file → Executable file
View File

@ -1,6 +1,6 @@
/*
* Author: Lay, Kuan Loon <kuan.loon.lay@intel.com>
* Copyright (c) 2015 Intel Corporation.
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -56,7 +56,7 @@ L3GD20::L3GD20(int device)
if (mraa_iio_create_trigger(m_iio, trigger) != MRAA_SUCCESS)
fprintf(stderr, "Create trigger %s failed\n", trigger);
if (mraa_iio_get_mounting_matrix(m_iio, m_mount_matrix) == MRAA_SUCCESS)
if (mraa_iio_get_mount_matrix(m_iio, "in_mount_matrix", m_mount_matrix) == MRAA_SUCCESS)
m_mount_matrix_exist = true;
else
m_mount_matrix_exist = false;
@ -88,18 +88,10 @@ L3GD20::~L3GD20()
free(m_filter.buff);
m_filter.buff = NULL;
}
if(m_iio)
if (m_iio)
mraa_iio_close(m_iio);
}
#ifdef JAVACALLBACK
void
L3GD20::installISR(IsrCallback* cb)
{
installISR(generic_callback_isr, cb);
}
#endif
void
L3GD20::installISR(void (*isr)(char*), void* arg)
{
@ -177,6 +169,8 @@ L3GD20::disableBuffer()
bool
L3GD20::setScale(float scale)
{
m_scale = scale;
mraa_iio_write_float(m_iio, "in_anglvel_x_scale", scale);
mraa_iio_write_float(m_iio, "in_anglvel_y_scale", scale);
mraa_iio_write_float(m_iio, "in_anglvel_z_scale", scale);
@ -224,6 +218,8 @@ L3GD20::extract3Axis(char* data, float* x, float* y, float* z)
iio_y = getChannelValue((unsigned char*) (data + channels[1].location), &channels[1]);
iio_z = getChannelValue((unsigned char*) (data + channels[2].location), &channels[2]);
// Raw data is x, y, z axis angular velocity. Units after application of scale are radians per
// second
*x = (iio_x * m_scale);
*y = (iio_y * m_scale);
*z = (iio_z * m_scale);

20
src/l3gd20/l3gd20.hpp Executable file → Normal file
View File

@ -1,6 +1,6 @@
/*
* Author: Lay, Kuan Loon <kuan.loon.lay@intel.com>
* Copyright (c) 2015 Intel Corporation.
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -100,7 +100,7 @@ class L3GD20
/**
* Enable trigger buffer
* @param trigger buffer length in string
* @param trigger buffer length in integer
*/
bool enableBuffer(int length);
@ -111,13 +111,17 @@ class L3GD20
/**
* Set scale
* @param scale in string
* @param scale in float
* Available scales are 0.000153(250dps), 0.000305(500dps), and 0.001222(2000dps)
* Default scale is 0.000153
*/
bool setScale(const float scale);
/**
* Set sampling frequency
* @param sampling frequency in string
* @param sampling frequency in float
* Available sampling frequency are 95, 190, 380, and 760
* Default sampling frequency is 95
*/
bool setSamplingFrequency(const float sampling_frequency);
@ -202,9 +206,9 @@ class L3GD20
bool m_mount_matrix_exist; // is mount matrix exist
float m_mount_matrix[9]; // mount matrix
float m_scale; // gyroscope data scale
int m_event_count; // sample data arrive
bool m_calibrated; // calibrate state
gyro_cal_t m_cal_data; // calibrate data
filter_median_t m_filter; // filter data
int m_event_count; // sample data arrive
bool m_calibrated; // calibrate state
gyro_cal_t m_cal_data; // calibrate data
filter_median_t m_filter; // filter data
};
}

View File

@ -46,13 +46,23 @@ Jhd1313m1::Jhd1313m1(int bus, int lcdAddress, int rgbAddress)
": I2c.address() failed");
}
/* HD44780 requires writing three times to initialize or reset
according to the hardware errata on page 45 figure 23 of
the Hitachi HD44780 datasheet */
/* First try */
usleep(50000);
ret = command(LCD_FUNCTIONSET | LCD_2LINE);
ret = command(LCD_FUNCTIONSET | LCD_8BITMODE);
/* Second try */
usleep(4500);
ret = command(LCD_FUNCTIONSET | LCD_8BITMODE);
/* Third try */
usleep(150);
ret = command(LCD_FUNCTIONSET | LCD_8BITMODE);
UPM_CHECK_MRAA_SUCCESS(ret, "Unable to initialise the LCD controller");
if (!ret) {
ret = command(LCD_FUNCTIONSET | LCD_2LINE);
UPM_CHECK_MRAA_SUCCESS(ret, "Unable to initialise the LCD controller");
}
/* Set 2 row mode and font size */
ret = command(LCD_FUNCTIONSET | LCD_8BITMODE | LCD_2LINE | LCD_5x10DOTS);
UPM_CHECK_MRAA_SUCCESS(ret, "Unable to initialise the LCD controller");
usleep(100);
ret = displayOn();

View File

@ -9,7 +9,7 @@
"url": "https://github.com/intel-iot-devkit/upm"
},
"engines" : {
"node": ">= 0.10.x"
"node": ">= 4.4.x"
},
"bugs": {
"url" : "http://github.com/intel-iot-devkit/upm/issues"

28
src/t8100/CMakeLists.txt Normal file
View File

@ -0,0 +1,28 @@
set (libname "t8100")
set (libdescription "upm module for the Telaire T8100 Ventostat")
set (module_src ${libname}.cxx)
set (module_hpp ${libname}.hpp)
pkg_check_modules(BACNET libbacnet)
if (BACNET_FOUND)
# upm-libbacnetmstp will bring in libbacnet, I hope
set (reqlibname "upm-bacnetmstp")
include_directories(${BACNET_INCLUDE_DIRS})
include_directories("../bacnetmstp")
upm_module_init()
target_link_libraries(${libname} bacnetmstp)
if (BUILDSWIG)
if (BUILDSWIGNODE)
set_target_properties(${SWIG_MODULE_jsupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (jsupm_${libname} bacnetmstp)
endif()
if (BUILDSWIGPYTHON)
set_target_properties(${SWIG_MODULE_pyupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (pyupm_${libname} bacnetmstp)
endif()
if (BUILDSWIGJAVA)
set_target_properties(${SWIG_MODULE_javaupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (javaupm_${libname} bacnetmstp)
endif()
endif()
endif ()

22
src/t8100/javaupm_t8100.i Normal file
View File

@ -0,0 +1,22 @@
%module javaupm_t8100
%include "../upm.i"
%include "typemaps.i"
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "t8100.hpp"
%{
#include "t8100.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_t8100");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

10
src/t8100/jsupm_t8100.i Normal file
View File

@ -0,0 +1,10 @@
%module jsupm_t8100
%include "../upm.i"
%include "stdint.i"
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "t8100.hpp"
%{
#include "t8100.hpp"
%}

14
src/t8100/pyupm_t8100.i Normal file
View File

@ -0,0 +1,14 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_t8100
%include "../upm.i"
%include "stdint.i"
%feature("autodoc", "3");
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "t8100.hpp"
%{
#include "t8100.hpp"
%}

254
src/t8100/t8100.cxx Normal file
View File

@ -0,0 +1,254 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <assert.h>
#include <errno.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "t8100.hpp"
using namespace upm;
using namespace std;
// conversion from fahrenheit to celcius and back
static float f2c(float f)
{
return ((f - 32.0) / (9.0 / 5.0));
}
static float c2f(float c)
{
return (c * (9.0 / 5.0) + 32.0);
}
T8100::T8100(uint32_t targetDeviceObjectID) :
BACNETUTIL(targetDeviceObjectID)
{
setDebug(false);
// we disable this by default for performance reasons
checkReliability(false);
m_isTempInitialized = false;
m_isCelcius = false;
m_humidity = 0.0;
m_temperature = 0.0;
m_co2 = 0.0;
m_relayState = false;
}
T8100::~T8100()
{
}
void T8100::update()
{
if (!m_isTempInitialized)
{
// this will update internals so conversions work properly
getTemperatureScale();
}
float tmpF = getAnalogInput(AI_Temperature_Thermistor);
if (m_isCelcius)
m_temperature = tmpF;
else
m_temperature = f2c(tmpF);
m_humidity = getAnalogInput(AI_Relative_Humidity);
m_co2 = getAnalogInput(AI_CO2);
m_relayState = getBinaryInput(BI_Relay_State);
}
float T8100::getTemperature(bool fahrenheit)
{
if (fahrenheit)
return c2f(m_temperature);
else
return m_temperature;
}
void T8100::setTemperatureScale(bool fahrenheit)
{
setBinaryValue(BV_Temperature_Units, fahrenheit);
m_isTempInitialized = true;
m_isCelcius = (fahrenheit) ? false : true;
}
bool T8100::getTemperatureScale()
{
bool scale = getBinaryValue(BV_Temperature_Units);
m_isTempInitialized = true;
m_isCelcius = !scale;
return scale;
}
float T8100::getTemperatureOffset()
{
return getAnalogValue(AV_Temperature_Offset);
}
void T8100::setTemperatureOffset(float value)
{
// Always in C...
if (value < -50.0 || value > 50.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between -50 and 50,"
+ " in degrees Celcius");
}
setAnalogValue(AV_Temperature_Offset, value);
}
float T8100::getHumidityOffset()
{
return getAnalogValue(AV_RH_Offset);
}
void T8100::setHumidityOffset(float value)
{
if (value < -100.0 || value > 100.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between -100 and 100");
}
setAnalogValue(AV_RH_Offset, value);
}
float T8100::getRelaySetPoint()
{
return getAnalogValue(AV_Relay_Set_Point);
}
void T8100::setRelaySetPoint(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Relay_Set_Point, value);
}
float T8100::getRelayHysteresis()
{
return getAnalogValue(AV_Relay_Hysteresis);
}
void T8100::setRelayHysteresis(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Relay_Hysteresis, value);
}
float T8100::getElevation()
{
return getAnalogValue(AV_Elevation);
}
void T8100::setElevation(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Elevation, value);
}
float T8100::getCalibrationSinglePoint()
{
return getAnalogValue(AV_Calibration_Single_Point);
}
void T8100::setCalibrationSinglePoint(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Calibration_Single_Point, value);
}
float T8100::getBaudRate()
{
return getAnalogValue(AV_Baud_Rate);
}
float T8100::getMACAddress()
{
return getAnalogValue(AV_MAC_Address);
}
bool T8100::getABCLogicState()
{
return getBinaryValue(BV_ABC_Logic_State);
}
void T8100::setABCLogicState(bool value)
{
setBinaryValue(BV_ABC_Logic_State, value);
}
bool T8100::getABCLogicReset()
{
return getBinaryValue(BV_ABC_Logic_Reset);
}
void T8100::setABCLogicReset(bool value)
{
setBinaryValue(BV_ABC_Logic_Reset, value);
}
bool T8100::getCO2Calibration()
{
return getBinaryValue(BV_CO2_Calibration);
}
void T8100::setCO2Calibration(bool value)
{
setBinaryValue(BV_CO2_Calibration, value);
}

379
src/t8100/t8100.hpp Normal file
View File

@ -0,0 +1,379 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include <map>
#include "bacnetmstp.hpp"
#include "bacnetutil.hpp"
namespace upm {
/**
* @brief Amphenol Telaire Ventostat T8100 Ventilation Controller
* @defgroup t8100 libupm-t8100
* @ingroup uart temp gaseous
*/
/**
* @library t8100
* @sensor t8100
* @comname UPM API for the Amphenol Telaire Ventostat T8100
* Ventilation Controller
* @type gaseous temp
* @man amphenol
* @con uart
* @web https://www.instrumart.com/products/configure/18180?quantity=1
*
* @brief UPM API for the Amphenol Telaire Ventostat T8100
* Ventilation Controller
*
* This module implements support for the Amphenol Telaire Ventostat
* T8100 Ventilation Controller with BACnet interface. It may also
* support the T8200 and T8300 models, but they have not been
* tested.
*
* The Telaire Ventostat T8100 reports Temperature, Humidity and CO2
* concentrations. It supports an optional relay with a settable
* trigger point. The unit this driver was tested under did not
* support the optional relay. The temperature range supported is
* 0-50C, humidity is 0-100% non-condensing, and CO2 range is
* appoximately 0-2000 PPM for the T8100. Other sensors in this
* family support wider ranges.
*
* This module was developed using the upm::BACNETMSTP library,
* based on libbacnet-stack 0.8.3. Both libbacnet 0.8.3 and the
* upm::BACNETMSTP libraries must be present in order to build this
* module.
*
* It was connected using an RS232->RS485 interface. You cannot use
* the built in MCU TTL UART pins for accessing this device -- you
* must use a full Serial RS232->RS485 or USB-RS485 interface
* connected via USB.
*
* @snippet t8100.cxx Interesting
*/
class T8100 : public BACNETUTIL {
public:
// Supported Analog Value Objects. These are readable and writable.
typedef enum : uint32_t {
AV_Temperature_Offset = 1,
AV_RH_Offset = 2,
AV_Relay_Set_Point = 3,
AV_Relay_Hysteresis = 4,
AV_Elevation = 5,
AV_Calibration_Single_Point = 6,
AV_Baud_Rate = 7,
AV_MAC_Address = 8
} ANALOG_VALUES_T;
// Supported Analog Input Objects. These are read only.
typedef enum : uint32_t {
AI_CO2 = 1,
AI_Relative_Humidity = 2,
AI_Temperature_ChipCap = 3,
AI_Temperature_Thermistor = 4
} ANALOG_INPUTS_T;
// Supported Binary Value Objects. These are readable and writable.
typedef enum : uint32_t {
BV_Temperature_Units = 1,
BV_ABC_Logic_State = 2,
BV_ABC_Logic_Reset = 3,
BV_CO2_Calibration = 4
} BINARY_VALUES_T;
// Supported Binary Input Objects. These are read only.
typedef enum : uint32_t {
BI_Relay_State = 1
} BINARY_INPUTS_T;
/**
* T8100 constructor
*
* @param targetDeviceObjectID the unique Instance ID of the
* Device Object. This number is used to uniquely identify
* devices on the BACnet network, and ranges from 1 to 4194302.
* This is not the device's MAC address, though on some devices,
* the MAC address may be used as part of this number. On the
* T8100, this number is 568XXX, where XXX are the 3 digits of the
* set MAC address. The MAC address is configured via DIP switches
* within the device.
*/
T8100(uint32_t targetDeviceObjectID);
/**
* T8100 Destructor
*/
~T8100();
/**
* Read current values from the sensor and update internal stored
* values for temperature, humidity, CO2 concentration and relay
* state. This method must be called prior to querying any
* of the aforementioned values.
*/
void update();
/**
* Get the current relative humidity. update() must have been
* called prior to calling this method.
*
* @return The last humidity reading
*/
float getHumidity()
{
return m_humidity;
}
/**
* Get the current CO2 concentration in Parts per Million (PPM).
* update() must have been called prior to calling this method.
*
* @return The last CO2 reading
*/
float getCO2()
{
return m_co2;
}
/**
* Get the current temperature. update() must have been called
* prior to calling this method.
*
* @param fahrenheit true to return the temperature in degrees
* fahrenheit, false to return the temperature in degrees celcius.
* The default is false (degrees Celcius).
* @return The last temperature reading in Celcius or Fahrenheit.
*/
float getTemperature(bool fahrenheit=false);
/**
* Return the current state of the relay. This function will
* always return false if the relay option is not installed.
* update() must have been called prior to calling this method.
*
* @return true if the relay is active, false if inactive.
*/
bool getRelayState()
{
return m_relayState;
}
/**
* Set the device temperature scale to Celcius of Fahrenheit. For
* devices with an LCD display, this will affect which scale is
* displayed. When changing the scale, it may take several
* seconds for the setting to take effect.
*
* @param fahrenheit true to set the scale to fahrenheit, false
* for celcius.
*/
void setTemperatureScale(bool fahrenheit);
/**
* Get the device temperature scale.
*
* @return true if scale is fahrenheit, false for celcius.
*/
bool getTemperatureScale();
/**
* Get the current temperature offset.
*
* @return The configured temperature offset.
*/
float getTemperatureOffset();
/**
* Set the device temperature offset. The offset is applied by
* the device internally to the temperature reading. The offset
* must always be specified in degrees Celcius. Valid values must
* be between -50 and 50.
*
* @param value The temperature offset to configure.
*/
void setTemperatureOffset(float value);
/**
* Get the current humidity offset.
*
* @return The configured humidity offset.
*/
float getHumidityOffset();
/**
* Set the device humidity offset. The offset is applied by the
* device internally to the humidity reading. Valid values must
* be between -100 and 100.
*
* @param value The humidity offset to configure.
*/
void setHumidityOffset(float value);
/**
* Return the current relay set point (in PPM). This set point is
* the CO2 concentration point in PPM that causes the relay to
* trigger.
*
* @return The relay set point value.
*/
float getRelaySetPoint();
/**
* Set the relay set point in PPM. This set point is the CO2
* concentration point in PPM that causes the relay to trigger.
* Valid values are between 0-65535.
*
* @param value The desired relay set point value.
*/
void setRelaySetPoint(float value);
/**
* Return the current relay hysteresis.
*
* @return The relay hysteresis value.
*/
float getRelayHysteresis();
/**
* Set the relay hysteresis. Valid values are between 0-65535.
*
* @param value The desired relay set point value.
*/
void setRelayHysteresis(float value);
/**
* Return the current elevation setting (in meters).
*
* @return The current elevation setting.
*/
float getElevation();
/**
* Set the elevation setting in meters. Valid values are between
* 0-65535.
*
* @param value The desired elevation setting in meters.
*/
void setElevation(float value);
/**
* Return the current calibration single point value (in PPM).
*
* @return The current calibration single point value.
*/
float getCalibrationSinglePoint();
/**
* Set the calibration single point value in PPM. Valid values
* are between 0-65535.
*
* @param value The desired calibration single point value in PPM.
*/
void setCalibrationSinglePoint(float value);
/**
* Return the current baud rate.
*
* @return The current baud rate.
*/
float getBaudRate();
/**
* Return the current MAC address. The MAC address is configured
* via DIP switches within the device.
*
* @return The current MAC address.
*/
float getMACAddress();
/**
* Return the current ABC (Automatic Background Calibration)
* logic state. See the datasheet for details.
*
* @return The current ABC logic state.
*/
bool getABCLogicState();
/**
* Set the ABC (Automatic Background Calibration) logic state.
* Valid values are true for ON, false for OFF.
*
* @param value The desired ABC logic state.
*/
void setABCLogicState(bool value);
/**
* Return the current ABC (Automatic Background Calibration)
* reset state. See the datasheet for details.
*
* @return The current ABC reset state.
*/
bool getABCLogicReset();
/**
* Set the ABC (Automatic Background Calibration) reset state.
* Valid values are true for Reset, false for Normal.
*
* @param value The desired ABC reset state.
*/
void setABCLogicReset(bool value);
/**
* Return the current CO2 calibration state. See the datasheet
* for details.
*
* @return The current CO2 calibration state.
*/
bool getCO2Calibration();
/**
* Set the CO2 calibration state.
* Valid values are true for Calibrate, false for Normal.
*
* @param value The desired ABC reset state.
*/
void setCO2Calibration(bool value);
protected:
float m_humidity;
// always stored in C
float m_temperature;
float m_co2;
bool m_relayState;
private:
// Have we checked the device's temperature unit setting yet
bool m_isTempInitialized;
// Is the device configured for Celcius?
bool m_isCelcius;
};
}

28
src/tb7300/CMakeLists.txt Normal file
View File

@ -0,0 +1,28 @@
set (libname "tb7300")
set (libdescription "upm module for the TB7300 Fan Coil Thermostat")
set (module_src ${libname}.cxx)
set (module_hpp ${libname}.hpp)
pkg_check_modules(BACNET libbacnet)
if (BACNET_FOUND)
# upm-libbacnetmstp will bring in libbacnet, I hope
set (reqlibname "upm-bacnetmstp")
include_directories(${BACNET_INCLUDE_DIRS})
include_directories("../bacnetmstp")
upm_module_init()
target_link_libraries(${libname} bacnetmstp)
if (BUILDSWIG)
if (BUILDSWIGNODE)
set_target_properties(${SWIG_MODULE_jsupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (jsupm_${libname} bacnetmstp)
endif()
if (BUILDSWIGPYTHON)
set_target_properties(${SWIG_MODULE_pyupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (pyupm_${libname} bacnetmstp)
endif()
if (BUILDSWIGJAVA)
set_target_properties(${SWIG_MODULE_javaupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (javaupm_${libname} bacnetmstp)
endif()
endif()
endif ()

View File

@ -0,0 +1,32 @@
%module javaupm_tb7300
%include "../upm.i"
%include "typemaps.i"
// We need to use this method for enum wrapping since the enum typedefs used
// by the derived classes (like ANALOG_VALUES_T) are passed to methods
// in the base class which expect a uint32_t. This is fine, and
// works everywhere except Java. It's type safety is a little too
// stringent in these cases. %javaconst(1) is generally recommended
// as it avoids JNI calls to determine the enumerant values at
// runtime.
%include "enumtypeunsafe.swg"
%javaconst(1);
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "tb7300.hpp"
%{
#include "tb7300.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_tb7300");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

10
src/tb7300/jsupm_tb7300.i Normal file
View File

@ -0,0 +1,10 @@
%module jsupm_tb7300
%include "../upm.i"
%include "stdint.i"
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "tb7300.hpp"
%{
#include "tb7300.hpp"
%}

14
src/tb7300/pyupm_tb7300.i Normal file
View File

@ -0,0 +1,14 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_tb7300
%include "../upm.i"
%include "stdint.i"
%feature("autodoc", "3");
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "tb7300.hpp"
%{
#include "tb7300.hpp"
%}

108
src/tb7300/tb7300.cxx Normal file
View File

@ -0,0 +1,108 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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 <unistd.h>
#include <errno.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "tb7300.hpp"
using namespace upm;
using namespace std;
// conversion from fahrenheit to celcius and back
static float f2c(float f)
{
return ((f - 32.0) / (9.0 / 5.0));
}
static float c2f(float c)
{
return (c * (9.0 / 5.0) + 32.0);
}
TB7300::TB7300(uint32_t targetDeviceObjectID) :
BACNETUTIL(targetDeviceObjectID)
{
setDebug(false);
// we disable this by default for performance reasons
checkReliability(false);
m_isTempInitialized = false;
m_isCelcius = false;
// room temperature only
m_temperature = 0.0;
}
TB7300::~TB7300()
{
}
void TB7300::update()
{
if (!m_isTempInitialized)
{
// this will update internals so conversions work properly
getTemperatureScale();
}
float tmpF = getAnalogValue(AV_Room_Temperature);
if (m_isCelcius)
m_temperature = tmpF;
else
m_temperature = f2c(tmpF);
}
float TB7300::getTemperature(bool fahrenheit)
{
if (fahrenheit)
return c2f(m_temperature);
else
return m_temperature;
}
void TB7300::setTemperatureScale(bool fahrenheit)
{
setBinaryValue(BV_Temperature_Scale, fahrenheit);
m_isTempInitialized = true;
m_isCelcius = (fahrenheit) ? false : true;
}
bool TB7300::getTemperatureScale()
{
bool scale = getBinaryValue(BV_Temperature_Scale);
m_isTempInitialized = true;
m_isCelcius = !scale;
return scale;
}

258
src/tb7300/tb7300.hpp Normal file
View File

@ -0,0 +1,258 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 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.
*/
#pragma once
#include <string>
#include <map>
#include "bacnetmstp.hpp"
#include "bacnetutil.hpp"
namespace upm {
/**
* @brief Honeywell TB7300 Communicating Fan Coil Thermostat
* @defgroup tb7300 libupm-tb7300
* @ingroup uart temp
*/
/**
* @library tb7300
* @sensor tb7300
* @comname UPM API for the Honeywell TB7300 Communicating Fan Coil
* Thermostat
* @type temp
* @man honeywell
* @con uart
* @web https://parts-hvac.com/tb7300c5014b.html
*
* @brief Honeywell TB7300 Communicating Fan Coil Thermostat
*
* This module implements support for the Honeywell TB7300
* Communicating Fan Coil Thermostat. It may also support the
* TB7200, though only the TB7300 was available for development of
* this driver.
*
* The TB7200 Series PI thermostats are designed for zoning
* applications, and the TB7300 Series PI thermostats are designed
* for fan coil control. Both Series are communicating thermostats
* with models available in BACnet® MS/TP protocol and can be easily
* integrated into a WEBs-AX building automation system based on the
* NiagaraAX® platform.
*
* TB7200 and TB7300 Series thermostats are compatible with the
* Honeywell Occupancy Sensor Cover. Thermostats equipped with an
* occupancy sensor cover provide advanced active occupancy logic,
* which will automatically switch occupancy levels from Occupied to
* Stand-By and Unoccupied as required by local activity being
* present or not. This advanced occupancy functionality provides
* advantageous energy savings during occupied hours without
* sacrificing occupant comfort. All thermostats can be ordered with
* or without a factory installed PIR cover.
*
* If you intend to work with this device and driver, it is
* strongly suggested you get the BACnet Intergration Guide document
* for this device: 63-4524.pdf as recommended in the device
* documentation.
*
* This module was developed using the upm::BACNETMSTP library,
* based on libbacnet-stack 0.8.3. Both libbacnet 0.8.3 and the
* upm::BACNETMSTP libraries must be present in order to build this
* module.
*
* It was connected using an RS232->RS485 interface. You cannot use
* the built in MCU TTL UART pins for accessing this device -- you
* must use a full Serial RS232->RS485 or USB-RS485 interface
* connected via USB.
*
* @snippet tb7300.cxx Interesting
*/
class TB7300 : public BACNETUTIL {
public:
// Supported Analog Value Objects. These are readable and writable.
typedef enum : uint32_t {
AV_Room_Temperature = 7,
// GRP 20 Control Output
AV_PI_Heating_Demand = 21,
AV_PI_Cooling_Demand = 22,
// GRP 38 Temperature Setpoints
AV_Occupied_Heat_Setpoint = 39,
AV_Occupied_Cool_Setpoint = 40,
AV_Standby_Heat_Setpoint = 41,
AV_Standby_Cool_Setpoint = 42,
AV_Unoccupied_Heat_Setpoint = 43,
AV_Unoccupied_Cool_Setpoint = 44,
// GRP 55 General Options 2
AV_Password_Value = 56,
AV_Heating_Setpoint_Limit = 58,
AV_Cooling_Setpoint_Limit = 59,
AV_Deadband = 63,
AV_Standby_Time = 67,
AV_Unoccupied_Time = 68
} ANALOG_VALUES_T;
// Supported Analog Input Objects. These are read only.
typedef enum : uint32_t {
AI_Supply_Temperature = 12
} ANALOG_INPUTS_T;
// Supported Binary Value Objects. These are readable and writable.
typedef enum : uint32_t {
BV_Temp_Override = 8,
BV_Aux_Command = 14,
// GRP 45 General Options 1
BV_Menu_Scroll = 49,
BV_Auto_Mode_Enable = 50,
BV_Temperature_Scale = 51,
// GRP 55 General Option 2
BV_Setpoint_Type = 60,
BV_Setpoint_Function = 61,
BV_Reheat_Timebase = 64,
BV_Auto_Fan = 66,
// GRP 74 Output Configuration Options
BV_Control_type = 75,
BV_Direct_Reverse_Acting = 78
} BINARY_VALUES_T;
// Supported Binary Input Objects. These are read only.
typedef enum : uint32_t {
// GRP 24 Controller Status
BI_AUX_Status = 25,
BI_BI1_Status = 29,
BI_BI2_Status = 30,
BI_UI3_Status = 31,
BI_Local_Motion = 32,
// GRP 34 Controller Alarms
BI_Window_Alarm = 35,
BI_Filter_Alarm = 36,
BI_Service_Alarm = 37
} BINARY_INPUTS_T;
// Supported Multi-State Value Objects. These are readable and
// writable.
typedef enum : uint32_t {
MV_Sequence_of_Operation = 15,
MV_System_Mode = 16,
MV_Fan_Mode = 17,
MV_Occupancy_Command = 18,
MV_Keypad_Lockout = 19,
// GRP 24 Controller Status
MV_Heating_Valve_Status = 26,
MV_Cooling_Valve_Status = 27,
MV_Fan_Status = 28,
MV_Effective_Occupancy = 33,
// GRP 45 General Options 1
MV_BI1_Configuration = 46,
MV_BI2_Configuration = 47,
MV_UI1_Configuration = 48,
MV_Pipe_Number = 52,
MV_Out1_Config = 53,
MV_AUX_Configuration = 54,
// GRP 55 General Option 2
MV_Fan_Mode_Sequence = 58,
MV_Temporary_Occupancy_Time = 62,
MV_Proportional_Band = 65,
// GRP 74 Output Configuration Options
MV_Floating_Motor_Timing = 76,
MV_On_Off_Control_CPH = 77
} MULTISTATE_VALUES_T;
/**
* TB7300 constructor
*
* @param targetDeviceObjectID the unique Instance ID of the
* Device Object. This number is used to uniquely identify
* devices on the BACnet network, and ranges from 1 to 4194302.
* This is not the device's MAC address, though on some devices,
* the MAC address may be used as part of this number. On the
* TB7300, this number depends on the model and the MAC address.
*/
TB7300(uint32_t targetDeviceObjectID);
/**
* TB7300 Destructor
*/
~TB7300();
/**
* Read current temperature from the sensor and update internal
* stored value. This method must be called prior to querying the
* temperature. All other values in the device must be queried
* directly via the appropriate BACNETUTIL::get*() methods
* depending on the object of interest.
*/
void update();
/**
* Get the current temperature. update() must have been called
* prior to calling this method.
*
* @param fahrenheit true to return the temperature in degrees
* fahrenheit, false to return the temperature in degrees celcius.
* The default is false (degrees Celcius).
* @return The last temperature reading in Celcius or Fahrenheit.
*/
float getTemperature(bool fahrenheit=false);
/**
* Set the device temperature scale to Celcius of Fahrenheit. For
* devices with an LCD display, this will affect which scale is
* displayed. When changing the scale, it may take several
* seconds for the setting to take effect.
*
* @param fahrenheit true to set the scale to fahrenheit, false
* for celcius.
*/
void setTemperatureScale(bool fahrenheit);
/**
* Get the device temperature scale.
*
* @return true if scale is fahrenheit, false for celcius.
*/
bool getTemperatureScale();
protected:
// always stored in C
float m_temperature;
bool m_isTempInitialized;
bool m_isCelcius;
private:
};
}