CO2 Sensor for Schools




Introduction: CO2 Sensor for Schools


The scientific understanding of COVID-19 transmission has turned away from the early, highly-publicized measures of fomites (touchable objects that can have the virus on them) and is now focused on aerosols (small, airborne particles that may not drop onto surfaces). Detailed reading here.

Simply put, perhaps your biggest concern regarding COVID transmission should be clean air.

If you are breathing air that has already been exhaled, you could potentially be breathing in aerosols containing the virus. Carbon dioxide (CO2) is a great indicator of the amount of previously respired air in a room - the air we exhale is 4-5% CO2 which is 100 times the amount of CO2 in air we inhale. So CO2 will build up in a room with poor ventilation, just as COVID-containing aerosols will.

With schools, and other places of business, returning to in-person activities, it is challenging to know the air quality in a room. CO2 sensors are a pretty good way to indicate how dense the amount of previously-respired air in a space is, and therefore how much potential COVID could be in the air.

There are good CO2 sensors on the market (We like the Aranet4), as well as quite a few bad ones. General tip: make sure to spend the money on an NDIR-based sensor. We can also make our own for about half of the price! This project comes in around $70-$80 in supplies vs. $150 or more for reliable, 'store-bought' NDIR CO2 sensors.

Created by the Innovation Lab at La Jolla Country Day School, La Jolla, CA, USA.


Note: We link to Adafruit when possible because we believe in their company philosophy. You can order these same parts at other places.

Arduino Nano Every - With headers attached if you want to have minimal soldering required.

Sensirion SDC30 CO2 sensor board ($50-60) - This is a highly accurate and reliable board utilizing NDIR technology. We think it is the best in class and has useful documentation from SparkFun. You will have to purchase and solder your own headers on to the sensor. Otherpurchasingsites.

Headers - Any headers (plug to plug) will work! Need 7 to solder to your SDC30 Sensor.

RGB LED - We use an RGB LED to indicate the CO2 levels via color. Possible to use three, individual colored LED's instead!

Sunfounder LCD1602 - Many LCD Screens *could* work, but the code and pinouts are specifically designed to be used with this style. Note: The LCD takes a lot of power, so not recommended for battery power.

Half-size Breadboard

Plug-to-Plug (M/M) 75mm Jumper wires

Depending on what USB ports your computer has pick one:

USB Cable - USB A - Micro - (*Most* computers feature at least 1 USB-A port)

USB Cable - USB-C - Micro - (Newer computers have more USB-C. Since 2019, MacBook's have been exclusively USB-C ports.)

Equipment Needed

Soldering Iron. The CO2 sensor does not come with headers attached. Learn to solder.

Optional: Laser Cutter or 3D printer for a housing.

Step 1: Assemble

While assembling the circuit, please be mindful of a few things:

  • The wiring for the RGB LED can be a little bit tricky to place the legs into the correct slots as shown in the photo. There's enough space to bend the legs and get them in the right slots without having any of the 4 legs touch, but it's always a good idea to have a couple extra LEDs in case the legs end up getting too bent :)
  • Your Arduino and SCD30 may not have the slots labeled exactly as they are in this diagram, so make sure that you're plugging from the TX/SCL port on the arduino (The image shows a4 but the pin does both!), to the TX/SCL pin on the sensor, and similarly for the RX/SDA pins.
  • On the topic of labels being slightly different, the farthest left pin (VDD or VIN) is where you want your power for the sensor to route to.
  • Specifically this is set up for a 16 x 2 LCD screen that uses a 4 pin I2C backpack (as pictured and as linked in supply!)
  • Make sure you power the LCD screen with 5V, and the Sensor with 3.3v! If you try to power the screen with only 3.3v you're going to have some problems :)
  • Don't forget about the brightness adjustment on the back of the LCD Screen! Try adjusting that before assuming you wired/coded something incorrectly

Step 2: Arduino Coding

We use the Arduino Create Online IDE. Here is our program, which has the following features you may want to edit:

1. LED colors and thresholds (defaults are green: 300-600ppm, purple: 600-800ppm, red: >800ppm)

2. Frequency of sampling (default is one sample per second).

3. Averaging of sampling values (default is 10 samples).

This results is an updated number and LED status every ten seconds.

Tip: Power-efficient options are now laid out in step 5!

Step 3: Verify and Test

We found that (at our humidity and altitude levels in San Diego, CA, USA) the SDC30 is accurate enough out of the box to be used soon after being installed. We compared it to a number of NDIR CO2 sensors and found it to be quite accurate.

To ensure long-term accuracy, though, it runs a self-calibration routine so for the first 7 days it is running you want to give it some fresh air (~1hr per day near a window or in a well-ventilated room). If you unplug it during those first 7 days, the self-calibration routine will restart. Again, this is to get very accurate readings - for inexact purposes like ours, you are probably fine right out of the box.

Detailed procedure on how to measure ventilation rate here.

Step 4: Optional: Choose a Housing

You can make your own housing to protect the sensor unit, just make sure that air can flow to the sensor.

Or, if you have a laser cutter or 3D printer, our students have created files that you can use for your project.

3D Print: The cable for the Arduino might not be perfectly aligned vertically and you may need to place a spacer underneath the breadboard.

Laser cutting file: Made for 3.2mm baltic birch plywood (~1/8th inch). Had space for all the components listed, as well as a piece to hold the breadboard in an each location to line up the slot for the plug!

Step 5: (Optional) Battery Power Alternates

Currently this device works best if it's plugged directly into power (either through a USB port, or a converter to a wall socket!)

However, if portability and battery power are a must for the user, here are a couple suggestions for how you can get the most out of your device!

1) Remove the LCD Screen! The screen itself is the largest power draw of the whole operation. If you remove the screen and rely simply on the Red/Yellow/Green of the LED to indicate for you, the power draw of the device is drastically lowered.

1a) You can also switch the LCD screen to a more power efficient variety, an OLED screen! Currently these are on order, and this guide will be updated once they've arrived and been tested.

2) The current version of the code is set up to take 1 reading from the sensor every second, and after 10 seconds return an average of the 10 measurements it took.

"int times_to_read = 10; // This will control how many readings we take before averaging the data.

unsigned int time_to_wait = 1000; // Controls the time between readings. In Milli seconds (1000 ms = 1 s)"

The first variable here will tell the arduino how many readings to take for it's average, but the SECOND variable will control the time between each data grab (in milliseconds!) Reading every 1 second is very handy for testing, but in practice you don't need updates this frequently. Increasing this variable will increase the time between each read, thus cutting the power. 1000 (the default) is one read a second, but other fine alternatives would be 10000 (one read every 10 seconds) or even 60000 (one read every 60 seconds, or 1 minute)

3) If running on battery power is a must, make sure you choose the most efficient batteries you can! 9V batteries are VERY inefficient for this project, a couple of tests I ran killed the batteries in under 3 hours. 4x AA batteries, or maybe even a LIPO if you're able will likely last longer, but overall the project is best ran on direct power.

Feel free to message or mail in any other power saving tips you might have!

Step 6: Changelog:

Hey all, just adding in a quick section to detail changes we have made to the projects build and coding over the few months we've been using them around our school:

Jan 15:

Fixed error where screen would show gibberish characters instead of actual data until resetting. Program now loads properly without resetting!

Added a startup sequence where the LED flashes Red, Green, and then Blue (In this Order, RGB!). This allows users to make sure the LED is working properly and the colours shown are expected!

Made several updates to the laser cut housings file:

  • Created a slot to mount the LCD screen.
  • Added in more vertical space for the wires and electronics inside.
  • Created a tab and key system to hold the box together
  • Added in a flip top lid for easier access to the inside electronics

Known Bugs:

  • System sometimes freezes up after an extended period of time (12+ hours). I have tried to trim and reduce the code, but there has been no luck finding the source of this issue! If anyone has any leads, please let me know!

5 People Made This Project!


  • Game Design: Student Design Challenge

    Game Design: Student Design Challenge
  • For the Home Contest

    For the Home Contest
  • Big and Small Contest

    Big and Small Contest



1 year ago

As you can see I made this CO2 sensor that I put in a box. I like this application very much and I would like to make one or two more to put in other rooms of my apartment.
Unfortunately after a few hours of operation it crashes, I don't know the reason. I used an Arduino EVERY then an Arduino UNO then an Arduino NANO without success.
As recommended, I powered the assembly via the USB socket.
I'm not a computer scientist, that's why I'm coming to you for help.
Maybe someone has found the fix to the problem.
Thanks a lot for your help.

P.S. sorry for my poor English, moreover I am 76 years old but still interested in these problems


2 years ago

This is a great idea, and an easy build. Me and my 9 year old did this and had great fun. We also got a hang after a few hours. Actually - it was running for a number of hours on a bread board, and then the next day, after about 30 minutes of it running it on a proto shield, we got a hang. The sensor still wouldn't read reliably after a reboot.

I looked at the datasheet for the sensor (which I really should have done first) and it says that the i2c lines are not 5V tolerant. My Uno has 5V i2c lines, I think the Nano Every is the same. Anyway, after putting level shifter on SDA and SCL between the Uno and the SCD30 it's giving readings again!

I don't know if the hang was related to the voltage levels, but would not be suprised if driving 5V to these lines has unpredictable results,

Datasheet is a

"Communication lines for I2C have an internal pull-up (45kOhm) to3V, for higher voltages a level shifter is needed"


2 years ago on Step 6

If your Arduino is crashing after 12 hours, it is likely that you are getting a fragmented heap. The heap just slowly gets bigger and bigger until there is none left. Here's an article that explains the issues.
There are programming techniques that use arrays instead of strings to help minimize fragmentation. Some fragmentation may occur in libraries, where it is not easy to fix.
Here's a link showing some programming techniques to avoid fragmentation.


Reply 2 years ago

Thank you for this (and the tip about the resistor)!

I've made some changes to the code to hopefully reduce the load put on the memory by strings, going to do some testing for a few days to see if I fixed it up!

Will update code (or i guess it updates live thru the link) when i verify I have made things better and not worse!


2 years ago on Step 1

Don't the RGB LED color leads need 200 ohm resistors to prevent too much current flow?