Introduction
CO2 is a key factor for indoor air quality as high levels compromise human’s cognitive performance and well-being. 
This Gravity: SCD41 CO2 sensor is based on the SCD41 miniature CO2 sensor from Sensirion. SCD41 builds on the photoacoustic NDIR sensing principle and Sensirion’s patented PAsens® and CMOSens® technology to offer high accuracy at an unmatched price and smallest form factor. On-chip signal compensation is realized with the built-in temperature and humidity sensor, while temperature and humidity data outputs are also available. 
SCD41 sensor detects the amount of energy that is absorbed by CO2 molecules. When pulsing the infra-red emitter, CO2 molecules absorb infrared light periodically. This causes additional molecular vibration resulting in a pressure wave inside the measurement chamber. The higher the CO2 concentration, the more light is absorbed, and thus the greater the amplitude of this acoustic wave becomes. A microphone inside the gas chamber measures this, from which the CO2 concentration can then be calculated. 

Click to learn more about PAsens® technology.
Click to learn more about NDIR sensor.
Click to learn more about What types of NDIR sensors exist and how do they work?
Click to learn more about Design-in guide
Features
- CO2, temperature and humidity, three in one
- A small size of 32*27*8mm
- Low power, average current<4mA
Application
- Indoor CO2 concentration monitoring
- Ambient monitoring in greenhouse
- Smart ventilation systems
Specification
 
- Power Supply: 3.3V to 5V
- Average Operating Current: <4mA
- I2C Address: 0x62
- Product Size: 32×27×8mm/1.26×1.06×0.31"
CO2
- Accuracy: ±(40 ppm + 5% MV)
- Measuring Range: 400 - 5000 ppm
- Response Time: 60s
Humidity
- Typical Relative Humidity Accuracy: 6%RH
- Relative Humidity Measuring Range: 0 to 95%RH
- Response Time: 120s
Temperature
- Typical Temperature Accuracy: 0.8℃
- Temperature Measuring Range: -10 to 60℃
- Response Time: 120s
Board Overview

| Num | Label | Description | 
|---|---|---|
| 1 | VCC | + | 
| 2 | GND | - | 
| 3 | SCL | I2C Clock Line | 
| 4 | SDA | I2C Data Line | 
Arduino Tutorial
Requirements
- 
Hardware - DFRduino UNO R3 (or similar) × 1
- Gravity: SCD41 Infrared CO2 Sensor - I2C × 1
- M-M/F-M/F-F Jumper wires
 
- 
Software - Arduino IDE
- Download and install the SCD4X Library. (About how to install the library?)
 
Connection Diagram

Sample Code 1 - Period Measurement
Read data from SCD41 periodly.
/*!
 * @file  periodMeasure.ino
 * @brief  This sample shows how to configure period measurement mode, compensation and calibration.
 * @note  The actual compensation and calibration parameter should be changed according to the operating environment
 * @copyright  Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license  The MIT License (MIT)
 * @author  [qsjhyy]([email protected])
 * @version  V1.0
 * @date  2022-05-11
 * @url  https://github.com/DFRobot/DFRobot_SCD4X
 */
#include <DFRobot_SCD4X.h>
/**
 * @brief Constructor
 * @param pWire - Wire object is defined in Wire.h, so just use &Wire and the methods in Wire can be pointed to and used
 * @param i2cAddr - SCD4X I2C address.
 */
DFRobot_SCD4X SCD4X(&Wire, /*i2cAddr = */SCD4X_I2C_ADDR);
void setup(void)
{
  Serial.begin(115200);
  // Init the sensor
  while( !SCD4X.begin() ){
    Serial.println("Communication with device failed, please check connection");
    delay(3000);
  }
  Serial.println("Begin ok!");
  /**
   * @brief set periodic measurement mode
   * @param mode - periodic measurement mode:
   * @n       SCD4X_START_PERIODIC_MEASURE : start periodic measurement, signal update interval is 5 seconds.
   * @n       SCD4X_STOP_PERIODIC_MEASURE : stop periodic measurement command
   * @n       SCD4X_START_LOW_POWER_MEASURE :  start low power periodic measurement, signal update interval is approximately 30 seconds.
   * @return None
   * @note The measurement mode must be disabled when configuring the sensor; after giving the stop_periodic_measurement command, the sensor needs to wait 500ms before responding to other commands.
   */
  SCD4X.enablePeriodMeasure(SCD4X_STOP_PERIODIC_MEASURE);
  /**
   * @brief set temperature offset
   * @details T(offset_actual) = T(SCD4X) - T(reference) + T(offset_previous)
   * @n T(offset_actual): the calculated actual temperature offset that is required
   * @n T(SCD4X): the temperature measured by the sensor (wait for a period of time to get steady readings)
   * @n T(reference): the standard reference value of the current ambient temperature
   * @n T(offset_previous): the previously set temperature offset
   * @n For example : 32(T(SCD4X)) - 30(T(reference)) + 2(T(offset_previous)) = 4(T(offset_actual))
   * @param tempComp - temperature offset value, unit ℃
   * @return None
   * @note When executing the command, the sensor can't be in period measurement mode
   */
  SCD4X.setTempComp(4.0);
  /**
   * @brief get temperature offset
   * @return The current set temp compensation value, unit ℃
   * @note When executing the command, the sensor can't be in period measurement mode
   */
  float temp = 0;
  temp = SCD4X.getTempComp();
  Serial.print("The current temperature compensation value : ");
  Serial.print(temp);
  Serial.println(" C");
  /**
   * @brief set sensor altitude
   * @param altitude - the current ambient altitude, unit m
   * @return None
   * @note When executing the command, the sensor can't be in period measurement mode
   */
  SCD4X.setSensorAltitude(540);
  /**
   * @brief get sensor altitude
   * @return The current set ambient altitude, unit m
   * @note When executing the command, the sensor can't be in period measurement mode
   */
  uint16_t altitude = 0;
  altitude = SCD4X.getSensorAltitude();
  Serial.print("Set the current environment altitude : ");
  Serial.print(altitude);
  Serial.println(" m");
  /**
   * @brief set automatic self calibration enabled
   * @param mode - automatic self-calibration mode:
   * @n       true : enable automatic self-calibration
   * @n       false : disable automatic self-calibration
   * @return None
   * @note When executing the command, the sensor can't be in period measurement mode
   */
  // SCD4X.setAutoCalibMode(true);
  /**
   * @brief get automatic self calibration enabled
   * @return Automatic self-calibration mode:
   * @n        true : enable automatic self-calibration
   * @n        false : disable automatic self-calibration
   * @note When executing the command, the sensor can't be in period measurement mode
   */
  // if(SCD4X.getAutoCalibMode()) {
  //   Serial.println("Automatic calibration on!");
  // } else {
  //   Serial.println("Automatic calibration off!");
  // }
  /**
   * @brief persist settings
   * @details Configuration settings such as the temperature offset, sensor altitude and the ASC enabled/disabled 
   * @n  parameter are by default stored in the volatile memory (RAM) only and will be lost after a power-cycle.
   * @return None
   * @note To avoid unnecessary wear of the EEPROM, the persist_settings command should only be sent 
   * @n  when persistence is required and if actual changes to the configuration have been made. 
   * @n  The EEPROM is guaranteed to endure at least 2000 write cycles before failure.
   * @note Command execution time : 800 ms
   * @n When executing the command, the sensor can't be in period measurement mode
   */
  // SCD4X.persistSettings();
  /**
   * @brief reinit reinit
   * @details  The reinit command reinitializes the sensor by reloading user settings from EEPROM.
   * @return None
   * @note Before sending the reinit command, the stop measurement command must be issued.
   * @n  If the reinit command does not trigger the desired re-initialization, 
   * @n  a power-cycle should be applied to the SCD4x.
   * @n  Command execution time : 20 ms
   * @n When executing the command, the sensor can't be in period measurement mode
   */
  //SCD4X.moduleReinit();
  /**
   * @brief set periodic measurement mode
   * @param mode - periodic measurement mode:
   * @n       SCD4X_START_PERIODIC_MEASURE : start periodic measurement, signal update interval is 5 seconds.
   * @n       SCD4X_STOP_PERIODIC_MEASURE : stop periodic measurement command
   * @n       SCD4X_START_LOW_POWER_MEASURE :  start low power periodic measurement, signal update interval is approximately 30 seconds.
   * @return None
   * @note The measurement mode must be disabled when changing the sensor settings; after giving the stop_periodic_measurement command, the sensor needs to wait 500ms before responding to other commands.
   */
  SCD4X.enablePeriodMeasure(SCD4X_START_PERIODIC_MEASURE);
  Serial.println();
}
void loop()
{
  /**
   * @brief get data ready status
   * @return data ready status:
   * @n        true : data ready
   * @n        false : data not ready
   */
  if(SCD4X.getDataReadyStatus()) {
    /**
     * @brief set ambient pressure
     * @param ambientPressure - the current ambient pressure, unit Pa
     * @return None
     */
    // SCD4X.setAmbientPressure(96000);
    /**
     * @brief Read the measured data
     * @param data - sSensorMeasurement_t, the values measured by the sensor, including CO2 concentration (ppm), temperature (℃) and humidity (RH)
     * @n  typedef struct {
     * @n    uint16_t   CO2ppm;
     * @n    float   temp;
     * @n    float   humidity;
     * @n  } sSensorMeasurement_t;
     * @return None
     * @note CO2 measurement range: 0~40000 ppm; temperature measurement range: -10~60 ℃; humidity measurement range: 0~100 %RH.
     */
    DFRobot_SCD4X::sSensorMeasurement_t data;
    SCD4X.readMeasurement(&data);
    Serial.print("Carbon dioxide concentration : ");
    Serial.print(data.CO2ppm);
    Serial.println(" ppm");
    Serial.print("Environment temperature : ");
    Serial.print(data.temp);
    Serial.println(" C");
    Serial.print("Relative humidity : ");
    Serial.print(data.humidity);
    Serial.println(" RH");
    Serial.println();
  }
  delay(1000);
}
Expected Result 1

Sample Code 2 - Single Measurement
Read data after waking up the sensor, then let it enter sleep mode again.
/*!
 * @file  singleShotMeasure.ino
 * @brief  This sample shows how to set single measurement mode, perform reset operation, and set sleep and wake-up mode.
 * @details Get 6 data from single measurement, take the average value, print it, enter sleep mode, wake up the sensor after 5 minutes, and repeat the above measurement process
 * @copyright  Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @license  The MIT License (MIT)
 * @author  [qsjhyy]([email protected])
 * @version  V1.0
 * @date  2022-05-11
 * @url  https://github.com/DFRobot/DFRobot_SCD4X
 */
#include <DFRobot_SCD4X.h>
/**
 * @brief Constructor
 * @param pWire - Wire object is defined in Wire.h, so just use &Wire and the methods in Wire can be pointed to and used
 * @param i2cAddr - SCD4X I2C address.
 */
DFRobot_SCD4X SCD4X(&Wire, /*i2cAddr = */SCD4X_I2C_ADDR);
void setup(void)
{
  Serial.begin(115200);
  // Init the sensor
  while( !SCD4X.begin() ){
    Serial.println("Communication with device failed, please check connection");
    delay(3000);
  }
  Serial.println("Begin ok!");
  /**
   * @brief set periodic measurement mode
   * @param mode - periodic measurement mode:
   * @n       SCD4X_START_PERIODIC_MEASURE : start periodic measurement, signal update interval is 5 seconds.
   * @n       SCD4X_STOP_PERIODIC_MEASURE : stop periodic measurement command
   * @n       SCD4X_START_LOW_POWER_MEASURE :  start low power periodic measurement, signal update interval is approximately 30 seconds.
   * @return None
   * @note The measurement mode must be disabled when configuring the sensor; after giving the stop_periodic_measurement command, the sensor needs to wait 500ms before responding to other commands.
   */
  SCD4X.enablePeriodMeasure(SCD4X_STOP_PERIODIC_MEASURE);
  /**
   * @brief perform self test
   * @details The perform_self_test feature can be used as an end-of-line test to check sensor 
   * @n  functionality and the customer power supply to the sensor.
   * @return module status:
   * @n        0 : no malfunction detected
   * @n        other : malfunction detected
   * @note Command execution time : 10000 ms
   * @n When executing the command, the sensor can't be in period measurement mode.
   */
  if(0 != SCD4X.performSelfTest()) {
    Serial.println("Malfunction detected!");
  }
  Serial.println();
}
void loop()
{
  /**
   * @brief Set the sensor as sleep or wake-up mode (SCD41 only)
   * @param mode - Sleep and wake-up mode:
   * @n       SCD4X_POWER_DOWN : Put the sensor from idle to sleep to reduce current consumption.
   * @n       SCD4X_WAKE_UP : Wake up the sensor from sleep mode into idle mode.
   * @return None
   * @note Note that the SCD4x does not acknowledge the wake_up command. Command execution time : 20 ms
   * @n When executing the command, the sensor can't be in period measurement mode.
   */
  Serial.print("Waking sensor...");
  SCD4X.setSleepMode(SCD4X_WAKE_UP);
  DFRobot_SCD4X::sSensorMeasurement_t data[6];
  memset(data, 0, sizeof(data));
  uint32_t averageCO2ppm=0;
  float averageTemp=0.0, averageHumidity=0.0;
  Serial.print("Measuring...");
  for(uint8_t i=0; i<6; i++) {
    /**
     * @brief measure single shot(SCD41 only)
     * @details  On-demand measurement of CO2 concentration, relative humidity and temperature.
     * @n  Get the measured data through readMeasurement(sSensorMeasurement_t data) interface
     * @param mode - Single-measurement mode:
     * @n       SCD4X_MEASURE_SINGLE_SHOT : On-demand measurement of CO2 concentration, relative humidity and temperature. 
     * @n                                   Max command duration 5000 [ms].
     * @n       SCD4X_MEASURE_SINGLE_SHOT_RHT_ONLY : On-demand measurement of relative humidity and temperature only.
     * @n                                            Max command duration 50 [ms].
     * @note In SCD4X_MEASURE_SINGLE_SHOT_RHT_ONLY mode, CO2 output is returned as 0 ppm.
     * @return None
     * @note When executing the command, the sensor can't be in period measurement mode.
     */
    SCD4X.measureSingleShot(SCD4X_MEASURE_SINGLE_SHOT);
    /**
     * @brief get data ready status
     * @return data ready status:
     * @n        true : data ready
     * @n        false : data not ready
     */
    while(!SCD4X.getDataReadyStatus()) {
      delay(100);
    }
    /**
     * @brief Read the measured data
     * @param data - sSensorMeasurement_t, the values measured by the sensor, including CO2 concentration (ppm), temperature (℃) and humidity (RH)
     * @n  typedef struct {
     * @n    uint16_t   CO2ppm;
     * @n    float   temp;
     * @n    float   humidity;
     * @n  } sSensorMeasurement_t;
     * @return None
     * @note CO2 measurement range: 0~40000 ppm; temperature measurement range: -10~60 ℃; humidity measurement range: 0~100 %RH.
     */
    SCD4X.readMeasurement(&data[i]);
    if(0 != i) {   // Discard the first set of data, because the chip datasheet indicates the first reading obtained after waking up is invalid
      averageCO2ppm += data[i].CO2ppm;
      averageTemp += data[i].temp;
      averageHumidity += data[i].humidity;
    }
    Serial.print(i);
  }
  Serial.print("\nCarbon dioxide concentration : ");
  Serial.print(averageCO2ppm / 5);
  Serial.println(" ppm");
  Serial.print("Environment temperature : ");
  Serial.print(averageTemp / 5);
  Serial.println(" C");
  Serial.print("Relative humidity : ");
  Serial.print(averageHumidity / 5);
  Serial.println(" RH\n");
  // Put the sensor from idle to sleep to reduce current consumption.
  Serial.print("Sleeping sensor...");
  SCD4X.setSleepMode(SCD4X_POWER_DOWN);
  delay(300000);   // Wake up the sensor after 5 minutes, and repeat the above measurement process
}
Expected Result 2

Main API Functions
/**
   * @fn enablePeriodMeasure
   * @brief set periodic measurement mode
   * @param mode - periodic measurement mode:
   * @n       SCD4X_START_PERIODIC_MEASURE : start periodic measurement, signal update interval is 5 seconds.
   * @n       SCD4X_STOP_PERIODIC_MEASURE : stop periodic measurement command
   * @n       SCD4X_START_LOW_POWER_MEASURE :  start low power periodic measurement, signal update interval is approximately 30 seconds.
   * @return None
   * @note The measurement mode must be disabled when configuring the sensor; after giving the stop_periodic_measurement command, the sensor needs to wait 500ms before responding to other commands.
   */
  void enablePeriodMeasure(uint16_t mode);
  /**
   * @fn readMeasurement
   * @brief Read the measured data
   * @param data - sSensorMeasurement_t, the values measured by the sensor, including CO2 concentration (ppm), temperature (℃) and humidity (RH)
   * @return None
   * @note CO2 measurement range: 0~40000 ppm; temperature measurement range: -10~60 ℃; humidity measurement range: 0~100 %RH.
   */
  void readMeasurement(sSensorMeasurement_t * data);
  /**
   * @fn getDataReadyStatus
   * @brief get data ready status
   * @return data ready status:
   * @n        true : data ready
   * @n        false : data not ready
   */
  bool getDataReadyStatus(void);
Raspberry Pi Tutorial
Requirements
- 
Hardware - Raspberry Pi 4 Model B (or similar) x 1
- Gravity: SCD41 Infrared CO2 Sensor - I2C x 1
- M-M/F-M/F-F Jumper wires x 1
 
- 
Software - Download and install the SCD41 CO2 Sensor python library.
- RASPBIAN
 
Connection Diagram
- Connect the module to Raspberry Pi according to the connection diagram. The I2C address is 0x62.

Installation
- 
Enable the I2C interface of Raspberry Pi. If it's already enabled, skip this step. Open Terminal, type the following command, and press Enter: 
 pi@raspberrypi:~ $ sudo raspi-config
 Then use the up and down keys to select "5 Interfacing Options" -> "P5 I2C" and press Enter to confirm “YES”. Reboot the Raspberry Pi.
- 
Installing Python dependency libraries and git (networking required). If it is already installed, skip this step. In the Terminal, type the following commands, and press Enter: 
 pi@raspberrypi:~ $ sudo apt-get update
 pi@raspberrypi:~ $ sudo apt-get install build-essential python-dev python-smbus git
- 
Download DFRobot_SCD4X driver library. In Terminal, type the following commands, and press Enter: 
 pi@raspberrypi:~ $ cd Desktop/
 pi@raspberrypi:~/Desktop $ git clone https://github.com/dfrobot/DFRobot_SCD4X
Sample Code
- Sample Code 1 - Period Measurement (period_measure.py)
- Sample Code 2 - Single-shot Measurement (single_shot_measure.py)
Sample Code 1 - Period Measurement (period_measure.py)
- In Terminal, type the following commands and press Enter to run sample codes:
 pi@raspberrypi:~/Desktop $ cd DFRobot_SCD4X/python/raspberrypi/examples/
 pi@raspberrypi:~/Desktop/DFRobot_SCD4X/python/raspberrypi/examples/ $ python period_measure.py
Sample Code 2 - Single-shot Measurement (single_shot_measure.py)
- In Terminal, type the following commands and press Enter to run sample codes:
 pi@raspberrypi:~/Desktop $ cd DFRobot_SCD4X/python/raspberrypi/examples/
 pi@raspberrypi:~/Desktop/DFRobot_SCD4X/python/raspberrypi/examples/ $ python single_shot_measure.py
FAQ
For any questions, advice or cool ideas to share, please visit the DFRobot Forum.
Q:Encountering I2C address conflicts?
A: For a comprehensive guide on identifying and resolving I2C address conflicts in embedded systems, check out this detailed article: How to Resolve I2C Address Conflicts. It covers practical hardware and software solutions to ensure smooth communication in your IoT devices.
