c2-utopia/lib/RTIMULib/RTPressureBMP180.cpp

227 lines
7.2 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// This file is part of RTIMULib-Arduino
//
// Copyright (c) 2014-2015, richards-tech
//
// 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 "RTPressureBMP180.h"
#if defined(BMP180)
RTPressureBMP180::RTPressureBMP180(RTIMUSettings *settings) : RTPressure(settings)
{
m_validReadings = false;
}
RTPressureBMP180::~RTPressureBMP180()
{
}
bool RTPressureBMP180::pressureInit()
{
unsigned char result;
unsigned char data[22];
m_pressureAddr = m_settings->m_I2CPressureAddress;
// check ID of chip
if (!I2Cdev::readBytes(m_pressureAddr, BMP180_REG_ID, 1, &result))
return false;
if (result != BMP180_ID) {
return false;
}
// get calibration data
if (!I2Cdev::readBytes(m_pressureAddr, BMP180_REG_AC1, 22, data))
return false;
m_AC1 = (int16_t)(((uint16_t)data[0]) << 8) + (uint16_t)data[1];
m_AC2 = (int16_t)(((uint16_t)data[2]) << 8) + (uint16_t)data[3];
m_AC3 = (int16_t)(((uint16_t)data[4]) << 8) + (uint16_t)data[4];
m_AC4 = (((uint16_t)data[6]) << 8) + (uint16_t)data[7];
m_AC5 = (((uint16_t)data[8]) << 8) + (uint16_t)data[9];
m_AC6 = (((uint16_t)data[10]) << 8) + (uint16_t)data[11];
m_B1 = (int16_t)(((uint16_t)data[12]) << 8) + (uint16_t)data[13];
m_B2 = (int16_t)(((uint16_t)data[14]) << 8) + (uint16_t)data[15];
m_MB = (int16_t)(((uint16_t)data[16]) << 8) + (uint16_t)data[17];
m_MC = (int16_t)(((uint16_t)data[18]) << 8) + (uint16_t)data[19];
m_MD = (int16_t)(((uint16_t)data[20]) << 8) + (uint16_t)data[21];
m_state = BMP180_STATE_IDLE;
m_oss = BMP180_SCO_PRESSURECONV_UHR;
return true;
}
bool RTPressureBMP180::pressureRead(float &latestPressure, float &latestTemperature)
{
latestPressure = 0;
latestTemperature = 0;
if (m_state == BMP180_STATE_IDLE) {
// start a temperature conversion
if (!I2Cdev::writeByte(m_pressureAddr, BMP180_REG_SCO, BMP180_SCO_TEMPCONV)) {
return false;
} else {
m_state = BMP180_STATE_TEMPERATURE;
}
}
pressureBackground();
if (m_validReadings) {
latestTemperature = m_temperature;
latestPressure = m_pressure;
}
return true;
}
void RTPressureBMP180::pressureBackground()
{
uint8_t data[2];
switch (m_state) {
case BMP180_STATE_IDLE:
break;
case BMP180_STATE_TEMPERATURE:
if (!I2Cdev::readBytes(m_pressureAddr, BMP180_REG_SCO, 1, data)) {
break;
}
if ((data[0] & 0x20) == 0x20)
break; // conversion not finished
if (!I2Cdev::readBytes(m_pressureAddr, BMP180_REG_RESULT, 2, data)) {
m_state = BMP180_STATE_IDLE;
break;
}
m_rawTemperature = (((uint16_t)data[0]) << 8) | (uint16_t)data[1];
data[0] = 0x34 + (m_oss << 6);
if (!I2Cdev::writeBytes(m_pressureAddr, BMP180_REG_SCO, 1, data)) {
m_state = BMP180_STATE_IDLE;
break;
}
m_state = BMP180_STATE_PRESSURE;
break;
case BMP180_STATE_PRESSURE:
if (!I2Cdev::readBytes(m_pressureAddr, BMP180_REG_SCO, 1, data)) {
break;
}
if ((data[0] & 0x20) == 0x20)
break; // conversion not finished
if (!I2Cdev::readBytes(m_pressureAddr, BMP180_REG_RESULT, 2, data)) {
m_state = BMP180_STATE_IDLE;
break;
}
m_rawPressure = (((uint16_t)data[0]) << 8) | (uint16_t)data[1];
if (!I2Cdev::readBytes(m_pressureAddr, BMP180_REG_XLSB, 1, data)) {
m_state = BMP180_STATE_IDLE;
break;
}
// call this function for testing only
// should give T = 150 (15.0C) and pressure 6996 (699.6hPa)
// setTestData();
int32_t pressure = ((((uint32_t)(m_rawPressure)) << 8) + (uint32_t)(data[0])) >> (8 - m_oss);
m_state = BMP180_STATE_IDLE;
// calculate compensated temperature
int32_t X1 = ((m_rawTemperature - (int32_t)m_AC6) * (int32_t)m_AC5) / 32768;
if ((X1 + m_MD) == 0) {
break;
}
int32_t X2 = ((int32_t)m_MC * 2048) / (X1 + (int32_t)m_MD);
int32_t B5 = X1 + X2;
m_temperature = (RTFLOAT)((B5 + 8) / 16) / (RTFLOAT)10;
// calculate compensated pressure
int32_t B6 = B5 - 4000;
// printf("B6 = %d\n", B6);
X1 = (m_B2 * ((B6 * B6) / 4096)) / 2048;
// printf("X1 = %d\n", X1);
X2 = (m_AC2 * B6) / 2048;
// printf("X2 = %d\n", X2);
int32_t X3 = X1 + X2;
// printf("X3 = %d\n", X3);
int32_t B3 = (((m_AC1 * 4 + X3) << m_oss) + 2) / 4;
// printf("B3 = %d\n", B3);
X1 = (m_AC3 * B6) / 8192;
// printf("X1 = %d\n", X1);
X2 = (m_B1 * ((B6 * B6) / 4096)) / 65536;
// printf("X2 = %d\n", X2);
X3 = ((X1 + X2) + 2) / 4;
// printf("X3 = %d\n", X3);
uint32_t B4 = (m_AC4 * (uint32_t)(X3 + 32768)) / 32768;
// printf("B4 = %d\n", B4);
uint32_t B7 = (uint32_t)(pressure - B3) * (50000 >> m_oss);
// printf("B7 = %d\n", B7);
int32_t p;
if (B7 < 0x80000000)
p = (B7 * 2) / B4;
else
p = (B7 / B4) * 2;
// printf("p = %d\n", p);
X1 = (p / 256) * (p / 256);
// printf("X1 = %d\n", X1);
X1 = (X1 * 3038) / 65536;
// printf("X1 = %d\n", X1);
X2 = (-7357 * p) / 65536;
// printf("X2 = %d\n", X2);
m_pressure = (RTFLOAT)(p + (X1 + X2 + 3791) / 16) / (RTFLOAT)100; // the extra 100 factor is to get 1hPa units
m_validReadings = true;
// printf("UP = %d, P = %f, UT = %d, T = %f\n", m_rawPressure, m_pressure, m_rawTemperature, m_temperature);
break;
}
}
void RTPressureBMP180::setTestData()
{
m_AC1 = 408;
m_AC2 = -72;
m_AC3 = -14383;
m_AC4 = 32741;
m_AC5 = 32757;
m_AC6 = 23153;
m_B1 = 6190;
m_B2 = 4;
m_MB = -32767;
m_MC = -8711;
m_MD = 2868;
m_rawTemperature = 27898;
m_rawPressure = 23843;
}
#endif