upm/src/si7005/si7005.cxx
Jon Trulson baec9966f0 spelling: correct many misspellings of celsius
Signed-off-by: Jon Trulson <jtrulson@ics.com>
2016-07-12 17:42:01 -06:00

204 lines
6.0 KiB
C++

/*
* Author: Scott Ware <scott.r.ware@intel.com>
* 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 <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include "mraa-utils.hpp"
#include "si7005.hpp"
/* 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::getTemperatureCelsius () {
uint16_t rawTemperature = getTemperatureRaw();
rawTemperature = ((rawTemperature >> 2) & 0xFFFF);
last_temperature = ((float)rawTemperature) / SI7005_TEMPERATURE_SLOPE - SI7005_TEMPERATURE_OFFSET;
return static_cast<int>(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<int>(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::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;
}