├── .gitattributes ├── LICENSE.md ├── README.md ├── documents └── Sensirion_CO2_Sensors_SCD30_Preliminary-Datasheet.pdf ├── examples ├── Example1_BasicReadings │ └── Example1_BasicReadings.ino ├── Example2_SetOptions │ └── Example2_SetOptions.ino ├── Example3_WireOptions │ └── Example3_WireOptions.ino ├── Example4_EnableCalibrate │ └── Example4_EnableCalibrate.ino └── Example5_GetSettings │ └── Example5_GetSettings.ino ├── keywords.txt ├── library.properties └── src ├── SparkFun_SCD30_Arduino_Library.cpp └── SparkFun_SCD30_Arduino_Library.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | SparkFun License Information 2 | ============================ 3 | 4 | SparkFun uses two different licenses for our files — one for hardware and one for code. 5 | 6 | Hardware 7 | --------- 8 | 9 | **SparkFun hardware is released under [Creative Commons Share-alike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/).** 10 | 11 | Note: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-sa/4.0/legalcode). 12 | 13 | You are free to: 14 | 15 | Share — copy and redistribute the material in any medium or format 16 | Adapt — remix, transform, and build upon the material 17 | for any purpose, even commercially. 18 | The licensor cannot revoke these freedoms as long as you follow the license terms. 19 | Under the following terms: 20 | 21 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 22 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 23 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | Notices: 25 | 26 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 27 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 28 | 29 | 30 | Code 31 | -------- 32 | 33 | **SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).** 34 | 35 | The MIT License (MIT) 36 | 37 | Copyright (c) 2020 SparkFun Electronics 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy 40 | of this software and associated documentation files (the "Software"), to deal 41 | in the Software without restriction, including without limitation the rights 42 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | copies of the Software, and to permit persons to whom the Software is 44 | furnished to do so, subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun SCD30 CO₂ Sensor Library 2 | =========================================================== 3 | 4 | ![SparkFun SCD30 CO₂ Sensor](https://cdn.sparkfun.com//assets/parts/1/2/9/8/4/SparkFun_Sensirion_SCD30.jpg) 5 | 6 | [*SparkX CO₂ Humidity and Temperature Sensor - SCD30 (SPX-14751)*](https://www.sparkfun.com/products/14751) 7 | 8 | The SCD30 from Sensirion is a high quality [NDIR](https://en.wikipedia.org/wiki/Nondispersive_infrared_sensor) based CO₂ sensor capable of detecting 400 to 10000ppm with an accuracy of ±(30ppm+3%). In order to improve accuracy the SCD30 has temperature and humidity sensing built-in, as well as commands to compensate for altitude. 9 | 10 | We've written an Arduino library to make reading the CO₂, humidity, and temperature very easy. It can be downloaded through the Arduino Library manager: search for 'SparkFun SCD30'. We recommend using a [Qwiic Breadboard Cable](https://www.sparkfun.com/products/14425) to connect the SCD30 to a Qwiic compatible board. The Ye*LL*ow wire goes in the SC*L* pin. The SCD30 also supports a serial interface but we haven't worked with it. 11 | 12 | The CO₂ sensor works very well and for additional accuracy the SCD30 accepts ambient pressure readings. We recommend using the SCD30 in conjunction with the [Qwiic Pressure Sensor - MS5637](https://www.sparkfun.com/products/14688) or the [Qwiic Environmental Sensor - BME680](https://www.sparkfun.com/products/14570) to obtain the current barometric pressure. 13 | 14 | Note: The SCD30 has an automatic self-calibration routine. Sensirion recommends 7 days of continuous readings with at least 1 hour a day of 'fresh air' for self-calibration to complete. 15 | 16 | Library written by Nathan Seidle ([SparkFun](http://www.sparkfun.com)). 17 | 18 | Thanks to! 19 | 20 | * [jobr97](https://github.com/jobr97) for adding the getTemperatureOffset() method 21 | * [bobobo1618](https://github.com/bobobo1618) for writing a CRC check and improving the return values of the library 22 | * [labeneator](https://github.com/labeneator) for adding method to disable calibrate at begin 23 | * [AndreasExner](https://github.com/AndreasExner) for adding [reset and getAutoSelfCalibration methods](https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library/pull/17) 24 | * [awatterott](https://github.com/awatterott) for adding [getAltitudeCompensation()](https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library/pull/18) 25 | * [jogi-k](https://github.com/jogi-k) for adding [teensy i2clib](https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library/pull/19) support 26 | * [paulvha](https://github.com/paulvha) for the suggestions and corrections in [his version of the library](https://github.com/paulvha/scd30) 27 | * [yamamaya](https://github.com/yamamaya) for the [3ms delay](https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library/pull/24) 28 | 29 | Repository Contents 30 | ------------------- 31 | 32 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 33 | * **/src** - Source files for the library (.cpp, .h). 34 | * **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 35 | * **library.properties** - General library properties for the Arduino package manager. 36 | 37 | Documentation 38 | -------------- 39 | 40 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 41 | 42 | License Information 43 | ------------------- 44 | 45 | This product is _**open source**_! 46 | 47 | Please use, reuse, and modify these files as you see fit. Please maintain attribution to SparkFun Electronics and release anything derivative under the same license. 48 | 49 | Distributed as-is; no warranty is given. 50 | 51 | - Your friends at SparkFun. 52 | -------------------------------------------------------------------------------- /documents/Sensirion_CO2_Sensors_SCD30_Preliminary-Datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_SCD30_Arduino_Library/10468a13e023df6ec434bd6d319da80efbc0b317/documents/Sensirion_CO2_Sensors_SCD30_Preliminary-Datasheet.pdf -------------------------------------------------------------------------------- /examples/Example1_BasicReadings/Example1_BasicReadings.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading CO2, humidity and temperature from the SCD30 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: May 22nd, 2018 6 | License: MIT. See license file for more information but you can 7 | basically do whatever you want with this code. 8 | 9 | Feel like supporting open source hardware? 10 | Buy a board from SparkFun! https://www.sparkfun.com/products/15112 11 | 12 | This example prints the current CO2 level, relative humidity, and temperature in C. 13 | 14 | Hardware Connections: 15 | Attach RedBoard to computer using a USB cable. 16 | Connect SCD30 to RedBoard using Qwiic cable. 17 | Open Serial Monitor at 115200 baud. 18 | */ 19 | 20 | #include 21 | 22 | #include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30 23 | SCD30 airSensor; 24 | 25 | void setup() 26 | { 27 | Serial.begin(115200); 28 | Serial.println("SCD30 Example"); 29 | Wire.begin(); 30 | 31 | if (airSensor.begin() == false) 32 | { 33 | Serial.println("Air sensor not detected. Please check wiring. Freezing..."); 34 | while (1) 35 | ; 36 | } 37 | 38 | //The SCD30 has data ready every two seconds 39 | } 40 | 41 | void loop() 42 | { 43 | if (airSensor.dataAvailable()) 44 | { 45 | Serial.print("co2(ppm):"); 46 | Serial.print(airSensor.getCO2()); 47 | 48 | Serial.print(" temp(C):"); 49 | Serial.print(airSensor.getTemperature(), 1); 50 | 51 | Serial.print(" humidity(%):"); 52 | Serial.print(airSensor.getHumidity(), 1); 53 | 54 | Serial.println(); 55 | } 56 | else 57 | Serial.println("Waiting for new data"); 58 | 59 | delay(500); 60 | } 61 | -------------------------------------------------------------------------------- /examples/Example2_SetOptions/Example2_SetOptions.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading CO2, humidity and temperature from the SCD30 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: May 22nd, 2018 6 | License: MIT. See license file for more information but you can 7 | basically do whatever you want with this code. 8 | 9 | Feel like supporting open source hardware? 10 | Buy a board from SparkFun! https://www.sparkfun.com/products/15112 11 | 12 | This example prints the current CO2 level, relative humidity, and temperature in C. 13 | 14 | Hardware Connections: 15 | Attach RedBoard to computer using a USB cable. 16 | Connect SCD30 to RedBoard using Qwiic cable. 17 | Open Serial Monitor at 115200 baud. 18 | 19 | Note: All settings (interval, altitude, etc) are saved to non-volatile memory and are 20 | loaded by the SCD30 at power on. There's no damage in sending that at each power on. 21 | 22 | Note: 100kHz I2C is fine, but according to the datasheet 400kHz I2C is not supported by the SCD30 23 | */ 24 | 25 | #include 26 | 27 | #include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30 28 | SCD30 airSensor; 29 | 30 | void setup() 31 | { 32 | Serial.begin(115200); 33 | Serial.println("SCD30 Example"); 34 | Wire.begin(); 35 | 36 | if (airSensor.begin() == false) 37 | { 38 | Serial.println("Air sensor not detected. Please check wiring. Freezing..."); 39 | while (1) 40 | ; 41 | } 42 | 43 | airSensor.setMeasurementInterval(16); //Change number of seconds between measurements: 2 to 1800 (30 minutes), stored in non-volatile memory of SCD30 44 | 45 | //While the setting is recorded, it is not immediately available to be read. 46 | delay(200); 47 | 48 | int interval = airSensor.getMeasurementInterval(); 49 | Serial.print("Measurement Interval: "); 50 | Serial.println(interval); 51 | 52 | //My desk is ~1600m above sealevel 53 | airSensor.setAltitudeCompensation(1600); //Set altitude of the sensor in m, stored in non-volatile memory of SCD30 54 | 55 | //Read altitude compensation value 56 | unsigned int altitude = airSensor.getAltitudeCompensation(); 57 | Serial.print("Current altitude: "); 58 | Serial.print(altitude); 59 | Serial.println("m"); 60 | 61 | //Pressure in Boulder, CO is 24.65inHg or 834.74mBar 62 | airSensor.setAmbientPressure(835); //Current ambient pressure in mBar: 700 to 1200, will overwrite altitude compensation 63 | 64 | airSensor.setTemperatureOffset(5); //Optionally we can set temperature offset to 5°C, stored in non-volatile memory of SCD30 65 | 66 | //Read temperature offset 67 | float offset = airSensor.getTemperatureOffset(); 68 | Serial.print("Current temp offset: "); 69 | Serial.print(offset, 2); 70 | Serial.println("C"); 71 | } 72 | 73 | void loop() 74 | { 75 | if (airSensor.dataAvailable()) 76 | { 77 | Serial.print("co2(ppm):"); 78 | Serial.print(airSensor.getCO2()); 79 | 80 | Serial.print(" temp(C):"); 81 | Serial.print(airSensor.getTemperature(), 1); 82 | 83 | Serial.print(" humidity(%):"); 84 | Serial.print(airSensor.getHumidity(), 1); 85 | 86 | Serial.println(); 87 | } 88 | else 89 | Serial.print("."); 90 | 91 | delay(1000); 92 | } 93 | -------------------------------------------------------------------------------- /examples/Example3_WireOptions/Example3_WireOptions.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading CO2, humidity and temperature from the SCD30 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: May 22nd, 2018 6 | License: MIT. See license file for more information but you can 7 | basically do whatever you want with this code. 8 | 9 | Feel like supporting open source hardware? 10 | Buy a board from SparkFun! https://www.sparkfun.com/products/15112 11 | 12 | This example prints the current CO2 level, relative humidity, and temperature in C. 13 | 14 | Hardware Connections: 15 | This example requires a platform that has multiple I2C ports. 16 | It will not compile on an Uno. Try an Artemis RedBoard or ATP. 17 | 18 | Note: 100kHz I2C is fine, but according to the datasheet 400kHz I2C is not supported by the SCD30 19 | */ 20 | 21 | #include 22 | 23 | #include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30 24 | SCD30 airSensor; 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | Serial.println("SCD30 Example"); 30 | 31 | Wire1.begin(); //Start the wire hardware that may be supported by your platform 32 | 33 | if (airSensor.begin(Wire1) == false) //Pass the Wire port to the .begin() function 34 | { 35 | Serial.println("Air sensor not detected. Please check wiring. Freezing..."); 36 | while (1) 37 | ; 38 | } 39 | 40 | //The library will now use Wire1 for all communication 41 | } 42 | 43 | void loop() 44 | { 45 | if (airSensor.dataAvailable()) 46 | { 47 | Serial.print("co2(ppm):"); 48 | Serial.print(airSensor.getCO2()); 49 | 50 | Serial.print(" temp(C):"); 51 | Serial.print(airSensor.getTemperature(), 1); 52 | 53 | Serial.print(" humidity(%):"); 54 | Serial.print(airSensor.getHumidity(), 1); 55 | 56 | Serial.println(); 57 | } 58 | else 59 | Serial.print("."); 60 | 61 | delay(1000); 62 | } 63 | -------------------------------------------------------------------------------- /examples/Example4_EnableCalibrate/Example4_EnableCalibrate.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading CO2, humidity and temperature from the SCD30 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: May 22nd, 2018 6 | License: MIT. See license file for more information but you can 7 | basically do whatever you want with this code. 8 | 9 | Feel like supporting open source hardware? 10 | Buy a board from SparkFun! https://www.sparkfun.com/products/15112 11 | 12 | This example turns on the auto-calibrate function during .begin() 13 | Please see section 1.3.6 of the SCD30 datasheet: 14 | 15 | "When activated for the first time a 16 | period of minimum 7 days is needed so that the algorithm can find its initial parameter set for ASC. The sensor has to be exposed 17 | to fresh air for at least 1 hour every day. Also during that period, the sensor may not be disconnected from the power supply, 18 | otherwise the procedure to find calibration parameters is aborted and has to be restarted from the beginning. The successfully 19 | calculated parameters are stored in non-volatile memory of the SCD30 having the effect that after a restart the previously found 20 | parameters for ASC are still present. " 21 | 22 | Hardware Connections: 23 | Attach RedBoard to computer using a USB cable. 24 | Connect SCD30 to RedBoard using Qwiic cable. 25 | Open Serial Monitor at 115200 baud. 26 | */ 27 | 28 | #include 29 | 30 | #include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30 31 | SCD30 airSensor; 32 | 33 | void setup() 34 | { 35 | Serial.begin(115200); 36 | Serial.println("SCD30 Example"); 37 | Wire.begin(); 38 | 39 | //Start sensor using the Wire port and enable the auto-calibration (ASC) 40 | if (airSensor.begin(Wire, true) == false) 41 | { 42 | Serial.println("Air sensor not detected. Please check wiring. Freezing..."); 43 | while (1) 44 | ; 45 | } 46 | 47 | Serial.print("Auto calibration set to "); 48 | if (airSensor.getAutoSelfCalibration() == true) 49 | Serial.println("true"); 50 | else 51 | Serial.println("false"); 52 | 53 | //The SCD30 has data ready every two seconds 54 | } 55 | 56 | void loop() 57 | { 58 | if (airSensor.dataAvailable()) 59 | { 60 | Serial.print("co2(ppm):"); 61 | Serial.print(airSensor.getCO2()); 62 | 63 | Serial.print(" temp(C):"); 64 | Serial.print(airSensor.getTemperature(), 1); 65 | 66 | Serial.print(" humidity(%):"); 67 | Serial.print(airSensor.getHumidity(), 1); 68 | 69 | Serial.println(); 70 | } 71 | else 72 | Serial.println("Waiting for new data"); 73 | 74 | delay(500); 75 | } 76 | -------------------------------------------------------------------------------- /examples/Example5_GetSettings/Example5_GetSettings.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading CO2, humidity and temperature from the SCD30 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: May 22nd, 2018 6 | License: MIT. See license file for more information but you can 7 | basically do whatever you want with this code. 8 | 9 | Feel like supporting open source hardware? 10 | Buy a board from SparkFun! https://www.sparkfun.com/products/15112 11 | 12 | This example gets the SCD30's settings using the new getSettingValue function (thank you paulvha) 13 | 14 | Hardware Connections: 15 | Attach RedBoard to computer using a USB cable. 16 | Connect SCD30 to RedBoard using Qwiic cable. 17 | Open Serial Monitor at 115200 baud. 18 | */ 19 | 20 | #include 21 | 22 | #include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_SCD30 23 | SCD30 airSensor; 24 | 25 | void setup() 26 | { 27 | Serial.begin(115200); 28 | Serial.println("SCD30 Example"); 29 | Wire.begin(); 30 | 31 | //Start sensor using the Wire port, but disable the auto-calibration 32 | if (airSensor.begin(Wire, false) == false) 33 | { 34 | Serial.println("Air sensor not detected. Please check wiring. Freezing..."); 35 | while (1) 36 | ; 37 | } 38 | 39 | uint16_t settingVal; // The settings will be returned in settingVal 40 | 41 | if (airSensor.getForcedRecalibration(&settingVal) == true) // Get the setting 42 | { 43 | Serial.print("Forced recalibration factor (ppm) is "); 44 | Serial.println(settingVal); 45 | } 46 | else 47 | { 48 | Serial.print("getForcedRecalibration failed! Freezing..."); 49 | while (1) 50 | ; // Do nothing more 51 | } 52 | 53 | if (airSensor.getMeasurementInterval(&settingVal) == true) // Get the setting 54 | { 55 | Serial.print("Measurement interval (s) is "); 56 | Serial.println(settingVal); 57 | } 58 | else 59 | { 60 | Serial.print("getMeasurementInterval failed! Freezing..."); 61 | while (1) 62 | ; // Do nothing more 63 | } 64 | 65 | if (airSensor.getTemperatureOffset(&settingVal) == true) // Get the setting 66 | { 67 | Serial.print("Temperature offset (C) is "); 68 | Serial.println(((float)settingVal) / 100.0, 2); 69 | } 70 | else 71 | { 72 | Serial.print("getTemperatureOffset failed! Freezing..."); 73 | while (1) 74 | ; // Do nothing more 75 | } 76 | 77 | if (airSensor.getAltitudeCompensation(&settingVal) == true) // Get the setting 78 | { 79 | Serial.print("Altitude offset (m) is "); 80 | Serial.println(settingVal); 81 | } 82 | else 83 | { 84 | Serial.print("getAltitudeCompensation failed! Freezing..."); 85 | while (1) 86 | ; // Do nothing more 87 | } 88 | 89 | if (airSensor.getFirmwareVersion(&settingVal) == true) // Get the setting 90 | { 91 | Serial.print("Firmware version is 0x"); 92 | Serial.println(settingVal, HEX); 93 | } 94 | else 95 | { 96 | Serial.print("getFirmwareVersion! Freezing..."); 97 | while (1) 98 | ; // Do nothing more 99 | } 100 | 101 | Serial.print("Auto calibration set to "); 102 | if (airSensor.getAutoSelfCalibration() == true) 103 | Serial.println("true"); 104 | else 105 | Serial.println("false"); 106 | 107 | //The SCD30 has data ready every two seconds 108 | } 109 | 110 | void loop() 111 | { 112 | if (airSensor.dataAvailable()) 113 | { 114 | Serial.print("co2(ppm):"); 115 | Serial.print(airSensor.getCO2()); 116 | 117 | Serial.print(" temp(C):"); 118 | Serial.print(airSensor.getTemperature(), 1); 119 | 120 | Serial.print(" humidity(%):"); 121 | Serial.print(airSensor.getHumidity(), 1); 122 | 123 | Serial.println(); 124 | } 125 | else 126 | Serial.println("Waiting for new data"); 127 | 128 | delay(500); 129 | } 130 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | SCD30 KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | SCD30 KEYWORD2 16 | begin KEYWORD2 17 | isConnected KEYWORD2 18 | enableDebugging KEYWORD2 19 | beginMeasuring KEYWORD2 20 | StopMeasurement KEYWORD2 21 | 22 | setAmbientPressure KEYWORD2 23 | 24 | getSettingValue KEYWORD2 25 | getFirmwareVersion KEYWORD2 26 | getCO2 KEYWORD2 27 | getHumidity KEYWORD2 28 | getTemperature KEYWORD2 29 | 30 | getMeasurementInterval KEYWORD2 31 | setMeasurementInterval KEYWORD2 32 | 33 | getAltitudeCompensation KEYWORD2 34 | setAltitudeCompensation KEYWORD2 35 | 36 | getAutoSelfCalibration KEYWORD2 37 | setAutoSelfCalibration KEYWORD2 38 | 39 | getForcedRecalibration KEYWORD2 40 | setForcedRecalibrationFactor KEYWORD2 41 | 42 | getTemperatureOffset KEYWORD2 43 | setTemperatureOffset KEYWORD2 44 | 45 | dataAvailable KEYWORD2 46 | readMeasurement KEYWORD2 47 | reset KEYWORD2 48 | sendCommand KEYWORD2 49 | readRegister KEYWORD2 50 | computeCRC8 KEYWORD2 51 | 52 | useStaleData KEYWORD2 53 | 54 | ####################################### 55 | # Constants (LITERAL1) 56 | ####################################### 57 | 58 | SCD30_ADDRESS LITERAL1 59 | COMMAND_CONTINUOUS_MEASUREMENT LITERAL1 60 | COMMAND_SET_MEASUREMENT_INTERVAL LITERAL1 61 | COMMAND_GET_DATA_READY LITERAL1 62 | COMMAND_READ_MEASUREMENT LITERAL1 63 | COMMAND_AUTOMATIC_SELF_CALIBRATION LITERAL1 64 | COMMAND_SET_FORCED_RECALIBRATION_FACTOR LITERAL1 65 | COMMAND_SET_TEMPERATURE_OFFSET LITERAL1 66 | COMMAND_SET_ALTITUDE_COMPENSATION LITERAL1 67 | COMMAND_RESET LITERAL1 68 | COMMAND_STOP_MEAS LITERAL1 69 | COMMAND_READ_FW_VER LITERAL1 70 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun SCD30 Arduino Library 2 | version=1.0.20 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=Library for the Sensirion SCD30 CO2 Sensor 6 | paragraph=An Arduino library for the SCD30 CO2 sensor from Sensirion. The SCD30 is a high quality NDIR based CO₂ sensor capable of detecting 400 to 10000ppm with an accuracy of ±(30ppm+3%). In order to improve accuracy the SCD30 has temperature and humidity sensing built-in, as well as commands to set the current altitude.

Get the SCD30 here. 7 | category=Sensors 8 | url=https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/SparkFun_SCD30_Arduino_Library.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library written for the SCD30 3 | SparkFun sells these at its website: www.sparkfun.com 4 | Do you like this library? Help support SparkFun. Buy a board! 5 | https://www.sparkfun.com/products/14751 6 | 7 | Written by Nathan Seidle @ SparkFun Electronics, May 22nd, 2018 8 | 9 | Updated February 1st 2021 to include some of the features of paulvha's version of the library 10 | (while maintaining backward-compatibility): 11 | https://github.com/paulvha/scd30 12 | Thank you Paul! 13 | 14 | The SCD30 measures CO2 with accuracy of +/- 30ppm. 15 | 16 | This library handles the initialization of the SCD30 and outputs 17 | CO2 levels, relative humidty, and temperature. 18 | 19 | https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library 20 | 21 | Development environment specifics: 22 | Arduino IDE 1.8.13 23 | 24 | SparkFun code, firmware, and software is released under the MIT License. 25 | Please see LICENSE.md for more details. 26 | */ 27 | 28 | #include "SparkFun_SCD30_Arduino_Library.h" 29 | 30 | SCD30::SCD30(void) 31 | { 32 | // Constructor 33 | } 34 | 35 | // Initialize the Serial port 36 | #ifdef USE_TEENSY3_I2C_LIB 37 | bool SCD30::begin(i2c_t3 &wirePort, bool autoCalibrate, bool measBegin) 38 | #else 39 | bool SCD30::begin(TwoWire &wirePort, bool autoCalibrate, bool measBegin) 40 | #endif 41 | { 42 | _i2cPort = &wirePort; // Grab which port the user wants us to use 43 | 44 | /* Especially during obtaining the ACK BIT after a byte sent the SCD30 is using clock stretching (but NOT only there)! 45 | * The need for clock stretching is described in the Sensirion_CO2_Sensors_SCD30_Interface_Description.pdf 46 | * 47 | * The default clock stretch (maximum wait time) on the ESP8266-library (2.4.2) is 230us which is set during _i2cPort->begin(); 48 | * In the current implementation of the ESP8266 I2C driver there is NO error message when this time expired, while 49 | * the clock stretch is still happening, causing uncontrolled behaviour of the hardware combination. 50 | * 51 | * To set ClockStretchlimit() a check for ESP8266 boards has been added in the driver. 52 | * 53 | * With setting to 20000, we set a max timeout of 20mS (> 20x the maximum measured) basically disabling the time-out 54 | * and now wait for clock stretch to be controlled by the client. 55 | */ 56 | 57 | #if defined(ARDUINO_ARCH_ESP8266) 58 | _i2cPort->setClockStretchLimit(200000); 59 | #endif 60 | 61 | if (isConnected() == false) 62 | return (false); 63 | 64 | if (measBegin == false) // Exit now if measBegin is false 65 | return (true); 66 | 67 | // Check for device to respond correctly 68 | if (beginMeasuring() == true) // Start continuous measurements 69 | { 70 | setMeasurementInterval(2); // 2 seconds between measurements 71 | setAutoSelfCalibration(autoCalibrate); // Enable auto-self-calibration 72 | 73 | return (true); 74 | } 75 | 76 | return (false); // Something went wrong 77 | } 78 | 79 | // Returns true if device responds to a firmware request 80 | bool SCD30::isConnected() 81 | { 82 | uint16_t fwVer; 83 | if (getFirmwareVersion(&fwVer) == false) // Read the firmware version. Return false if the CRC check fails. 84 | return (false); 85 | 86 | if (_printDebug == true) 87 | { 88 | _debugPort->print(F("Firmware version 0x")); 89 | _debugPort->println(fwVer, HEX); 90 | } 91 | 92 | return (true); 93 | } 94 | 95 | // Calling this function with nothing sets the debug port to Serial 96 | // You can also call it with other streams like Serial1, SerialUSB, etc. 97 | void SCD30::enableDebugging(Stream &debugPort) 98 | { 99 | _debugPort = &debugPort; 100 | _printDebug = true; 101 | } 102 | 103 | // Returns the latest available CO2 level 104 | // If the current level has already been reported, trigger a new read 105 | uint16_t SCD30::getCO2(void) 106 | { 107 | if (co2HasBeenReported == true) // Trigger a new read 108 | { 109 | if (readMeasurement() == false) // Pull in new co2, humidity, and temp into global vars 110 | if (!_useStaleData) 111 | co2 = 0; // Failed to read sensor 112 | } 113 | 114 | co2HasBeenReported = true; 115 | 116 | return (uint16_t)co2; // Cut off decimal as co2 is 0 to 10,000 117 | } 118 | 119 | // Returns the latest available humidity 120 | // If the current level has already been reported, trigger a new read 121 | float SCD30::getHumidity(void) 122 | { 123 | if (humidityHasBeenReported == true) // Trigger a new read 124 | if (readMeasurement() == false) // Pull in new co2, humidity, and temp into global vars 125 | if (!_useStaleData) 126 | humidity = 0; // Failed to read sensor 127 | 128 | humidityHasBeenReported = true; 129 | 130 | return humidity; 131 | } 132 | 133 | // Returns the latest available temperature 134 | // If the current level has already been reported, trigger a new read 135 | float SCD30::getTemperature(void) 136 | { 137 | if (temperatureHasBeenReported == true) // Trigger a new read 138 | if (readMeasurement() == false) // Pull in new co2, humidity, and temp into global vars 139 | if (!_useStaleData) 140 | temperature = 0; // Failed to read sensor 141 | 142 | temperatureHasBeenReported = true; 143 | 144 | return temperature; 145 | } 146 | 147 | // Enables or disables the ASC 148 | bool SCD30::setAutoSelfCalibration(bool enable) 149 | { 150 | if (enable) 151 | return sendCommand(COMMAND_AUTOMATIC_SELF_CALIBRATION, 1); // Activate continuous ASC 152 | else 153 | return sendCommand(COMMAND_AUTOMATIC_SELF_CALIBRATION, 0); // Deactivate continuous ASC 154 | } 155 | 156 | // Set the forced recalibration factor. See 1.3.7. 157 | // The reference CO2 concentration has to be within the range 400 ppm ≤ cref(CO2) ≤ 2000 ppm. 158 | bool SCD30::setForcedRecalibrationFactor(uint16_t concentration) 159 | { 160 | if (concentration < 400 || concentration > 2000) 161 | { 162 | return false; // Error check. 163 | } 164 | return sendCommand(COMMAND_SET_FORCED_RECALIBRATION_FACTOR, concentration); 165 | } 166 | 167 | // Get the temperature offset. See 1.3.8. 168 | float SCD30::getTemperatureOffset(void) 169 | { 170 | uint16_t response = readRegister(COMMAND_SET_TEMPERATURE_OFFSET); 171 | 172 | union 173 | { 174 | int16_t signed16; 175 | uint16_t unsigned16; 176 | } signedUnsigned; // Avoid any ambiguity casting int16_t to uint16_t 177 | signedUnsigned.unsigned16 = response; 178 | 179 | return (((float)signedUnsigned.signed16) / 100.0); 180 | } 181 | 182 | // Set the temperature offset to remove module heating from temp reading 183 | bool SCD30::setTemperatureOffset(float tempOffset) 184 | { 185 | // Temp offset is only positive. See: https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library/issues/27#issuecomment-971986826 186 | //"The SCD30 offset temperature is obtained by subtracting the reference temperature from the SCD30 output temperature" 187 | // https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/9.5_CO2/Sensirion_CO2_Sensors_SCD30_Low_Power_Mode.pdf 188 | 189 | if (tempOffset < 0.0) 190 | return (false); 191 | 192 | uint16_t value = tempOffset * 100; 193 | 194 | return sendCommand(COMMAND_SET_TEMPERATURE_OFFSET, value); 195 | } 196 | 197 | // Get the altitude compenstation. See 1.3.9. 198 | uint16_t SCD30::getAltitudeCompensation(void) 199 | { 200 | return readRegister(COMMAND_SET_ALTITUDE_COMPENSATION); 201 | } 202 | 203 | // Set the altitude compenstation. See 1.3.9. 204 | bool SCD30::setAltitudeCompensation(uint16_t altitude) 205 | { 206 | return sendCommand(COMMAND_SET_ALTITUDE_COMPENSATION, altitude); 207 | } 208 | 209 | // Set the pressure compenstation. This is passed during measurement startup. 210 | // mbar can be 700 to 1200 211 | bool SCD30::setAmbientPressure(uint16_t pressure_mbar) 212 | { 213 | if (pressure_mbar < 700 || pressure_mbar > 1200) 214 | { 215 | return false; 216 | } 217 | return sendCommand(COMMAND_CONTINUOUS_MEASUREMENT, pressure_mbar); 218 | } 219 | 220 | // SCD30 soft reset 221 | void SCD30::reset() 222 | { 223 | sendCommand(COMMAND_RESET); 224 | } 225 | 226 | // Get the current ASC setting 227 | bool SCD30::getAutoSelfCalibration() 228 | { 229 | uint16_t response = readRegister(COMMAND_AUTOMATIC_SELF_CALIBRATION); 230 | if (response == 1) 231 | { 232 | return true; 233 | } 234 | else 235 | { 236 | return false; 237 | } 238 | } 239 | 240 | // Begins continuous measurements 241 | // Continuous measurement status is saved in non-volatile memory. When the sensor 242 | // is powered down while continuous measurement mode is active SCD30 will measure 243 | // continuously after repowering without sending the measurement command. 244 | // Returns true if successful 245 | bool SCD30::beginMeasuring(uint16_t pressureOffset) 246 | { 247 | return (sendCommand(COMMAND_CONTINUOUS_MEASUREMENT, pressureOffset)); 248 | } 249 | 250 | // Overload - no pressureOffset 251 | bool SCD30::beginMeasuring(void) 252 | { 253 | return (beginMeasuring(0)); 254 | } 255 | 256 | // Stop continuous measurement 257 | bool SCD30::StopMeasurement(void) 258 | { 259 | return (sendCommand(COMMAND_STOP_MEAS)); 260 | } 261 | 262 | // Sets interval between measurements 263 | // 2 seconds to 1800 seconds (30 minutes) 264 | bool SCD30::setMeasurementInterval(uint16_t interval) 265 | { 266 | return sendCommand(COMMAND_SET_MEASUREMENT_INTERVAL, interval); 267 | } 268 | 269 | // Gets interval between measurements 270 | // 2 seconds to 1800 seconds (30 minutes) 271 | uint16_t SCD30::getMeasurementInterval(void) 272 | { 273 | uint16_t interval = 0; 274 | getSettingValue(COMMAND_SET_MEASUREMENT_INTERVAL, &interval); 275 | return (interval); 276 | } 277 | 278 | // Returns true when data is available 279 | bool SCD30::dataAvailable() 280 | { 281 | uint16_t response = readRegister(COMMAND_GET_DATA_READY); 282 | 283 | if (response == 1) 284 | return (true); 285 | return (false); 286 | } 287 | 288 | // Get 18 bytes from SCD30 289 | // Updates global variables with floats 290 | // Returns true if success 291 | bool SCD30::readMeasurement() 292 | { 293 | // Verify we have data from the sensor 294 | if (dataAvailable() == false) 295 | return (false); 296 | 297 | ByteToFl tempCO2; 298 | tempCO2.value = 0; 299 | ByteToFl tempHumidity; 300 | tempHumidity.value = 0; 301 | ByteToFl tempTemperature; 302 | tempTemperature.value = 0; 303 | 304 | _i2cPort->beginTransmission(SCD30_ADDRESS); 305 | _i2cPort->write(COMMAND_READ_MEASUREMENT >> 8); // MSB 306 | _i2cPort->write(COMMAND_READ_MEASUREMENT & 0xFF); // LSB 307 | if (_i2cPort->endTransmission() != 0) 308 | return (0); // Sensor did not ACK 309 | 310 | delay(3); 311 | 312 | const uint8_t receivedBytes = _i2cPort->requestFrom((uint8_t)SCD30_ADDRESS, (uint8_t)18); 313 | bool error = false; 314 | if (_i2cPort->available()) 315 | { 316 | uint8_t bytesToCrc[2]; 317 | for (uint8_t x = 0; x < 18; x++) 318 | { 319 | uint8_t incoming = _i2cPort->read(); 320 | 321 | switch (x) 322 | { 323 | case 0: 324 | case 1: 325 | case 3: 326 | case 4: 327 | tempCO2.array[x < 3 ? 3 - x : 4 - x] = incoming; 328 | bytesToCrc[x % 3] = incoming; 329 | break; 330 | case 6: 331 | case 7: 332 | case 9: 333 | case 10: 334 | tempTemperature.array[x < 9 ? 9 - x : 10 - x] = incoming; 335 | bytesToCrc[x % 3] = incoming; 336 | break; 337 | case 12: 338 | case 13: 339 | case 15: 340 | case 16: 341 | tempHumidity.array[x < 15 ? 15 - x : 16 - x] = incoming; 342 | bytesToCrc[x % 3] = incoming; 343 | break; 344 | default: 345 | // Validate CRC 346 | uint8_t foundCrc = computeCRC8(bytesToCrc, 2); 347 | if (foundCrc != incoming) 348 | { 349 | if (_printDebug == true) 350 | { 351 | _debugPort->print(F("readMeasurement: found CRC in byte ")); 352 | _debugPort->print(x); 353 | _debugPort->print(F(", expected 0x")); 354 | _debugPort->print(foundCrc, HEX); 355 | _debugPort->print(F(", got 0x")); 356 | _debugPort->println(incoming, HEX); 357 | } 358 | error = true; 359 | } 360 | break; 361 | } 362 | } 363 | } 364 | else 365 | { 366 | if (_printDebug == true) 367 | { 368 | _debugPort->print(F("readMeasurement: no SCD30 data found from I2C, i2c claims we should receive ")); 369 | _debugPort->print(receivedBytes); 370 | _debugPort->println(F(" bytes")); 371 | } 372 | return false; 373 | } 374 | 375 | if (error) 376 | { 377 | if (_printDebug == true) 378 | _debugPort->println(F("readMeasurement: encountered error reading SCD30 data.")); 379 | return false; 380 | } 381 | // Now copy the uint32s into their associated floats 382 | co2 = tempCO2.value; 383 | temperature = tempTemperature.value; 384 | humidity = tempHumidity.value; 385 | 386 | // Mark our global variables as fresh 387 | co2HasBeenReported = false; 388 | humidityHasBeenReported = false; 389 | temperatureHasBeenReported = false; 390 | 391 | return (true); // Success! New data available in globals. 392 | } 393 | 394 | // Gets a setting by reading the appropriate register. 395 | // Returns true if the CRC is valid. 396 | bool SCD30::getSettingValue(uint16_t registerAddress, uint16_t *val) 397 | { 398 | _i2cPort->beginTransmission(SCD30_ADDRESS); 399 | _i2cPort->write(registerAddress >> 8); // MSB 400 | _i2cPort->write(registerAddress & 0xFF); // LSB 401 | if (_i2cPort->endTransmission() != 0) 402 | return (false); // Sensor did not ACK 403 | 404 | delay(3); 405 | 406 | _i2cPort->requestFrom((uint8_t)SCD30_ADDRESS, (uint8_t)3); // Request data and CRC 407 | if (_i2cPort->available()) 408 | { 409 | uint8_t data[2]; 410 | data[0] = _i2cPort->read(); 411 | data[1] = _i2cPort->read(); 412 | uint8_t crc = _i2cPort->read(); 413 | *val = (uint16_t)data[0] << 8 | data[1]; 414 | uint8_t expectedCRC = computeCRC8(data, 2); 415 | if (crc == expectedCRC) // Return true if CRC check is OK 416 | return (true); 417 | if (_printDebug == true) 418 | { 419 | _debugPort->print(F("getSettingValue: CRC fail: expected 0x")); 420 | _debugPort->print(expectedCRC, HEX); 421 | _debugPort->print(F(", got 0x")); 422 | _debugPort->println(crc, HEX); 423 | } 424 | } 425 | return (false); 426 | } 427 | 428 | // Gets two bytes from SCD30 429 | uint16_t SCD30::readRegister(uint16_t registerAddress) 430 | { 431 | _i2cPort->beginTransmission(SCD30_ADDRESS); 432 | _i2cPort->write(registerAddress >> 8); // MSB 433 | _i2cPort->write(registerAddress & 0xFF); // LSB 434 | if (_i2cPort->endTransmission() != 0) 435 | return (0); // Sensor did not ACK 436 | 437 | delay(3); 438 | 439 | _i2cPort->requestFrom((uint8_t)SCD30_ADDRESS, (uint8_t)2); 440 | if (_i2cPort->available()) 441 | { 442 | uint8_t msb = _i2cPort->read(); 443 | uint8_t lsb = _i2cPort->read(); 444 | return ((uint16_t)msb << 8 | lsb); 445 | } 446 | return (0); // Sensor did not respond 447 | } 448 | 449 | // Sends a command along with arguments and CRC 450 | bool SCD30::sendCommand(uint16_t command, uint16_t arguments) 451 | { 452 | uint8_t data[2]; 453 | data[0] = arguments >> 8; 454 | data[1] = arguments & 0xFF; 455 | uint8_t crc = computeCRC8(data, 2); // Calc CRC on the arguments only, not the command 456 | 457 | _i2cPort->beginTransmission(SCD30_ADDRESS); 458 | _i2cPort->write(command >> 8); // MSB 459 | _i2cPort->write(command & 0xFF); // LSB 460 | _i2cPort->write(arguments >> 8); // MSB 461 | _i2cPort->write(arguments & 0xFF); // LSB 462 | _i2cPort->write(crc); 463 | if (_i2cPort->endTransmission() != 0) 464 | return (false); // Sensor did not ACK 465 | 466 | return (true); 467 | } 468 | 469 | // Sends just a command, no arguments, no CRC 470 | bool SCD30::sendCommand(uint16_t command) 471 | { 472 | _i2cPort->beginTransmission(SCD30_ADDRESS); 473 | _i2cPort->write(command >> 8); // MSB 474 | _i2cPort->write(command & 0xFF); // LSB 475 | if (_i2cPort->endTransmission() != 0) 476 | return (false); // Sensor did not ACK 477 | 478 | return (true); 479 | } 480 | 481 | // Given an array and a number of bytes, this calculate CRC8 for those bytes 482 | // CRC is only calc'd on the data portion (two bytes) of the four bytes being sent 483 | // From: http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html 484 | // Tested with: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html 485 | // x^8+x^5+x^4+1 = 0x31 486 | uint8_t SCD30::computeCRC8(uint8_t data[], uint8_t len) 487 | { 488 | uint8_t crc = 0xFF; // Init with 0xFF 489 | 490 | for (uint8_t x = 0; x < len; x++) 491 | { 492 | crc ^= data[x]; // XOR-in the next input byte 493 | 494 | for (uint8_t i = 0; i < 8; i++) 495 | { 496 | if ((crc & 0x80) != 0) 497 | crc = (uint8_t)((crc << 1) ^ 0x31); 498 | else 499 | crc <<= 1; 500 | } 501 | } 502 | 503 | return crc; // No output reflection 504 | } 505 | -------------------------------------------------------------------------------- /src/SparkFun_SCD30_Arduino_Library.h: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library written for the SCD30 3 | SparkFun sells these at its website: www.sparkfun.com 4 | Do you like this library? Help support SparkFun. Buy a board! 5 | https://www.sparkfun.com/products/14751 6 | 7 | Written by Nathan Seidle @ SparkFun Electronics, May 22nd, 2018 8 | 9 | Updated February 1st 2021 to include some of the features of paulvha's version of the library 10 | (while maintaining backward-compatibility): 11 | https://github.com/paulvha/scd30 12 | Thank you Paul! 13 | 14 | The SCD30 measures CO2 with accuracy of +/- 30ppm. 15 | 16 | This library handles the initialization of the SCD30 and outputs 17 | CO2 levels, relative humidty, and temperature. 18 | 19 | https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library 20 | 21 | Development environment specifics: 22 | Arduino IDE 1.8.13 23 | 24 | SparkFun code, firmware, and software is released under the MIT License. 25 | Please see LICENSE.md for more details. 26 | */ 27 | 28 | #ifndef __SparkFun_SCD30_ARDUINO_LIBARARY_H__ 29 | #define __SparkFun_SCD30_ARDUINO_LIBARARY_H__ 30 | 31 | // Uncomment the next #define if using an Teensy >= 3 or Teensy LC and want to use the dedicated I2C-Library for it 32 | // Then you also have to include on your application instead of 33 | 34 | // #define USE_TEENSY3_I2C_LIB 35 | 36 | #include "Arduino.h" 37 | #ifdef USE_TEENSY3_I2C_LIB 38 | #include 39 | #else 40 | #include 41 | #endif 42 | 43 | // The default I2C address for the SCD30 is 0x61. 44 | #define SCD30_ADDRESS 0x61 45 | 46 | // Available commands 47 | 48 | #define COMMAND_CONTINUOUS_MEASUREMENT 0x0010 49 | #define COMMAND_SET_MEASUREMENT_INTERVAL 0x4600 50 | #define COMMAND_GET_DATA_READY 0x0202 51 | #define COMMAND_READ_MEASUREMENT 0x0300 52 | #define COMMAND_AUTOMATIC_SELF_CALIBRATION 0x5306 53 | #define COMMAND_SET_FORCED_RECALIBRATION_FACTOR 0x5204 54 | #define COMMAND_SET_TEMPERATURE_OFFSET 0x5403 55 | #define COMMAND_SET_ALTITUDE_COMPENSATION 0x5102 56 | #define COMMAND_RESET 0xD304 // Soft reset 57 | #define COMMAND_STOP_MEAS 0x0104 58 | #define COMMAND_READ_FW_VER 0xD100 59 | 60 | typedef union 61 | { 62 | uint8_t array[4]; 63 | float value; 64 | } ByteToFl; // paulvha 65 | 66 | class SCD30 67 | { 68 | public: 69 | SCD30(void); 70 | 71 | bool begin(bool autoCalibrate) { return begin(Wire, autoCalibrate); } 72 | #ifdef USE_TEENSY3_I2C_LIB 73 | bool begin(i2c_t3 &wirePort = Wire, bool autoCalibrate = false, bool measBegin = true); // By default use Wire port 74 | #else 75 | bool begin(TwoWire &wirePort = Wire, bool autoCalibrate = false, bool measBegin = true); // By default use Wire port 76 | #endif 77 | 78 | bool isConnected(); 79 | void enableDebugging(Stream &debugPort = Serial); // Turn on debug printing. If user doesn't specify then Serial will be used. 80 | 81 | bool beginMeasuring(uint16_t pressureOffset); 82 | bool beginMeasuring(void); 83 | bool StopMeasurement(void); // paulvha 84 | 85 | bool setAmbientPressure(uint16_t pressure_mbar); 86 | 87 | bool getSettingValue(uint16_t registerAddress, uint16_t *val); 88 | bool getFirmwareVersion(uint16_t *val) { return (getSettingValue(COMMAND_READ_FW_VER, val)); } 89 | uint16_t getCO2(void); 90 | float getHumidity(void); 91 | float getTemperature(void); 92 | 93 | uint16_t getMeasurementInterval(void); 94 | bool getMeasurementInterval(uint16_t *val) { return (getSettingValue(COMMAND_SET_MEASUREMENT_INTERVAL, val)); } 95 | bool setMeasurementInterval(uint16_t interval); 96 | 97 | uint16_t getAltitudeCompensation(void); 98 | bool getAltitudeCompensation(uint16_t *val) { return (getSettingValue(COMMAND_SET_ALTITUDE_COMPENSATION, val)); } 99 | bool setAltitudeCompensation(uint16_t altitude); 100 | 101 | bool getAutoSelfCalibration(void); 102 | bool setAutoSelfCalibration(bool enable); 103 | 104 | bool getForcedRecalibration(uint16_t *val) { return (getSettingValue(COMMAND_SET_FORCED_RECALIBRATION_FACTOR, val)); } 105 | bool setForcedRecalibrationFactor(uint16_t concentration); 106 | 107 | float getTemperatureOffset(void); 108 | bool getTemperatureOffset(uint16_t *val) { return (getSettingValue(COMMAND_SET_TEMPERATURE_OFFSET, val)); } 109 | bool setTemperatureOffset(float tempOffset); 110 | 111 | bool dataAvailable(); 112 | bool readMeasurement(); 113 | 114 | void reset(); 115 | 116 | bool sendCommand(uint16_t command, uint16_t arguments); 117 | bool sendCommand(uint16_t command); 118 | 119 | uint16_t readRegister(uint16_t registerAddress); 120 | 121 | uint8_t computeCRC8(uint8_t data[], uint8_t len); 122 | 123 | void useStaleData(bool enable) { _useStaleData = enable; } 124 | 125 | private: 126 | // Variables 127 | #ifdef USE_TEENSY3_I2C_LIB 128 | i2c_t3 *_i2cPort; // The generic connection to user's chosen I2C hardware 129 | #else 130 | TwoWire *_i2cPort; // The generic connection to user's chosen I2C hardware 131 | #endif 132 | // Global main datums 133 | float co2 = 0; 134 | float temperature = 0; 135 | float humidity = 0; 136 | bool _useStaleData = false; // If true, stale data is returned instead of zeros 137 | 138 | // These track the staleness of the current data 139 | // This allows us to avoid calling readMeasurement() every time individual datums are requested 140 | bool co2HasBeenReported = true; 141 | bool humidityHasBeenReported = true; 142 | bool temperatureHasBeenReported = true; 143 | 144 | // Debug 145 | Stream *_debugPort; // The stream to send debug messages to if enabled. Usually Serial. 146 | boolean _printDebug = false; // Flag to print debugging variables 147 | }; 148 | #endif 149 | --------------------------------------------------------------------------------