File content as of revision 2:3a52d110213a:
/**
* @brief BMP180.cpp
* @details Digital Pressure Sensor.
* Functions file.
*
*
* @return N/A
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre N/A
* @warning N/A
* @pre This code belongs to Nimbus Centre ( http://www.nimbus.cit.ie ).
*/
#include "BMP180.h"
BMP180::BMP180 ( PinName sda, PinName scl, uint32_t addr, uint32_t freq )
: _i2c ( sda, scl )
, _BMP180_Addr ( addr )
{
_i2c.frequency( freq );
}
BMP180::~BMP180()
{
}
/**
* @brief BMP180_GetID ( BMP180_chip_id_data_t* )
* @details It gets the chip-ID.
*
* @param[in] N/A.
*
* @param[out] myID: Chip-ID
*
*
* @return Status of BMP180_GetID.
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre It must be 0x55.
* @warning N/A.
*/
BMP180::BMP180_status_t BMP180::BMP180_GetID ( BMP180_chip_id_data_t* myID )
{
char cmd = 0U;
uint32_t aux;
/* Get ID */
cmd = BMP180_ID;
aux = _i2c.write ( _BMP180_Addr, &cmd, 1U, true );
aux = _i2c.read ( _BMP180_Addr, (char*)&myID->id, 1U );
if ( aux == I2C_SUCCESS ) {
return BMP180_SUCCESS;
} else {
return BMP180_FAILURE;
}
}
/**
* @brief BMP180_SoftReset ( void )
* @details It performs a soft reset.
*
* @param[in] N/A.
*
* @param[out] N/A
*
*
* @return Status of BMP180_SoftReset.
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre N/A
* @warning N/A.
*/
BMP180::BMP180_status_t BMP180::BMP180_SoftReset ( void )
{
char cmd[] = { 0, 0 };
uint32_t aux;
cmd[0] = BMP180_SOFT;
cmd[1] = SOFT_SOFT_RESET;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
if ( aux == I2C_SUCCESS ) {
return BMP180_SUCCESS;
} else {
return BMP180_FAILURE;
}
}
/**
* @brief BMP180_Get_Cal_Param ( BMP180_calibration_data_t* )
* @details It reads the calibration data.
*
* @param[in] N/A.
*
* @param[out] myCalibrationData: Calibration data from the sensor.
*
*
* @return Status of BMP180_Get_Cal_Param.
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre N/A
* @warning N/A
*/
BMP180::BMP180_status_t BMP180::BMP180_Get_Cal_Param ( BMP180_calibration_data_t* myCalibrationData )
{
char cmd[22] = { 0U };
uint32_t aux;
/* Read out all calibration data from the sensor ( auto-increment ) */
cmd[0] = BMP180_AC1_MSB;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], 1U, true );
aux = _i2c.read ( _BMP180_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
/* Parse the data */
myCalibrationData->ac1 = cmd[0];
myCalibrationData->ac1 <<= 8U;
myCalibrationData->ac1 |= cmd[1];
myCalibrationData->ac2 = cmd[2];
myCalibrationData->ac2 <<= 8U;
myCalibrationData->ac2 |= cmd[3];
myCalibrationData->ac3 = cmd[4];
myCalibrationData->ac3 <<= 8U;
myCalibrationData->ac3 |= cmd[5];
myCalibrationData->ac4 = cmd[6];
myCalibrationData->ac4 <<= 8U;
myCalibrationData->ac4 |= cmd[7];
myCalibrationData->ac5 = cmd[8];
myCalibrationData->ac5 <<= 8U;
myCalibrationData->ac5 |= cmd[9];
myCalibrationData->ac6 = cmd[10];
myCalibrationData->ac6 <<= 8U;
myCalibrationData->ac6 |= cmd[11];
myCalibrationData->b1 = cmd[12];
myCalibrationData->b1 <<= 8U;
myCalibrationData->b1 |= cmd[13];
myCalibrationData->b2 = cmd[14];
myCalibrationData->b2 <<= 8U;
myCalibrationData->b2 |= cmd[15];
myCalibrationData->mb = cmd[16];
myCalibrationData->mb <<= 8U;
myCalibrationData->mb |= cmd[17];
myCalibrationData->mc = cmd[18];
myCalibrationData->mc <<= 8U;
myCalibrationData->mc |= cmd[19];
myCalibrationData->md = cmd[20];
myCalibrationData->md <<= 8U;
myCalibrationData->md |= cmd[21];
if ( aux == I2C_SUCCESS ) {
return BMP180_SUCCESS;
} else {
return BMP180_FAILURE;
}
}
/**
* @brief BMP180_Get_UT ( BMP180_uncompensated_data_t* )
* @details It reads uncompensated temperature value.
*
* @param[in] N/A.
*
* @param[out] myUT: Uncompensated temperature value.
*
*
* @return Status of BMP180_Get_UT.
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre This function checks the bit SCO until the conversion is complete instead of
* 4.5ms.
* @warning N/A
*/
BMP180::BMP180_status_t BMP180::BMP180_Get_UT ( BMP180_uncompensated_data_t* myUT )
{
char cmd[] = { 0U, 0U };
uint32_t myTimeout = 0U;
uint32_t aux;
/* Read out the uncompensated temperature data */
cmd[0] = BMP180_CTRL_MEAS;
cmd[1] = BMP180_TRIGGER_TEMPERATURE;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
/* Wait until conversion is complete or timeout */
myTimeout = 0x232323;
do {
cmd[0] = BMP180_CTRL_MEAS;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], 1U, true );
aux = _i2c.read ( _BMP180_Addr, &cmd[0], 1U );
myTimeout--;
} while ( ( ( cmd[0] & CTRL_MEAS_SCO_MASK ) == CTRL_MEAS_SCO_CONVERSION_IN_PROGRESS ) && ( myTimeout > 0U ) );
/* Parse the data only if not timeout */
if ( myTimeout > 0U ) {
cmd[0] = BMP180_OUT_MSB;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], 1U, true );
aux = _i2c.read ( _BMP180_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
/* Parse the data */
myUT->ut = cmd[0];
myUT->ut <<= 8U;
myUT->ut |= cmd[1];
}
if ( ( aux == I2C_SUCCESS ) && ( myTimeout > 0U ) ) {
return BMP180_SUCCESS;
} else {
return BMP180_FAILURE;
}
}
/**
* @brief BMP180_Get_UP ( BMP180_pressure_resolution_t , BMP180_uncompensated_data_t* )
* @details It reads uncompensated pressure value.
*
* @param[in] myPressureResolutionMode: Resolution mode.
*
* @param[out] myUP: Uncompensated pressure value.
*
*
* @return Status of BMP180_Get_UP.
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre This function checks the bit SCO until the conversion is complete instead of
* the delay depending of the resolution mode:
* - Ultra low power mode 4.5ms ( max. )
* - Standard mode 7.5ms ( max. )
* - High resolution mode 13.5ms ( max. )
* - Ultra high resolution mode 25.5ms ( max. )
* @warning N/A
*/
BMP180::BMP180_status_t BMP180::BMP180_Get_UP ( BMP180_pressure_resolution_t myPressureResolutionMode, BMP180_uncompensated_data_t* myUP )
{
char cmd[] = { 0U, 0U, 0U };
uint32_t myTimeout = 0U;
uint32_t aux;
/* Read out the uncompensated pressure data according to the chosen resolution mode */
cmd[0] = BMP180_CTRL_MEAS;
cmd[1] = ( BMP180_TRIGGER_PRESSURE | myPressureResolutionMode ) ;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], 2U, false );
/* Wait until conversion is complete or timeout */
myTimeout = 0x232323;
do {
cmd[0] = BMP180_CTRL_MEAS;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], 1U, true );
aux = _i2c.read ( _BMP180_Addr, &cmd[0], 1U );
myTimeout--;
} while ( ( ( cmd[0] & CTRL_MEAS_SCO_MASK ) == CTRL_MEAS_SCO_CONVERSION_IN_PROGRESS ) && ( myTimeout > 0U ) );
/* Parse the data only if not timeout */
if ( myTimeout > 0U ) {
cmd[0] = BMP180_OUT_MSB;
aux = _i2c.write ( _BMP180_Addr, &cmd[0], 1U, true );
aux = _i2c.read ( _BMP180_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
/* Parse the data */
myUP->up = cmd[0];
myUP->up <<= 8U;
myUP->up |= cmd[1];
myUP->up <<= 8U;
myUP->up |= cmd[2];
myUP->up >>= ( 8U - ( myPressureResolutionMode >> 6U ) );
}
if ( ( aux == I2C_SUCCESS ) && ( myTimeout > 0U ) ) {
return BMP180_SUCCESS;
} else {
return BMP180_FAILURE;
}
}
/**
* @brief BMP180_Get_Temperature ( BMP180_calibration_data_t , BMP180_uncompensated_data_t )
* @details It calculates true temperature.
*
* @param[in] myCalibrationData: Calibration data.
* @param[in] myUT: Uncompensated temperature value.
*
* @param[out] N/A.
*
*
* @return True temperature.
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre True temperature in 0.1 C.
* @pre It is sufficient to measure the temperature only once per second and use this value for all pressure measurements during the same period.
* @warning This function should have been called at least once: BMP180_Get_Cal_Param.
* @warning This function should have been called before: BMP180_Get_UT.
*/
BMP180::BMP180_temperature_data_t BMP180::BMP180_Get_Temperature ( BMP180_calibration_data_t myCalibrationData, BMP180_uncompensated_data_t myUT )
{
int32_t x1 = 0, x2 = 0;
BMP180_temperature_data_t myTrueData;
/* Calculate X1 */
x1 = ( myUT.ut - myCalibrationData.ac6 ) * myCalibrationData.ac5 / 32768.0f;
/* Calculate X2 */
x2 = ( myCalibrationData.mc * 2048.0f );
x2 /= ( x1 + myCalibrationData.md );
/* Calculate B5 */
myTrueData.b5 = ( x1 + x2 );
/* Calculate True Temperature */
myTrueData.temp = ( myTrueData.b5 + 8.0f ) / 16.0f;
return myTrueData;
}
/**
* @brief BMP180_Get_CalPressure ( BMP180_calibration_data_t , BMP180_data_t , BMP180_pressure_resolution_t , BMP180_uncompensated_data_t )
* @details It calculates true pressure.
*
* @param[in] myCalibrationData: Calibration data.
* @param[in] myB5: Temperature parameter value.
* @param[in] myPressureResolutionMode: Resolution mode.
* @param[in] myUP: Uncompensated pressure value.
*
* @param[out] N/A.
*
*
* @return True Pressure.
*
* @author Manuel Caballero
* @date 11/September/2018
* @version 11/September/2018 The ORIGIN
* @pre True temperature in Pa.
* @pre It is sufficient to measure the temperature only once per second and use this value for all pressure measurements during the same period.
* @warning These functions should have been called at least once: BMP180_Get_Cal_Param and BMP180_Get_Temperature.
* @warning This function should have been called before: BMP180_Get_UP.
*/
BMP180::BMP180_pressure_data_t BMP180::BMP180_Get_CalPressure ( BMP180_calibration_data_t myCalibrationData, BMP180_temperature_data_t myB5, BMP180_pressure_resolution_t myPressureResolutionMode, BMP180_uncompensated_data_t myUP )
{
int32_t b6 = 0, x1 = 0, x2 = 0, x3 = 0, b3 = 0;
uint32_t b4 = 0, b7 = 0;
BMP180_pressure_data_t myTrueData;
/* Calculate B6 */
b6 = ( myB5.b5 - 4000.0f );
/* Calculate X1 */
x1 = ( myCalibrationData.b2 * ( b6 * b6 / 4096.0f ) ) / 2048.0f;
/* Calculate X2 */
x2 = myCalibrationData.ac2 * b6 / 4096.0f;
/* Calculate X3 */
x3 = x1 + x2;
/* Calculate B3 */
b3 = ( ( ( ( (long)myCalibrationData.ac1 * 4 + x3 ) << ( myPressureResolutionMode >> 6U ) ) + 2 ) ) / 4.0f;
/* Re-calculate X1 */
x1 = ( myCalibrationData.ac3 * b6 ) / 524288.0f;
/* Re-calculate X2 */
x2 = ( myCalibrationData.b1 * ( b6 * b6 / 4096.0f ) ) / 65536.0f;
/* Re-calculate X3 */
x3 = ( ( x1 + x2 ) + 2.0f ) / 4.0f;
/* Calculate B4 */
b4 = myCalibrationData.ac4 * (unsigned long)( x3 + 32768.0f ) / 32768.0f;
/* Calculate B7 */
b7 = ( (unsigned long)myUP.up - b3 ) * ( 50000 >> ( myPressureResolutionMode >> 6U ) );
if ( b7 < 0x80000000 ) {
myTrueData.press = ( b7 * 2.0f ) / b4;
} else {
myTrueData.press = ( b7 / b4 ) * 2.0f;
}
/* Re-calculate X1 */
x1 = ( myTrueData.press / 256.0f ) * ( myTrueData.press / 256.0f );
x1 = ( x1 * 3038.0f ) / 65536.0f;
/* Re-calculate X2 */
x2 = ( -7357.0f * myTrueData.press ) / 65536.0f;
/* Calculate True Pressure */
myTrueData.press += ( x1 + x2 + 3791.0f ) / 16.0f;
return myTrueData;
}