227 lines
7.2 KiB
C++
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 |