CO2, humidity, and temperature sensor

Revision:
2:0d0174b46fd3
Parent:
0:c0b0ed4e6574
--- a/SCD30.cpp	Fri May 07 11:46:50 2021 +0000
+++ b/SCD30.cpp	Fri May 07 13:06:14 2021 +0000
@@ -0,0 +1,1046 @@
+/**
+ * @brief       SCD30.c
+ * @details     CO2, humidity and temperature sensor.
+ *              Functions file.
+ *
+ *
+ * @return      N/A
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A
+ * @pre         This code belongs to Nimbus Centre ( http://www.nimbus.cit.ie ).
+ */
+
+ #include "SCD30.h"
+
+
+SCD30::SCD30 ( PinName sda, PinName scl, uint32_t addr, uint32_t freq )
+    : _i2c         ( sda, scl )
+    , _SCD30_Addr  ( addr )
+{
+    _i2c.frequency( freq );
+}
+
+
+SCD30::~SCD30()
+{
+}
+
+
+
+/**
+ * @brief       SCD30_TriggerContinuousMeasurement    ( uint16_t  )
+ * @details     It triggers continuous measurement with or without ambient pressure compensation.
+ *
+ * @param[in]    pressure_compensation: 0 (desactivates pressure compensation) or [700 - 1400]. Pressure in mBar.
+ *
+ * @param[out]   N/A
+ *
+ *
+ * @return      Status of SCD30_TriggerContinuousMeasurement.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_TriggerContinuousMeasurement ( uint16_t pressure_compensation )
+{
+  char      cmd[5] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_TRIGGERS_CONTINUOUS_MEASUREMENT >> 8U );
+  cmd[1]   =  (char)( SCD30_TRIGGERS_CONTINUOUS_MEASUREMENT & 0xFF );
+  cmd[2]   =  (char)( pressure_compensation >> 8U );
+  cmd[3]   =  (char)( pressure_compensation & 0xFF );
+  cmd[4]   =  SCD30_CalculateI2C_CRC8 ( pressure_compensation );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_StopContinuousMeasurement    ( void )
+ * @details     It stops the continuous measurement.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   N/A
+ *
+ *
+ * @return      Status of SCD30_StopContinuousMeasurement.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_StopContinuousMeasurement ( void )
+{
+  char      cmd[2] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_STOP_CONTINUOUS_MEASUREMENT >> 8U );
+  cmd[1]   =  (char)( SCD30_STOP_CONTINUOUS_MEASUREMENT & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_SetMeasurementInterval    ( uint16_t )
+ * @details     It sets the measurement interval.
+ *
+ * @param[in]    measurement_interval:  [2 - 1800]. Interval in seconds.
+ *
+ * @param[out]   N/A
+ *
+ *
+ * @return      Status of SCD30_SetMeasurementInterval.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_SetMeasurementInterval ( uint16_t measurement_interval )
+{
+  char      cmd[5] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_STOP_CONTINUOUS_MEASUREMENT >> 8U );
+  cmd[1]   =  (char)( SCD30_STOP_CONTINUOUS_MEASUREMENT & 0xFF );
+  cmd[2]   =  (char)( measurement_interval >> 8U );
+  cmd[3]   =  (char)( measurement_interval & 0xFF );
+  cmd[4]   =  SCD30_CalculateI2C_CRC8 ( measurement_interval );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_GetMeasurementInterval    ( uint16_t* )
+ * @details     It sets the measurement interval.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   measurement_interval:  Value. Interval in seconds.
+ *
+ *
+ * @return      Status of SCD30_GetMeasurementInterval.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_GetMeasurementInterval ( uint16_t* measurement_interval )
+{
+  char      cmd[4] = { 0U };
+  uint8_t   aux_crc;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_STOP_CONTINUOUS_MEASUREMENT >> 8U );
+  cmd[1]   =  (char)( SCD30_STOP_CONTINUOUS_MEASUREMENT & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  *measurement_interval   =   cmd[0];
+  *measurement_interval <<=   8U;
+  *measurement_interval  |=   cmd[1];
+
+  /* Check the CRC   */
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( *measurement_interval );
+
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( ( aux_crc - cmd[2] ) == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_GetDataReadyStatus    ( SCD30_get_ready_status_bit_t* )
+ * @details     It gets the status when the data is ready to be read.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   status:          Data ready status.
+ *
+ *
+ * @return      Status of SCD30_GetDataReadyStatus.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_GetDataReadyStatus ( SCD30_get_ready_status_bit_t* status )
+{
+  char      cmd[3] = { 0U };
+  uint8_t   aux_crc;
+  uint16_t  aux_res;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_GET_DATA_READY_STATUS >> 8U );
+  cmd[1]   =  (char)( SCD30_GET_DATA_READY_STATUS & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  aux_res   =  cmd[0];
+  aux_res <<=   8U;
+  aux_res  |=  cmd[1];
+  
+  *status   =  (SCD30_get_ready_status_bit_t)aux_res;
+
+  /* Check the CRC   */
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( *status );
+
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( ( aux_crc - cmd[2] ) == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_ReadRawMeasurement    ( SCD30_raw_output_data_t* )
+ * @details     It gets all the raw data.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   raw_data:        All the data in raw values.
+ *
+ *
+ * @return      Status of SCD30_ReadRawMeasurement.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_ReadRawMeasurement ( SCD30_raw_output_data_t* raw_data )
+{
+  char      cmd[18] = { 0U };
+  uint16_t  aux_seed;
+  uint8_t   aux_crc;
+  uint8_t   aux_return = 0U;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_READ_MEASUREMENT >> 8U );
+  cmd[1]   =  (char)( SCD30_READ_MEASUREMENT & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  raw_data->co2_mmsb                  =   cmd[0];
+  raw_data->co2_mlsb                  =   cmd[1];
+  raw_data->co2_mmsb_mlsb_crc         =   cmd[2];
+
+  /* Check the CRC   */
+  aux_seed   =  raw_data->co2_mmsb;
+  aux_seed <<=  8U;
+  aux_seed  |=  raw_data->co2_mlsb;
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( aux_seed );
+
+  if ( ( aux_crc - raw_data->co2_mmsb_mlsb_crc ) != 0U )
+  {
+    aux_return++;
+  }
+
+  raw_data->co2_lmsb                  =   cmd[3];
+  raw_data->co2_llsb                  =   cmd[4];
+  raw_data->co2_lmsb_llsb_crc         =   cmd[5];
+
+  /* Check the CRC   */
+  aux_seed   =  raw_data->co2_lmsb;
+  aux_seed <<=  8U;
+  aux_seed  |=  raw_data->co2_llsb;
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( aux_seed );
+
+  if ( ( aux_crc - raw_data->co2_lmsb_llsb_crc ) != 0U )
+  {
+    aux_return++;
+  }
+
+  raw_data->temperature_mmsb          =   cmd[6];
+  raw_data->temperature_mlsb          =   cmd[7];
+  raw_data->temperature_mmsb_mlsb_crc =   cmd[8];
+
+  /* Check the CRC   */
+  aux_seed   =  raw_data->temperature_mmsb;
+  aux_seed <<=  8U;
+  aux_seed  |=  raw_data->temperature_mlsb;
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( aux_seed );
+
+  if ( ( aux_crc - raw_data->temperature_mmsb_mlsb_crc ) != 0U )
+  {
+    aux_return++;
+  }
+
+  raw_data->temperature_lmsb          =   cmd[9];
+  raw_data->temperature_llsb          =   cmd[10];
+  raw_data->temperature_lmsb_llsb_crc =   cmd[11];
+
+  /* Check the CRC   */
+  aux_seed   =  raw_data->temperature_lmsb;
+  aux_seed <<=  8U;
+  aux_seed  |=  raw_data->temperature_llsb;
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( aux_seed );
+
+  if ( ( aux_crc - raw_data->temperature_lmsb_llsb_crc ) != 0U )
+  {
+    aux_return++;
+  }
+
+  raw_data->humidity_mmsb             =   cmd[12];
+  raw_data->humidity_mlsb             =   cmd[13];
+  raw_data->humidity_mmsb_mlsb_crc    =   cmd[14];
+
+  /* Check the CRC   */
+  aux_seed   =  raw_data->humidity_mmsb;
+  aux_seed <<=  8U;
+  aux_seed  |=  raw_data->humidity_mlsb;
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( aux_seed );
+
+  if ( ( aux_crc - raw_data->humidity_mmsb_mlsb_crc ) != 0U )
+  {
+    aux_return++;
+  }
+
+  raw_data->humidity_lmsb             =   cmd[15];
+  raw_data->humidity_llsb             =   cmd[16];
+  raw_data->humidity_lmsb_llsb_crc    =   cmd[17];
+
+  /* Check the CRC   */
+  aux_seed   =  raw_data->humidity_lmsb;
+  aux_seed <<=  8U;
+  aux_seed  |=  raw_data->humidity_llsb;
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( aux_seed );
+
+  if ( ( aux_crc - raw_data->humidity_lmsb_llsb_crc ) != 0U )
+  {
+    aux_return++;
+  }
+
+  
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( aux_return == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_ReadMeasurement    ( SCD30_output_data_t* )
+ * @details     It gets all the data.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   data:            All the data.
+ *
+ *
+ * @return      Status of SCD30_ReadMeasurement.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         This function updates the raw data too.
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_ReadMeasurement ( SCD30_output_data_t* data )
+{
+  SCD30::SCD30_status_t  aux;
+  uint32_t               data_aux;
+
+  /* Read all the raw data  */
+  aux      =  SCD30_ReadRawMeasurement ( (SCD30_raw_output_data_t*)&data->raw );
+
+    
+  /* Parse the data  */
+  data_aux    =   data->raw.co2_mmsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.co2_mlsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.co2_lmsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.co2_llsb;
+  
+  data->processed.co2  =  *(float*)&data_aux;
+
+  data_aux    =   data->raw.temperature_mmsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.temperature_mlsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.temperature_lmsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.temperature_llsb;
+  
+  data->processed.temperature  =  *(float*)&data_aux;
+
+  data_aux    =   data->raw.humidity_mmsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.humidity_mlsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.humidity_lmsb;
+  data_aux  <<=   8U;
+  data_aux   |=   data->raw.humidity_llsb;
+  
+  data->processed.humidity  =  *(float*)&data_aux;
+
+
+  return   aux;
+}
+
+
+
+/**
+ * @brief       SCD30_SetContinuousASC    ( SCD30_continuous_auto_selfcal_t )
+ * @details     It enables/disables the continuous automatic self-calibration.
+ *
+ * @param[in]    asc:             Continuous automatic self-calibration value.
+ *
+ * @param[out]   N/A
+ *
+ *
+ * @return      Status of SCD30_SetContinuousASC.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_SetContinuousASC ( SCD30_continuous_auto_selfcal_t asc )
+{
+  char      cmd[5] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_CONTINUOUS_AUTOMATIC_SELF_CALIBRATION >> 8U );
+  cmd[1]   =  (char)( SCD30_CONTINUOUS_AUTOMATIC_SELF_CALIBRATION & 0xFF );
+  cmd[2]   =  (char)( asc >> 8U );
+  cmd[3]   =  (char)( asc & 0xFF );
+  cmd[4]   =  SCD30_CalculateI2C_CRC8 ( asc );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_GetContinuousASC    ( SCD30_continuous_auto_selfcal_t* )
+ * @details     It gets the continuous automatic self-calibration bit.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   asc:             Continuous automatic self-calibration value.
+ *
+ *
+ * @return      Status of SCD30_GetContinuousASC.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_GetContinuousASC ( SCD30_continuous_auto_selfcal_t* asc )
+{
+  char      cmd[4] = { 0U };
+  uint8_t   aux_crc;
+  uint16_t  aux_res;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_CONTINUOUS_AUTOMATIC_SELF_CALIBRATION >> 8U );
+  cmd[1]   =  (char)( SCD30_CONTINUOUS_AUTOMATIC_SELF_CALIBRATION & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  aux_res   =   cmd[0];
+  aux_res <<=   8U;
+  aux_res  |=   cmd[1];
+  
+  *asc   =  (SCD30_continuous_auto_selfcal_t)aux_res;
+
+  /* Check the CRC   */
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( *asc );
+
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( ( aux_crc - cmd[2] ) == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_SetForcedRecalibrationValue    ( uint16_t )
+ * @details     It sets the forced recalibration value.
+ *
+ * @param[in]    frc:             Forced recalibration value.
+ *
+ * @param[out]   N/A
+ *
+ *
+ * @return      Status of SCD30_SetForcedRecalibrationValue.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_SetForcedRecalibrationValue ( uint16_t frc )
+{
+  char      cmd[5] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_SET_FORCED_RECALIBRATION >> 8U );
+  cmd[1]   =  (char)( SCD30_SET_FORCED_RECALIBRATION & 0xFF );
+  cmd[2]   =  (char)( frc >> 8U );
+  cmd[3]   =  (char)( frc & 0xFF );
+  cmd[4]   =  SCD30_CalculateI2C_CRC8 ( frc );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_GetForcedRecalibrationValue    ( uint16_t* )
+ * @details     It gets the forced recalibration value.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   frc:             Forced recalibration value.
+ *
+ *
+ * @return      Status of SCD30_GetForcedRecalibrationValue.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_GetForcedRecalibrationValue ( uint16_t* frc )
+{
+  char      cmd[3] = { 0U };
+  uint8_t   aux_crc;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_SET_FORCED_RECALIBRATION >> 8U );
+  cmd[1]   =  (char)( SCD30_SET_FORCED_RECALIBRATION & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  *frc   =   cmd[0];
+  *frc <<=   8U;
+  *frc  |=   cmd[1];
+
+  /* Check the CRC   */
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( *frc );
+
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( ( aux_crc - cmd[2] ) == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_SetTemperatureOffsetValue    ( uint16_t )
+ * @details     It sets the temperature offset value.
+ *
+ * @param[in]    temp_offset:     Temperature offset value.
+ *
+ * @param[out]   N/A
+ *
+ *
+ * @return      Status of SCD30_SetTemperatureOffsetValue.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_SetTemperatureOffsetValue ( uint16_t temp_offset )
+{
+  char      cmd[5] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_SET_TEMPERATURE_OFFSET >> 8U );
+  cmd[1]   =  (char)( SCD30_SET_TEMPERATURE_OFFSET & 0xFF );
+  cmd[2]   =  (char)( temp_offset >> 8U );
+  cmd[3]   =  (char)( temp_offset & 0xFF );
+  cmd[4]   =  SCD30_CalculateI2C_CRC8 ( temp_offset );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_GetTemperatureOffsetValue    ( uint16_t* )
+ * @details     It gets the temperature offset value.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   temp_offset:     Temperature offset value.
+ *
+ *
+ * @return      Status of SCD30_GetTemperatureOffsetValue.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_GetTemperatureOffsetValue ( uint16_t* temp_offset )
+{
+  char      cmd[3] = { 0U };
+  uint8_t   aux_crc;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_SET_FORCED_RECALIBRATION >> 8U );
+  cmd[1]   =  (char)( SCD30_SET_FORCED_RECALIBRATION & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  *temp_offset   =   cmd[0];
+  *temp_offset <<=   8U;
+  *temp_offset  |=   cmd[1];
+
+  /* Check the CRC   */
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( *temp_offset );
+
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( ( aux_crc - cmd[2] ) == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_SetAltitudeCompensationValue    ( uint16_t )
+ * @details     It sets the altitude compensation value.
+ *
+ * @param[in]    alt_comp:        Altitude compensation value.
+ *
+ * @param[out]   N/A
+ *
+ *
+ * @return      Status of SCD30_SetAltitudeCompensationValue.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_SetAltitudeCompensationValue ( uint16_t alt_comp )
+{
+  char      cmd[5] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_SET_ALTITUDE_COMPENSATION >> 8U );
+  cmd[1]   =  (char)( SCD30_SET_ALTITUDE_COMPENSATION & 0xFF );
+  cmd[2]   =  (char)( alt_comp >> 8U );
+  cmd[3]   =  (char)( alt_comp & 0xFF );
+  cmd[4]   =  SCD30_CalculateI2C_CRC8 ( alt_comp );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_GetAltitudeCompensationValue    ( uint16_t* )
+ * @details     It gets the altitude compensation value.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   alt_comp:        Altitude compensation value.
+ *
+ *
+ * @return      Status of SCD30_GetAltitudeCompensationValue.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_GetAltitudeCompensationValue ( uint16_t* alt_comp )
+{
+  char      cmd[3] = { 0U };
+  uint8_t   aux_crc;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_SET_ALTITUDE_COMPENSATION >> 8U );
+  cmd[1]   =  (char)( SCD30_SET_ALTITUDE_COMPENSATION & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  *alt_comp   =   cmd[0];
+  *alt_comp <<=   8U;
+  *alt_comp  |=   cmd[1];
+
+  /* Check the CRC   */
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( *alt_comp );
+
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( ( aux_crc - cmd[2] ) == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_GetFirmwareVersion    ( SCD30_fw_version_t* )
+ * @details     It gets the firmware version value.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   fw:              Firmware version value.
+ *
+ *
+ * @return      Status of SCD30_GetFirmwareVersion.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_GetFirmwareVersion ( SCD30_fw_version_t* fw )
+{
+  char      cmd[3] = { 0U };
+  uint16_t  aux_seed;
+  uint8_t   aux_crc;
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_FIRMWARE_VERSION >> 8U );
+  cmd[1]   =  (char)( SCD30_FIRMWARE_VERSION & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], 2U, false );
+
+  /* Read the register   */
+  aux     |=  _i2c.read ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) );
+  
+  /* Parse the data  */
+  fw->version_major  =   cmd[0];
+  fw->version_minor  =   cmd[1];
+  
+  /* Check the CRC   */
+  aux_seed   =  fw->version_major;
+  aux_seed <<=  8U;
+  aux_seed  |=  fw->version_minor;
+  aux_crc    =  SCD30_CalculateI2C_CRC8 ( aux_seed );
+
+  if ( aux == I2C_SUCCESS )
+  {
+    if ( ( aux_crc - cmd[2] ) == 0U )
+    {
+      return   SCD30_SUCCESS;
+    }
+    else
+    {
+      return   SCD30_DATA_CORRUPTED;
+    }
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_SoftReset    ( void )
+ * @details     It performs a software reset.
+ *
+ * @param[in]    N/A.
+ *
+ * @param[out]   N/A.
+ *
+ *
+ * @return      Status of SCD30_SoftReset.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+SCD30::SCD30_status_t  SCD30::SCD30_SoftReset ( void )
+{
+  char      cmd[2] = { 0U };
+  uint32_t  aux;
+
+  /* Write the register  */
+  cmd[0]   =  (char)( SCD30_SOFTRESET >> 8U );
+  cmd[1]   =  (char)( SCD30_SOFTRESET & 0xFF );
+  aux      =  _i2c.write ( _SCD30_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false );
+ 
+
+
+  if ( aux == I2C_SUCCESS )
+  {
+      return   SCD30_SUCCESS;
+  }
+  else
+  {
+      return   SCD30_FAILURE;
+  }
+}
+
+
+
+/**
+ * @brief       SCD30_CalculateI2C_CRC8    ( uint16_t )
+ * @details     It calculates the I2C checksum calculation (CRC-8).
+ *
+ * @param[in]    seed: Data to calculate the CRC-8.
+ *
+ * @param[out]   N/A.
+ *
+ *
+ * @return      Status of SCD30_CalculateI2C_CRC8.
+ *
+ * @author      Manuel Caballero
+ * @date        07/May/2021
+ * @version     07/May/2021    The ORIGIN
+ * @pre         N/A
+ * @warning     N/A.
+ */
+uint8_t  SCD30::SCD30_CalculateI2C_CRC8 ( uint16_t seed )
+{
+  uint8_t bit;                  
+  uint8_t crc = SCD30_CRC8_INITIALIZATION; 
+
+  // calculates 8-Bit checksum with given polynomial
+ 
+  crc ^= ( seed >> 8U ) & 255U;
+  for(bit = 8U; bit > 0U; --bit)
+  {
+    if( crc & 0x80U )
+    {
+      crc = ( crc << 1U ) ^ SCD30_CRC8_POLYNOMIAL;
+    }
+    else
+    {
+      crc = ( crc << 1U );
+    }
+  }
+ 
+  crc ^= seed & 255U;
+  for( bit = 8U; bit > 0U; --bit )
+  {
+    if( crc & 0x80 )
+    {
+      crc = ( crc << 1U ) ^ SCD30_CRC8_POLYNOMIAL;
+    }
+    else
+    {
+      crc = ( crc << 1U );
+    }
+  }
+    
+  return crc;
+}
\ No newline at end of file