
Die Hardware
Die Sensoren SCD40 und SCD41 (zusammengefasst als SCD4x) messen Temperatur, Luftfeuchtigkeit und den CO2-Gehalt in der Luft.
Der Sensor SDC4x arbeitet nach dem photoakustischen Messprinzip:
Gasmoleküle wie das CO2 nehmen nur Licht ganz bestimmter Wellenlängen auf. Schickt man infrarotes Licht, das nur von CO2 absorbiert wird, durch ein Gasgemisch, erhöht sich die Ausdehnung der angeregten Moleküle. Die Lichtquelle wird periodisch ein- und ausgeschaltet, dadurch schwankt die Ausdehnung der Moleküle ebenfalls periodisch. Diese Druckschwankungen werden werden als akustische Signale von einem Mikrofon aufgefangen. Das akustische Signal ist proportional zur Konzentration des Gases im Gasgemisch.
Eigenschaften des Sensors
- automatische oder händische Kalibrierung
- Selbsttest mit Prüfung der Funktionen
- Einstellungen können im EEPROM gespeichert werden
Funktionen des Sensors
Schlüsselwort | Anzeige/Parameter |
---|---|
begin(Wire, SCD41_I2C_ADDR_62); | Sensor starten |
performFactoryReset(); | auf Standardeinstellungen zurücksetzen |
persistSettings(); | Einstellungen in den EEPROM schreiben |
performSelfTest(Wert) | Selbsttest durchführen 0 = Selbsttest erfolgreich |
reinit(); | Voreinstellungen aus dem EEPROM des SCD4x lesen |
wakeUp(); | Sensor aufwecken |
powerDown(); | Sensor ausschalten |
setAutomaticSelfCalibrationEnabled(Wert); | 0 = automatische Kalibrierung ausschalten 1 = automatische Kalibrierung einschalten |
setAutomaticSelfCalibrationTarget(CO2-Wert); | Wert der automatischen Kalibrierung anpassen Angabe in ppm |
setAutomaticSelfCalibrationInitialPeriod(Wert_in_Stunden) | Zeitraum für automatische Kalibrierung festlegen |
setSensorAltitude(Höhe in m); | Standort des Sensors anpassen (Höhe in m) |
setAmbientPressure(Luftdruck) | Luftdruck anpassen |
setTemperatureOffset(Wert); | Abweichung der Temperatur korrigieren |
startPeriodicMeasurement(); | Periodische Messungen starten (alle 5 Sekunden) |
stopPeriodicMeasurement(); | Periodische Messungen beenden |
startLowPowerPeriodicMeasurement(); | Periodische Messungen starten (alle 30 Sekunden) |
measureSingleShot() | SingleShot: jede Messung einzeln starten (nur SCD41) |
readMeasurement(CO2, Temperatur, Luftfeuchtigkeit); | Messwerte lesen |
measureAndReadSingleShot(CO2, Temperatur, Luftfeuchtigkeit); | Messung im SingleShot-Modus (nur SCD41) |
Einstellungen
schreiben
- Einstellungen im EEPROM speichern
persistSettings
(); - auf Werkseinstellungen zurücksetzen
performFactoryReset
(); - Höhe des Standorts bestimmen
setSensorAltitude
(Höhe_in_m);
Der Luftdruck schwankt je nach der Höhe des Standorts. Die Standardeinstellung ist 0, wenn die Höhe deutlich abweicht, sollte sie angepasst werden. - Temperatur anpassen
setTemperatureOffset
(Wert_als_float);
Da der Sensor sich erwärmt, kann die Temperatur mit einem Vergleich eines anderen Messgeräts angepasst werden. - Luftdruck überschreiben
setAmbientPressure
(Wert_in_hPa*100);
Diese Einstellung ist nur sinnvoll, wenn ein präzises Messgerät zum Vergleich zur Verfügung steht
lesen

Funktionstest

#include "Arduino.h"
#include "SensirionI2cScd4x.h"
#include "Wire.h"
SensirionI2cScd4x sensor;
float TemperaturAbweichung;
uint32_t LuftdruckAnpassung;
uint16_t HoeheAnpassung;
uint16_t ASCaktiviert;
uint16_t ASCZiel;
uint16_t KalibrierungInitialPeriode;
uint16_t KalibrierungStandardPeriode;
uint16_t sensorStatus;
void setup()
{
Serial.begin(9600);
// I2C
Wire.begin();
sensor.begin(Wire, SCD41_I2C_ADDR_62);
// R4 WiFi mit QWIIC-Anschluss
// Wire1.begin();
// sensor.begin(Wire1, SCD41_I2C_ADDR_62);
delay(30);
sensor.wakeUp();
sensor.stopPeriodicMeasurement();
sensor.reinit();
sensor.getTemperatureOffset(TemperaturAbweichung);
Serial.print(F("Temperatur Anpassung °C: "));
Serial.println(TemperaturAbweichung);
sensor.getAmbientPressure(LuftdruckAnpassung);
Serial.print(F("Luftdruck Anpassung in Pa: "));
Serial.println(LuftdruckAnpassung);
sensor.getSensorAltitude(HoeheAnpassung);
Serial.print(F("Anpassung Höhe in m: "));
Serial.println(HoeheAnpassung);
Serial.println();
Serial.println(F("Automatische Selbstkalibrierung (ASC):"));
sensor.getAutomaticSelfCalibrationEnabled(ASCaktiviert);
if (ASCaktiviert)
{
Serial.println(F("aktiviert"));
}
else Serial.println(F("nicht aktiviert"));
sensor.getAutomaticSelfCalibrationTarget(ASCZiel);
Serial.print(F("- Ziel für die automatische Kalibrierung in ppm: "));
Serial.println(ASCZiel);
sensor.getAutomaticSelfCalibrationInitialPeriod(KalibrierungInitialPeriode);
Serial.print(F("- Periode für die Initielisierung in Stunden: "));
Serial.println(KalibrierungInitialPeriode);
sensor.getAutomaticSelfCalibrationStandardPeriod(KalibrierungStandardPeriode);
Serial.print(F("- Standard-Periode in Stunden: "));
Serial.println(KalibrierungStandardPeriode);
Serial.println();
Serial.print(F("Selbsttest durchführen ... "));
sensor.performSelfTest(sensorStatus);
if(sensorStatus == 0) Serial.println("Der Sensor funktioniert einwandfrei!");
else
{
Serial.println("Fehler beim Test des Sensors!");
while(1);
}
}
void loop()
{
// bleibt leer
}
Kalibrierung des Sensors
Automatische Selbstkalibrierung (ASC)
Die automatische Selbstkalibrierung verläuft in zwei Phasen:
44 Stunden für die Erstkalibrierung und 156 Stunden für die folgende Standardkalibrierung. Der Sensor muss wenigsten einmal während dieser Zeit einen bekannten Tiefstwert der CO2-Konzentration (400 ppm) erreichen. Allerdings ist der Tiefstwert im Durchschnitt inzwischen auf 430 ppm gestiegen (🔗Umweltbundesamt).
Der Zielwert kann mit setAutomaticSelfCalibrationTarget
(ppm) gesetzt werden.
Die Zeit in Stunden für die Erst- und Standardkalibrierung kann mitsetAutomaticSelfCalibrationInitialPeriod
(Stunden)setAutomaticSelfCalibrationStandardPeriod
(Stunden)
geändert werden. Der Wert in Stunden muss ein Vielfaches von 4 sein.
Während der automatischen Kalibrierung muss der Sensor in einem gut gelüfteten Raum sein.
Erzwungene Kalibrierung (FRC – forced Recalibration)
Neben der automatischen Kalibrierung kannst du alternativ mit performForcedRecalibration(CO2Richtwert, frcCorr)
die Kalibrierung erzwingen. Hierzu wird ein Wert (CO2Richtwert) festgelegt, auf den kalibriert werden soll. frcCorr ist ein Kerrekturwert, der im Falle eines Misserfolgs 0xFFFF ausgibt.
Um eine FRC erfolgreich durchzuführen, müssen die folgenden Schritte durchgeführt werden:
- Die periodische Messung (
startPeriodicMeasurement)
muss mindestens drei Minuten in einer Umgebung mit möglichst konstantem CO2-Wert ausgeführt werden. - Nach dieser Zeit wird die periodische Messung gestoppt (
stopPeriodicMeasurement
). - Nach einer Wartezeit von 500 Millisekunden kann dem Sensor mit
performForcedRecalibration
der neue CO2-Richtwert mitgeteilt werden.
#include "Arduino.h"
#include "SensirionI2cScd4x.h"
#include "Wire.h"
uint16_t sensorStatus = 1;
// CO2-Richtwert
#define CO2Richtwert 430
uint16_t frcCorr = 0;
SensirionI2cScd4x sensor;
void setup()
{
// auf Seriellen Monitor warten
Serial.begin(9600);
while (!Serial)
{
delay(200);
}
// UNO R4 WiFi QWIIC-Anschluss
// Wire1.begin();
// sensor.begin(Wire1, SCD41_I2C_ADDR_62);
// I2C
Wire.begin();
sensor.begin(Wire, SCD41_I2C_ADDR_62);
// auf Werkseinstellungen zurücksetzen
// sensor.performFactoryReset();
delay(30);
// Sensor aufwecken
sensor.wakeUp();
// periodische Messung stoppen
sensor.stopPeriodicMeasurement();
// Voreinstellungen aus dem EEPROM lesen
sensor.reinit();
sensor.performSelfTest(sensorStatus);
if(sensorStatus == 0) Serial.println("Der Sensor funktioniert einwandfrei!");
else
{
Serial.println("Fehler beim Test des Sensors!");
while(1);
}
// Anpassungen
// Höhe des Standorts in m
// sensor.setSensorAltitude(80);
sensor.startPeriodicMeasurement();
// 3 Minuten in Sekunden
int i = 1800;
while (i > 0)
{
if (i % 100 == 0) Serial.println("Noch " + String(i / 10) + " Sekunden ...");
i -= 10;
delay(1000);
}
sensor.stopPeriodicMeasurement();
delay(500);
sensor.performForcedRecalibration(CO2Richtwert, frcCorr);
sensor.startPeriodicMeasurement();
Serial.println();
Serial.print("Korrekturwert frcCorr: ");
Serial.print(frcCorr, HEX);
Serial.println();
}
void loop()
{
bool SensorBereit = false;
uint16_t CO2 = 0;
float Temperatur = 0.0;
float Luftfeuchtigkeit = 0.0;
sensor.getDataReadyStatus(SensorBereit);
// wenn der Sensor bereit ist -> Messung durchführen
if (SensorBereit)
{
// periodische Messung
sensor.readMeasurement(CO2, Temperatur, Luftfeuchtigkeit);
String AnzeigeTemperatur = String(Temperatur);
String AnzeigeLuftfeuchtigkeit = String(Luftfeuchtigkeit);
AnzeigeTemperatur.replace(".", ",");
AnzeigeLuftfeuchtigkeit.replace(".", ",");
// Anzeige Serieller Monitor
Serial.print("CO2 Konzentration: ");
Serial.print(CO2);
Serial.println(" ppm");
Serial.print("Temperatur: ");
Serial.print(AnzeigeTemperatur);
Serial.println("°C");
Serial.print("Luftfeuchtigkeit: ");
Serial.print(AnzeigeLuftfeuchtigkeit);
Serial.println("%");
Serial.println("------------------------");
}
}
Das Programm




Benötigte Bibliotheken
für den Sensor SCD4x

Verwendung des OLEDs

Anzeige auf einem LCD

Anschluss des Sensors

Die Anzeigemodule können an den anderen I²C-Pins A4 und A5 angeschlossen werden.

Messmodi
Periodische Messung
Die periodische Messung ermittelt alle 5 Sekunden die Messwerte. Sie wird mit startPeriodicMeasurement();
angestoßen.
#include "Arduino.h"
#include "SensirionI2cScd4x.h"
#include "Wire.h"
uint16_t sensorStatus = 1;
SensirionI2cScd4x sensor;
void setup()
{
// auf Seriellen Monitor warten
Serial.begin(9600);
while (!Serial)
{
delay(200);
}
// UNO R4 WiFi QWIIC-Anschluss
// Wire1.begin();
// sensor.begin(Wire1, SCD41_I2C_ADDR_62);
// I2C
Wire.begin();
sensor.begin(Wire, SCD41_I2C_ADDR_62);
// auf Werkseinstellungen zurücksetzen
// sensor.performFactoryReset();
delay(30);
// Sensor aufwecken
sensor.wakeUp();
// periodische Messung stoppen
sensor.stopPeriodicMeasurement();
// Voreinstellungen aus dem EEPROM lesen
sensor.reinit();
sensor.performSelfTest(sensorStatus);
if(sensorStatus == 0) Serial.println("Der Sensor funktioniert einwandfrei!");
else
{
Serial.println("Fehler beim Test des Sensors!");
while(1);
}
// Höhe des Standorts in m
sensor.setSensorAltitude(80);
// Temperaturschwankung berücksichtigen
sensor.setTemperatureOffset(2.0);
// Mittelwert des Luftdrucks hPa *100
// nur sinnvoll, wenn ein präzises Messgerät für einen Vergleich verfügbar ist
// sensor.setAmbientPressure(100400);;
// Periodic: alle 5 Sekunden messen
sensor.startPeriodicMeasurement();
}
void loop()
{
bool SensorBereit = false;
uint16_t CO2 = 0;
float Temperatur = 0.0;
float Luftfeuchtigkeit = 0.0;
sensor.getDataReadyStatus(SensorBereit);
// wenn der Sensor bereit ist -> Messung durchführen
if (SensorBereit)
{
// periodische Messung
sensor.readMeasurement(CO2, Temperatur, Luftfeuchtigkeit);
String AnzeigeTemperatur = String(Temperatur);
String AnzeigeLuftfeuchtigkeit = String(Luftfeuchtigkeit);
AnzeigeTemperatur.replace(".", ",");
AnzeigeLuftfeuchtigkeit.replace(".", ",");
// Anzeige Serieller Monitor
Serial.print("CO2 Konzentration: ");
Serial.print(CO2);
Serial.println(" ppm");
Serial.print("Temperatur: ");
Serial.print(AnzeigeTemperatur);
Serial.println("°C");
Serial.print("Luftfeuchtigkeit: ");
Serial.print(AnzeigeLuftfeuchtigkeit);
Serial.println("%");
Serial.println("------------------------");
}
}
In den Lösungen findest du die Programme für die Anzeige auf dem ⇒LCD und auf einem ⇒OLED.
Low-Power Messung
Die Low-Power Messung misst die Werte alle 30 Sekunden.
Statt startPeriodicMeasurement
(); wird die Messung mit startLowPowerPeriodicMeasurement()
; gestartet.
#include "Arduino.h"
#include "SensirionI2cScd4x.h"
#include "Wire.h"
uint16_t sensorStatus = 1;
SensirionI2cScd4x sensor;
void setup()
{
// auf Seriellen Monitor warten
Serial.begin(9600);
while (!Serial)
{
delay(200);
}
// UNO R4 WiFi QWIIC-Anschluss
// Wire1.begin();
// sensor.begin(Wire1, SCD41_I2C_ADDR_62);
// I2C
Wire.begin();
sensor.begin(Wire, SCD41_I2C_ADDR_62);
// auf Werkseinstellungen zurücksetzen
// sensor.performFactoryReset();
delay(30);
// Sensor aufwecken
sensor.wakeUp();
// periodische Messung stoppen
sensor.stopPeriodicMeasurement();
// Voreinstellungen aus dem EEPROM lesen
sensor.reinit();
sensor.performSelfTest(sensorStatus);
if(sensorStatus == 0) Serial.println("Der Sensor funktioniert einwandfrei!");
else
{
Serial.println("Fehler beim Test des Sensors!");
while(1);
}
// Höhe des Standorts in m
sensor.setSensorAltitude(80);
// Temperaturschwankung berücksichtigen
sensor.setTemperatureOffset(2.0);
// Mittelwert des Luftdrucks hPa *100
// nur sinnvoll, wenn ein präzises Messgerät für einen Vergleich verfügbar ist
// sensor.setAmbientPressure(100400);;
// LowPower: alle 30 Sekunden messen
sensor.startLowPowerPeriodicMeasurement();
}
void loop()
{
bool SensorBereit = false;
uint16_t CO2 = 0;
float Temperatur = 0.0;
float Luftfeuchtigkeit = 0.0;
sensor.getDataReadyStatus(SensorBereit);
// wenn der Sensor bereit ist -> Messung durchführen
if (SensorBereit)
{
// periodische Messung
sensor.readMeasurement(CO2, Temperatur, Luftfeuchtigkeit);
String AnzeigeTemperatur = String(Temperatur);
String AnzeigeLuftfeuchtigkeit = String(Luftfeuchtigkeit);
AnzeigeTemperatur.replace(".", ",");
AnzeigeLuftfeuchtigkeit.replace(".", ",");
// Anzeige Serieller Monitor
Serial.print("CO2 Konzentration: ");
Serial.print(CO2);
Serial.println(" ppm");
Serial.print("Temperatur: ");
Serial.print(AnzeigeTemperatur);
Serial.println("°C");
Serial.print("Luftfeuchtigkeit: ");
Serial.print(AnzeigeLuftfeuchtigkeit);
Serial.println("%");
Serial.println("------------------------");
}
}
SingleShot Messung
Nur der SCD41 kann SingleShot-Messungen durchführen.
#include "Arduino.h"
#include "SensirionI2cScd4x.h"
#include "Wire.h"
uint16_t sensorStatus = 1;
SensirionI2cScd4x sensor;
void setup()
{
// auf Seriellen Monitor warten
Serial.begin(9600);
while (!Serial)
{
delay(200);
}
// UNO R4 WiFi QWIIC-Anschluss
// Wire1.begin();
// sensor.begin(Wire1, SCD41_I2C_ADDR_62);
// I2C
Wire.begin();
sensor.begin(Wire, SCD41_I2C_ADDR_62);
// auf Werkseinstellungen zurücksetzen
// sensor.performFactoryReset();
delay(30);
// Sensor aufwecken
sensor.wakeUp();
// periodische Messung stoppen
sensor.stopPeriodicMeasurement();
// Voreinstellungen aus dem EEPROM lesen
sensor.reinit();
sensor.performSelfTest(sensorStatus);
if (sensorStatus == 0) Serial.println("Der Sensor funktioniert einwandfrei!");
else {
Serial.println("Fehler beim Test des Sensors");
while (1);
}
// Höhe des Standorts in m
sensor.setSensorAltitude(80);
// Temperaturschwankung berücksichtigen
sensor.setTemperatureOffset(2.0);
// Mittelwert des Luftdrucks hPa *100
// nur sinnvoll, wenn ein präzises Messgerät verfügbar ist
// sensor.setAmbientPressure(100400);;
}
void loop()
{
bool SensorBereit = false;
uint16_t CO2 = 0;
float Temperatur = 0.0;
float Luftfeuchtigkeit = 0.0;
sensor.measureSingleShot();
sensor.measureAndReadSingleShot(CO2, Temperatur, Luftfeuchtigkeit);
String AnzeigeTemperatur = String(Temperatur);
String AnzeigeLuftfeuchtigkeit = String(Luftfeuchtigkeit);
AnzeigeTemperatur.replace(".", ",");
AnzeigeLuftfeuchtigkeit.replace(".", ",");
// Anzeige Serieller Monitor
Serial.print("CO2 Konzentration: ");
Serial.print(CO2);
Serial.println(" ppm");
Serial.print("Temperatur: ");
Serial.print(AnzeigeTemperatur);
Serial.println("°C");
Serial.print("Luftfeuchtigkeit: ");
Serial.print(AnzeigeLuftfeuchtigkeit);
Serial.println("%");
Serial.println("------------------------");
}
Die Programme für die Anzeige auf dem ⇒LCD und auf einem ⇒OLED findest du in den Lösungen.
Quellen
- Übersicht SCD4x bei Sensirion
- Datenblatt SCD4x
- Low-Power/High-Power-Modes des SCD4x
- Wikipedia-Artikel zur photoakustischen Untersuchung von Gasen
- Erklärung des Messprinzips beim Fraunhofer-Institut für Physikalische Messtechnik
- Durchschnittliche CO2-Werte beim Bundesumweltamt
Letzte Aktualisierung: