summaryrefslogtreecommitdiff
path: root/CCS811.h
blob: 26405355babe402bb4dd19ec4bc311b29a9d4d00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#ifndef _CCS811_H
#define _CCS811_H

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire.h>


/*I2C ADDRESS*/
#define CCS811_I2C_ADDRESS1                      0x5A
#define CCS811_I2C_ADDRESS2                      0x5B

#define CCS811_REG_STATUS                        0x00
#define CCS811_REG_MEAS_MODE                     0x01
#define CCS811_REG_ALG_RESULT_DATA               0x02
#define CCS811_REG_RAW_DATA                      0x03
#define CCS811_REG_ENV_DATA                      0x05
#define CCS811_REG_NTC                           0x06
#define CCS811_REG_THRESHOLDS                    0x10
#define CCS811_REG_BASELINE                      0x11
#define CCS811_REG_HW_ID                         0x20
#define CCS811_REG_HW_VERSION                    0x21
#define CCS811_REG_FW_BOOT_VERSION               0x23
#define CCS811_REG_FW_APP_VERSION                0x24
#define CCS811_REG_INTERNAL_STATE                0xA0
#define CCS811_REG_ERROR_ID                      0xE0
#define CCS811_REG_SW_RESET                      0xFF

#define CCS811_BOOTLOADER_APP_ERASE              0xF1
#define CCS811_BOOTLOADER_APP_DATA               0xF2
#define CCS811_BOOTLOADER_APP_VERIFY             0xF3
#define CCS811_BOOTLOADER_APP_START              0xF4

#define CCS811_HW_ID                             0x81
//Open the macro to see the detailed program execution process.
//#define ENABLE_DBG

#ifdef ENABLE_DBG
#define DBG(...) {Serial.print("[");Serial.print(__FUNCTION__); Serial.print("(): "); Serial.print(__LINE__); Serial.print(" ] "); Serial.println(__VA_ARGS__);}
#else
#define DBG(...)
#endif

class CCS811
{
public:
    #define ERR_OK             0      //OK 
    #define ERR_DATA_BUS      -1      //error in data bus
    #define ERR_IC_VERSION    -2      //chip version mismatch
    
    uint8_t _deviceAddr;
    typedef enum{
        eMode0, //Idle (Measurements are disabled in this mode)
        eMode1, //Constant power mode, IAQ measurement every second
        eMode2, //Pulse heating mode IAQ measurement every 10 seconds
        eMode3, //Low power pulse heating mode IAQ measurement every 60 seconds
        eMode4  //Constant power mode, sensor measurement every 250ms 1xx: Reserved modes (For future use)
    }eDRIVE_MODE_t;
    
    typedef enum{
        eClosed,      //Idle (Measurements are disabled in this mode)
        eCycle_1s,    //Constant power mode, IAQ measurement every second
        eCycle_10s,   //Pulse heating mode IAQ measurement every 10 seconds
        eCycle_60s,   //Low power pulse heating mode IAQ measurement every 60 seconds
        eCycle_250ms  //Constant power mode, sensor measurement every 250ms 1xx: Reserved modes (For future use)
    }eCycle_t;
    /**
     * @brief Constructor 
     * @param Input in Wire address
     */
    CCS811(TwoWire *pWire = &Wire, uint8_t deviceAddr = 0x5A){_pWire = pWire; _deviceAddr = deviceAddr;};
    
              /**
               * @brief Constructor
               * @return Return 0 if initialization succeeds, otherwise return non-zero.
               */
    int       begin();
              /**
               * @brief Judge if there is data to read 
               * @return Return 1 if there is, otherwise return 0. 
               */
    bool      checkDataReady();
              /**
               * @brief Reset sensor, clear all configured data.
               */
    void      softReset(),
              /**
               * @brief Set environment parameter 
               * @param temperature Set temperature value, unit: centigrade, range (-40~85℃)
               * @param humidity    Set humidity value, unit: RH, range (0~100)
               */
              setInTempHum(float temperature, float humidity),
              /**
               * @brief Measurement parameter configuration 
               * @param thresh:0 for Interrupt mode operates normally; 1 for interrupt mode only asserts the nINT signal (driven low) if the new
               * @param interrupt:0 for Interrupt generation is disabled; 1 for the nINT signal is asserted (driven low) when a new sample is ready in
               * @param mode:in typedef enum eDRIVE_MODE_t
               */
              setMeasurementMode(uint8_t thresh, uint8_t interrupt, eDRIVE_MODE_t mode),
              /**
               * @brief Measurement parameter configuration 
               * @param mode:in typedef enum eDRIVE_MODE_t
               */
              setMeasCycle(eCycle_t cycle),
              /**
               * @brief Set interrupt thresholds 
               * @param lowToMed: interrupt triggered value in range low to middle 
               * @param medToHigh: interrupt triggered value in range middle to high 
               */
              setThresholds(uint16_t lowToMed, uint16_t medToHigh);
              /**
               * @brief Get current configured parameter
               * @return configuration code, needs to be converted into binary code to analyze
               *         The 2nd: Interrupt mode (if enabled) operates normally,1: Interrupt mode (if enabled) only asserts the nINT signal (driven low) if the new
               *         The 3rd: Interrupt generation is disabled,1: The nINT signal is asserted (driven low) when a new sample is ready in
               *         The 4th: 6th: in typedef enum eDRIVE_MODE_t
               */
    uint8_t   getMeasurementMode();

              /**
               * @brief Get the current carbon dioxide concentration
               * @return current carbon dioxide concentration, unit:ppm
               */
    uint16_t  getCO2PPM(),
              /**
               * @brief Get current TVOC concentration
               * @return Return current TVOC concentration, unit: ppb
               */
              getTVOCPPB();
    uint16_t  readBaseLine();
    void      writeBaseLine(uint16_t baseLine);
    
protected:

    typedef struct{
        /*
         * The CCS811 received an I²C write request addressed to this station but with invalid register address ID
         */
        uint8_t sWRITE_REG_INVALID: 1;
        /*
         * The CCS811 received an I²C read request to a mailbox ID that is invalid
         */
        uint8_t sREAD_REG_INVALID: 1;
        /*
         * The CCS811 received an I²C request to write an unsupported mode to MEAS_MODE
         */
        uint8_t sMEASMODE_INVALID: 1;
        /*
         * The sensor resistance measurement has reached or exceeded the maximum range
         */
        uint8_t sMAX_RESISTANCE: 1;
        /*
         * The The Heater current in the CCS811 is not in range
         */
        uint8_t sHEATER_FAULT: 1;
        /*
         * The Heater voltage is not being applied correctly
         */
        uint8_t sHEATER_SUPPLY: 1;
    } __attribute__ ((packed))sError_id;
    
    typedef struct{
        /* 
         * ALG_RESULT_DATA crosses one of the thresholds set in the THRESHOLDS register 
         * by more than the hysteresis value (also in the THRESHOLDS register)
         */
        uint8_t sINT_THRESH: 1;
        /* 
         * At the end of each measurement cycle (250ms, 1s, 10s, 60s) a flag is set in the
         * STATUS register regardless of the setting of this bit.
         */
        uint8_t sINT_DATARDY: 1;
        /* 
         * A new sample is placed in ALG_RESULT_DATA and RAW_DATA registers and the
         * DATA_READY bit in the STATUS register is set at the defined measurement interval.
         */
        uint8_t sDRIVE_MODE: 3;
    } __attribute__ ((packed))sMeas_mode;
    
    typedef struct{
        /* 
         * This bit is cleared by reading ERROR_ID
         * It is not sufficient to read the ERROR field of ALG_RESULT_DATA and STATUS
         */
        uint8_t sERROR: 1;
        /* 
         * ALG_RESULT_DATA is read on the I²C interface
         */
        uint8_t sDATA_READY: 1;
        uint8_t sAPP_VALID: 1;
        /* 
         * After issuing a VERIFY command the application software must wait 70ms before 
         * issuing any transactions to CCS811 over the I²C interface
         */
        uint8_t sAPP_VERIFY: 1;
        /* 
         * After issuing the ERASE command the application software must wait 500ms 
         * before issuing any transactions to the CCS811 over the I2C interface.
         */
        uint8_t sAPP_ERASE: 1;
        uint8_t sFW_MODE: 1;
    } __attribute__ ((packed))sStatus;
    
    
    void getData(void);
    
    void writeConfig();
         
    virtual void writeReg(uint8_t reg, const void* pBuf, size_t size);
    virtual uint8_t readReg(uint8_t reg, const void* pBuf, size_t size);
    
    

private:
    TwoWire *_pWire;
    
    uint16_t eCO2;
    uint16_t eTVOC;
};

#endif