Infrared Thermopile Sensor in Chip-Scale Package

TMP006.cpp

Committer:
mcm
Date:
2018-12-11
Revision:
4:56398c14bf1f
Parent:
3:f632c66b30df

File content as of revision 4:56398c14bf1f:

/**
 * @brief       TMP006.c
 * @details     Infrared Thermopile Sensor in Chip-Scale Package.
 *              Functions file.
 *
 *
 * @return      N/A
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018    The ORIGIN
 * @pre         N/A
 * @warning     N/A
 * @pre         This code belongs to Nimbus Centre ( http://www.nimbus.cit.ie ). All rights reserved.
 */

#include "TMP006.h"


TMP006::TMP006 ( PinName sda, PinName scl, uint32_t addr, uint32_t freq )
    : _i2c          ( sda, scl )
    , _TMP006_Addr  ( addr )
{
    _i2c.frequency( freq );
}


TMP006::~TMP006()
{
}


/**
 * @brief       TMP006_GetManufacturerID ( TMP006_data_t* )
 *
 * @details     It gets the manufacturer ID.
 *
 * @param[in]    N/A
 *
 * @param[out]   myManufacturerID:  Manufacturer ID.
 *
 *
 * @return       Status of TMP006_GetManufacturerID.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_GetManufacturerID ( TMP006_data_t* myManufacturerID )
{
    char     cmd[]    =    { 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_MANUFACTURER_ID;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );


    /* Parse data   */
    myManufacturerID->ManufacturerID   =   ( cmd[0] << 8U );
    myManufacturerID->ManufacturerID  |=   cmd[1];




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_GetDeviceID ( TMP006_data_t* )
 *
 * @details     It gets the device ID.
 *
 * @param[in]    N/A.
 *
 * @param[out]   myDeviceID:      Device ID.
 *
 *
 * @return       Status of TMP006_GetDeviceID.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_GetDeviceID ( TMP006_data_t* myDeviceID )
{
    char     cmd[]    =    { 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_DEVICE_ID;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );


    /* Parse data   */
    myDeviceID->DeviceID   =   ( cmd[0] << 8U );
    myDeviceID->DeviceID  |=   cmd[1];




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_ReadConfigurationRegister ( TMP006_data_t* )
 *
 * @details     It reads the configuration register.
 *
 * @param[in]    N/A
 *
 * @param[out]   myConfReg:       Configuration register value.
 *
 *
 * @return       Status of TMP006_ReadConfigurationRegister.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_ReadConfigurationRegister ( TMP006_data_t* myConfReg )
{
    char     cmd[]    =    { 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );


    /* Parse data   */
    myConfReg->ConfigurationRegister   =   ( cmd[0] << 8U );
    myConfReg->ConfigurationRegister  |=   cmd[1];




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_SoftwareReset ( void )
 *
 * @details     It performs a software reset.
 *
 * @param[in]    N/A.
 *
 * @param[out]   N/A.
 *
 *
 * @return       Status of TMP006_SoftwareReset.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_SoftwareReset ( void )
{
    char     cmd[]    =    { 0U, 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], 2U );

    /* Mask the option and update the register   */
    cmd[2]   =   cmd[1];
    cmd[1]   =   ( ( cmd[0] & ~RST_BIT_MASK ) | RST_SOFTWARE_RESET );
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_SetModeOperation ( TMP006_mod_t )
 *
 * @details     It sets mode of operation.
 *
 * @param[in]    myModeOpreation: Mode of operation ( low power mode ).
 *
 * @param[out]   N/A.
 *
 *
 * @return       Status of TMP006_SetModeOperation.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_SetModeOperation ( TMP006_mod_t myModeOpreation )
{
    char     cmd[]    =    { 0U, 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], 2U );

    /* Mask the option and update the register   */
    cmd[2]   =   cmd[1];
    cmd[1]   =   ( ( cmd[0] & ~MOD_MASK ) | myModeOpreation );
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_SetConversionRate ( TMP006_cr_t )
 *
 * @details     It sets conversion rate.
 *
 * @param[in]    myConversionRate:  Conversion rate.
 *
 * @param[out]   N/A.
 *
 *
 * @return       Status of TMP006_SetConversionRate.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_SetConversionRate ( TMP006_cr_t myConversionRate )
{
    char     cmd[]    =    { 0U, 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], 2U );

    /* Mask the option and update the register   */
    cmd[2]   =   cmd[1];
    cmd[1]   =   ( ( cmd[0] & ~CR_MASK ) | myConversionRate );
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_SetnDRDY_EnableBit ( TMP006_en_t )
 *
 * @details     It sets conversion rate.
 *
 * @param[in]    myEnableBit:     Enable bit pin behaviour.
 *
 * @param[out]   N/A.
 *
 *
 * @return       Status of TMP006_SetnDRDY_EnableBit.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_SetnDRDY_EnableBit ( TMP006_en_t myEnableBit )
{
    char     cmd[]    =    { 0U, 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], 2U );

    /* Mask the option and update the register   */
    cmd[2]   =   cmd[1];
    cmd[1]   =   ( ( cmd[0] & ~EN_MASK ) | myEnableBit );
    cmd[0]   =   TMP006_CONFIGURATION;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_GetRawTemperature ( TMP006_data_t* )
 *
 * @details     It reads raw temperature ( T_DIE ) value.
 *
 * @param[in]    N/A
 *
 * @param[out]   myRawTemperature:  Raw temperature value.
 *
 *
 * @return       Status of TMP006_GetRawTemperature.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_GetRawTemperature ( TMP006_data_t* myRawTemperature )
{
    char     cmd[]    =    { 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_LOCAL_TEMPERATURE;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );

    /* Parse the data   */
    myRawTemperature->TemperatureRegister   = cmd[0];
    myRawTemperature->TemperatureRegister <<= 8U;
    myRawTemperature->TemperatureRegister  |= cmd[1];
    
    /* Temperature register is configured as a 14-bit value   */
    myRawTemperature->TemperatureRegister >>= 2U;




    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_GetRawSensorVoltage ( TMP006_data_t* )
 *
 * @details     It reads raw sensor voltage result ( V_SENSOR ) register.
 *
 * @param[in]    N/A.
 *
 * @param[out]   myRawVoltage:    Raw sensor voltage value.
 *
 *
 * @return       Status of TMP006_GetRawSensorVoltage.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     N/A.
 */
TMP006::TMP006_status_t  TMP006::TMP006_GetRawSensorVoltage ( TMP006_data_t* myRawVoltage )
{
    char     cmd[]    =    { 0U, 0U };
    uint32_t aux;


    /* Read the register */
    cmd[0]   =   TMP006_SENSOR_VOLTAGE;
    aux      =   _i2c.write ( _TMP006_Addr, &cmd[0], 1U, true );
    aux      =   _i2c.read  ( _TMP006_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );

    /* Parse the data   */
    myRawVoltage->SensorVoltageResultRegister   = cmd[0];
    myRawVoltage->SensorVoltageResultRegister <<= 8U;
    myRawVoltage->SensorVoltageResultRegister  |= cmd[1];
    



    if ( aux == I2C_SUCCESS )
    {
        return   TMP006_SUCCESS;
    }
    else
    {
        return   TMP006_FAILURE;
    }
}



/**
 * @brief       TMP006_CalculateSensorVoltage ( TMP006_data_t* )
 *
 * @details     It calculates the real sensor voltage ( V_SENSOR ) value.
 *
 * @param[in]    SensorVoltageResultRegister:  Raw sensor voltage value.
 *
 * @param[out]   myV_sensor:                   Real sensor voltage value.
 *
 *
 * @return       Status of TMP006_CalculateSensorVoltage.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     11/December/2018   Bug fixed. Negative values are taken into consideration
 *              10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     TMP006_GetRawSensorVoltage function must be called first.
 */
TMP006::TMP006_status_t  TMP006::TMP006_CalculateSensorVoltage ( TMP006_data_t* myV_sensor  )
{
    uint8_t   myDataPosNeg  =   0U;
    uint16_t  aux  =   0U;

    aux  =   myV_sensor->SensorVoltageResultRegister;

    /* Check if the sensor voltage value is negative, MSB = 1  */
    if ( ( aux & 0x8000 ) == 0x8000 )
    {
      aux   =  ~aux;
      aux  +=   1U;
      
      myDataPosNeg   =   1U;
    }


    /* Parse the data   */
    myV_sensor->V_Sensor   =  (double)( aux * SVOL_1LSB / 1000000000.0 );                        
    
    if ( myDataPosNeg == 1U )
    {
      myV_sensor->V_Sensor  *=  -1.0;
    }


    return   TMP006_SUCCESS;
}



/**
 * @brief       TMP006_CalculateTemperature ( TMP006_data_t* )
 *
 * @details     It calculates the real temperature ( T_DIE ) value.
 *
 * @param[in]    myRawTemperature:  Raw temperature value.
 *
 * @param[out]   myTemperature:     Real Temperature value.
 *
 *
 * @return       Status of TMP006_CalculateTemperature.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     11/December/2018   Bug fixed. Negative values are taken into consideration
 *              10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     TMP006_GetRawTemperature function must be called first.
 */
TMP006::TMP006_status_t  TMP006::TMP006_CalculateTemperature ( TMP006_data_t* myTemperature  )
{
    uint8_t   myDataPosNeg  =   0U;
    uint16_t  aux  =   0U;

    aux  =   myTemperature->TemperatureRegister;

    /* Check if the temperature value is negative, MSB = 1  */
    if ( ( aux & 0x2000 ) == 0x2000 )
    {
      aux   =  ~aux;
      aux  +=   1U;
      
      myDataPosNeg   =   1U;
    }


    /* Parse the data   */
    myTemperature->TemperatureC   =  (float)( aux * TEMP_1LSB );                        // Celsius degrees
    
    if ( myDataPosNeg == 1U )
    {
      myTemperature->TemperatureC  *=  -1.0;
    }
    
    myTemperature->TemperatureK   =  (float)( myTemperature->TemperatureC + 273.15 );   // Kelvins degrees



    return   TMP006_SUCCESS;
}



/**
 * @brief       TMP006_CalculateObjectTemperature ( TMP006_data_t* )
 *
 * @details     It calculates the real temperature ( T_DIE ) value.
 *
 * @param[in]    myRawTemperature:  Raw temperature value.
 *
 * @param[out]   myObjTemperature:  Real Object Temperature value.
 *
 *
 * @return       Status of TMP006_CalculateObjectTemperature.
 *
 *
 * @author      Manuel Caballero
 * @date        10/December/2018
 * @version     11/December/2018   Precision was increased from float to double
 *              10/December/2018   The ORIGIN
 * @pre         N/A.
 * @warning     TMP006_CalculateTemperature and TMP006_GetRawSensorVoltage functions must be called first.
 */
TMP006::TMP006_status_t  TMP006::TMP006_CalculateObjectTemperature ( TMP006_data_t* myObjTemperature  )
{
    double     s       =   0.0;
    double     v_os    =   0.0;
    double     f_v_obj =   0.0;

    /* Claculate the sensitivity of the thermopile sensor  */
    s  =   myObjTemperature->s0 * ( 1.0 + A1 * ( myObjTemperature->TemperatureK - T_REF ) + A2 * pow( ( myObjTemperature->TemperatureK - T_REF ), (double)2U ) );

    /* Calculate the offset voltage  */
    v_os   =   B0 + B1 * (double)( myObjTemperature->TemperatureK - T_REF ) + B2 * pow( ( myObjTemperature->TemperatureK - T_REF ), (double)2U );
    
    /* Model the Seebeck coefficients of the thermopile  */
    f_v_obj  =   ( myObjTemperature->V_Sensor - v_os ) + C2 * pow( ( myObjTemperature->V_Sensor - v_os ), (double)2U );
    
    /* Relates the radiant transfer of IR energy between the target object and the TMP006 and the conducted heat in the thermopile in the TMP006  */ 
    myObjTemperature->ObjectTemperatureK    =  sqrt( sqrt( pow( (double)myObjTemperature->TemperatureK, (double)4U ) + (double)( f_v_obj / s ) ) );
    myObjTemperature->ObjectTemperatureC    =  ( myObjTemperature->ObjectTemperatureK - 273.15 );



    return   TMP006_SUCCESS;
}