CO2, humidity, and temperature sensor

SCD30.h

Committer:
mcm
Date:
2021-05-10
Revision:
3:ca833b38050f
Parent:
2:0d0174b46fd3

File content as of revision 3:ca833b38050f:

/**
 * @brief       SCD30.h
 * @details     CO2, humidity and temperature sensor.
 *              Header 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 ).
 */
#ifndef SCD30_H_
#define SCD30_H_

#include "mbed.h"


/**
    Example:

@code
#include "mbed.h"
#include "SCD30.h"

SCD30 mySCD30 ( I2C_SDA, I2C_SCL, SCD30::SCD30_ADDRESS, 100000 );               // I2C_SDA | I2C_SCL
Serial pc     ( USBTX, USBRX );                                                 // tx, rx

DigitalOut  myled   ( LED1 );
Ticker      newAction;


//@brief Constants.


//@brief Variables.
volatile uint32_t myState;                                                      // State that indicates when to perform a new sample


//@brief   FUNCTION PROTOTYPES
void    changeDATA     ( void );


//@brief FUNCTION FOR APPLICATION MAIN ENTRY.
int main()
{
    SCD30::SCD30_status_t aux;
    SCD30::SCD30_data_t   mySCD30_Data;

    pc.baud ( 115200 );

    myled   =   1;
    wait(3);
    myled   =   0;

    // It performs a software reset
    aux  =   mySCD30.SCD30_SoftReset ();
    wait_ms (2000);

    // It gets the firmware version
    aux  =   mySCD30.SCD30_GetFirmwareVersion ( &mySCD30_Data.firmware );
    pc.printf ( "Version Major: %d, Version Minor: %d\r\n", mySCD30_Data.firmware.version_major, mySCD30_Data.firmware.version_minor );

    // It sets two mesurement interval
    mySCD30_Data.measurement_interval  =   2U;
    aux  =   mySCD30.SCD30_SetMeasurementInterval ( mySCD30_Data.measurement_interval );

    // It configures the continuous automatic self-calibration
    mySCD30_Data.asc  =   SCD30::CONTINUOUS_AUTOMATIC_SELF_CALIBRATION_ASC_ACTIVATE;
    aux  =   mySCD30.SCD30_SetContinuousASC ( mySCD30_Data.asc );
    wait_ms(2000);

    // It sets the trigger without pressure compensation
    mySCD30_Data.pressure_compensation  =   0U;
    aux  =   mySCD30.SCD30_TriggerContinuousMeasurement ( mySCD30_Data.pressure_compensation );

    myState  =   0UL;                                                           // Reset the variable
    newAction.attach( &changeDATA, 5U );                                        // the address of the function to be attached ( changeDATA ) and the interval ( 5s )

    // Let the callbacks take care of everything
    while(1) {
        sleep();

        if ( myState == 1UL ) {
            myled = 1U;

            // Trigger to get a new data set
            aux  =   mySCD30.SCD30_TriggerContinuousMeasurement ( mySCD30_Data.pressure_compensation );

            // Wait for a new data value
            do {
                aux  =   mySCD30.SCD30_GetDataReadyStatus ( &mySCD30_Data.status );
                wait_ms (100);
            } while( mySCD30_Data.status == SCD30::GET_READY_STATUS_BIT_DATA_NO_READY );

            // Get all the values
            aux  =   mySCD30.SCD30_ReadMeasurement ( &mySCD30_Data.data );

            // Send data through the UART
            pc.printf ( "CO2: %d ppm, T: %d C, RH: %d %%\r\n", (uint32_t)mySCD30_Data.data.processed.co2, (uint32_t)mySCD30_Data.data.processed.temperature, (uint32_t)mySCD30_Data.data.processed.humidity );

            // Reset the variables
            myState  =   0UL;
            myled    =   0U;
        }
    }
}


// @brief       changeDATA ( void  )
//
// @details     It changes myState variable
//
// @param[in]    N/A
//
// @param[out]   N/A.
//
// @return       N/A.
//
// @author      Manuel Caballero
// @date        07/May/2021
// @version     07/May/2021   The ORIGIN
// @pre         N/A
// @warning     N/A.
void changeDATA ( void )
{
    myState  =   1UL;
}
@endcode
*/


/*!
 Library for the SCD30 CO2, humidity and temperature sensor.
*/
class SCD30
{
public:
    /**
    * @brief   DEFAULT ADDRESS
    */
    typedef enum {
        SCD30_ADDRESS     =   ( 0x61 << 1U )                       /*!<   SCD30 ADDR              */
    } SCD30_address_t;



    /**
      * @brief   COMMAND REGISTERS
      */
    typedef enum {
        SCD30_TRIGGERS_CONTINUOUS_MEASUREMENT       =   0x0010,   /*!<  Triggers continuous measurement. Ambient pressure is optional   */
        SCD30_STOP_CONTINUOUS_MEASUREMENT           =   0x0104,   /*!<  Stop continuous measurement                                     */
        SCD30_SET_MEASUREMENT_INTERVAL              =   0x4600,   /*!<  Set measurement interval for continuous measurement mode        */
        SCD30_GET_DATA_READY_STATUS                 =   0x0202,   /*!<  Data ready status                                               */
        SCD30_READ_MEASUREMENT                      =   0x0300,   /*!<  Reads a single measurement of C02 concentration                 */
        SCD30_CONTINUOUS_AUTOMATIC_SELF_CALIBRATION =   0x5306,   /*!<  Continuous automatic self-calibration can be (de-)activated     */
        SCD30_SET_FORCED_RECALIBRATION              =   0x5204,   /*!<  Forced recalibration (FRC)                                      */
        SCD30_SET_TEMPERATURE_OFFSET                =   0x5403,   /*!<  Temperature offset                                              */
        SCD30_SET_ALTITUDE_COMPENSATION             =   0x5102,   /*!<  Altitude compensation                                           */
        SCD30_FIRMWARE_VERSION                      =   0xD100,   /*!<  Firmware version                                                */
        SCD30_SOFTRESET                             =   0xD304    /*!<  Software reset: Restart the sensor                              */
    } SCD30_command_registers_t;



    /**
      * @brief   GET DATA READY STATUS.
      *           NOTE: N/A.
      */
    /* BIT <0>
     *    NOTE: N/A.
     */
    typedef enum {
        GET_READY_STATUS_BIT_MASK           =   ( 1U << 0U ),   /*!<  BIT mask                                                        */
        GET_READY_STATUS_BIT_DATA_NO_READY  =   ( 0U << 0U ),   /*!<  Measurement is not ready to be read from the sensor             */
        GET_READY_STATUS_BIT_DATA_READY     =   ( 1U << 0U )    /*!<  Measurement is ready to be read from the sensor                 */
    } SCD30_get_ready_status_bit_t;


    /**
      * @brief   CONTINUOUS AUTOMATIC SELF CALIBRATION.
      *           NOTE: N/A.
      */
    /* ASC <0>
     *    NOTE: N/A.
     */
    typedef enum {
        CONTINUOUS_AUTOMATIC_SELF_CALIBRATION_ASC_MASK        =   ( 1U << 0U ),   /*!<  ASC mask                                                        */
        CONTINUOUS_AUTOMATIC_SELF_CALIBRATION_ASC_DEACTIVATE  =   ( 0U << 0U ),   /*!<  Deactivate continuous ASC                                       */
        CONTINUOUS_AUTOMATIC_SELF_CALIBRATION_ASC_ACTIVATE    =   ( 1U << 0U )    /*!<  Activate continuous ASC                                         */
    } SCD30_continuous_auto_selfcal_t;


    /**
      * @brief   CRC-8.
      *           NOTE: Polynomial:     0x31 (x^8 + x^5 + x^4 + 1)
      *                 Initialization: 0xFF
      *                 Final XOR:      0x00.
      */
#define SCD30_CRC8_POLYNOMIAL       0x31                                      /*!<  SCD30 CRC-8: Polynomial                                         */
#define SCD30_CRC8_INITIALIZATION   0xFF                                      /*!<  SCD30 CRC-8: Initialization                                     */
#define SCD30_CRC8_FINAL_XOR        0x00                                      /*!<  SCD30 CRC-8: Final XOR                                          */






#ifndef SCD30_VECTOR_STRUCT_H
#define SCD30_VECTOR_STRUCT_H
    /* Firmware version  */
    typedef struct {
        uint8_t  version_major;
        uint8_t  version_minor;
    } SCD30_fw_version_t;


    /* Raw measurement data  */
    typedef struct {
        uint8_t  co2_mmsb;
        uint8_t  co2_mlsb;
        uint8_t  co2_mmsb_mlsb_crc;

        uint8_t  co2_lmsb;
        uint8_t  co2_llsb;
        uint8_t  co2_lmsb_llsb_crc;

        uint8_t  temperature_mmsb;
        uint8_t  temperature_mlsb;
        uint8_t  temperature_mmsb_mlsb_crc;

        uint8_t  temperature_lmsb;
        uint8_t  temperature_llsb;
        uint8_t  temperature_lmsb_llsb_crc;

        uint8_t  humidity_mmsb;
        uint8_t  humidity_mlsb;
        uint8_t  humidity_mmsb_mlsb_crc;

        uint8_t  humidity_lmsb;
        uint8_t  humidity_llsb;
        uint8_t  humidity_lmsb_llsb_crc;
    } SCD30_raw_output_data_t;


    /* Measurement processed data  */
    typedef struct {
        float  co2;
        float  temperature;
        float  humidity;
    } SCD30_processed_data_t;


    /* Measurement data: Raw and processed data  */
    typedef struct {
        SCD30_raw_output_data_t raw;
        SCD30_processed_data_t  processed;
    } SCD30_output_data_t;




    /* USER: User's variables  */
    typedef struct {
        /* Output data   */
        SCD30_output_data_t             data;                   /*< Data (processed and raw): CO2, Temperature and Humidity                   */

        /* Pressure compensation   */
        uint16_t                        pressure_compensation;  /*< 0 (desactivates pressure compensation) or [700 - 1400]. Pressure in mBar  */

        /* Set measurement interval  */
        uint16_t                        measurement_interval;   /*< [2 - 1800]. Interval in seconds                                           */

        /* Status  */
        SCD30_get_ready_status_bit_t    status;                 /*< Measurement is ready to be read from the sensor                           */

        /* (De-)Activate automatic self-calibration  */
        SCD30_continuous_auto_selfcal_t asc;                    /*< Continuos automatic self-calibration                                      */

        /* Forced recalibration  */
        uint16_t                        frc;                    /*< Value of C02 concentration in ppm                                         */

        /* Set temperature offset  */
        uint16_t                        temperature_offset;     /*< Value of Temperature offset. [°C x 100]. One tick corresponds to 0.01 C   */

        /* Altitude compensation  */
        uint16_t                        altitude_compensation;  /*< Altitude compensation value. Height over sea level in [m] above 0         */

        /* Firmware version  */
        SCD30_fw_version_t              firmware;               /*< Firmware version                                                          */
    } SCD30_data_t;
#endif




    /**
      * @brief   INTERNAL CONSTANTS
      */
    typedef enum {
        SCD30_SUCCESS           =       0,
        SCD30_FAILURE           =       1,
        SCD30_DATA_CORRUPTED    =       2,
        I2C_SUCCESS             =       0
    } SCD30_status_t;



    /**
      * @brief   FUNCTION PROTOTYPES
      */
    /** Create an SCD30 object connected to the specified I2C pins.
      *
      * @param sda     I2C data pin
      * @param scl     I2C clock pin
      * @param addr    I2C slave address
      * @param freq    I2C frequency in Hz.
      */
    SCD30 ( PinName sda, PinName scl, uint32_t addr, uint32_t freq );

    /** Delete SCD30 object.
     */
    ~SCD30();

    /** It configures the I2C peripheral.
    */
    SCD30_status_t  SCD30_Init                          ( void                                  );

    /** It triggers continuous measurement with or without ambient pressure compensation.
      */
    SCD30_status_t  SCD30_TriggerContinuousMeasurement  ( uint16_t pressure_compensation        );

    /** It stops the continuous measurement.
      */
    SCD30_status_t  SCD30_StopContinuousMeasurement     ( void                                  );

    /** It sets the measurement interval.
      */
    SCD30_status_t  SCD30_SetMeasurementInterval        ( uint16_t measurement_interval         );

    /** It gets the measurement interval.
      */
    SCD30_status_t  SCD30_GetMeasurementInterval        ( uint16_t* measurement_interval        );

    /** It gets the status when the data is ready to be read.
      */
    SCD30_status_t  SCD30_GetDataReadyStatus            ( SCD30_get_ready_status_bit_t* status  );

    /** It gets all the raw data.
      */
    SCD30_status_t  SCD30_ReadRawMeasurement            ( SCD30_raw_output_data_t* raw_data     );

    /** It gets all the data.
      */
    SCD30_status_t  SCD30_ReadMeasurement               ( SCD30_output_data_t* data             );

    /** It enables/disables the continuous automatic self-calibration.
      */
    SCD30_status_t  SCD30_SetContinuousASC              ( SCD30_continuous_auto_selfcal_t asc   );

    /** It gets the continuous automatic self-calibration bit.
      */
    SCD30_status_t  SCD30_GetContinuousASC              ( SCD30_continuous_auto_selfcal_t* asc  );

    /** It sets the forced recalibration value.
      */
    SCD30_status_t  SCD30_SetForcedRecalibrationValue   ( uint16_t frc                          );

    /** It gets the forced recalibration value.
      */
    SCD30_status_t  SCD30_GetForcedRecalibrationValue   ( uint16_t* frc                         );

    /** It sets the temperature offset value.
      */
    SCD30_status_t  SCD30_SetTemperatureOffsetValue     ( uint16_t temp_offset                  );

    /** It gets the temperature offset value.
      */
    SCD30_status_t  SCD30_GetTemperatureOffsetValue     ( uint16_t* temp_offset                 );

    /** It sets the altitude compensation value.
      */
    SCD30_status_t  SCD30_SetAltitudeCompensationValue  ( uint16_t alt_comp                     );

    /** It gets the altitude compensation value.
      */
    SCD30_status_t  SCD30_GetAltitudeCompensationValue  ( uint16_t* alt_comp                    );

    /** It gets the firmware version value.
      */
    SCD30_status_t  SCD30_GetFirmwareVersion            ( SCD30_fw_version_t* fw                );

    /** It performs a software reset.
      */
    SCD30_status_t  SCD30_SoftReset                     ( void                                  );

private:
    /** It calculates the I2C checksum calculation (CRC-8).
      */
    uint8_t         SCD30_CalculateI2C_CRC8             ( uint16_t seed                         );

    I2C      _i2c;
    uint32_t _SCD30_Addr;
};

#endif /* SCD30_H */