Arduino UNO Q - SCD40 CO2 Sensor

Feeling sleepy in a closed room is often a sign of too much CO2. With an SCD40 sensor, the Arduino UNO Q can measure the real CO2 level in your room — and its Linux side can text you on Telegram when it is time to open a window.

In this tutorial, you will learn:

Arduino UNO Q SCD40 CO2 Sensor

Hardware Preparation

1×Arduino UNO Q
1×USB Cable for Arduino Uno Q
1×SCD40 CO2 Sensor Module
1×Jumper Wires
1×Recommended: Screw Terminal Block Shield for Arduino Uno
1×Recommended: Sensors/Servo Expansion Shield for Arduino Uno
1×Recommended: Breadboard Shield for Arduino Uno
1×Recommended: Enclosure for Arduino Uno
1×Recommended: Prototyping Base Plate & Breadboard Kit for Arduino UNO

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 the SCD40 CO2 Sensor

The SCD40 from Sensirion measures true CO2, not a guess based on other gases (the "eCO2" of sensors like the MQ135 or CCS811). Inside, a tiny infrared light pulses through a small chamber. CO2 absorbs some of that light and makes a very small pressure "sound", which a microphone picks up — more CO2 gives a stronger signal. This is called photoacoustic NDIR sensing.

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
Update Rate 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
SCD40 CO2 Sensor Pinout

The SCD40 module has 4 pins:

  • VCC (VIN): Power, 2.4V to 5.5V — on the Arduino UNO Q, use 3.3V
  • GND: Ground (0V)
  • SCL: I2C clock line
  • SDA: I2C data line

Most SCD40 breakout modules already have I2C pull-up resistors on board, so no extra parts are needed.

What do the numbers mean?

CO2 Level Air Quality
about 400 ppm Fresh outdoor air
400 – 1000 ppm Good indoor air
1000 – 2000 ppm Stuffy — open a window
above 2000 ppm Poor — headache and drowsiness possible

※ NOTE THAT:

  • Automatic self-calibration (ASC) is on by default. It expects the sensor to see fresh outdoor-level air (about 400 ppm) at least once a week, ideally for an hour or more — for example, an aired room or a window sill.
  • The first few readings after power-up can be less accurate. Let it run for a few minutes.

Wiring Diagram

The wiring diagram between Arduino UNO Q SCD40 CO2 sensor

This image is created using Fritzing. Click to enlarge image

SCD40 Pin Arduino UNO Q MCU
VCC 3.3V
GND GND
SDA SDA
SCL SCL

Use the pins labeled SDA and SCL on the Arduino UNO Q header — they are the MCU's default I2C bus, which Wire.begin() uses.

How To Program For SCD40

  • Include the Sensirion library and Wire, then create the sensor object:
#include <SensirionI2cScd4x.h> #include <Wire.h> SensirionI2cScd4x scd4x;
  • Start I2C and attach the sensor at address 0x62:
Wire.begin(); scd4x.begin(Wire, SCD40_I2C_ADDR_62);
  • Give the sensor a clean start, then begin measuring (a new value every 5 seconds):
scd4x.wakeUp(); scd4x.stopPeriodicMeasurement(); scd4x.reinit(); scd4x.startPeriodicMeasurement();
  • Check whether a new value is waiting:
bool dataReady = false; scd4x.getDataReadyStatus(dataReady);
  • Read it — one call returns CO2, temperature, and humidity together:
uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; int16_t error = scd4x.readMeasurement(co2, temperature, humidity);
  • If error is not 0, turn it into readable text:
char errorMessage[64]; errorToString(error, errorMessage, sizeof errorMessage);

Arduino UNO Q Code

The Arduino UNO Q splits the work between two processors:

  • The STM32 MCU talks to the SCD40 over I2C
  • The Qualcomm MPU runs Debian Linux and has Wi-Fi
  • For now only the MCU runs code. The Bridge section later lets Linux read the CO2 value too.

This first sketch focuses on CO2 only. Every time the sensor has a new value, it prints the ppm and a one-word rating from the table above.

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-scd40-co2-sensor */ // Arduino UNO Q - SCD40 CO2 Sensor: read the CO2 level (ppm) // The SCD40 talks I2C (address 0x62) on the SDA/SCL header pins of the Arduino UNO Q MCU. // Library: "Sensirion I2C SCD4x" by Sensirion (needs "Sensirion Core") #include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h> SensirionI2cScd4x scd4x; int16_t error; char errorMessage[64]; // 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 "Stuffy - open a window"; return "Poor"; } void setup() { Serial.begin(115200); delay(1500); Wire.begin(); // SDA/SCL pins of the Arduino UNO Q scd4x.begin(Wire, SCD40_I2C_ADDR_62); // Clean start: the sensor may still be measuring from an earlier run scd4x.wakeUp(); // result ignored: fails if already awake scd4x.stopPeriodicMeasurement(); scd4x.reinit(); error = scd4x.startPeriodicMeasurement(); // a new reading every 5 seconds if (error != 0) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print("startPeriodicMeasurement error: "); Serial.println(errorMessage); return; } Serial.println("Arduino UNO Q SCD40 ready - first reading in about 5 seconds"); } void loop() { delay(1000); // ask the sensor once per second if new data is ready bool dataReady = false; error = scd4x.getDataReadyStatus(dataReady); if (error != 0) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print("getDataReadyStatus error: "); Serial.println(errorMessage); return; } if (!dataReady) { return; // no new value yet } uint16_t co2 = 0; float temperature = 0.0f; // read together with CO2, not printed in this sketch float humidity = 0.0f; error = scd4x.readMeasurement(co2, temperature, humidity); if (error != 0) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print("readMeasurement error: "); Serial.println(errorMessage); return; } Serial.print("CO2: "); Serial.print(co2); Serial.print(" ppm -> "); Serial.println(airQuality(co2)); }

Detailed Instructions

First time with Arduino UNO Q? Read Getting Started with Arduino UNO Q first.

  • Wire: Connect the SCD40 to the Arduino UNO Q as shown in the wiring diagram (4 wires).
  • Open Arduino App Lab: Wait until it detects your Arduino UNO Q.
  • Create a new App: Click Create New App.
Create New App in Arduino App Lab on Arduino UNO Q
  • Name it SCD40CO2 and click Create.
Arduino App Lab App folders and files on Arduino UNO Q
  • Paste the sketch: Put the code above into sketch/sketch.ino. Keep the other files as they are.
  • Install the library: Click the Add sketch library button (the open book icon with a + sign) in the left sidebar.
Add sketch library in Arduino App Lab on Arduino UNO Q
  • Search for Sensirion I2C SCD4x created by Sensirion and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Sensirion I2C SCD4x Sensirion

Enables you to use the SCD4X sensor family via I2C.

1.1.0
Install
More Info
  • Search for Sensirion Core created by Sensirion and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Sensirion Core Sensirion

All Libraries for Sensirion Sensors use this library as a code base. In this library the Sensirion specific parts for I2C and UART communication are implemented. It provides dynamic frame construction, checksum calculation and buffer handling.

0.7.3
Install
More Info
  • Run: Click the Run button.
Click Run button in Arduino App Lab on Arduino UNO Q
  • Test it: Wait about 5 seconds for the first value. Then breathe gently toward the sensor from a short distance — your breath is full of CO2, so the number jumps up and slowly falls back.

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-10-10 10:05:01] Arduino UNO Q SCD40 ready - first reading in about 5 seconds [2026-10-10 10:05:06] CO2: 618 ppm -> Good [2026-10-10 10:05:11] CO2: 624 ppm -> Good [2026-10-10 10:05:16] CO2: 1187 ppm -> Stuffy - open a window [2026-10-10 10:05:21] CO2: 942 ppm -> Good [2026-10-10 10:05:26] CO2: 731 ppm -> Good

The jump to 1187 ppm is a breath on the sensor. In a closed bedroom overnight, it is normal to see the value climb past 1000 ppm on its own.

Bridge: Linux + MCU

Now let the Linux side read CO2 too:

  • The SCD40 sits on the MCU's I2C bus — the MPU cannot reach it directly
  • The MCU checks the sensor once per second and keeps the latest values in memory
  • The MCU shares them with Bridge.provide(): get_co2 (plus get_temperature, get_humidity, and get_status, used later)
  • Python calls Bridge.call("get_co2") and gets the cached value right away — the callback never waits for the sensor
  • ⚠️ /dev/ttyHS1 (Linux) and Serial1 (MCU) are RESERVED by the router — never open them in user code

In short: MCU reads the SCD40 every 5 seconds → caches CO2 → Python asks for it over Bridge → Linux can log it or send it online.

MCU Code (Bridge)

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-scd40-co2-sensor */ // Arduino UNO Q - SCD40 CO2 sensor shared with Linux via Bridge // The MCU reads the sensor and keeps the latest values. // Linux (Python) asks for them with Bridge.call("get_co2"), etc. #include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h> #include "Arduino_RouterBridge.h" SensirionI2cScd4x scd4x; uint16_t last_co2 = 0; // 0 = no reading yet float last_temperature = 0.0f; // °C float last_humidity = 0.0f; // %RH unsigned long last_check_ms = 0; // Read-only callbacks: they only return cached values, so they never block String get_co2(String arg) { return String(last_co2); } String get_temperature(String arg) { return String(last_temperature, 1); } String get_humidity(String arg) { return String(last_humidity, 1); } String get_status(String arg) { return "CO2: " + String(last_co2) + " ppm Temp: " + String(last_temperature, 1) + "°C Humidity: " + String(last_humidity, 1) + "%"; } void setup() { Bridge.begin(); Monitor.begin(); Wire.begin(); scd4x.begin(Wire, SCD40_I2C_ADDR_62); scd4x.wakeUp(); scd4x.stopPeriodicMeasurement(); scd4x.reinit(); if (scd4x.startPeriodicMeasurement() != 0) { Monitor.println("SCD40 not found - check the SDA/SCL wiring"); } Bridge.provide("get_co2", get_co2); Bridge.provide("get_temperature", get_temperature); Bridge.provide("get_humidity", get_humidity); Bridge.provide("get_status", get_status); Monitor.println("Arduino UNO Q SCD40 Bridge ready"); } void loop() { unsigned long now = millis(); if (now - last_check_ms < 1000) { return; // check once per second } last_check_ms = now; bool dataReady = false; if (scd4x.getDataReadyStatus(dataReady) != 0 || !dataReady) { return; // the SCD40 gives a new value about every 5 seconds } uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; if (scd4x.readMeasurement(co2, temperature, humidity) != 0) { Monitor.println("Failed to read from SCD40!"); return; } last_co2 = co2; last_temperature = temperature; last_humidity = humidity; Monitor.println("CO2: " + String(co2) + " ppm"); }

Python Code (Bridge)

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-scd40-co2-sensor """ from arduino.app_utils import * import time # Linux side: ask the MCU for the latest CO2 value every 5 seconds def air_label(ppm): if ppm <= 1000: return "Good" if ppm <= 2000: return "Stuffy - open a window" return "Poor" def loop(): co2_str = Bridge.call("get_co2") try: co2 = int(co2_str) except ValueError: co2 = 0 if co2 == 0: print("Waiting for the first SCD40 reading...") else: print(f"CO2: {co2} ppm ({air_label(co2)})") time.sleep(5) App.run(user_loop=loop)

Detailed Instructions

  • Create a new App in Arduino App Lab, for example SCD40Bridge.
  • Paste the MCU sketch into sketch/sketch.ino, and add the libraries:
  • Install the library: Click the Add sketch library button (the open book icon with a + sign) in the left sidebar.
Add sketch library in Arduino App Lab on Arduino UNO Q
  • Search for Sensirion I2C SCD4x created by Sensirion and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Sensirion I2C SCD4x Sensirion

Enables you to use the SCD4X sensor family via I2C.

1.1.0
Install
More Info
  • Search for Sensirion Core created by Sensirion and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Sensirion Core Sensirion

All Libraries for Sensirion Sensors use this library as a code base. In this library the Sensirion specific parts for I2C and UART communication are implemented. It provides dynamic frame construction, checksum calculation and buffer handling.

0.7.3
Install
More Info
  • Search for Arduino_RouterBridge created by Arduino and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Arduino_RouterBridge Arduino

This library provides a simple RPC bridge for Arduino UNO Q boards, allowing communication between the board and other devices using MsgPack serialization.

0.4.1
Install
More Info
  • Paste the Python code into the Python file of the same App.
  • Run: Click the Run button. The Python console prints the CO2 level every 5 seconds.

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-10-10 10:20:00] Arduino UNO Q SCD40 Bridge ready [2026-10-10 10:20:05] CO2: 655 ppm [2026-10-10 10:20:10] CO2: 661 ppm [2026-10-10 10:20:15] CO2: 670 ppm
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-10-10 10:20:02] Waiting for the first SCD40 reading... [2026-10-10 10:20:07] CO2: 655 ppm (Good) [2026-10-10 10:20:12] CO2: 661 ppm (Good) [2026-10-10 10:20:17] CO2: 670 ppm (Good)

Telegram

A CO2 sensor is most useful when it tells you something. This bot watches the room and sends one message when CO2 goes above 1000 ppm — the point where air starts to feel stuffy. When the level drops back under 800 ppm (after you open the window), it sends an "all clear". The gap between the two numbers stops the bot from spamming you when the value hovers near 1000.

MCU sketch: Keep the same MCU sketch from the Bridge section.

Python Code (Telegram)

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-scd40-co2-sensor """ from arduino.app_utils import * import requests import time TELEGRAM_BOT_TOKEN = "YOUR_TELEGRAM_BOT_TOKEN" CHAT_ID = "YOUR_CHAT_ID" API_URL = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}" CO2_ALERT_PPM = 1000 # above this: the room is stuffy, open a window CO2_CLEAR_PPM = 800 # below this: the air is fresh again (gap stops repeat alerts) last_update_id = 0 alert_active = False def get_updates(): try: resp = requests.get(f"{API_URL}/getUpdates", params={"offset": last_update_id + 1, "timeout": 5}, timeout=10) data = resp.json() if data.get("ok"): return data["result"] except Exception as e: print(f"Error getting updates: {e}") return [] def send_message(chat_id, text): try: requests.post(f"{API_URL}/sendMessage", data={"chat_id": chat_id, "text": text}, timeout=10) except Exception as e: print(f"Error sending message: {e}") def check_ventilation(): global alert_active try: co2 = int(Bridge.call("get_co2")) except ValueError: return if co2 == 0: return # no reading yet if co2 > CO2_ALERT_PPM and not alert_active: alert_active = True msg = f"🪟 CO2 is {co2} ppm - the air is getting stuffy. Please open a window." print(msg) send_message(CHAT_ID, msg) elif co2 < CO2_CLEAR_PPM and alert_active: alert_active = False msg = f"✅ CO2 is back to {co2} ppm - fresh air again." print(msg) send_message(CHAT_ID, msg) def loop(): global last_update_id check_ventilation() for update in get_updates(): last_update_id = update["update_id"] if "message" not in update: continue chat_id = update["message"]["chat"]["id"] text = update["message"].get("text", "").strip() print(f"Received: {text}") if text == "/co2": send_message(chat_id, f"CO2: {Bridge.call('get_co2')} ppm") elif text == "/climate": temp = Bridge.call("get_temperature") humi = Bridge.call("get_humidity") send_message(chat_id, f"Temperature: {temp}°C Humidity: {humi}%") elif text == "/status": send_message(chat_id, Bridge.call("get_status")) else: send_message(chat_id, "Arduino UNO Q SCD40 Air Bot\n" "/co2 - CO2 level in ppm\n" "/climate - temperature and humidity\n" "/status - all three values\n" f"Auto alert when CO2 goes above {CO2_ALERT_PPM} ppm.") time.sleep(3) App.run(user_loop=loop)

Detailed Instructions

  • Replace YOUR_TELEGRAM_BOT_TOKEN with your bot token from BotFather. New to bots? See How to Create a Telegram Bot.
  • Replace YOUR_CHAT_ID with your Telegram chat ID — the alerts go there.
  • Paste this code into the Python file of your App (keep the Bridge MCU sketch).
  • Click Run. Send /co2 to check the air. To test the alert, close the door and windows for a while, or breathe near the sensor.
  • Want a stricter or looser rule? Change CO2_ALERT_PPM (for example to 1500).

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-10-10 13:40:03] Received: /co2 [2026-10-10 14:52:18] 🪟 CO2 is 1043 ppm - the air is getting stuffy. Please open a window. [2026-10-10 15:09:33] ✅ CO2 is back to 768 ppm - fresh air again. [2026-10-10 15:10:05] Received: /status
Telegram
Telegram 12:45
Welcome to Telegram!
ArduinoBot 10:19
Chatting with Arduino...
telegram-botfather
BotFather Yesterday
Your bot has been created.

ArduinoBot

bot
Today
/co2
10:15 AM ✓✓
CO2: 712 ppm
10:16 AM
🪟 CO2 is 1043 ppm - the air is getting stuffy. Please open a window.
10:17 AM
✅ CO2 is back to 768 ppm - fresh air again.
10:18 AM
/status
10:19 AM ✓✓
CO2: 771 ppm Temp: 23.6°C Humidity: 47.2%
10:20 AM

Reading Temperature and Humidity from the SCD40

The SCD40 also has its own temperature and humidity sensor. It uses them inside to correct the CO2 value, but you can read them as well — they come from the same readMeasurement() call, so no extra wiring or library is needed.

Note that the Bridge sketch above already shares them as get_temperature and get_humidity, and the Telegram bot answers /climate with both. Below is the MCU-only version that prints all three values.

Arduino UNO Q Code — CO2, Temperature and Humidity

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-scd40-co2-sensor */ // Arduino UNO Q - SCD40: read CO2, temperature and humidity // Library: "Sensirion I2C SCD4x" by Sensirion (needs "Sensirion Core") #include <Arduino.h> #include <SensirionI2cScd4x.h> #include <Wire.h> SensirionI2cScd4x scd4x; int16_t error; char errorMessage[64]; void printError(const char* where) { errorToString(error, errorMessage, sizeof errorMessage); Serial.print(where); Serial.print(" error: "); Serial.println(errorMessage); } void setup() { Serial.begin(115200); delay(1500); Wire.begin(); scd4x.begin(Wire, SCD40_I2C_ADDR_62); scd4x.wakeUp(); // may fail if the sensor is already awake - that is OK scd4x.stopPeriodicMeasurement(); scd4x.reinit(); error = scd4x.startPeriodicMeasurement(); if (error != 0) { printError("startPeriodicMeasurement"); return; } Serial.println("Arduino UNO Q SCD40 (CO2 + temperature + humidity) ready"); } void loop() { delay(1000); bool dataReady = false; error = scd4x.getDataReadyStatus(dataReady); if (error != 0) { printError("getDataReadyStatus"); return; } if (!dataReady) { return; } uint16_t co2 = 0; float temperature = 0.0f; // °C float humidity = 0.0f; // %RH error = scd4x.readMeasurement(co2, temperature, humidity); if (error != 0) { printError("readMeasurement"); 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 and libraries as the first sketch.
  • Replace the code in sketch/sketch.ino with the sketch above and click Run.

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-10-10 16:30:01] Arduino UNO Q SCD40 (CO2 + temperature + humidity) ready [2026-10-10 16:30:06] CO2: 803 ppm | Temperature: 24.3°C | Humidity: 45.8% [2026-10-10 16:30:11] CO2: 809 ppm | Temperature: 24.3°C | Humidity: 45.6% [2026-10-10 16:30:16] CO2: 815 ppm | Temperature: 24.4°C | Humidity: 45.9%

※ NOTE THAT:

The SCD40 warms itself a little while it measures, so its temperature can read slightly higher than a separate thermometer. Keep it away from the Arduino UNO Q's hot parts and give it some airflow.

OpenClaw

You can adapt the OpenClaw to this tutorial by refering the instruction on Arduino Uno Q - OpenClaw Tutorial

Project Ideas

Ideas that use the SCD40 together with both processors of the Arduino UNO Q:

  • Classroom CO2 Light: Show green, yellow, or red on an RGB LED from the ppm table, so students know when to air the room
  • Bedroom Sleep Report: The Linux side logs CO2 all night and sends a Telegram summary in the morning with the highest value
  • Auto Ventilation Fan: Switch a fan through a relay when CO2 passes 1000 ppm, and turn it off below 800 ppm
  • Meeting Room Dashboard: Python reads CO2 over Bridge and serves it on a small web page for everyone in the office
  • Grow Tent Monitor: Track CO2, temperature, and humidity for plants, with a Telegram message if any value leaves its range

Challenge Yourself

Ready to go further with the SCD40 on Arduino UNO Q? Try these:

  • Easy: Blink the built-in LED in the MCU sketch while CO2 is above 1000 ppm.
  • Medium: Make the Python Bridge script save each reading with a timestamp to a CSV file, and print the highest CO2 of the last hour.
  • Advanced: Add a /trend Telegram command that compares the average of the last 5 minutes with the 5 minutes before, and answers "rising", "falling", or "stable" — plus how many minutes are left until 1000 ppm if it keeps rising.

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