CO2, humidity, and temperature sensor
SCD30.cpp
- Committer:
- mcm
- Date:
- 2021-05-07
- Revision:
- 2:0d0174b46fd3
- Parent:
- 0:c0b0ed4e6574
File content as of revision 2:0d0174b46fd3:
/** * @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; }