diff --git a/ampel-firmware.ino b/ampel-firmware.ino
index 4465ae09caf27796a7667b6526ead446a829e706..adcd5b98098670f300bddad1a4ac891f84bdc299 100644
--- a/ampel-firmware.ino
+++ b/ampel-firmware.ino
@@ -116,7 +116,7 @@ void loop() {
   // Short press for night mode, Long press for calibration.
   checkFlashButton();
 
-  sensor::getAndSendData();
+  sensor::processData();
 
   uint32_t duration = millis() - t0;
   if (duration > max_loop_duration) {
diff --git a/co2_sensor.cpp b/co2_sensor.cpp
index a51036a1fcf2b445da005988469d2d9d9f923e63..15b6ee49b13399a17f38891edad7fcb6d10a268d 100644
--- a/co2_sensor.cpp
+++ b/co2_sensor.cpp
@@ -97,6 +97,7 @@ namespace sensor {
   bool updateDataIfAvailable() {
     if (scd30.dataAvailable()) {
       // checkTimerDeviation();
+      timestamp = ntp::getLocalTime();
       co2 = scd30.getCO2();
       temperature = scd30.getTemperature();
       humidity = scd30.getHumidity();
@@ -130,7 +131,36 @@ namespace sensor {
     ESP.restart();
   }
 
-  void getAndSendData() {
+  void logToSerial() {
+    Serial.println(timestamp);
+    Serial.print(F("co2(ppm): "));
+    Serial.print(co2);
+    Serial.print(F(" temp(C): "));
+    Serial.print(temperature);
+    Serial.print(F(" humidity(%): "));
+    Serial.println(humidity);
+  }
+
+  void displayCO2OnLedRing() {
+    if (co2 < 250) {
+      // Sensor should be calibrated.
+      LedEffects::showWaitingLED(color::magenta);
+      return;
+    }
+    /**
+     * Display data, even if it's "old" (with breathing).
+     * Those effects include a short delay.
+     */
+    if (co2 < 2000) {
+      LedEffects::displayCO2color(co2);
+      LedEffects::breathe(co2);
+    } else {
+      // >= 2000: entire ring blinks red
+      LedEffects::redAlert();
+    }
+  }
+
+  void processData() {
     bool freshData = updateDataIfAvailable();
 
     //NOTE: Data is available, but it's sometimes erroneous: the sensor outputs zero ppm but non-zero temperature and non-zero humidity.
@@ -141,22 +171,14 @@ namespace sensor {
     }
 
     /**
-     * Fresh data. Show it and send it if needed.
+     * Fresh data. Log it and send it if needed.
      */
     if (freshData) {
       if (should_calibrate) {
         countStableMeasurements();
       }
-      timestamp = ntp::getLocalTime();
-      Serial.println(timestamp);
-
-      Serial.print(F("co2(ppm): "));
-      Serial.print(co2);
-      Serial.print(F(" temp(C): "));
-      Serial.print(temperature);
-      Serial.print(F(" humidity(%): "));
-      Serial.println(humidity);
 
+      logToSerial();
       csv_writer::logIfTimeHasCome(timestamp, co2, temperature, humidity);
 
 #ifdef MQTT
@@ -172,22 +194,6 @@ namespace sensor {
       return;
     }
 
-    if (co2 < 250) {
-      // Sensor should be calibrated.
-      LedEffects::showWaitingLED(color::magenta);
-      return;
-    }
-
-    /**
-     * Display data, even if it's "old" (with breathing).
-     * Those effects include a short delay.
-     */
-
-    if (co2 < 2000) {
-      LedEffects::displayCO2color(co2);
-      LedEffects::breathe(co2);
-    } else { // >= 2000: entire ring blinks red
-      LedEffects::redAlert();
-    }
+    displayCO2OnLedRing();
   }
 }
diff --git a/co2_sensor.h b/co2_sensor.h
index 5c0871214151571f55c1683a0c62e78bcb01afd4..25f79a79628cb895dc7eb2a7b085910d80fd308a 100644
--- a/co2_sensor.h
+++ b/co2_sensor.h
@@ -28,7 +28,7 @@ namespace sensor {
   extern String timestamp;
 
   void initialize();
-  void getAndSendData();
+  void processData();
   void startCalibrationProcess();
 }
 #endif