Using the SCD4x with Arduino involves wiring up the sensor to your Arduino-compatible microcontroller, installing the Arduino I2C SCD4x library written by Sensirion, and running the provided example code.
I2C Wiring
Here is how to wire up the sensor using one of the STEMMA QT connectors. The examples show a Metro but wiring will work the same for an Arduino or other compatible board.
- 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:
- 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.
Click the Manage Libraries ... menu item, search for SCD4x , and select the Sensirion I2C SCD4x library:
If asked about dependencies, click "Install all".
/* * 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); Serial.println(errorMessage); return; } while (!dataReady) { delay(100); error = sensor.getDataReadyStatus(dataReady); if (error != NO_ERROR) { Serial.print("Error trying to execute getDataReadyStatus(): "); errorToString(error, errorMessage, sizeof errorMessage); Serial.println(errorMessage); return; } } // // If ambient pressure compenstation during measurement // is required, you should call the respective functions here. // Check out the header file for the function definition. error = sensor.readMeasurement(co2Concentration, temperature, relativeHumidity); if (error != NO_ERROR) { Serial.print("Error trying to execute readMeasurement(): "); errorToString(error, errorMessage, sizeof errorMessage); Serial.println(errorMessage); return; } // // Print results in physical units. Serial.print("CO2 concentration [ppm]: "); Serial.print(co2Concentration); Serial.println(); Serial.print("Temperature [°C]: "); Serial.print(temperature); Serial.println(); Serial.print("Relative Humidity [RH]: "); Serial.print(relativeHumidity); Serial.println(); }
After opening the demo file, upload to your Arduino wired up to the sensor. Once you upload the code, you will see the CO2, temperature, and relative humidity data values being printed when you open the Serial Monitor (Tools->Serial Monitor) at 115200 baud, similar to this:
Page last edited January 31, 2025
Text editor powered by tinymce.