Digital Pressure Sensor
BMP180.cpp
- Committer:
- mcm
- Date:
- 2018-09-11
- Revision:
- 3:60816c745222
- Parent:
- 2:3a52d110213a
File content as of revision 3:60816c745222:
/** * @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; }