Arduino UNO R4 - SCD40 CO2 Sensor

In this guide, we will learn how to use the SCD40 CO2 sensor with the Arduino UNO R4 WiFi or Minima to find out how much carbon dioxide is in the air around your desk. A room full of people slowly fills with CO2, and high levels make us tired. With this project you can see the number and know when to open a window. In detail, we will learn:

Arduino UNO R4 and SCD40 CO2 sensor module

Overview of SCD40 CO2 Sensor

The SCD40 is a small sensor from Sensirion (part of the SCD4x family). Many cheap "air quality" sensors only guess the CO2 level from other gases. For example, the MQ2 in our Arduino UNO R4 - Gas Sensor tutorial reacts to many gases at once. The SCD40 measures CO2 itself, using a method called photoacoustic NDIR: a tiny infrared light pulses inside the sensor, CO2 absorbs some of that light and makes a very small pressure "sound", and a microphone picks it up. More CO2 gives a stronger sound.

SCD40
Supply voltage 2.4V to 5.5V
Interface I2C, address 0x62
Output range 0 to 40,000 ppm
Accuracy ±(50 ppm + 5% of reading), from 400 to 2,000 ppm
New reading every 5 seconds (every 30 seconds in low-power mode)
Temperature accuracy ±0.8°C (15°C to 35°C)
Humidity accuracy ±6 %RH (15°C to 35°C, 20 to 65 %RH)
Average current about 15 mA at 3.3V

The sensor has Automatic Self-Calibration (ASC), and it is on by default. It expects to see fresh, outdoor-level air (about 400 ppm) at least once a week, best for an hour or more. A room that is aired out from time to time is enough. Also, the first few readings after power-on can be a bit off while the sensor warms up.

What the numbers mean:

CO2 (ppm) Air quality
About 400 Fresh outdoor air
400 - 1000 Good indoor air
1000 - 2000 Stuffy, open a window
Above 2000 Poor, may cause headache or drowsiness
SCD40 CO2 sensor pinout

The SCD40 module has four pins:

  • VCC pin (may be labeled VIN): connect to 5V or 3.3V of the Arduino UNO R4.
  • GND pin: connect to GND (0V).
  • SCL pin: I2C clock, connect to the SCL pin of the Arduino UNO R4.
  • SDA pin: I2C data, connect to the SDA pin of the Arduino UNO R4.

Most SCD40 modules already have I2C pull-up resistors on board, so there's no need to add them yourself.

Wiring Diagram

The Arduino UNO R4 has its main I2C bus on A4 (SDA) and A5 (SCL). The same two signals also come out on the SDA and SCL header pins near the AREF pin, so you can use either place.

The wiring diagram between Arduino UNO R4 SCD40 CO2 sensor

This image is created using Fritzing. Click to enlarge image

See The best way to supply power to the Arduino Uno R4 and other components.

SCD40 Module Arduino UNO R4
VCC 5V
GND GND
SCL SCL (A5)
SDA SDA (A4)

※ NOTE THAT:

The Qwiic connector on the Arduino UNO R4 WiFi is a different I2C bus (Wire1) and works at 3.3V. This guide uses the normal pins and Wire, so it works the same on the WiFi and the Minima.

How To Program For SCD40 Sensor

  • Include the libraries.
#include <SensirionI2cScd4x.h> #include <Wire.h>
  • Create an SCD40 sensor object.
SensirionI2cScd4x scd4x;
  • Start the I2C bus and connect the sensor at address 0x62:
Wire.begin(); scd4x.begin(Wire, SCD40_I2C_ADDR_62);
  • Start the periodic measurement:
scd4x.startPeriodicMeasurement();
  • Check if a new reading is ready, then read it:
bool dataReady = false; scd4x.getDataReadyStatus(dataReady); if (dataReady) { scd4x.readMeasurement(co2, temperature, humidity); }

Every library function returns an error code. When it is not 0, errorToString() turns it into readable text, and the code prints it to the Serial Monitor.

Arduino UNO R4 Code - SCD40 CO2

/* * This Arduino UNO R4 code was developed by newbiely.com * * This Arduino UNO R4 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-r4/arduino-uno-r4-scd40-co2-sensor */ // Arduino UNO R4 + SCD40: read the CO2 level in ppm // Wiring: SDA -> SDA (A4), SCL -> SCL (A5), VCC -> 5V, GND -> GND #include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h> SensirionI2cScd4x scd4x; // the SCD40 sensor object char errorMessage[64]; int16_t error; // Turn a CO2 value into a simple air quality word const char *airQuality(uint16_t co2) { if (co2 < 1000) return "Good"; if (co2 < 2000) return "Moderate - open a window"; return "Poor"; } void setup() { Serial.begin(9600); while (!Serial) { delay(10); } Wire.begin(); // the default I2C bus of the Arduino UNO R4 scd4x.begin(Wire, SCD40_I2C_ADDR_62); // Clean start: wake the sensor, stop any old measurement, reload settings scd4x.wakeUp(); // may return an error if the sensor is already awake - that is OK scd4x.stopPeriodicMeasurement(); scd4x.reinit(); // Start measuring: the SCD40 makes a new reading every 5 seconds error = scd4x.startPeriodicMeasurement(); if (error != 0) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print("Cannot start the measurement: "); Serial.println(errorMessage); return; } Serial.println("SCD40 started. Waiting for the first reading..."); } void loop() { bool dataReady = false; uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; // Ask the sensor every second if a new reading is ready delay(1000); error = scd4x.getDataReadyStatus(dataReady); if (error != 0) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print("Data ready error: "); Serial.println(errorMessage); return; } if (!dataReady) { return; // not ready yet, try again in the next loop } // Read the measurement (temperature and humidity are not used here) error = scd4x.readMeasurement(co2, temperature, humidity); if (error != 0) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print("Read error: "); Serial.println(errorMessage); return; } Serial.print("CO2: "); Serial.print(co2); Serial.print(" ppm -> "); Serial.println(airQuality(co2)); }

Detailed Instructions

Follow these instructions step by step:

  • If this is your first time using the Arduino Uno R4 WiFi/Minima, refer to the tutorial on setting up the environment for Arduino Uno R4 WiFi/Minima in the Arduino IDE.
  • Wire the components according to the provided diagram.
  • Connect the Arduino Uno R4 board to your computer using a USB cable.
  • Launch the Arduino IDE on your computer.
  • Select the appropriate Arduino Uno R4 board (e.g., Arduino Uno R4 WiFi) and COM port.
  • Click on the Libraries icon on the left side of the Arduino IDE.
  • Type "SCD4x" in the search box and find the Sensirion I2C SCD4x library by Sensirion.
  • Click the Install button. When the IDE asks to install the dependency Sensirion Core, click Install All.
  • Search for Sensirion I2C SCD4x created by Sensirion and click the Install button.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Uno R4 WiFi
Library Manager
Type:
All
Topic:
All
Sensirion I2C SCD4x by Sensirion
Enables you to use the SCD4X sensor family via I2C. More info
1.1.0
INSTALL
Newbiely.ino
···
1 void setup() {
Output
Serial Monitor
Ln 1, Col 1
Arduino Uno R4 WiFi on COM15
1
  • Copy the code above and paste it into the Arduino IDE.
  • Click the Upload button to upload the code to the Arduino UNO R4.
  • Open the Serial Monitor and wait about 5 seconds for the first value.
  • Breathe slowly toward the sensor for a few seconds and watch the number rise, then fall again.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Uno R4 WiFi
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Uno R4 WiFi' on 'COM15')
New Line
9600 baud
SCD40 started. Waiting for the first reading... CO2: 538 ppm -> Good CO2: 544 ppm -> Good CO2: 551 ppm -> Good CO2: 1187 ppm -> Moderate - open a window CO2: 1462 ppm -> Moderate - open a window CO2: 1093 ppm -> Moderate - open a window CO2: 812 ppm -> Good CO2: 626 ppm -> Good
Ln 11, Col 1
Arduino Uno R4 WiFi on COM15
2

A new line appears about every 5 seconds, because that is how often the SCD40 makes a new measurement.

※ NOTE THAT:

If you only see error messages, check the SDA and SCL wires first. They are easy to swap by mistake.

Reading Temperature and Humidity from the SCD40

The SCD40 also has its own temperature and humidity sensor inside. The chip uses it to correct the CO2 value, and you can read it too. In fact, readMeasurement() already returns all three values in one call. The first sketch simply did not print them. The code below prints CO2, temperature and humidity on one line.

/* * This Arduino UNO R4 code was developed by newbiely.com * * This Arduino UNO R4 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-r4/arduino-uno-r4-scd40-co2-sensor */ // Arduino UNO R4 + SCD40: read CO2, temperature and humidity // Wiring: SDA -> SDA (A4), SCL -> SCL (A5), VCC -> 5V, GND -> GND #include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h> SensirionI2cScd4x scd4x; // the SCD40 sensor object char errorMessage[64]; int16_t error; // Print the error text when a command fails void printError(const char *label) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print(label); Serial.println(errorMessage); } void setup() { Serial.begin(9600); while (!Serial) { delay(10); } Wire.begin(); // the default I2C bus of the Arduino UNO R4 scd4x.begin(Wire, SCD40_I2C_ADDR_62); // Clean start scd4x.wakeUp(); // may return an error if the sensor is already awake - that is OK scd4x.stopPeriodicMeasurement(); scd4x.reinit(); error = scd4x.startPeriodicMeasurement(); // new reading every 5 seconds if (error != 0) { printError("Cannot start the measurement: "); return; } Serial.println("SCD40 started. Waiting for the first reading..."); } void loop() { bool dataReady = false; uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; delay(1000); error = scd4x.getDataReadyStatus(dataReady); if (error != 0) { printError("Data ready error: "); return; } if (!dataReady) { return; // wait until the sensor has a new reading } // One command gives all three values error = scd4x.readMeasurement(co2, temperature, humidity); if (error != 0) { printError("Read error: "); return; } Serial.print("CO2: "); Serial.print(co2); Serial.print(" ppm | Temperature: "); Serial.print(temperature, 1); Serial.print(" °C | Humidity: "); Serial.print(humidity, 1); Serial.println(" %"); }

Detailed Instructions

  • Keep the same wiring.
  • Copy the code above and paste it into the Arduino IDE.
  • Click the Upload button to upload the code to the Arduino UNO R4.
  • Open the Serial Monitor.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Uno R4 WiFi
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Uno R4 WiFi' on 'COM15')
New Line
9600 baud
SCD40 started. Waiting for the first reading... CO2: 702 ppm | Temperature: 24.6 °C | Humidity: 47.3 % CO2: 709 ppm | Temperature: 24.6 °C | Humidity: 47.1 % CO2: 715 ppm | Temperature: 24.7 °C | Humidity: 47.0 % CO2: 721 ppm | Temperature: 24.7 °C | Humidity: 46.8 %
Ln 11, Col 1
Arduino Uno R4 WiFi on COM15
2

The temperature can read a little higher than the room, because the sensor and the board warm up slightly while they work.

Video Tutorial

Function References

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!