Revision:
2:3a52d110213a
Parent:
0:8481133a48ba
--- a/BMP180.cpp	Tue Sep 11 10:18:23 2018 +0000
+++ b/BMP180.cpp	Tue Sep 11 10:34:58 2018 +0000
@@ -0,0 +1,465 @@
+/**
+ * @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;
+}