Sen­sor SCD4x: Tem­pe­ra­tur, Luft­feuch­tig­keit und CO2 messen

Lese­zeit: 7 Minu­ten


Die Hard­ware

Die Sen­so­ren SCD40 und SCD41 (zusam­men­ge­fasst als SCD4x) mes­sen Tem­pe­ra­tur, Luft­feuch­tig­keit und den CO2-Gehalt in der Luft.
Der Sen­sor SDC4x arbei­tet nach dem pho­to­akus­ti­schen Messprinzip:

Gas­mo­le­kü­le wie das CO2 neh­men nur Licht ganz bestimm­ter Wel­len­län­gen auf. Schickt man infra­rotes Licht, das nur von CO2 absor­biert wird, durch ein Gas­ge­misch, erhöht sich die Aus­deh­nung der ange­reg­ten Mole­kü­le. Die Licht­quel­le wird peri­odisch ein- und aus­ge­schal­tet, dadurch schwankt die Aus­deh­nung der Mole­kü­le eben­falls peri­odisch. Die­se Druck­schwan­kun­gen wer­den wer­den als akus­ti­sche Signa­le von einem Mikro­fon auf­ge­fan­gen. Das akus­ti­sche Signal ist pro­por­tio­nal zur Kon­zen­tra­ti­on des Gases im Gasgemisch.

Eigen­schaf­ten des Sensors

  • auto­ma­ti­sche oder hän­di­sche Kalibrierung
  • Selbst­test mit Prü­fung der Funktionen
  • Ein­stel­lun­gen kön­nen im EEPROM gespei­chert werden

Funk­tio­nen des Sensors

Schlüs­sel­wortAnzeige/Parameter
begin(Wire, SCD41_I2C_ADDR_62);Sen­sor starten
per­form­Fac­to­ry­Re­set();auf Stan­dard­ein­stel­lun­gen zurücksetzen
per­sist­Set­tings();Ein­stel­lun­gen in den EEPROM schreiben
performSelfTest(Wert)Selbst­test durchführen
0 = Selbst­test erfolgreich
reinit();Vor­ein­stel­lun­gen aus dem EEPROM des SCD4x lesen
wake­Up();Sen­sor aufwecken
power­Down();Sen­sor ausschalten
setAutomaticSelfCalibrationEnabled(Wert);0 = auto­ma­ti­sche Kali­brie­rung ausschalten
1 = auto­ma­ti­sche Kali­brie­rung einschalten
setAutomaticSelfCalibrationTarget(CO2-Wert);Wert der auto­ma­ti­schen Kali­brie­rung anpassen
Anga­be in ppm
setAutomaticSelfCalibrationInitialPeriod(Wert_in_Stunden)Zeit­raum für auto­ma­ti­sche Kali­brie­rung festlegen
setSensorAltitude(Höhe in m);Stand­ort des Sen­sors anpas­sen (Höhe in m)
setAmbientPressure(Luftdruck)Luft­druck anpassen
setTemperatureOffset(Wert);Abwei­chung der Tem­pe­ra­tur korrigieren
start­Pe­ri­odic­Me­a­su­re­ment();Peri­odi­sche Mes­sun­gen star­ten (alle 5 Sekunden)
stop­Pe­ri­odic­Me­a­su­re­ment();Peri­odi­sche Mes­sun­gen beenden
start­Low­Power­Pe­ri­odic­Me­a­su­re­ment();Peri­odi­sche Mes­sun­gen star­ten (alle 30 Sekunden)
mea­su­reS­in­g­le­Shot()Sin­g­le­Shot: jede Mes­sung ein­zeln starten
(nur SCD41)
readMeasurement(CO2, Tem­pe­ra­tur, Luftfeuchtigkeit);Mess­wer­te lesen
measureAndReadSingleShot(CO2, Tem­pe­ra­tur, Luftfeuchtigkeit);Mes­sung im Sin­g­le­Shot-Modus (nur SCD41)

Ein­stel­lun­gen

schrei­ben

  • Ein­stel­lun­gen im EEPROM spei­chern
    persistSettings();
  • auf Werks­ein­stel­lun­gen zurück­set­zen
    performFactoryReset();
  • Höhe des Stand­orts bestim­men
    setSensorAltitude(Höhe_in_m);
    Der Luft­druck schwankt je nach der Höhe des Stand­orts. Die Stan­dard­ein­stel­lung ist 0, wenn die Höhe deut­lich abweicht, soll­te sie ange­passt werden.
  • Tem­pe­ra­tur anpas­sen
    setTemperatureOffset(Wert_als_float);
    Da der Sen­sor sich erwärmt, kann die Tem­pe­ra­tur mit einem Ver­gleich eines ande­ren Mess­ge­räts ange­passt werden.
  • Luft­druck über­schrei­ben
    setAmbientPressure(Wert_in_hPa*100);
    Die­se Ein­stel­lung ist nur sinn­voll, wenn ein prä­zi­ses Mess­ge­rät zum Ver­gleich zur Ver­fü­gung steht

lesen

Funk­ti­ons­test

#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
}

Kali­brie­rung des Sensors

Auto­ma­ti­sche Selbst­ka­li­brie­rung (ASC)

Die auto­ma­ti­sche Selbst­ka­li­brie­rung ver­läuft in zwei Pha­sen:
44 Stun­den für die Erst­ka­li­brie­rung und 156 Stun­den für die fol­gen­de Stan­dard­ka­li­brie­rung. Der Sen­sor muss wenigs­ten ein­mal wäh­rend die­ser Zeit einen bekann­ten Tiefst­wert der CO2-Kon­zen­tra­ti­on (400 ppm) errei­chen. Aller­dings ist der Tiefst­wert im Durch­schnitt inzwi­schen auf 430 ppm gestie­gen (🔗Umwelt­bun­des­amt).
Der Ziel­wert kann mit setAutomaticSelfCalibrationTarget(ppm) gesetzt wer­den.
Die Zeit in Stun­den für die Erst- und Stan­dard­ka­li­brie­rung kann mit
setAutomaticSelfCalibrationInitialPeriod(Stun­den)
setAutomaticSelfCalibrationStandardPeriod(Stun­den)
geän­dert wer­den. Der Wert in Stun­den muss ein Viel­fa­ches von 4 sein.

Wäh­rend der auto­ma­ti­schen Kali­brie­rung muss der Sen­sor in einem gut gelüf­te­ten Raum sein.

Erzwun­ge­ne Kali­brie­rung (FRC – forced Recalibration)

Neben der auto­ma­ti­schen Kali­brie­rung kannst du alter­na­tiv mit performForcedRecalibration(CO2Richtwert, frcCorr)die Kali­brie­rung erzwin­gen. Hier­zu wird ein Wert (CO2Richtwert) fest­ge­legt, auf den kali­briert wer­den soll. frc­Corr ist ein Ker­rek­tur­wert, der im Fal­le eines Miss­erfolgs 0xFFFF ausgibt.

Um eine FRC erfolg­reich durch­zu­füh­ren, müs­sen die fol­gen­den Schrit­te durch­ge­führt werden:

  • Die peri­odi­sche Mes­sung (startPeriodicMeasurement) muss min­des­tens drei Minu­ten in einer Umge­bung mit mög­lichst kon­stan­tem CO2-Wert aus­ge­führt werden.
  • Nach die­ser Zeit wird die peri­odi­sche Mes­sung gestoppt (stopPeriodicMeasurement).
  • Nach einer War­te­zeit von 500 Mil­li­se­kun­den kann dem Sen­sor mit performForcedRecalibration der neue CO2-Richt­wert mit­ge­teilt 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();

  // Vor­ein­stel­lun­gen 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 Pro­gramm

Benö­tig­te Bibliotheken

für den Sen­sor SCD4x

Ver­wen­dung des OLEDs

Anzei­ge auf einem LCD

Anschluss des Sensors

Die Anzei­ge­mo­du­le kön­nen an den ande­ren I²C-Pins A4 und A5 ange­schlos­sen werden.

Mess­mo­di

Peri­odi­sche Messung

Die peri­odi­sche Mes­sung ermit­telt alle 5 Sekun­den die Mess­wer­te. 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();

  // Vor­ein­stel­lun­gen 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ösun­gen fin­dest du die Pro­gram­me für die Anzei­ge auf dem ⇒LCD und auf einem ⇒OLED.

Low-Power Mes­sung

Die Low-Power Mes­sung misst die Wer­te alle 30 Sekun­den.
Statt startPeriodicMeasurement(); wird die Mes­sung mit startLowPowerPeriodicMeasurement(); gestar­tet.

#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();

  // Vor­ein­stel­lun­gen 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("------------------------");
  }
}

Sin­g­le­Shot Messung

Nur der SCD41 kann Sin­g­le­Shot-Mes­sun­gen 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();

  // Vor­ein­stel­lun­gen 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 Pro­gram­me für die Anzei­ge auf dem ⇒LCD und auf einem ⇒OLED fin­dest du in den Lösungen. 


Quel­len


Letzte Aktualisierung: Sep. 17, 2025 @ 8:36