diff --git a/src/si7005/CMakeLists.txt b/src/si7005/CMakeLists.txt new file mode 100644 index 00000000..6aaec974 --- /dev/null +++ b/src/si7005/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(..) +set (libname "si7005") +set (libdescription "upm SI7005") +set (module_src ${libname}.cxx mraa-utils.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/si7005/jsupm_si7005.i b/src/si7005/jsupm_si7005.i new file mode 100644 index 00000000..9af5003c --- /dev/null +++ b/src/si7005/jsupm_si7005.i @@ -0,0 +1,8 @@ +%module jsupm_si7005 +%include "../upm.i" + +%{ + #include "si7005.h" +%} + +%include "si7005.h" diff --git a/src/si7005/mraa-utils.cxx b/src/si7005/mraa-utils.cxx new file mode 100644 index 00000000..3c12561d --- /dev/null +++ b/src/si7005/mraa-utils.cxx @@ -0,0 +1,72 @@ +/* + * Author: Henry Bruce + * 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 "mraa-utils.h" +#include "mraa/gpio.hpp" + + #define UPM_THROW(msg) throw std::runtime_error(std::string(__FUNCTION__) + ": " + (msg)) + +void MraaUtils::setGpio(int pin, int level) +{ +/* + mraa_result_t status = MRAA_ERROR_NO_RESOURCES; + mraa_gpio_context gpio = mraa_gpio_init(pin); + if (gpio != NULL) + { + mraa_gpio_dir(gpio, MRAA_GPIO_OUT); + status = mraa_gpio_write(gpio, level); + mraa_gpio_close(gpio); + } + return status; +*/ + mraa::Gpio gpio(pin); + gpio.dir(mraa::DIR_OUT); + if (gpio.write(level) != mraa::SUCCESS) + UPM_THROW("gpio write failed"); +} + + +int MraaUtils::getGpio(int pin) +{ +/* + mraa_result_t status = MRAA_ERROR_NO_RESOURCES; + mraa_gpio_context gpio = mraa_gpio_init(pin); + if (gpio != NULL) + { + status = mraa_gpio_dir(gpio, MRAA_GPIO_IN); + int value = mraa_gpio_read(gpio); + if (value != -1) + *level = value; + else + status = MRAA_ERROR_NO_RESOURCES; + mraa_gpio_close(gpio); + } + return status; +*/ + mraa::Gpio gpio(pin); + gpio.dir(mraa::DIR_IN); + return gpio.read(); +} + + diff --git a/src/si7005/mraa-utils.h b/src/si7005/mraa-utils.h new file mode 100644 index 00000000..f9e6acc3 --- /dev/null +++ b/src/si7005/mraa-utils.h @@ -0,0 +1,37 @@ +/* + * Author: Henry Bruce + * 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. + */ + +#pragma once + +#include "mraa/types.h" + +class __attribute__ ((visibility("hidden"))) MraaUtils +{ +public: + static void setGpio(int pin, int level); + static int getGpio(int pin); +}; + + + diff --git a/src/si7005/pyupm_si7005.i b/src/si7005/pyupm_si7005.i new file mode 100644 index 00000000..a6e67ff8 --- /dev/null +++ b/src/si7005/pyupm_si7005.i @@ -0,0 +1,11 @@ +%module pyupm_si7005 +%include "../upm.i" + +%include "stdint.i" + +%feature("autodoc", "3"); + +%include "si7005.h" +%{ + #include "si7005.h" +%} diff --git a/src/si7005/si7005.cxx b/src/si7005/si7005.cxx new file mode 100644 index 00000000..b8403008 --- /dev/null +++ b/src/si7005/si7005.cxx @@ -0,0 +1,207 @@ +/* + * Author: Scott Ware + * 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 + +#include "mraa-utils.h" +#include "si7005.h" + +/* REGISTER ADDRESSES */ +#define SI7005_REG_STATUS ( 0x00 ) +#define SI7005_REG_DATA_LENGTH ( 2 ) +#define SI7005_REG_DATA_START ( 0x01 ) +#define SI7005_REG_DATA_HIGH ( 0 ) +#define SI7005_REG_DATA_LOW ( 1 ) +#define SI7005_REG_CONFIG ( 0x03 ) +#define SI7005_REG_ID ( 0x11 ) + +/* STATUS REGISTER */ +#define SI7005_STATUS_NOT_READY ( 0x01 ) + +/* CONFIG REGISTER */ +#define SI7005_CONFIG_START ( 0x01 ) +#define SI7005_CONFIG_HEAT ( 0x02 ) +#define SI7005_CONFIG_HUMIDITY ( 0x00 ) +#define SI7005_CONFIG_TEMPERATURE ( 0x10 ) +#define SI7005_CONFIG_FAST ( 0x20 ) +#define SI7005_CONFIG_RESET ( 0x00 ) + +/* ID REGISTER */ +#define SI7005_ID ( 0x50 ) + +/* COEFFICIENTS */ +#define SI7005_TEMPERATURE_OFFSET ( 50 ) +#define SI7005_TEMPERATURE_SLOPE ( 32 ) +#define SI7005_HUMIDITY_OFFSET ( 24 ) +#define SI7005_HUMIDITY_SLOPE ( 16 ) +#define A0 ( -4.7844 ) +#define A1 ( 0.4008 ) +#define A2 ( -0.00393 ) +#define Q0 ( 0.1973 ) +#define Q1 ( 0.00237 ) + +/* MISCELLANEOUS */ +#define SI7005_WAKE_UP_TIME ( 15000 ) + +using namespace upm; + +SI7005::SI7005 (int bus, int pin) { + + m_controlAddr = SI7005_ADDRESS; + m_bus = bus; + m_pin = pin; + last_temperature = 25.0; + config_reg = SI7005_CONFIG_RESET; + + // Disable chip until we need to do something with it + MraaUtils::setGpio(m_pin, 1); + m_i2c = new mraa::I2c(m_bus); + status = m_i2c->address(m_controlAddr); + if (!isAvailable()) + UPM_THROW("config failure"); +} + +SI7005::~SI7005() { + delete m_i2c; +} + +uint16_t +SI7005::getTemperatureRaw () { + return getMeasurement( SI7005_CONFIG_TEMPERATURE ); +} + +int +SI7005::getTemperatureCelcius () { + uint16_t rawTemperature = getTemperatureRaw(); + rawTemperature = ((rawTemperature >> 2) & 0xFFFF); + last_temperature = ((float)rawTemperature) / SI7005_TEMPERATURE_SLOPE - SI7005_TEMPERATURE_OFFSET; + return static_cast(last_temperature + 0.5); +} + +uint16_t +SI7005::getHumidityRaw () { + return getMeasurement( SI7005_CONFIG_HUMIDITY ); +} + +int +SI7005::getHumidityRelative () { + uint16_t rawHumidity = getHumidityRaw(); + rawHumidity = ((rawHumidity >> 4) & 0xFFFF); + float linearHumidity = ((float)rawHumidity) / SI7005_HUMIDITY_SLOPE - SI7005_HUMIDITY_OFFSET; + linearHumidity -= A2 * linearHumidity * linearHumidity + A1 * linearHumidity + A0; + linearHumidity += ( last_temperature - 30 ) * ( Q1 * linearHumidity + Q0 ); + return static_cast(linearHumidity + 0.5); +} + + +uint16_t SI7005::getMeasurement(uint8_t configValue) { + + uint16_t rawData; + uint8_t data[SI7005_REG_DATA_LENGTH]; + uint8_t measurementStatus; + + // Enable the sensor + MraaUtils::setGpio(m_pin, 0); + + // Wait for sensor to wake up + usleep(SI7005_WAKE_UP_TIME); + + // Setup config register + m_i2c->address(m_controlAddr); + status = m_i2c->writeReg(SI7005_REG_CONFIG, SI7005_CONFIG_START | configValue | config_reg); + + // FIXME: readReg() returns 0 on failure which is same as "reading ready" status + // FIXME: no timeout if device never gets to "reading ready" status + // Wait for the measurement to finish + measurementStatus = SI7005_STATUS_NOT_READY; + while ( measurementStatus == SI7005_STATUS_NOT_READY ) { + measurementStatus = m_i2c->readReg(SI7005_REG_STATUS); + } + + // Read data registers + int length = m_i2c->readBytesReg(SI7005_REG_DATA_START, data, SI7005_REG_DATA_LENGTH); + + // Disable the sensor + MraaUtils::setGpio(m_pin, 1); + + // Check we got the data we need + if(length != SI7005_REG_DATA_LENGTH) + UPM_THROW("read error"); + + // Merge MSB and LSB + rawData = ((uint16_t)( data[SI7005_REG_DATA_LOW] & 0xFFFF )) + ( (uint16_t)(( data[SI7005_REG_DATA_HIGH] & 0xFFFF ) << 8 )); + + return rawData; +} + +bool +SI7005::isConfigured() { + return status == mraa::SUCCESS; +} + +bool +SI7005::isAvailable( ) +{ + // Enable the sensor + MraaUtils::setGpio(m_pin, 0); + + // Wait for sensor to wake up + usleep(SI7005_WAKE_UP_TIME); + + // Read id register + m_i2c->address(m_controlAddr); + uint8_t deviceID = m_i2c->readReg(SI7005_REG_ID); + + // Disable the sensor + MraaUtils::setGpio(m_pin, 1); + + return (( deviceID & SI7005_ID) == SI7005_ID ); +} + +void +SI7005::enableHeater( ) +{ + config_reg |= SI7005_CONFIG_HEAT; +} + +void +SI7005::disableHeater( ) +{ + config_reg ^= SI7005_CONFIG_HEAT; +} + +void +SI7005::enableFastConversionMode( ) +{ + config_reg |= SI7005_CONFIG_FAST; +} + +void +SI7005::disableFastConversionMode( ) +{ + config_reg ^= SI7005_CONFIG_FAST; +} diff --git a/src/si7005/si7005.h b/src/si7005/si7005.h new file mode 100644 index 00000000..f5718631 --- /dev/null +++ b/src/si7005/si7005.h @@ -0,0 +1,143 @@ +/* + * Author: Scott Ware + * 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. + */ +#pragma once + +#include + +#include "upm/iTemperatureSensor.h" +#include "upm/iHumiditySensor.h" + +/* ADDRESS AND NOT_FOUND VALUE */ +#define SI7005_ADDRESS ( 0x40 ) +#define SI7005_NOT_FOUND ( 0x00 ) + + +namespace upm { + +/** + * @brief Si7005 digital I2C humidity and temperature sensor library + * @defgroup si7005 libupm-si7005 + * @ingroup i2c silabs temp itemperaturesensor + */ + +/** + * @brief C++ API for SI7005 sensor (Humidity And Temperature Sensor) + * + * The Silicon Labs Si7005 + * [SI7005](https://www.silabs.com/Support%20Documents/TechnicalDocs/Si7005.pdf) + * is a digital relative humidity and temperature sensor. + * + * @library si7005 + * @sensor si7005 + * @comname Silicon Labs Si7005 LED lighting controller + * @altname Si7005 + * @type temp + * @man silabs + * @con i2c + * @if itemperaturesensor + + */ +class SI7005 : public ITemperatureSensor, public IHumiditySensor { + public: + /** + * Instantiates a SI7005 object + * + * @param bus number of used bus + * @param devAddr address of used i2c device + * @param pin mraa gpio number for chip select pin + */ + SI7005 (int bus, int pin); + + /** + * SI7005 object destructor. + */ + ~SI7005 (); + + /** + * Get temperature measurement. + */ + uint16_t getTemperatureRaw (); + + /** + * Get temperature measurement. + */ + int getTemperatureCelcius (); + + /** + * Get relative humidity measurement. + */ + uint16_t getHumidityRaw (); + + /** + * Get relative humidity measurement. + */ + int getHumidityRelative (); + /** + * Returns whether the sensor is configured. + */ + bool isConfigured(); + + /** + * Returns sensor module name + */ + const char* getModuleName() { return "si7005"; } + + /** + * Detects the sensor to ensure it is connected as required. + */ + bool isAvailable(); + + /** + * Enables the integrated heating element. + */ + void enableHeater(); + + /** + * Disables the integrated heating element. + */ + void disableHeater(); + + /** + * Enables fast conversion mode. + */ + void enableFastConversionMode(); + + /** + * Enables fast conversion mode. + */ + void disableFastConversionMode(); + + private: + int m_controlAddr; + int m_bus; + int m_pin; + mraa::I2c* m_i2c; + mraa::Result status; + uint8_t config_reg; + float last_temperature; + + uint16_t getMeasurement(uint8_t configValue); +}; + +}