Skip to content
SCD-41: Atmospheric CO2, Temp & Humidity

icon picker
SCD-41 Setup Guide

Overview

adafruit_products_SDC41_top.jpg
Take a deep breath in...now slowly breathe out. Mmm, isn't it wonderful? All that air around us, which we bring into our lungs, extracts oxygen from and then breathes out carbon dioxide. CO2 is essential for life on this planet we call Earth - we and plants take turns using and emitting CO2 in an elegant symbiosis. But it's important to keep that CO2 balanced - you don't want too much around, not good for humans and not good for our planet.
adafruit_products_SDC40_top_header.jpg
The SCD-40 and SCD-41 are photoacoustic 'true' CO2 sensors that will tell you the CO2 PPM (parts-per-million) composition of ambient air. - they really are measuring the CO2 concentration! That means they're bigger and more expensive, but they are the real thing. Perfect for environmental sensing, scientific experiments, air quality and ventilation studies, and more.
adafruit_products_SDC41_top_angle.jpg
, this sensor uses a different measurement technique, which allows it to be much smaller. The overall data quality should be very similar, however. Like the SCD-30, this sensor has data read over I2C, so it works very nicely with just about any microcontroller or microcomputer. There's both Arduino and Python/CircuitPython code so you can get started in a jiffy.
adafruit_products_SDC40_top_header.jpg
There are two variants of this sensor - the SCD-40 and SCD-41
The SCD-40 is lower cost and is perfect for indoor/outdoor air quality and CO2 measurements. It has a range of 400~2000 ppm with an accuracy of ±(50 ppm + 5% of reading)
The SCD-41 is more expensive, and while it can definitely be used for air quality, it's wide range means it's best used for industrial or scientific CO2 measurements where the ppm can get very high. It has a range of 400~5000 ppm with an accuracy of ±(40 ppm + 5% of reading)
adafruit_products_SDC41_STEMMA_side.jpg
Nice sensor, right? So we made it easy for you to get right into your next project. The sensor is soldered onto a custom-made PCB in the, making them easy to interface with. The on either side are compatible with the I2C connectors. This allows you to make solderless connections between your development board and the SCD-4x or to chain it with a wide range of other sensors and accessories using a .
adafruit_products_SDC4x_back.jpg
This sensor can run from 3.3 to 5V, but it's more important for it to have a quiet power supply with low ripple, than any particular voltage. You’ll need a 3.3V regulator and level shifters: when connecting to a 5V microcontroller like an Arduino UNO the 5V supply is often shared with other electronic components that add noise. The onboard regulator will keep the voltage nice and quiet. For advanced hackers, they can cut/solder the backtraces to change whether the regulator is enabled and what I2C logic level is desired.

Pinouts

adafruit_products_SCD4x_pinouts.jpg
The SCD-40 and SCD-41 have the same pinouts.

Power Pins

VIN - This is the power pin. To power the board, give it the same power as the logic level of your microcontroller - e.g. for a 3V microcontroller like a Feather M4, use 3V, or for a 5V microcontroller like Arduino, use 5V.
3Vo - This is the output from the onboard 3.3V regulator. If you have a need for a clean 3.3V output, you can use this! It can provide at least 100mA output.
GND - This is common ground for power and logic.

I2C Logic Pins

The default I2C address for the SCD-4x is 0x62.
SCL - I2C clock pin, connect to your microcontroller I2C clock line. There's a 10K pullup on this pin.
SDA - I2C data pin, connect to your microcontroller I2C data line. There's a 10K pullup on this pin.
- These connectors allow you to connectors to development boards with STEMMA QT connectors or to other things with .

Status LED

There is a statis LED marked "on" when the sensor is powered (circled in green).
adafruit_products_stemma-circuit_-_Copy.png
If you do not want this LED to light up (saving power or avoiding light), cut the circuit board jumper in the red box. If you ever want to reenable it, bridge the pads with a bit of solder.


Jumpers

The SCD-4x can run from 3 to 5V DC, for both power and I2C data/logic. Normally that would mean we wouldn't put a regulator and logic level shifter on the breakout. However, the SCD-4x also does best with a quiet power supply that can also supply ~200mA peak. Since that may or may not be the same as the logic power supply of the microcontroller, advanced users can customize the power/logic level setup for the sensor.
On the left is the level-shifted I2C logic level. Most of the time, Vin is the power and logic level for the microcontroller. However, if you are, say, powering from 5v because it's a better power supply source, but are using a 3V logic microcontroller, you can cut and re-solder this jumper.
On the right is the Sensor Power jumper. By default we power the sensor through the 3V regulator. If you happen to have a nice and quiet Vin power supply, you can cut and re-solder this jumper.
adafruit_products_SDC4x_board_back_correct_jumper_labels.jpg
The original silkscreen on the SDC4x boards labeled the jumpers backwards. Sensor Power was on the left and I2C logic was on the right, as shown below. If the image below matches your board, be aware that they are INCORRECTLY labeled!
adafruit_products_image.png

Arduino

Using the SCD4x with Arduino involves wiring up the sensor to your Arduino-compatible microcontroller, installing the library written by Sensirion, and running the provided example code.

I2C Wiring

Here is how to wire up the sensor using one of the connectors. The examples show a Metro but wiring will work the same for an Arduino or other compatible board.
The contents of image.jpeg appear to present a security risk
Connect board VIN (red wire) to Arduino 5V if you are running a 5V board Arduino (Uno, etc.). If your board is 3V, connect to that instead.
Connect board GND (black wire) to Arduino GND
Connect board SCL (yellow wire) to Arduino SCL
Connect board SDA (blue wire) to Arduino SDA
Here is how to wire the sensor to a board using a solderless breadboard:
The contents of image.jpeg appear to present a security risk
Connect board VIN (red wire) to Arduino 5V if you are running a 5V board Arduino (Uno, etc.). If your board is 3V, connect to that instead.
Connect board GND (black wire) to Arduino GND
Connect board SCL (yellow wire) to Arduino SCL
Connect board SDA (blue wire) to Arduino SDA

Library Installation

You can install the Sensirion I2C SCD4x library for Arduino using the Library Manager in the Arduino IDE.
adafruit_products_Arduino_Open_Library_Manager.png
Click the Manage Libraries ... menu item, search for SCD4x , and select the Sensirion I2C SCD4x library:
adafruit_products_SCD4x_arduino_library_install.png
If asked about dependencies, click "Install all".
adafruit_products_Screenshot_2025-01-31_at_15.13.40.png
/*
* THIS FILE IS AUTOMATICALLY GENERATED
*
* Generator: sensirion-driver-generator 1.1.2
* Product: scd4x
* Model-Version: 2.0
*/
/*
* Copyright (c) 2025, Sensirion AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sensirion AG nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <Arduino.h>
#include <SensirionI2cScd4x.h>
#include <Wire.h>

// macro definitions
// make sure that we use the proper definition of NO_ERROR
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0

SensirionI2cScd4x sensor;

static char errorMessage[64];
static int16_t error;

void PrintUint64(uint64_t& value) {
Serial.print("0x");
Serial.print((uint32_t)(value >> 32), HEX);
Serial.print((uint32_t)(value & 0xFFFFFFFF), HEX);
}

void setup() {

Serial.begin(115200);
while (!Serial) {
delay(100);
}
Wire.begin();
sensor.begin(Wire, SCD41_I2C_ADDR_62);

uint64_t serialNumber = 0;
delay(30);
// Ensure sensor is in clean state
error = sensor.wakeUp();
if (error != NO_ERROR) {
Serial.print("Error trying to execute wakeUp(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
}
error = sensor.stopPeriodicMeasurement();
if (error != NO_ERROR) {
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
}
error = sensor.reinit();
if (error != NO_ERROR) {
Serial.print("Error trying to execute reinit(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
}
// Read out information about the sensor
error = sensor.getSerialNumber(serialNumber);
if (error != NO_ERROR) {
Serial.print("Error trying to execute getSerialNumber(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
return;
}
Serial.print("serial number: ");
PrintUint64(serialNumber);
Serial.println();
//
// If temperature offset and/or sensor altitude compensation
// is required, you should call the respective functions here.
// Check out the header file for the function definitions.
// Start periodic measurements (5sec interval)
error = sensor.startPeriodicMeasurement();
if (error != NO_ERROR) {
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
return;
}
//
// If low-power mode is required, switch to the low power
// measurement function instead of the standard measurement
// function above. Check out the header file for the definition.
// For SCD41, you can also check out the single shot measurement example.
//
}

void loop() {

bool dataReady = false;
uint16_t co2Concentration = 0;
float temperature = 0.0;
float relativeHumidity = 0.0;
//
// Slow down the sampling to 0.2Hz.
//
delay(5000);
error = sensor.getDataReadyStatus(dataReady);
if (error != NO_ERROR) {
Serial.print("Error trying to execute getDataReadyStatus(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.