CO2, humidity, and temperature sensor
Diff: SCD30.cpp
- 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