Arduino Giga R1 WiFi SCD40 CO2 Sensor

In this guide, we will learn how to use the SCD40 sensor with the Arduino Giga R1 WiFi to find out how much carbon dioxide (CO2) is in the air of a room. In detail, we will learn:

Arduino Giga R1 WiFi and SCD40 CO2 sensor module

A closed room with a few people in it fills up with CO2 faster than you think. When the level gets high, people feel tired and lose focus. With the SCD40 and the Giga R1 WiFi, you can see this happen in numbers, and later send the values over Wi-Fi to a dashboard.

Hardware Preparation

1×Arduino Giga R1 WiFi
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×SCD40 CO2 Sensor Module
1×Jumper Wires
1×Recommended: Screw Terminal Block Shield for Arduino Uno/Mega/Giga
1×Recommended: Sensors/Servo Expansion Shield for Arduino Mega/Giga
1×Recommended: Breadboard Shield for Arduino Mega/Giga
1×Recommended: Enclosure for Arduino Giga
1×Recommended: Power Splitter for Arduino Giga

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Overview of SCD40 CO2 Sensor

The SCD40 from Sensirion measures true CO2. It does not guess the value from other gases, like the cheap "eCO2" sensors (MQ135, CCS811) do. It uses photoacoustic NDIR sensing: a tiny infrared light pulses inside a small chamber, the CO2 in the air takes in some of that light and makes a very small pressure "sound", and a microphone hears it. More CO2 gives a stronger sound. The module also has a temperature and humidity sensor inside, which the chip uses to correct the CO2 value.

Feature SCD40
Supply voltage 2.4V to 5.5V
Interface I2C, address 0x62
CO2 output range 0 to 40,000 ppm
CO2 accuracy ±(50 ppm + 5% of reading), from 400 to 2,000 ppm
New reading every 5 seconds (low-power mode every 30 seconds)
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

Two things to know before you start:

  • Self-calibration (ASC) is ON by default. The sensor expects to see fresh, outdoor-level air (about 400 ppm) at least once a week, best for an hour or more. Air your room from time to time, and the readings stay correct.
  • The first readings after power-up can be a bit off. Give the sensor a few minutes to settle.

Pinout

SCD40 CO2 sensor module pinout
  • VCC pin (sometimes VIN): connect to 3.3V of the Arduino Giga R1 WiFi
  • GND pin: connect to GND (0V)
  • SCL pin: I2C clock line, connect to the SCL pin of the Arduino Giga R1 WiFi
  • SDA pin: I2C data line, connect to the SDA pin of the Arduino Giga R1 WiFi

Most SCD40 breakout modules already carry the I2C pull-up resistors, so there's no need to add them. This makes wiring or soldering easier.

What the CO2 Numbers Mean

CO2 is given in ppm (parts per million). Use this table to judge your room:

CO2 Level Air Quality What To Do
About 400 ppm Outdoor air Nothing, this is fresh air
400 to 1,000 ppm Good indoor air Nothing
1,000 to 2,000 ppm Stuffy Open a window
Above 2,000 ppm Poor Air the room now; headache and sleepiness are possible

Wiring Diagram

The SCD40 needs only four wires. The Giga R1 WiFi has three I2C buses. This guide uses the main one, called Wire, on pin 20 (SDA) and pin 21 (SCL).

The wiring diagram between Arduino Giga R1 WiFi SCD40 CO2 sensor

This image is created using Fritzing. Click to enlarge image

SCD40 Pin Arduino Giga R1 WiFi Pin
VCC 3.3V
GND GND
SDA 20 (SDA)
SCL 21 (SCL)

The SCD40 works from 2.4V to 5.5V, so 5V would power it too. We still pick 3.3V on purpose: the pull-up resistors on the module then pull the I2C lines up to 3.3V, which is the level that the Giga pins expect.

How To Program For SCD40

  • Include the libraries:
#include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h>
  • Create a sensor object:
SensirionI2cScd4x scd4x;
  • Start the I2C bus and tell the library which bus and address to use:
Wire.begin(); scd4x.begin(Wire, SCD40_I2C_ADDR_62);
  • Give the sensor a clean start, then start periodic measurement:
scd4x.wakeUp(); scd4x.stopPeriodicMeasurement(); scd4x.reinit(); scd4x.startPeriodicMeasurement();
  • Check if a new result is ready:
bool dataReady = false; int16_t scdError = scd4x.getDataReadyStatus(dataReady);
  • Read the result. The sensor always sends CO2, temperature and humidity together:
uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; scdError = scd4x.readMeasurement(co2, temperature, humidity);
  • If a function returns a value other than 0, turn it into readable text:
char errorMessage[64]; errorToString(scdError, errorMessage, sizeof errorMessage);

wakeUp() may report an error when the sensor is already awake. That is normal, so the sketch ignores its result.

Arduino Giga R1 WiFi Code - SCD40 CO2 Sensor

What the sketch does:

  1. Starts the SCD40 in periodic mode, so it makes a new measurement every 5 seconds.
  2. Asks the sensor once per second if a new result is ready.
  3. When it is ready, prints the CO2 value in ppm.
  4. Adds a word from the table above: Good (below 1,000 ppm), Moderate (1,000 to 2,000 ppm) or Poor (above 2,000 ppm).
/* * This Arduino Giga R1 WiFi code was developed by newbiely.com * * This Arduino Giga R1 WiFi code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-giga/arduino-giga-r1-wifi-scd40-co2-sensor */ // Arduino Giga R1 WiFi - read CO2 from the SCD40 sensor // The SCD40 is on the main I2C bus "Wire": SDA = pin 20, SCL = pin 21 // Library: "Sensirion I2C SCD4x" by Sensirion (needs "Sensirion Core") #include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h> SensirionI2cScd4x scd4x; char errorMessage[64]; int16_t scdError; // 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(); scd4x.begin(Wire, SCD40_I2C_ADDR_62); // Clean start: wake the sensor, stop any old measurement, reload settings scd4x.wakeUp(); // may report an error if the sensor is already awake - ignore it scd4x.stopPeriodicMeasurement(); scd4x.reinit(); // Start periodic mode: a new reading every 5 seconds scdError = scd4x.startPeriodicMeasurement(); if (scdError) { errorToString(scdError, errorMessage, sizeof errorMessage); Serial.print("Cannot start the SCD40: "); Serial.println(errorMessage); return; } Serial.println("SCD40 started. First result in about 5 seconds..."); } void loop() { delay(1000); // Check if a new result is ready bool dataReady = false; scdError = scd4x.getDataReadyStatus(dataReady); if (scdError) { errorToString(scdError, errorMessage, sizeof errorMessage); Serial.print("Status error: "); Serial.println(errorMessage); return; } if (!dataReady) { return; // not ready yet, try again next loop } // Read the result. The sensor always sends all three values. uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; scdError = scd4x.readMeasurement(co2, temperature, humidity); if (scdError) { errorToString(scdError, 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:

  • New to this board? Set it up first with the Arduino Giga R1 WiFi getting started guide.
  • Wire the components according to the provided diagram.
  • Plug the Giga R1 WiFi into your computer with the USB Type-C cable.
  • Launch the Arduino IDE on your computer.
  • Select the appropriate Arduino Giga R1 WiFi board (e.g., Arduino Giga R1 WiFi) and COM port.
  • Click the Libraries icon on the left bar of the Arduino IDE.
  • Type SCD4x in the search box, then 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.
  • Paste the code above into a new sketch.
  • Press the Upload button and wait until the upload is done.
  • Open the Serial Monitor at 9600 baud.
  • Wait about 5 seconds for the first value. Then breathe gently toward the sensor from a short distance and watch the CO2 number go up.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Giga R1
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Giga R1' on 'COM15')
New Line
9600 baud
SCD40 started. First result in about 5 seconds... CO2: 731 ppm -> Good CO2: 738 ppm -> Good CO2: 744 ppm -> Good CO2: 892 ppm -> Good CO2: 1263 ppm -> Moderate - open a window CO2: 1187 ppm -> Moderate - open a window CO2: 1009 ppm -> Moderate - open a window CO2: 936 ppm -> Good CO2: 812 ppm -> Good
Ln 11, Col 1
Arduino Giga R1 on COM15
2

A new line shows up about every 5 seconds, because that is how often the SCD40 makes a new measurement. The jump in the middle is a breath. Your breath has a lot of CO2, so the value rises quickly and then falls back as the air mixes.

Nothing is printed, or you see an error? Check that SDA is on pin 20 and SCL is on pin 21, not swapped. Also check that VCC goes to 3.3V and GND to GND.

Reading Temperature and Humidity from the SCD40

The SCD40 does more than CO2. Each time it measures, it also sends the air temperature in °C and the relative humidity in %. In fact, the first sketch already received these two values from readMeasurement(), it just did not print them. So no new wiring and no new library are needed. We only print all three values.

Keep in mind that the sensor warms itself a little while it works, so the temperature can read a bit higher than a thermometer in the same room.

/* * This Arduino Giga R1 WiFi code was developed by newbiely.com * * This Arduino Giga R1 WiFi code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-giga/arduino-giga-r1-wifi-scd40-co2-sensor */ // Arduino Giga R1 WiFi - read CO2, temperature and humidity from the SCD40 sensor // The SCD40 is on the main I2C bus "Wire": SDA = pin 20, SCL = pin 21 // Library: "Sensirion I2C SCD4x" by Sensirion (needs "Sensirion Core") #include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h> SensirionI2cScd4x scd4x; char errorMessage[64]; int16_t scdError; void setup() { Serial.begin(9600); while (!Serial) { delay(10); } Wire.begin(); scd4x.begin(Wire, SCD40_I2C_ADDR_62); // Clean start: wake the sensor, stop any old measurement, reload settings scd4x.wakeUp(); // may report an error if the sensor is already awake - ignore it scd4x.stopPeriodicMeasurement(); scd4x.reinit(); // Start periodic mode: a new reading every 5 seconds scdError = scd4x.startPeriodicMeasurement(); if (scdError) { errorToString(scdError, errorMessage, sizeof errorMessage); Serial.print("Cannot start the SCD40: "); Serial.println(errorMessage); return; } Serial.println("SCD40 started. First result in about 5 seconds..."); } void loop() { delay(1000); // Check if a new result is ready bool dataReady = false; scdError = scd4x.getDataReadyStatus(dataReady); if (scdError) { errorToString(scdError, errorMessage, sizeof errorMessage); Serial.print("Status error: "); Serial.println(errorMessage); return; } if (!dataReady) { return; // not ready yet, try again next loop } // Read CO2 (ppm), temperature (°C) and relative humidity (%) uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; scdError = scd4x.readMeasurement(co2, temperature, humidity); if (scdError) { errorToString(scdError, errorMessage, sizeof errorMessage); Serial.print("Read error: "); Serial.println(errorMessage); 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.
  • Paste the new code into the Arduino IDE and upload it.
  • Open the Serial Monitor at 9600 baud.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Giga R1
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Giga R1' on 'COM15')
New Line
9600 baud
SCD40 started. First result in about 5 seconds... CO2: 764 ppm | Temperature: 23.4 °C | Humidity: 47.8 % CO2: 769 ppm | Temperature: 23.4 °C | Humidity: 47.6 % CO2: 777 ppm | Temperature: 23.5 °C | Humidity: 47.5 % CO2: 781 ppm | Temperature: 23.5 °C | Humidity: 47.3 %
Ln 11, Col 1
Arduino Giga R1 on COM15
2

Next step: show the three values on the Arduino Giga R1 WiFi - OLED Display, or switch on a fan with the Arduino Giga R1 WiFi - Controls Fan tutorial when the CO2 level goes above 1,000 ppm.

Video Tutorial

Learn More

※ 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!