From c18a9433fc2917f12613e0246524bd7364b9c587 Mon Sep 17 00:00:00 2001 From: Kiveisha Yevgeniy Date: Mon, 16 Jun 2014 16:43:05 +0000 Subject: [PATCH] gy65: Added new digital pressure sensor Signed-off-by: Kiveisha Yevgeniy --- examples/CMakeLists.txt | 3 + examples/gy65.cxx | 77 +++++++++++++++++ src/gy65/CMakeLists.txt | 5 ++ src/gy65/gy65.cxx | 222 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gy65/gy65.h | 161 +++++++++++++++++++++++++++++++++++ src/gy65/jsupm_gy65.i | 7 ++ src/gy65/pyupm_gy65.i | 10 +++ 7 files changed, 485 insertions(+) create mode 100644 examples/gy65.cxx create mode 100644 src/gy65/CMakeLists.txt create mode 100644 src/gy65/gy65.cxx create mode 100644 src/gy65/gy65.h create mode 100644 src/gy65/jsupm_gy65.i create mode 100644 src/gy65/pyupm_gy65.i diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7dc24fd..8372666 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable (proximity max44000.cxx) add_executable (accelerometer mma7455.cxx) add_executable (lcd st7735.cxx) add_executable (max31855-example max31855.cxx) +add_executable (gy65-example gy65.cxx) include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l) include_directories (${PROJECT_SOURCE_DIR}/src/grove) @@ -30,6 +31,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/max44000) include_directories (${PROJECT_SOURCE_DIR}/src/mma7455) include_directories (${PROJECT_SOURCE_DIR}/src/st7735) include_directories (${PROJECT_SOURCE_DIR}/src/max31855) +include_directories (${PROJECT_SOURCE_DIR}/src/gy65) target_link_libraries (compass hmc5883l ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (groveled grove ${CMAKE_THREAD_LIBS_INIT}) @@ -49,3 +51,4 @@ target_link_libraries (proximity max44000 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (accelerometer mma7455 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (lcd st7735 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (max31855-example max31855 ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries (gy65-example gy65 ${CMAKE_THREAD_LIBS_INIT}) diff --git a/examples/gy65.cxx b/examples/gy65.cxx new file mode 100644 index 0000000..c1681cf --- /dev/null +++ b/examples/gy65.cxx @@ -0,0 +1,77 @@ +/* + * Author: Yevgeniy Kiveisha + * Copyright (c) 2014 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 +#include +#include "gy65.h" +#include + +int doWork = 0; +upm::GY65 *sensor = NULL; + +void +sig_handler(int signo) +{ + printf("got signal\n"); + if (signo == SIGINT) { + printf("exiting application\n"); + doWork = 1; + } +} + +int +main(int argc, char **argv) +{ + //! [Interesting] + uint32_t presure = 0; + float temperature = 0; + float altitude = 0; + uint32_t sealevel = 0; + + sensor = new upm::GY65(0, ADDR); + + while (!doWork) { + presure = sensor->getPressure (); + temperature = sensor->getTemperature (); + altitude = sensor->getAltitude (); + sealevel = sensor->getSealevelPressure (); + + std::cout << "pressure value = " << + presure << + ", atitude value = " << + altitude << + ", sealevel value = " << + sealevel << + ", temperature = " << + temperature << std::endl; + usleep (100000); + } + //! [Interesting] + + std::cout << "exiting application" << std::endl; + + delete sensor; + + return 0; +} diff --git a/src/gy65/CMakeLists.txt b/src/gy65/CMakeLists.txt new file mode 100644 index 0000000..3607be3 --- /dev/null +++ b/src/gy65/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "gy65") +set (libdescription "upm GY65") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/gy65/gy65.cxx b/src/gy65/gy65.cxx new file mode 100644 index 0000000..b473c8c --- /dev/null +++ b/src/gy65/gy65.cxx @@ -0,0 +1,222 @@ +/* + * Author: Yevgeniy Kiveisha + * Copyright (c) 2014 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 +#include +#include + +#include "gy65.h" + +using namespace upm; + +GY65::GY65 (int bus, int devAddr, uint8_t mode) { + m_name = "GY65"; + + m_controlAddr = devAddr; + m_bus = bus; + + m_i2ControlCtx = maa_i2c_init(m_bus); + + maa_result_t ret = maa_i2c_address(m_i2ControlCtx, m_controlAddr); + if (ret != MAA_SUCCESS) { + fprintf(stderr, "Messed up i2c bus\n"); + } + + if (i2cReadReg_8 (0xD0) != 0x55) { + std::cout << "Error :: Cannot continue" << std::endl; + return; + } + + if (mode > BMP085_ULTRAHIGHRES) { + mode = BMP085_ULTRAHIGHRES; + } + oversampling = mode; + + /* read calibration data */ + ac1 = i2cReadReg_16 (BMP085_CAL_AC1); + ac2 = i2cReadReg_16 (BMP085_CAL_AC2); + ac3 = i2cReadReg_16 (BMP085_CAL_AC3); + ac4 = i2cReadReg_16 (BMP085_CAL_AC4); + ac5 = i2cReadReg_16 (BMP085_CAL_AC5); + ac6 = i2cReadReg_16 (BMP085_CAL_AC6); + + b1 = i2cReadReg_16 (BMP085_CAL_B1); + b2 = i2cReadReg_16 (BMP085_CAL_B2); + + mb = i2cReadReg_16 (BMP085_CAL_MB); + mc = i2cReadReg_16 (BMP085_CAL_MC); + md = i2cReadReg_16 (BMP085_CAL_MD); +} + +GY65::~GY65() { + maa_i2c_stop(m_i2ControlCtx); +} + +int32_t +GY65::getPressure () { + int32_t UT, UP, B3, B5, B6, X1, X2, X3, p; + uint32_t B4, B7; + + UT = getTemperatureRaw(); + UP = getPressureRaw(); + B5 = computeB5(UT); + + // do pressure calcs + B6 = B5 - 4000; + X1 = ((int32_t)b2 * ( (B6 * B6)>>12 )) >> 11; + X2 = ((int32_t)ac2 * B6) >> 11; + X3 = X1 + X2; + B3 = ((((int32_t)ac1*4 + X3) << oversampling) + 2) / 4; + + X1 = ((int32_t)ac3 * B6) >> 13; + X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16; + X3 = ((X1 + X2) + 2) >> 2; + B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15; + B7 = ((uint32_t)UP - B3) * (uint32_t)( 50000UL >> oversampling ); + + if (B7 < 0x80000000) { + p = (B7 * 2) / B4; + } else { + p = (B7 / B4) * 2; + } + X1 = (p >> 8) * (p >> 8); + X1 = (X1 * 3038) >> 16; + X2 = (-7357 * p) >> 16; + + p = p + ((X1 + X2 + (int32_t)3791)>>4); + + return p; +} + +int32_t +GY65::getPressureRaw () { + uint32_t raw; + + i2cWriteReg (BMP085_CONTROL, BMP085_READPRESSURECMD + (oversampling << 6)); + + if (oversampling == BMP085_ULTRALOWPOWER) { + usleep(5000); + } else if (oversampling == BMP085_STANDARD) { + usleep(8000); + } else if (oversampling == BMP085_HIGHRES) { + usleep(14000); + } else { + usleep(26000); + } + + raw = i2cReadReg_16 (BMP085_PRESSUREDATA); + + raw <<= 8; + raw |= i2cReadReg_8 (BMP085_PRESSUREDATA + 2); + raw >>= (8 - oversampling); + + return raw; +} + +int16_t +GY65::getTemperatureRaw () { + i2cWriteReg (BMP085_CONTROL, BMP085_READTEMPCMD); + usleep(5000); + return i2cReadReg_16 (BMP085_TEMPDATA); +} + +float +GY65::getTemperature () { + int32_t UT, B5; // following ds convention + float temp; + + UT = getTemperatureRaw (); + + B5 = computeB5 (UT); + temp = (B5 + 8) >> 4; + temp /= 10; + + return temp; +} + +int32_t +GY65::getSealevelPressure(float altitudeMeters) { + float pressure = getPressure (); + return (int32_t)(pressure / pow(1.0-altitudeMeters/44330, 5.255)); +} + +float +GY65::getAltitude (float sealevelPressure) { + float altitude; + + float pressure = getPressure (); + + altitude = 44330 * (1.0 - pow(pressure /sealevelPressure,0.1903)); + + return altitude; +} + +int32_t +GY65::computeB5(int32_t UT) { + int32_t X1 = (UT - (int32_t)ac6) * ((int32_t)ac5) >> 15; + int32_t X2 = ((int32_t)mc << 11) / (X1+(int32_t)md); + + return X1 + X2; +} + +maa_result_t +GY65::i2cWriteReg (uint8_t reg, uint8_t value) { + maa_result_t error = MAA_SUCCESS; + + uint8_t data[2] = { reg, value }; + error = maa_i2c_address (m_i2ControlCtx, m_controlAddr); + error = maa_i2c_write (m_i2ControlCtx, data, 2); + + return error; +} + +uint16_t +GY65::i2cReadReg_16 (int reg) { + uint16_t data; + + maa_i2c_address(m_i2ControlCtx, m_controlAddr); + maa_i2c_write_byte(m_i2ControlCtx, reg); + + maa_i2c_address(m_i2ControlCtx, m_controlAddr); + maa_i2c_read(m_i2ControlCtx, (uint8_t *)&data, 0x2); + + uint8_t high = (data & 0xFF00) >> 8; + data = (data << 8) & 0xFF00; + data |= high; + + return data; +} + +uint8_t +GY65::i2cReadReg_8 (int reg) { + uint8_t data; + + maa_i2c_address(m_i2ControlCtx, m_controlAddr); + maa_i2c_write_byte(m_i2ControlCtx, reg); + + maa_i2c_address(m_i2ControlCtx, m_controlAddr); + maa_i2c_read(m_i2ControlCtx, &data, 0x1); + + return data; +} diff --git a/src/gy65/gy65.h b/src/gy65/gy65.h new file mode 100644 index 0000000..f9d3ab0 --- /dev/null +++ b/src/gy65/gy65.h @@ -0,0 +1,161 @@ +/* + * Author: Yevgeniy Kiveisha + * Copyright (c) 2014 Intel Corporation. + * + * Credits to Adafruit. + * Based on Adafruit BMP085 library. + * + * 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 ADDR 0x77 // device address + +// registers address +#define BMP085_ULTRALOWPOWER 0 +#define BMP085_STANDARD 1 +#define BMP085_HIGHRES 2 +#define BMP085_ULTRAHIGHRES 3 +#define BMP085_CAL_AC1 0xAA // R Calibration data (16 bits) +#define BMP085_CAL_AC2 0xAC // R Calibration data (16 bits) +#define BMP085_CAL_AC3 0xAE // R Calibration data (16 bits) +#define BMP085_CAL_AC4 0xB0 // R Calibration data (16 bits) +#define BMP085_CAL_AC5 0xB2 // R Calibration data (16 bits) +#define BMP085_CAL_AC6 0xB4 // R Calibration data (16 bits) +#define BMP085_CAL_B1 0xB6 // R Calibration data (16 bits) +#define BMP085_CAL_B2 0xB8 // R Calibration data (16 bits) +#define BMP085_CAL_MB 0xBA // R Calibration data (16 bits) +#define BMP085_CAL_MC 0xBC // R Calibration data (16 bits) +#define BMP085_CAL_MD 0xBE // R Calibration data (16 bits) + +#define BMP085_CONTROL 0xF4 +#define BMP085_TEMPDATA 0xF6 +#define BMP085_PRESSUREDATA 0xF6 +#define BMP085_READTEMPCMD 0x2E +#define BMP085_READPRESSURECMD 0x34 + +#define HIGH 1 +#define LOW 0 + +namespace upm { + +/** + * @brief C++ API for GY65 chip (Atmospheric Pressure Sensor) + * + * This file defines the gy65 C++ interface for libgy65 + * + * @snippet gy65.cxx Interesting + */ +class GY65 { + public: + /** + * Instanciates a GY65 object + * + * @param bus number of used bus + * @param devAddr addres of used i2c device + */ + GY65 (int bus, int devAddr, uint8_t mode = BMP085_ULTRAHIGHRES); + + /** + * GY65 object destructor, basicaly it close i2c connection. + */ + ~GY65 (); + + /** + * Return calculated pressure + */ + int32_t getPressure (); + + /** + * + * Get raw pressure data + */ + int32_t getPressureRaw (); + + /** + * Get raw temperature data from chip + */ + int16_t getTemperatureRaw (); + + /** + * Return calculated temperature + */ + float getTemperature (); + + /** + * With given absolute altitude sea level can be calculated + * + * @param altitudeMeters altitude + */ + int32_t getSealevelPressure(float altitudeMeters = 0); + + /** + * With given sea level altitude in meters can be calculated + * + * @param sealevelPressure Sea level + */ + float getAltitude (float sealevelPressure = 101325); + + /** + * Calculation of B5 (check spec for more information) + * + * @param UT + */ + int32_t computeB5 (int32_t UT); + + /** + * Read two bytes register + * + * @param reg address of a register + */ + uint16_t i2cReadReg_16 (int reg); + + /** + * Write to one byte register + * + * @param reg address of a register + * @param value byte to be written + */ + maa_result_t i2cWriteReg (uint8_t reg, uint8_t value); + + /** + * Read one byte register + * + * @param reg address of a register + */ + uint8_t i2cReadReg_8 (int reg); + + private: + std::string m_name; + + int m_controlAddr; + int m_bus; + maa_i2c_context m_i2ControlCtx; + + uint8_t oversampling; + int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; + uint16_t ac4, ac5, ac6; +}; + +} diff --git a/src/gy65/jsupm_gy65.i b/src/gy65/jsupm_gy65.i new file mode 100644 index 0000000..ac5cba6 --- /dev/null +++ b/src/gy65/jsupm_gy65.i @@ -0,0 +1,7 @@ +%module jsupm_gy65 + +%{ + #include "gy65.h" +%} + +%include "gy65.h" diff --git a/src/gy65/pyupm_gy65.i b/src/gy65/pyupm_gy65.i new file mode 100644 index 0000000..f2e134f --- /dev/null +++ b/src/gy65/pyupm_gy65.i @@ -0,0 +1,10 @@ +%module pyupm_gy65 + +%include "stdint.i" + +%feature("autodoc", "3"); + +%include "gy65.h" +%{ + #include "gy65.h" +%} -- 2.7.4