I2C HUMIDITY AND TEMPERATURE SENSOR
SI7021.cpp
- Committer:
- mcm
- Date:
- 2018-02-05
- Revision:
- 3:75cece7f7329
- Parent:
- 2:18c159179b08
File content as of revision 3:75cece7f7329:
/** * @brief SI7021.h * @details I2C HUMIDITY AND TEMPERATURE SENSOR. * Header file. * * * @return NA * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre N/A. * @warning N/A * @pre This code belongs to AqueronteBlog ( http://unbarquero.blogspot.com ). */ #include "SI7021.h" SI7021::SI7021 ( PinName sda, PinName scl, uint32_t addr, uint32_t freq ) : _i2c ( sda, scl ) , _SI7021_Addr ( addr ) { _i2c.frequency( freq ); } SI7021::~SI7021() { } /** * @brief SI7021_Conf ( SI7021_measurement_resolution_t , SI7021_heater_t ) * * @details It configures the device: resolution and heater. * * @param[in] myResolution: Resolution for RH and temperature. * @param[in] myHeater: Enable/Disable heater. * * @param[out] N/A. * * * @return Status of SI7021_Conf. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre Except where noted, reserved register bits will always read back as “1,” and are not affected by write operations. For * future compatibility, it is recommended that prior to a write operation, registers should be read. Then the values read * from the RSVD bits should be written back unchanged during the write operation * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_Conf ( SI7021_measurement_resolution_t myResolution, SI7021_heater_t myHeater ) { char cmd[] = { SI7021_READ_RH_T_USER_REGISTER_1, 0 }; uint32_t aux = 0; // Read USER REGISTER to mask it aux = _i2c.write ( _SI7021_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _SI7021_Addr, &cmd[1], 1 ); // Update USER REGISTER according to user requirements // Resolution cmd[1] &= ~SI7021_RESOLUTION_MASK; cmd[1] |= myResolution; // Hater cmd[1] &= ~SI7021_HTRE_MASK; cmd[1] |= myHeater; // Update USER REGISTER cmd[0] = SI7021_WRITE_RH_T_USER_REGISTER_1; aux = _i2c.write ( _SI7021_Addr, &cmd[0], 2, false ); if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_SoftReset ( void ) * * @details It resets the device by software. * * @param[in] N/A * * @param[out] N/A. * * * @return Status of SI7021_SoftReset. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre N/A * @warning The user MUST keep in mind that the device will be * available after 5ms ( typically, 15ms maximum ) * The user MUST take care of this delay!. */ SI7021::SI7021_status_t SI7021::SI7021_SoftReset ( void ) { char cmd = SI7021_RESET; uint32_t aux = 0; aux = _i2c.write ( _SI7021_Addr, &cmd, 1, false ); // The user needs to wait for certain period of time before communicating // with the device again. if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_GetElectronicSerialNumber ( SI7021_vector_data_t* ) * * @details It gets the electronic serial number. * * @param[in] N/A * * @param[out] mySerialNumber: The Electronic Serial Number. * * * @return Status of SI7021_GetElectronicSerialNumber. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre This function does NOT check the CRC * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_GetElectronicSerialNumber ( SI7021_vector_data_t* mySerialNumber ) { char cmd[] = { SI7021_READ_ELECTRONIC_ID_FIRST_BYTE_CMD1, SI7021_READ_ELECTRONIC_ID_FIRST_BYTE_CMD2, 0, 0, 0, 0, 0, 0 }; uint32_t aux = 0; // Read Electronic Serial Number. First Access aux = _i2c.write ( _SI7021_Addr, &cmd[0], 2, true ); aux = _i2c.read ( _SI7021_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); mySerialNumber->ElectronicSerialNumber_MSB = ( ( cmd[0] << 24 ) | ( cmd[2] << 16 ) | ( cmd[4] << 8 ) | cmd[6] ); // Read Electronic Serial Number. Second Access cmd[0] = SI7021_READ_ELECTRONIC_ID_SECOND_BYTE_CMD1; cmd[1] = SI7021_READ_ELECTRONIC_ID_SECOND_BYTE_CMD2; aux = _i2c.write ( _SI7021_Addr, &cmd[0], 2, true ); aux = _i2c.read ( _SI7021_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); mySerialNumber->ElectronicSerialNumber_LSB = ( ( cmd[0] << 24 ) | ( cmd[2] << 16 ) | ( cmd[4] << 8 ) | cmd[6] ); if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_GetFirmwareRevision ( SI7021_vector_data_t* ) * * @details It gets the firmware revision. * * @param[in] N/A * * @param[out] myFirmwareRevision: The firmware revision. * * * @return Status of SI7021_GetFirmwareRevision. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre N/A. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_GetFirmwareRevision ( SI7021_vector_data_t* myFirmwareRevision ) { char cmd[] = { SI7021_READ_FIRMWARE_VERSION_CMD1, SI7021_READ_FIRMWARE_VERSION_CMD2 }; uint32_t aux = 0; // Read the firmware revision aux = _i2c.write ( _SI7021_Addr, &cmd[0], 2, true ); aux = _i2c.read ( _SI7021_Addr, &cmd[0], 1 ); myFirmwareRevision->FirmwareRevision = cmd[0]; if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_SetHeaterCurrent ( char ) * * @details It sets the heater current. * * @param[in] myHeaterCurrent: New heater current value * * @param[out] N/A. * * * @return Status of SI7021_SetHeaterCurrent. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre N/A. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_SetHeaterCurrent ( char myHeaterCurrent ) { char cmd[] = { SI7021_READ_HEATER_CONTROL_REGISTER, 0 }; uint32_t aux = 0; // myHeaterCurrent MUST be from 0 ( 0x00 ) to 15 ( 0x0F ) if ( myHeaterCurrent <= 15 ) { // Read the heater control register aux = _i2c.write ( _SI7021_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _SI7021_Addr, &cmd[1], 1 ); // Mask the data cmd[1] &= 0xF0; // Update the value cmd[0] = SI7021_WRITE_HEATER_CONTROL_REGISTER; cmd[1] |= myHeaterCurrent; aux = _i2c.write ( _SI7021_Addr, &cmd[0], 2, false ); } else return SI7021_FAILURE; if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_TriggerTemperature ( SI7021_master_mode_t ) * * @details It performs a new temperature measurement. * * @param[in] myMode: HOLD/NO HOLD mode. * * @param[out] N/A * * * @return Status of SI7021_TriggerTemperature. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre N/A. * @warning The user MUST respect the total conversion time. * 14-bit temperature: 7ms ( 10.8ms max ) * 13-bit temperature: 4ms ( 6.2ms max ) * 12-bit temperature: 2.4ms ( 3.8ms max ) * 11-bit temperature: 1.5ms ( 2.4ms max ) */ SI7021::SI7021_status_t SI7021::SI7021_TriggerTemperature ( SI7021_master_mode_t myMode ) { char cmd = 0; bool myI2C_stop = false; uint32_t aux = 0; // Check the mode if it is HOLD MASTER MODE, then not generate a stop bit if ( myMode == SI7021_HOLD_MASTER_MODE ) { cmd = SI7021_MEASURE_TEMPERATURE_HOLD_MASTER_MODE; myI2C_stop = true; } else { cmd = SI7021_MEASURE_TEMPERATURE_NO_HOLD_MASTER_MODE; myI2C_stop = false; } aux = _i2c.write ( _SI7021_Addr, &cmd, 1, myI2C_stop ); // NOTE: The user has to respect the total conversion time! if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_ReadTemperature ( SI7021_vector_data_t* ) * * @details It reads the temperature. * * @param[in] myMode: HOLD/NO HOLD mode. * * @param[out] myTemperature: The current temperature * * * @return Status of SI7021_ReadTemperature. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre SI7021_TriggerTemperature MUST be called first. This function does NOT * read CRC byte. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_ReadTemperature ( SI7021_vector_data_t* myTemperature ) { char cmd[] = { 0, 0 }; uint32_t aux = 0; aux = _i2c.read ( _SI7021_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); // Check if the is a valid data if ( ( cmd[1] & 0x02 ) == 0x00 ) { // Parse the data myTemperature->Temperature = ( ( cmd[0] << 8 ) | cmd[1] ); myTemperature->Temperature *= 175.72; myTemperature->Temperature /= 65536.0; myTemperature->Temperature -= 46.85; } else return SI7021_FAILURE; if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_ReadRawTemperatureFromRH ( SI7021_vector_data_t* ) * * @details It reads the raw temperature. * * @param[in] N/A. * * @param[out] myTemperature: The current temperature * * * @return Status of SI7021_ReadRawTemperatureFromRH. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre SI7021_TriggerHumidity MUST be called first. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_ReadRawTemperatureFromRH ( SI7021_vector_data_t* myTemperature ) { char cmd[] = { SI7021_READ_TEMPERATURE_VALUE_FROM_PREVIOUS_RH_MEASUREMENT, 0 }; uint32_t aux = 0; aux = _i2c.write ( _SI7021_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _SI7021_Addr, &cmd[0], 2 ); // Check if the is a valid data if ( ( cmd[1] & 0x02 ) == 0x00 ) { // Parse the data myTemperature->Temperature = ( ( cmd[0] << 8 ) | cmd[1] ); } else return SI7021_FAILURE; if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_ReadTemperatureFromRH ( SI7021_vector_data_t* ) * * @details It reads the temperature. * * @param[in] N/A. * * @param[out] myTemperature: The current temperature * * * @return Status of SI7021_ReadTemperatureFromRH. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre SI7021_TriggerHumidity MUST be called first. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_ReadTemperatureFromRH ( SI7021_vector_data_t* myTemperature ) { char cmd[] = { SI7021_READ_TEMPERATURE_VALUE_FROM_PREVIOUS_RH_MEASUREMENT, 0 }; uint32_t aux = 0; aux = _i2c.write ( _SI7021_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _SI7021_Addr, &cmd[0], 2 ); // Check if the is a valid data if ( ( cmd[1] & 0x02 ) == 0x00 ) { // Parse the data myTemperature->Temperature = ( ( cmd[0] << 8 ) | cmd[1] ); myTemperature->Temperature *= 175.72; myTemperature->Temperature /= 65536.0; myTemperature->Temperature -= 46.85; } else return SI7021_FAILURE; if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_TriggerHumidity ( SI7021_master_mode_t ) * * @details It performs a new relative humidity measurement. * * @param[in] myMode: HOLD/NO HOLD MASTER mode. * * @param[out] N/A * * * @return Status of SI7021_TriggerHumidity. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre Initiating a RH measurement will also automatically initiate a temperature measurement. * The total conversion time will be tCONV(RH) + tCONV(T). * @warning The user MUST respect the total conversion time. * 12-bit RH: 10ms ( 12ms max ) * 11-bit RH: 5.8ms ( 7ms max ) * 10-bit RH: 3.7ms ( 4.5ms max ) * 8-bit RH: 2.6ms ( 3.1ms max ) */ SI7021::SI7021_status_t SI7021::SI7021_TriggerHumidity ( SI7021_master_mode_t myMode ) { char cmd = myMode; uint32_t aux = 0; bool myI2C_stop = false; // Check the mode if it is HOLD MASTER MODE, then not generate a stop bit if ( myMode == SI7021_HOLD_MASTER_MODE ) { cmd = SI7021_MEASURE_RELATIVE_HUMIDITY_HOLD_MASTER_MODE; myI2C_stop = true; } else { cmd = SI7021_MEASURE_RELATIVE_HUMIDITY_NO_HOLD_MASTER_MODE; myI2C_stop = false; } aux = _i2c.write ( _SI7021_Addr, &cmd, 1, myI2C_stop ); // NOTE: The user has to respect the total conversion time! if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_ReadHumidity ( SI7021_vector_data_t* ) * * @details It reads the relative humidity. * * @param[in] N/A. * * @param[out] myHumidity: The current HUMIDITY * * * @return Status of SI7021_ReadHumidity. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre SI7021_TriggerHumidity MUST be called first. This function does NOT * read CRC byte. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_ReadHumidity ( SI7021_vector_data_t* myHumidity ) { char cmd[] = { 0, 0 }; uint32_t aux = 0; aux = _i2c.read ( _SI7021_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); // Check if the is a valid data if ( ( cmd[1] & 0x03 ) == 0x02 ) { // Parse the data myHumidity->RelativeHumidity = ( ( cmd[0] << 8 ) | cmd[1] ); myHumidity->RelativeHumidity *= 125.0; myHumidity->RelativeHumidity /= 65536.0; myHumidity->RelativeHumidity -= 6.0; } else return SI7021_FAILURE; if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_ReadRawHumidity ( SI7021_vector_data_t* ) * * @details It reads the raw relative humidity. * * @param[in] N/A. * * @param[out] myHumidity: The current HUMIDITY * * * @return Status of SI7021_ReadRawHumidity. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre SI7021_TriggerHumidity MUST be called first. This function does NOT * read CRC byte. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_ReadRawHumidity ( SI7021_vector_data_t* myHumidity ) { char cmd[] = { 0, 0 }; uint32_t aux = 0; aux = _i2c.read ( _SI7021_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); // Check if the is a valid data if ( ( cmd[1] & 0x03 ) == 0x02 ) { // Parse the data myHumidity->RelativeHumidity = ( ( cmd[0] << 8 ) | cmd[1] ); } else return SI7021_FAILURE; if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; } /** * @brief SI7021_GetBatteryStatus ( SI7021_vector_data_t* ) * * @details It reads the raw relative humidity. * * @param[in] N/A. * * @param[out] myBatteryStatus: The current battery status * * * @return Status of SI7021_GetBatteryStatus. * * * @author Manuel Caballero * @date 5/February/2018 * @version 5/February/2018 The ORIGIN * @pre N/A. * @warning N/A. */ SI7021::SI7021_status_t SI7021::SI7021_GetBatteryStatus ( SI7021_vector_data_t* myBatteryStatus ) { char cmd = SI7021_READ_RH_T_USER_REGISTER_1; uint32_t aux = 0; aux = _i2c.write ( _SI7021_Addr, &cmd, 1, true ); aux = _i2c.read ( _SI7021_Addr, &cmd, 1 ); myBatteryStatus->BatteryStatus = ( SI7021_vdds_status_t )( cmd & SI7021_VDDS_STATUS_MASK ); if ( aux == I2C_SUCCESS ) return SI7021_SUCCESS; else return SI7021_FAILURE; }