From aecdac255d922f044cbbd23f079417befaab57fc Mon Sep 17 00:00:00 2001 From: Norbert Wesp Date: Tue, 14 Feb 2017 12:05:01 +0100 Subject: [PATCH] hdc1000: Added upm support for sensor HDC1000 The HDC1000 is a digital humidity sensor with integrated temperature sensor. Signed-off-by: Norbert Wesp Signed-off-by: Mihai Tudor Panu --- doxy/samples.mapping.txt | 1 + examples/c++/CMakeLists.txt | 1 + examples/c++/hdc1000.cxx | 67 +++++++++++++++ examples/python/hdc1000.py | 57 +++++++++++++ src/hdc1000/CMakeLists.txt | 5 ++ src/hdc1000/hdc1000.cpp | 147 +++++++++++++++++++++++++++++++++ src/hdc1000/hdc1000.hpp | 148 ++++++++++++++++++++++++++++++++++ src/hdc1000/javaupm_hdc1000.i | 19 +++++ src/hdc1000/jsupm_hdc1000.i | 8 ++ src/hdc1000/pyupm_hdc1000.i | 15 ++++ 10 files changed, 468 insertions(+) create mode 100644 examples/c++/hdc1000.cxx create mode 100644 examples/python/hdc1000.py create mode 100644 src/hdc1000/CMakeLists.txt create mode 100644 src/hdc1000/hdc1000.cpp create mode 100644 src/hdc1000/hdc1000.hpp create mode 100644 src/hdc1000/javaupm_hdc1000.i create mode 100644 src/hdc1000/jsupm_hdc1000.i create mode 100644 src/hdc1000/pyupm_hdc1000.i diff --git a/doxy/samples.mapping.txt b/doxy/samples.mapping.txt index 15702a99..4d7b97a9 100644 --- a/doxy/samples.mapping.txt +++ b/doxy/samples.mapping.txt @@ -78,3 +78,4 @@ tcs37727.cxx tcs37727.py tmp006.cxx tmp006.py mma8x5x.cxx mma8x5x.py mag3110.cxx mag3110.py +hdc1000.cxx hdc1000.py diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 92d92425..9f4d2386 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -338,6 +338,7 @@ add_example (tcs37727) add_example (tmp006) add_example (mma8x5x) add_example (mag3110) +add_example (hdc1000) # These are special cases where you specify example binary, source file and module(s) include_directories (${PROJECT_SOURCE_DIR}/src) diff --git a/examples/c++/hdc1000.cxx b/examples/c++/hdc1000.cxx new file mode 100644 index 00000000..2d8a9943 --- /dev/null +++ b/examples/c++/hdc1000.cxx @@ -0,0 +1,67 @@ +/* Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * 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 +#include +#include + +#include "hdc1000.hpp" + +using namespace upm; + +bool run = true; + +void sig_handler(int sig) +{ + if (sig == SIGINT) + run = false; +} + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); + +//! [Interesting] + cout << "Initializing test-application..." << endl; + + // Instantiate an HDC1000 instance on bus 1 + upm::HDC1000 *mySensor = new upm::HDC1000(1); + + // update and print available values every second + while (run) + { + cout << "Humidity: " << mySensor->getHumidity(true) << endl + << "Temperature: " << mySensor->getTemperature(true) << endl; + + cout << endl; + + sleep(1); + } + + cout << "Exiting test-application..." << endl; + + delete mySensor; +//! [Interesting] + + return 0; +} \ No newline at end of file diff --git a/examples/python/hdc1000.py b/examples/python/hdc1000.py new file mode 100644 index 00000000..9ab3b5be --- /dev/null +++ b/examples/python/hdc1000.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +# Author: Norbert Wesp +# Copyright (c) 2017 Phytec Messtechnik GmbH. +# +# based on: tcs3414cs.py +# +# 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. + +from __future__ import print_function +import time, sys, signal, atexit +from upm import pyupm_hdc1000 as HDC1000 + +def main(): + # Instantiate the Temperature and Humidity Sensor on I2C on bus 1 + mySensor = HDC1000.HDC1000(1) + + ## Exit handlers ## + # This stops python from printing a stacktrace when you hit control-C + def SIGINTHandler(signum, frame): + raise SystemExit + + # This lets you run code on exit, + # including functions from mySensor + def exitHandler(): + print("Exiting") + sys.exit(0) + + # Register exit handlers + atexit.register(exitHandler) + signal.signal(signal.SIGINT, SIGINTHandler) + + # Print out the humidity and temperature value every 0.5 seconds + while(1): + mySensor.getHumidity(True) + mySensor.getTemperature(True) + + time.sleep(.5) + +if __name__ == '__main__': + main() diff --git a/src/hdc1000/CMakeLists.txt b/src/hdc1000/CMakeLists.txt new file mode 100644 index 00000000..a06ed52d --- /dev/null +++ b/src/hdc1000/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "hdc1000") +set (libdescription "Humidity/Temperature Sensor") +set (module_src ${libname}.cpp) +set (module_hpp ${libname}.hpp) +upm_module_init() diff --git a/src/hdc1000/hdc1000.cpp b/src/hdc1000/hdc1000.cpp new file mode 100644 index 00000000..ce224d99 --- /dev/null +++ b/src/hdc1000/hdc1000.cpp @@ -0,0 +1,147 @@ +/* + * Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * based on: RIOT-driver hdc1000 by Johann Fischer + * + * 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 +#include +#include + +#include +#include +#include + +#include "hdc1000.hpp" + +using namespace upm; + +HDC1000::HDC1000(int bus, int devAddr) : m_i2ControlCtx(bus) { + m_temperature = 0; + m_humidity = 0; + + m_name = HDC1000_NAME; + + m_controlAddr = devAddr; + m_bus = bus; + + mraa::Result ret = m_i2ControlCtx.address(m_controlAddr); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_address() failed"); + } + + if (checkID() != 0) { + /* sensor_id does not match! maybe wrong sensor chosen? */ + throw std::invalid_argument(std::string(__FUNCTION__) + + ": checkID() failed"); + } + + sampleData(); +} + +int +HDC1000::checkID(void) +{ + uint8_t tmp[2]; + uint16_t id; + int re = 0; + + re = m_i2ControlCtx.readBytesReg(HDC1000_DEVICE_ID_REG, tmp, 2); + if (re != 2) { + /* not enough bytes were read! */ + return -1; + } + + id = ((uint16_t)tmp[0] << 8) | tmp[1]; + + if (id != HDC1000_DEVICE_ID) { + return -1; + } + + return 0; +} + +void +HDC1000::resetSensor(void) +{ + mraa::Result ret = m_i2ControlCtx.address(m_controlAddr); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_address() failed"); + } + + ret = m_i2ControlCtx.writeByte(0); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_write_byte() failed"); + } + usleep(SLEEP_SEC); +} + +void +HDC1000::sampleData(void) +{ + uint8_t itemp[4]; + uint16_t traw, hraw; + int re = 0; + + resetSensor(); + + mraa::Result ret = m_i2ControlCtx.address(m_controlAddr); + if (ret != mraa::SUCCESS) { + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_address() failed"); + } + + re = m_i2ControlCtx.read(itemp, 4); + if (re != 4) { + /* not enough bytes were read! */ + throw std::invalid_argument(std::string(__FUNCTION__) + + ": mraa_i2c_read(4) failed"); + } + + traw = ((uint16_t)itemp[0] << 8) | itemp[1]; + m_temperature = ((((int32_t)traw * 16500) >> 16) -4000); + + hraw = ((uint16_t)itemp[2] << 8) | itemp[3]; + m_humidity = (((int32_t)hraw * 10000) >> 16); +} + +float +HDC1000::getTemperature(int bSampleData) +{ + if (bSampleData) { + sampleData(); + } + return (float)(m_temperature * 0.01); +} + +float +HDC1000::getHumidity(int bSampleData) +{ + if (bSampleData) { + sampleData(); + } + return (float)(m_humidity * 0.01); +} diff --git a/src/hdc1000/hdc1000.hpp b/src/hdc1000/hdc1000.hpp new file mode 100644 index 00000000..cf3e56e6 --- /dev/null +++ b/src/hdc1000/hdc1000.hpp @@ -0,0 +1,148 @@ +/* + * Author: Norbert Wesp + * Copyright (c) 2017 Phytec Messtechnik GmbH. + * + * based on: RIOT-driver hdc1000 by Johann Fischer + * + * 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 +#include +#include + +#define HDC1000_NAME "hdc1000" +#define HDC1000_i2C_ADDRESS 0x43 +#define HDC1000_MANUFACTURER_ID 0x5449 /* ID of Texas Instruments */ +#define HDC1000_DEVICE_ID 0x1000 /* ID of HDC1000 device */ + +/* HDC1000 Register Map */ +#define HDC1000_TEMPERATURE 0x00 +#define HDC1000_HUMIDITY 0x01 +#define HDC1000_CONFIGURATION 0x02 +#define HDC1000_MANUFACTURER_ID_REG 0xFE +#define HDC1000_DEVICE_ID_REG 0xFF + +/* HDC1000 configuration register bitmap */ +#define HDC1000_RST_SOFT 0x8000 +#define HDC1000_HEAT (1 << 13) +#define HDC1000_SEQ_MODE (1 << 12) +#define HDC1000_BTST_LOW (1 << 11) +#define HDC1000_TRES_14 (0) +#define HDC1000_TRES_11 (1 << 10) +#define HDC1000_HRES_14 (0) +#define HDC1000_HRES_11 (1 << 8) +#define HDC1000_HRES_8 (1 << 9) + +#define SLEEP_SEC (1000*1000) + +namespace upm { + +/** + * @brief HDC1000 Temperature and Humidity Sensor + * @defgroup hdc1000 libupm-hdc1000 + * @ingroup ti i2c temp + */ + +/** + * @library hdc1000 + * @sensor hdc1000 + * @comname HDC1000 Temperature & Humidity Sensor + * @type temp + * @man ti + * @web http://www.ti.com/lit/ds/symlink/hdc1000.pdf + * @con i2c + * + * @brief API for the HDC1000 Temperature & Humidity Sensor + * + * Description in web-link above: + * The HDC1000 is a digital humidity sensor with integrated temperature sensor + * that provides excellent measurement accuracy at very low power. The device + * measures humidity based on a novel capacitive sensor. The humidity and + * temperature sensors are factory calibrated. The innovative + * WLCSP (Wafer Level Chip Scale Package) simplifies board design with the use + * of an ultra-compact package. The sensing element of the HDC1000 is placed on + * the bottom part of the device, which makes the HDC1000 more robust against + * dirt, dust, and other environmental contaminants. The HDC1000 is functional + * within the full -40°C to +125 °C temperature range. + * + * @snippet hdc1000.cxx Interesting + */ +class HDC1000 { + public: + /** + * Instantiates an HDC1000 object + * + * @param bus Number of the used bus + * @param devAddr Address of the used I2C device + */ + HDC1000 (int bus, int devAddr=HDC1000_i2C_ADDRESS); + + /** + * Check device_id of sensor + * + * @return 0 on succes + * -1 on error + */ + int checkID(void); + + /** + * Performs a soft reset of the HDC1000 device to ensure + * it is in a known state. + */ + void resetSensor(void); + + /** + * Initiates a temperature/pressure mesasurement and waits + * to complete. + */ + void sampleData(void); + + /** + * Get the current measured humidity [RH] + * + * @param bSampleData Flag to read sensor + * @return The humidity sensor temp in degC + */ + float getHumidity(int bSampleData = false); + + /** + * Get the humidity cell temperature [degC] + * + * @param bSampleData Flag to read sensor + * @return The humidity sensor temp in degC + */ + float getTemperature(int bSampleData = false); + + private: + + std::string m_name; + + int m_controlAddr; + int m_bus; + mraa::I2c m_i2ControlCtx; + + int32_t m_temperature; + int32_t m_humidity; +}; + +} diff --git a/src/hdc1000/javaupm_hdc1000.i b/src/hdc1000/javaupm_hdc1000.i new file mode 100644 index 00000000..c6ec0197 --- /dev/null +++ b/src/hdc1000/javaupm_hdc1000.i @@ -0,0 +1,19 @@ +%module javaupm_hdc1000 +%include "../upm.i" + +%{ + #include "hdc1000.hpp" +%} + +%include "hdc1000.hpp" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_hdc1000"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} \ No newline at end of file diff --git a/src/hdc1000/jsupm_hdc1000.i b/src/hdc1000/jsupm_hdc1000.i new file mode 100644 index 00000000..b9ed9f39 --- /dev/null +++ b/src/hdc1000/jsupm_hdc1000.i @@ -0,0 +1,8 @@ +%module jsupm_hdc1000 +%include "../upm.i" + +%{ + #include "hdc1000.hpp" +%} + +%include "hdc1000.hpp" diff --git a/src/hdc1000/pyupm_hdc1000.i b/src/hdc1000/pyupm_hdc1000.i new file mode 100644 index 00000000..58fe7a31 --- /dev/null +++ b/src/hdc1000/pyupm_hdc1000.i @@ -0,0 +1,15 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_hdc1000 +%include "../upm.i" + +%feature("autodoc", "3"); + +#ifdef DOXYGEN +%include "hdc1000_doc.i" +#endif + +%include "hdc1000.hpp" +%{ + #include "hdc1000.hpp" +%}