Aller au contenu principal

Capteur CO2 intérieur

InformatiqueTechnologieNUCLEO-L476RG / Arduino / micro:bitCapteur SCD30Écran LCD RGBBandeau NeoPixelVittascience
ProjetDuréeDifficultéÂge
SteamCity2-3 heuresIntermédiaire12-16 ans

Matériel

  • 1 carte programmable (NUCLEO-L476RG, Arduino ou micro:bit)
  • 1 capteur de CO2 SCD30
  • 1 écran LCD RGB 16x2
  • 1 bandeau NeoPixel (30 LED)
  • Câbles de connexion
  • Ordinateur + éditeur Vittascience
Capteur CO2 intérieur

De quoi parle-t-on ?

Cette fiche technique accompagne la ressource Indoor Air Quality. Elle décrit cinq fiches pratiques successives : lire le taux de CO2 avec le capteur SCD30, configurer les couleurs de l'écran LCD, afficher des seuils de CO2 via un bandeau NeoPixel, combiner affichage et indicateur lumineux, puis exporter les données pour les visualiser en graphique.

Objectifs d'apprentissage

  • Lire la valeur de CO2 d'un capteur I2C (SCD30)
  • Contrôler un écran LCD RGB avec couleur et texte
  • Piloter un bandeau NeoPixel selon des seuils
  • Structurer un programme avec conditions if/else if/else
  • Exporter les données pour une analyse graphique

Fiche 1 : Afficher le taux de CO2 sur écran LCD (capteur SCD30)

Éditeurs : vittascience.com/l476, vittascience.com/arduino ou vittascience.com/microbit.

Assemblage Fiche 1
Assemblage du capteur SCD30 et de l'écran LCD

Code

#include <Wire.h>
#include <rgb_lcd.h>
#include <SCD30.h>

rgb_lcd lcdRgb;

float t_scd;
float scd30_co2 = 0;
float scd30_t = 0;
float scd30_h = 0;

void serial_setupConnection(int baudrate) {
Serial.begin(baudrate);
while (!Serial) {
Serial.println("En attente de l'ouverture du port série...");
delay(1000);
}
Serial.println("Port série activé. Baudrate: " + String(baudrate));
delay(50);
}

float scd30_read(uint8_t dataSelect) {
t_scd = millis() - t_scd;
if (t_scd > 1000 && scd30.isAvailable()) {
float result[3] = {0};
scd30.getCarbonDioxideConcentration(result);
scd30_co2 = result[0];
scd30_t = result[1];
scd30_h = result[2];
}
switch (dataSelect) {
case 0: return scd30_co2;
case 1: return scd30_t;
case 2: return scd30_h;
}
}

void setup() {
lcdRgb.begin(16, 2);
serial_setupConnection(9600);
Wire.begin();
scd30.initialize();
t_scd = millis();
lcdRgb.setCursor(0, 0);
lcdRgb.print(String("CO2 level (ppm)"));
lcdRgb.setCursor(0, 0);
lcdRgb.print(String(scd30_read(0)));
}

void loop() {}
Vue blocs Fiche 1
Vue blocs du programme Fiche 1

Fiche 2 : Configurer la couleur de l'écran LCD RGB

Assemblage Fiche 2
Assemblage de l'écran LCD RGB

Code

#include <Wire.h>
#include <rgb_lcd.h>

rgb_lcd lcdRgb;

void setup() {
lcdRgb.begin(16, 2);
lcdRgb.setRGB(255, 96, 0);
}

void loop() { }
Vue blocs Fiche 2
Vue blocs du programme Fiche 2

Fiche 3 : Indicateur LED CO2 (NeoPixel)

Ce programme combine le capteur SCD30 et le bandeau NeoPixel. Des structures conditionnelles if/else if/else permettent d'allumer les LED d'une couleur différente selon le taux de CO2.

On stocke la valeur mesurée dans une variable Taux de CO2 (via le menu Variables > Créer une variable) pour éviter de la recalculer à chaque test.

Assemblage Fiche 3
Assemblage du capteur SCD30 et du bandeau NeoPixel

Code

#include <Wire.h>
#include <SCD30.h>
#include <rgb_lcd.h>
#include <Adafruit_NeoPixel.h>

#define NP_LED_COUNT_2 30

rgb_lcd lcdRgb;
Adafruit_NeoPixel Neopixel_2(NP_LED_COUNT_2, 2, NEO_GRB + NEO_KHZ800);

float t_scd;
float scd30_co2 = 0;
float scd30_t = 0;
float scd30_h = 0;
float CO2_rate;

void serial_setupConnection(int baudrate) {
Serial.begin(baudrate);
while (!Serial) {
Serial.println("En attente de l'ouverture du port série...");
delay(1000);
}
Serial.println("Port série activé. Baudrate: " + String(baudrate));
delay(50);
}

float scd30_read(uint8_t dataSelect) {
t_scd = millis() - t_scd;
if (t_scd > 1000 && scd30.isAvailable()) {
float result[3] = {0};
scd30.getCarbonDioxideConcentration(result);
scd30_co2 = result[0];
scd30_t = result[1];
scd30_h = result[2];
}
switch (dataSelect) {
case 0: return scd30_co2;
case 1: return scd30_t;
case 2: return scd30_h;
}
}

void neopixel_showAllLed(Adafruit_NeoPixel *neoPx, uint8_t ledCount, uint8_t r, uint8_t g, uint8_t b) {
for (int i=0; i<ledCount; i++) {
neoPx->setPixelColor(i, neoPx->Color(r, g, b));
}
neoPx->show();
}

void setup() {
serial_setupConnection(9600);
Wire.begin();
scd30.initialize();
t_scd = millis();
lcdRgb.begin(16, 2);
Neopixel_2.begin();
}

void loop() {
CO2_rate = scd30_read(0);
lcdRgb.setCursor(0, 0);
lcdRgb.print(String("CO2 rate (ppm) :"));
lcdRgb.setCursor(0, 1);
lcdRgb.print(String(CO2_rate));
if (CO2_rate <= 600) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 51, 204, 0);
} else if (CO2_rate > 600 && CO2_rate < 800) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 255, 0);
} else if (CO2_rate >= 800 && CO2_rate < 1000) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 102, 0);
} else {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 0, 0);
}
delay(250);
}
Vue blocs Fiche 3
Vue blocs du programme Fiche 3

Fiche 4 : Affichage du CO2 avec temporisation

On ajoute une pause d'une seconde pour limiter la fréquence d'affichage à l'écran et faciliter la lecture des mesures.

Code

#include <Wire.h>
#include <SCD30.h>
#include <rgb_lcd.h>
#include <Adafruit_NeoPixel.h>

#define NP_LED_COUNT_2 30

rgb_lcd lcdRgb;
Adafruit_NeoPixel Neopixel_2(NP_LED_COUNT_2, 2, NEO_GRB + NEO_KHZ800);

float t_scd;
float scd30_co2 = 0;
float scd30_t = 0;
float scd30_h = 0;
float CO2_rate;

void serial_setupConnection(int baudrate) {
Serial.begin(baudrate);
while (!Serial) {
Serial.println("En attente de l'ouverture du port série...");
delay(1000);
}
Serial.println("Port série activé. Baudrate: " + String(baudrate));
delay(50);
}

float scd30_read(uint8_t dataSelect) {
t_scd = millis() - t_scd;
if (t_scd > 1000 && scd30.isAvailable()) {
float result[3] = {0};
scd30.getCarbonDioxideConcentration(result);
scd30_co2 = result[0];
scd30_t = result[1];
scd30_h = result[2];
}
switch (dataSelect) {
case 0: return scd30_co2;
case 1: return scd30_t;
case 2: return scd30_h;
}
}

void neopixel_showAllLed(Adafruit_NeoPixel *neoPx, uint8_t ledCount, uint8_t r, uint8_t g, uint8_t b) {
for (int i=0; i<ledCount; i++) {
neoPx->setPixelColor(i, neoPx->Color(r, g, b));
}
neoPx->show();
}

void setup() {
serial_setupConnection(9600);
Wire.begin();
scd30.initialize();
t_scd = millis();
lcdRgb.begin(16, 2);
Neopixel_2.begin();
CO2_rate = scd30_read(0);
delay(1000*1);
Serial.println(String(CO2_rate));
lcdRgb.setCursor(0, 0);
lcdRgb.print(String("CO2 rate (ppm)"));
lcdRgb.setCursor(0, 1);
lcdRgb.print(String(CO2_rate));
if (CO2_rate <= 600) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 51, 204, 0);
} else if (CO2_rate > 600 && CO2_rate < 800) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 255, 0);
} else if (CO2_rate >= 800 && CO2_rate < 1000) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 102, 0);
} else {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 0, 0);
}
delay(250);
}

void loop() { }
Vue blocs Fiche 4
Vue blocs du programme Fiche 4

Fiche 5 : Visualisation des données

  1. Dans la console d'affichage Vittascience, sélectionnez Mode graphique à droite.
  2. À partir du graphique, exportez les données au format .csv (bouton Exporter en bas de la fenêtre). Les données s'ouvrent alors dans Excel, LibreOffice Calc, Google Sheets ou Numbers, où la fonction Graphique permet de tracer l'évolution du CO2 au cours du temps.

Code (compatible avec la visualisation graphique de Vittascience)

#include <Wire.h>
#include <SCD30.h>
#include <rgb_lcd.h>
#include <Adafruit_NeoPixel.h>

#define NP_LED_COUNT_2 30

rgb_lcd lcdRgb;
Adafruit_NeoPixel Neopixel_2(NP_LED_COUNT_2, 2, NEO_GRB + NEO_KHZ800);

float t_scd;
float scd30_co2 = 0;
float scd30_t = 0;
float scd30_h = 0;
float CO2_rate;

void serial_setupConnection(int baudrate) {
Serial.begin(baudrate);
while (!Serial) {
Serial.println("En attente de l'ouverture du port série...");
delay(1000);
}
Serial.println("Port série activé. Baudrate: " + String(baudrate));
delay(50);
}

float scd30_read(uint8_t dataSelect) {
t_scd = millis() - t_scd;
if (t_scd > 1000 && scd30.isAvailable()) {
float result[3] = {0};
scd30.getCarbonDioxideConcentration(result);
scd30_co2 = result[0];
scd30_t = result[1];
scd30_h = result[2];
}
switch (dataSelect) {
case 0: return scd30_co2;
case 1: return scd30_t;
case 2: return scd30_h;
}
}

void neopixel_showAllLed(Adafruit_NeoPixel *neoPx, uint8_t ledCount, uint8_t r, uint8_t g, uint8_t b) {
for (int i=0; i<ledCount; i++) {
neoPx->setPixelColor(i, neoPx->Color(r, g, b));
}
neoPx->show();
}

void setup() {
serial_setupConnection(9600);
Wire.begin();
scd30.initialize();
t_scd = millis();
lcdRgb.begin(16, 2);
Neopixel_2.begin();
CO2_rate = scd30_read(0);
delay(1000*1);
Serial.print("@Graph:");
Serial.print("CO2 rate (in ppm):");
Serial.print(CO2_rate);
Serial.print("|");
Serial.print("\n");
delay(50);
lcdRgb.setCursor(0, 0);
lcdRgb.print(String("CO2 rate (ppm)"));
lcdRgb.setCursor(0, 1);
lcdRgb.print(String(CO2_rate));
if (CO2_rate <= 600) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 51, 204, 0);
} else if (CO2_rate > 600 && CO2_rate < 800) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 255, 0);
} else if (CO2_rate >= 800 && CO2_rate < 1000) {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 102, 0);
} else {
neopixel_showAllLed(&Neopixel_2, NP_LED_COUNT_2, 255, 0, 0);
}
delay(250);
}

void loop() { }
Vue blocs Fiche 5
Vue blocs du programme de visualisation

Cette fiche fait partie du projet SteamCity, financé par le programme Erasmus+. Contenu sous licence CC BY-SA 4.0.