diff --git a/README.md b/README.md
index e5421538c55f09946567ae3698882450de7884f1..9389e016950113580ab266e21e5178403af5d2ae 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,18 @@ It measures the current CO<sub>2</sub> concentration (in ppm), and displays it o
 
 The room should be ventilated as soon as one LED turns red.
 
+## Features
+
+The *CO<sub>2</sub> Ampel* can:
+
+* Display CO2 concentration on LED ring.
+* Allow calibration.
+* Get current time over NTP
+* Send data over MQTT.
+* Send data over LoRaWAN.
+* Display measurements and configuration on a small website.
+* Log data to a CSV file, directly on the ESP flash memory.
+
 ## Hardware Requirements
 
 * [ESP8266](https://en.wikipedia.org/wiki/ESP8266) or [ESP32](https://en.wikipedia.org/wiki/ESP32) microcontroller (this project has been tested with *ESP8266 ESP-12 WIFI* and *TTGO ESP32 SX1276 LoRa*)
diff --git a/ampel-firmware.h b/ampel-firmware/ampel-firmware.h
similarity index 94%
rename from ampel-firmware.h
rename to ampel-firmware/ampel-firmware.h
index 670c91d3eed7f9d96b38345a0941fc631182c90a..5c47dec1cc21cbb38963d9f31fe2a08743ea851a 100644
--- a/ampel-firmware.h
+++ b/ampel-firmware/ampel-firmware.h
@@ -3,7 +3,6 @@
 /*****************************************************************
  * Libraries                                                     *
  *****************************************************************/
-//TODO: check header dependencies, and simplify if possible.
 #include "config.h"
 #ifndef MEASUREMENT_TIMESTEP
 #  error Missing config.h file. Please copy config.public.h to config.h.
@@ -29,7 +28,6 @@
 
 #include "util.h"
 #include "co2_sensor.h"
-
 #include "led_effects.h"
 
 #if defined(ESP8266)
diff --git a/ampel-firmware.ino b/ampel-firmware/ampel-firmware.ino
similarity index 96%
rename from ampel-firmware.ino
rename to ampel-firmware/ampel-firmware.ino
index 0e550a3df89eff9867c1799fbac1b8663b48f53b..2713e2dc76413d27a673f9ac1e63b29b3c3cdbe3 100644
--- a/ampel-firmware.ino
+++ b/ampel-firmware/ampel-firmware.ino
@@ -59,14 +59,14 @@
  * Setup                                                         *
  *****************************************************************/
 void setup() {
-  LedEffects::setupOnBoardLED();
-  LedEffects::onBoardLEDOff();
+  led_effects::setupOnBoardLED();
+  led_effects::onBoardLEDOff();
 
   Serial.begin(BAUDS);
 
   pinMode(0, INPUT); // Flash button (used for forced calibration)
 
-  LedEffects::setupRing();
+  led_effects::setupRing();
 
   sensor::initialize();
 
@@ -165,18 +165,18 @@ void loop() {
  */
 void checkFlashButton() {
   if (!digitalRead(0)) { // Button has been pressed
-    LedEffects::onBoardLEDOn();
+    led_effects::onBoardLEDOn();
     delay(300);
     if (digitalRead(0)) {
       Serial.println(F("Flash has been pressed for a short time. Should toggle night mode."));
-      LedEffects::toggleNightMode();
+      led_effects::toggleNightMode();
     } else {
       Serial.println(F("Flash has been pressed for a long time. Keep it pressed for calibration."));
-      if (LedEffects::countdownToZero() < 0) {
+      if (led_effects::countdownToZero() < 0) {
         sensor::startCalibrationProcess();
       }
     }
-    LedEffects::onBoardLEDOff();
+    led_effects::onBoardLEDOff();
   }
 }
 
diff --git a/co2_sensor.cpp b/ampel-firmware/co2_sensor.cpp
similarity index 94%
rename from co2_sensor.cpp
rename to ampel-firmware/co2_sensor.cpp
index 59d7446619285c42f9e792d3db5339ae7d6a4d10..48761a4307087c60a44f904cbde6ef0ab6994ccb 100644
--- a/co2_sensor.cpp
+++ b/ampel-firmware/co2_sensor.cpp
@@ -44,7 +44,7 @@ namespace sensor {
     if (scd30.begin(config::auto_calibrate_sensor) == false) {
       Serial.println("Air sensor not detected. Please check wiring. Freezing...");
       while (1) {
-        LedEffects::showWaitingLED(color::red);
+        led_effects::showWaitingLED(color::red);
       }
     }
 
@@ -113,7 +113,7 @@ namespace sensor {
     scd30.setForcedRecalibrationFactor(config::co2_calibration_level);
     Serial.println(F(" Done!"));
     Serial.println(F("Sensor calibrated."));
-    resetAmpel();
+    ESP.restart(); // softer than ESP.reset
   }
 
   void logToSerial() {
@@ -129,7 +129,7 @@ namespace sensor {
   void displayCO2OnLedRing() {
     if (co2 < 250) {
       // Sensor should be calibrated.
-      LedEffects::showWaitingLED(color::magenta);
+      led_effects::showWaitingLED(color::magenta);
       return;
     }
     /**
@@ -137,11 +137,11 @@ namespace sensor {
      * Those effects include a short delay.
      */
     if (co2 < 2000) {
-      LedEffects::displayCO2color(co2);
-      LedEffects::breathe(co2);
+      led_effects::displayCO2color(co2);
+      led_effects::breathe(co2);
     } else {
       // >= 2000: entire ring blinks red
-      LedEffects::redAlert();
+      led_effects::redAlert();
     }
   }
 
@@ -162,7 +162,7 @@ namespace sensor {
     //NOTE: Data is available, but it's sometimes erroneous: the sensor outputs zero ppm but non-zero temperature and non-zero humidity.
     if (co2 <= 0) {
       // No measurement yet. Waiting.
-      LedEffects::showWaitingLED(color::blue);
+      led_effects::showWaitingLED(color::blue);
       return false;
     }
 
@@ -180,7 +180,7 @@ namespace sensor {
       if (stable_measurements == 60) {
         calibrateAndRestart();
       }
-      LedEffects::showWaitingLED(waiting_color);
+      led_effects::showWaitingLED(waiting_color);
       return false;
     }
 
diff --git a/co2_sensor.h b/ampel-firmware/co2_sensor.h
similarity index 100%
rename from co2_sensor.h
rename to ampel-firmware/co2_sensor.h
diff --git a/config.public.h b/ampel-firmware/config.public.h
similarity index 95%
rename from config.public.h
rename to ampel-firmware/config.public.h
index e2c5ed23e1bd48533b9d23fe730f13826c1815ce..6b87993ce03f4489ae242a48b2c6f2c87afe6e63 100644
--- a/config.public.h
+++ b/ampel-firmware/config.public.h
@@ -8,9 +8,9 @@
  */
 
 // Comment or remove those lines if you want to disable the corresponding services
-#  define AMPEL_WIFI    // WiFi, and all other dependent services (MQTT, HTTP, NTP, ...)
-#  define AMPEL_HTTP    // Should HTTP web server be started?
-#  define AMPEL_MQTT    // Should data be sent over MQTT?
+#  define AMPEL_WIFI    // Should ESP connect to WiFi? It allows the Ampel to get time from an NTP server.
+#  define AMPEL_HTTP    // Should HTTP web server be started? (AMPEL_WIFI should be enabled too)
+#  define AMPEL_MQTT    // Should data be sent over MQTT? (AMPEL_WIFI should be enabled too)
 #  define AMPEL_CSV     // Should data be logged as CSV, on the ESP flash memory?
 // #  define AMPEL_LORAWAN // Should data be sent over LoRaWAN? (Requires ESP32 + LoRa modem, and "MCCI LoRaWAN LMIC library")
 
@@ -124,7 +124,6 @@
 // 4) In order to use LoRaWAN, a gateway should be close to the co2ampel, and an account, an application and a device should be registered,
 //      e.g. on https://www.thethingsnetwork.org/docs/applications/
 // 5) The corresponding keys should be defined in LORAWAN_DEVICE_EUI, LORAWAN_APPLICATION_EUI and LORAWAN_APPLICATION_KEY
-
 // How often should measurements be sent over LoRaWAN?
 #  define LORAWAN_SENDING_INTERVAL 300 // [s] This value should not be too low. See https://www.thethingsnetwork.org/docs/lorawan/duty-cycle.html#maximum-duty-cycle
 
diff --git a/csv_writer.cpp b/ampel-firmware/csv_writer.cpp
similarity index 98%
rename from csv_writer.cpp
rename to ampel-firmware/csv_writer.cpp
index 84bdc646940cf7e6ac582c239113033fd040e06a..81b7278a3aa08819fee0474ef8af8c24cfdc0b96 100644
--- a/csv_writer.cpp
+++ b/ampel-firmware/csv_writer.cpp
@@ -135,7 +135,7 @@ namespace csv_writer {
   }
 
   void log(const String &timeStamp, const int16_t &co2, const float &temperature, const float &humidity) {
-    LedEffects::onBoardLEDOn();
+    led_effects::onBoardLEDOn();
     File csv_file = openOrCreate();
     char csv_line[42];
     snprintf(csv_line, sizeof(csv_line), "%s;%d;%.1f;%.1f\r\n", timeStamp.c_str(), co2, temperature, humidity);
@@ -155,7 +155,7 @@ namespace csv_writer {
       //NOTE: Can it ever happen that outfile is false?
       Serial.println(F("Problem on create file!"));
     }
-    LedEffects::onBoardLEDOff();
+    led_effects::onBoardLEDOff();
   }
 
   void logIfTimeHasCome(const String &timeStamp, const int16_t &co2, const float &temperature, const float &humidity) {
diff --git a/csv_writer.h b/ampel-firmware/csv_writer.h
similarity index 97%
rename from csv_writer.h
rename to ampel-firmware/csv_writer.h
index c6b71a1ed980fbd5ceca472056000af72b50ae8c..e0e0d5314ae9060ca8c39315737da2a73beb5d99 100644
--- a/csv_writer.h
+++ b/ampel-firmware/csv_writer.h
@@ -11,8 +11,10 @@
 #  error Board should be either ESP8266 or ESP832
 #endif
 
-#include "led_effects.h"
 #include "config.h"
+#include "util.h"
+#include "led_effects.h"
+
 namespace config {
   extern uint16_t csv_interval; // [s]
 }
diff --git a/led_effects.cpp b/ampel-firmware/led_effects.cpp
similarity index 97%
rename from led_effects.cpp
rename to ampel-firmware/led_effects.cpp
index 2f53b39d86f998d07963a7c567c13236de062702..ebe8beef0565a89bec811d64b9aedc870c6ff3b2 100644
--- a/led_effects.cpp
+++ b/ampel-firmware/led_effects.cpp
@@ -33,7 +33,7 @@ const uint16_t CO2_TICKS[NUMPIXELS + 1] = { 0, 500, 600, 700, 800, 900, 1000, 12
 const uint16_t LED_HUES[NUMPIXELS] = { 21845, 19114, 16383, 13653, 10922, 8191, 5461, 2730, 0, 0, 0, 0 }; // [hue angle]
 Adafruit_NeoPixel pixels(NUMPIXELS, NEOPIXELS_PIN, NEO_GRB + NEO_KHZ800);
 
-namespace LedEffects {
+namespace led_effects {
   //On-board LED on D4, aka GPIO02
   const int ONBOARD_LED_PIN = 2;
 
@@ -139,14 +139,14 @@ namespace LedEffects {
     pixels.show();
   }
 
-  void showRainbowWheel(int duration_s, uint16_t hue_increment) {
+  void showRainbowWheel(int duration_ms, uint16_t hue_increment) {
     if (config::night_mode) {
       return;
     }
     static uint16_t wheel_offset = 0;
-    unsigned long t0 = seconds();
+    unsigned long t0 = millis();
     pixels.setBrightness(config::max_brightness);
-    while (seconds() < t0 + duration_s) {
+    while (millis() < t0 + duration_ms) {
       for (int i = 0; i < NUMPIXELS; i++) {
         pixels.setPixelColor(i, pixels.ColorHSV(i * 65535 / NUMPIXELS + wheel_offset));
         wheel_offset += hue_increment;
diff --git a/led_effects.h b/ampel-firmware/led_effects.h
similarity index 89%
rename from led_effects.h
rename to ampel-firmware/led_effects.h
index 31368a2dea2842c4f2d3f884f71a2533d9e9a251..03aee3dc24a02dc403b0e20105c3013f678488e5 100644
--- a/led_effects.h
+++ b/ampel-firmware/led_effects.h
@@ -1,7 +1,6 @@
 #ifndef LED_EFFECTS_H_INCLUDED
 #define LED_EFFECTS_H_INCLUDED
 #include <Arduino.h>
-#include "util.h"
 #include "config.h"
 
 // Adafruit NeoPixel (Arduino library for controlling single-wire-based LED pixels and strip)
@@ -17,7 +16,7 @@ namespace color {
   const uint32_t magenta = 0xFF00FF;
 }
 
-namespace LedEffects {
+namespace led_effects {
   void setupOnBoardLED();
   void onBoardLEDOff();
   void onBoardLEDOn();
@@ -30,7 +29,7 @@ namespace LedEffects {
   int countdownToZero();
   void showWaitingLED(uint32_t color);
   void showKITTWheel(uint32_t color, uint16_t duration_s = 2);
-  void showRainbowWheel(int duration_s = 1, uint16_t hue_increment = 50);
+  void showRainbowWheel(int duration_ms = 1000, uint16_t hue_increment = 50);
   void displayCO2color(uint16_t co2);
 }
 #endif
diff --git a/lorawan.cpp b/ampel-firmware/lorawan.cpp
similarity index 98%
rename from lorawan.cpp
rename to ampel-firmware/lorawan.cpp
index 57894c499bb466e8a64ef3978c01534b9bbbd9aa..75363a0337ce887c860d38fb7c5a940bed3e642f 100644
--- a/lorawan.cpp
+++ b/ampel-firmware/lorawan.cpp
@@ -74,7 +74,7 @@ namespace lorawan {
     case EV_JOINED:
       waiting_for_confirmation = false;
       connected = true;
-      LedEffects::onBoardLEDOff();
+      led_effects::onBoardLEDOff();
       Serial.println(F("EV_JOINED"));
       {
         u4_t netid = 0;
@@ -121,12 +121,12 @@ namespace lorawan {
       break;
     case EV_TXCANCELED:
       waiting_for_confirmation = false;
-      LedEffects::onBoardLEDOff();
+      led_effects::onBoardLEDOff();
       Serial.println(F("EV_TXCANCELED"));
       break;
     case EV_JOIN_TXCOMPLETE:
       waiting_for_confirmation = false;
-      LedEffects::onBoardLEDOff();
+      led_effects::onBoardLEDOff();
       Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept."));
       Serial.println(F("Other services may resume."));
       break;
@@ -136,7 +136,7 @@ namespace lorawan {
       break;
     }
     if (waiting_for_confirmation) {
-      LedEffects::onBoardLEDOn();
+      led_effects::onBoardLEDOn();
       Serial.println(F("LoRa - waiting for OTAA confirmation. Freezing every other service!"));
     }
   }
diff --git a/lorawan.h b/ampel-firmware/lorawan.h
similarity index 99%
rename from lorawan.h
rename to ampel-firmware/lorawan.h
index 28ec97262fa8194326a567c574997d6ac8353a5c..a4e29ab2c89019202aceddb920c26f49978b085b 100644
--- a/lorawan.h
+++ b/ampel-firmware/lorawan.h
@@ -1,5 +1,8 @@
 #ifndef AMPEL_LORAWAN_H_
 #define AMPEL_LORAWAN_H_
+
+#include "config.h"
+
 #if defined(AMPEL_LORAWAN) && defined(ESP32)
 #include <Arduino.h>
 // Requires "MCCI LoRaWAN LMIC library", which will be automatically used with PlatformIO but should be added in "Arduino IDE".
@@ -10,7 +13,6 @@
 #include <SPI.h>
 
 #include "led_effects.h"
-#include "config.h"
 
 #include "util.h"
 
diff --git a/mqtt.cpp b/ampel-firmware/mqtt.cpp
similarity index 93%
rename from mqtt.cpp
rename to ampel-firmware/mqtt.cpp
index 08fe67ceb51960f3825b22049958c9ef049d1fd0..29f609fdf0751bbcebcc0b501c08e12d7212b6a6 100644
--- a/mqtt.cpp
+++ b/ampel-firmware/mqtt.cpp
@@ -40,7 +40,7 @@ namespace mqtt {
 
   void publish(const String &timestamp, int16_t co2, float temperature, float humidity) {
     if (WiFi.status() == WL_CONNECTED && mqttClient.connected()) {
-      LedEffects::onBoardLEDOn();
+      led_effects::onBoardLEDOn();
       Serial.print(F("Publishing MQTT message ... "));
 
       char payload[75]; // Should be enough for json...
@@ -52,7 +52,7 @@ namespace mqtt {
       } else {
         Serial.println(F("Failed."));
       }
-      LedEffects::onBoardLEDOff();
+      led_effects::onBoardLEDOff();
     }
   }
 
@@ -65,7 +65,7 @@ namespace mqtt {
       Serial.println("s.");
       sensor::scd30.setMeasurementInterval(messageString.toInt());
       config::measurement_timestep = messageString.toInt();
-      LedEffects::showKITTWheel(color::green, 1);
+      led_effects::showKITTWheel(color::green, 1);
     }
   }
 
@@ -75,7 +75,7 @@ namespace mqtt {
     Serial.print(F("Setting Sending Interval to : "));
     Serial.print(config::sending_interval);
     Serial.println("s.");
-    LedEffects::showKITTWheel(color::green, 1);
+    led_effects::showKITTWheel(color::green, 1);
   }
 
 #ifdef AMPEL_CSV
@@ -85,7 +85,7 @@ namespace mqtt {
     Serial.print(F("Setting CSV Interval to : "));
     Serial.print(config::csv_interval);
     Serial.println("s.");
-    LedEffects::showKITTWheel(color::green, 1);
+    led_effects::showKITTWheel(color::green, 1);
   }
 #endif
 
@@ -131,7 +131,7 @@ namespace mqtt {
     if (length == 0) {
       return;
     }
-    LedEffects::onBoardLEDOn();
+    led_effects::onBoardLEDOn();
     Serial.print(F("Message arrived on topic: "));
     Serial.print(sub_topic);
     Serial.print(F(". Message: '"));
@@ -160,20 +160,20 @@ namespace mqtt {
       setCSVinterval(messageString);
     } else if (messageString == "format_filesystem") {
       FS_LIB.format();
-      LedEffects::showKITTWheel(color::blue, 2);
+      led_effects::showKITTWheel(color::blue, 2);
 #endif
     } else if (messageString == "night_mode") {
-      LedEffects::toggleNightMode();
+      led_effects::toggleNightMode();
     } else if (messageString == "local_ip") {
       sendInfoAboutLocalNetwork();
     } else if (messageString == "reset") {
-      resetAmpel();
+      ESP.restart(); // softer than ESP.reset()
     } else {
-      LedEffects::showKITTWheel(color::red, 1);
+      led_effects::showKITTWheel(color::red, 1);
       Serial.println(F("Message not supported. Doing nothing."));
     }
     delay(50);
-    LedEffects::onBoardLEDOff();
+    led_effects::onBoardLEDOff();
   }
 
   void reconnect() {
@@ -187,10 +187,10 @@ namespace mqtt {
     }
     Serial.print(F("Attempting MQTT connection..."));
 
-    LedEffects::onBoardLEDOn();
+    led_effects::onBoardLEDOn();
     // Wait for connection, at most 15s (default)
     mqttClient.connect(publish_topic.c_str(), config::mqtt_user, config::mqtt_password);
-    LedEffects::onBoardLEDOff();
+    led_effects::onBoardLEDOff();
 
     connected = mqttClient.connected();
 
diff --git a/mqtt.h b/ampel-firmware/mqtt.h
similarity index 100%
rename from mqtt.h
rename to ampel-firmware/mqtt.h
diff --git a/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp b/ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp
diff --git a/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h b/ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/Adafruit_NeoPixel.h
diff --git a/src/lib/Adafruit_NeoPixel/CONTRIBUTING.md b/ampel-firmware/src/lib/Adafruit_NeoPixel/CONTRIBUTING.md
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/CONTRIBUTING.md
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/CONTRIBUTING.md
diff --git a/src/lib/Adafruit_NeoPixel/COPYING b/ampel-firmware/src/lib/Adafruit_NeoPixel/COPYING
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/COPYING
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/COPYING
diff --git a/src/lib/Adafruit_NeoPixel/README.md b/ampel-firmware/src/lib/Adafruit_NeoPixel/README.md
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/README.md
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/README.md
diff --git a/src/lib/Adafruit_NeoPixel/esp.c b/ampel-firmware/src/lib/Adafruit_NeoPixel/esp.c
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/esp.c
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/esp.c
diff --git a/src/lib/Adafruit_NeoPixel/esp8266.c b/ampel-firmware/src/lib/Adafruit_NeoPixel/esp8266.c
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/esp8266.c
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/esp8266.c
diff --git a/src/lib/Adafruit_NeoPixel/kendyte_k210.c b/ampel-firmware/src/lib/Adafruit_NeoPixel/kendyte_k210.c
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/kendyte_k210.c
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/kendyte_k210.c
diff --git a/src/lib/Adafruit_NeoPixel/keywords.txt b/ampel-firmware/src/lib/Adafruit_NeoPixel/keywords.txt
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/keywords.txt
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/keywords.txt
diff --git a/src/lib/Adafruit_NeoPixel/library.properties b/ampel-firmware/src/lib/Adafruit_NeoPixel/library.properties
similarity index 100%
rename from src/lib/Adafruit_NeoPixel/library.properties
rename to ampel-firmware/src/lib/Adafruit_NeoPixel/library.properties
diff --git a/src/lib/NTPClient-master/.travis.yml b/ampel-firmware/src/lib/NTPClient-master/.travis.yml
similarity index 100%
rename from src/lib/NTPClient-master/.travis.yml
rename to ampel-firmware/src/lib/NTPClient-master/.travis.yml
diff --git a/src/lib/NTPClient-master/CHANGELOG b/ampel-firmware/src/lib/NTPClient-master/CHANGELOG
similarity index 100%
rename from src/lib/NTPClient-master/CHANGELOG
rename to ampel-firmware/src/lib/NTPClient-master/CHANGELOG
diff --git a/src/lib/NTPClient-master/NTPClient.cpp b/ampel-firmware/src/lib/NTPClient-master/NTPClient.cpp
similarity index 100%
rename from src/lib/NTPClient-master/NTPClient.cpp
rename to ampel-firmware/src/lib/NTPClient-master/NTPClient.cpp
diff --git a/src/lib/NTPClient-master/NTPClient.h b/ampel-firmware/src/lib/NTPClient-master/NTPClient.h
similarity index 100%
rename from src/lib/NTPClient-master/NTPClient.h
rename to ampel-firmware/src/lib/NTPClient-master/NTPClient.h
diff --git a/src/lib/NTPClient-master/README.md b/ampel-firmware/src/lib/NTPClient-master/README.md
similarity index 100%
rename from src/lib/NTPClient-master/README.md
rename to ampel-firmware/src/lib/NTPClient-master/README.md
diff --git a/src/lib/NTPClient-master/keywords.txt b/ampel-firmware/src/lib/NTPClient-master/keywords.txt
similarity index 100%
rename from src/lib/NTPClient-master/keywords.txt
rename to ampel-firmware/src/lib/NTPClient-master/keywords.txt
diff --git a/src/lib/NTPClient-master/library.json b/ampel-firmware/src/lib/NTPClient-master/library.json
similarity index 100%
rename from src/lib/NTPClient-master/library.json
rename to ampel-firmware/src/lib/NTPClient-master/library.json
diff --git a/src/lib/NTPClient-master/library.properties b/ampel-firmware/src/lib/NTPClient-master/library.properties
similarity index 100%
rename from src/lib/NTPClient-master/library.properties
rename to ampel-firmware/src/lib/NTPClient-master/library.properties
diff --git a/src/lib/PubSubClient/CHANGES.txt b/ampel-firmware/src/lib/PubSubClient/CHANGES.txt
similarity index 100%
rename from src/lib/PubSubClient/CHANGES.txt
rename to ampel-firmware/src/lib/PubSubClient/CHANGES.txt
diff --git a/src/lib/PubSubClient/LICENSE.txt b/ampel-firmware/src/lib/PubSubClient/LICENSE.txt
similarity index 100%
rename from src/lib/PubSubClient/LICENSE.txt
rename to ampel-firmware/src/lib/PubSubClient/LICENSE.txt
diff --git a/src/lib/PubSubClient/README.md b/ampel-firmware/src/lib/PubSubClient/README.md
similarity index 100%
rename from src/lib/PubSubClient/README.md
rename to ampel-firmware/src/lib/PubSubClient/README.md
diff --git a/src/lib/PubSubClient/keywords.txt b/ampel-firmware/src/lib/PubSubClient/keywords.txt
similarity index 100%
rename from src/lib/PubSubClient/keywords.txt
rename to ampel-firmware/src/lib/PubSubClient/keywords.txt
diff --git a/src/lib/PubSubClient/library.json b/ampel-firmware/src/lib/PubSubClient/library.json
similarity index 100%
rename from src/lib/PubSubClient/library.json
rename to ampel-firmware/src/lib/PubSubClient/library.json
diff --git a/src/lib/PubSubClient/library.properties b/ampel-firmware/src/lib/PubSubClient/library.properties
similarity index 100%
rename from src/lib/PubSubClient/library.properties
rename to ampel-firmware/src/lib/PubSubClient/library.properties
diff --git a/src/lib/PubSubClient/src/PubSubClient.cpp b/ampel-firmware/src/lib/PubSubClient/src/PubSubClient.cpp
similarity index 100%
rename from src/lib/PubSubClient/src/PubSubClient.cpp
rename to ampel-firmware/src/lib/PubSubClient/src/PubSubClient.cpp
diff --git a/src/lib/PubSubClient/src/PubSubClient.h b/ampel-firmware/src/lib/PubSubClient/src/PubSubClient.h
similarity index 100%
rename from src/lib/PubSubClient/src/PubSubClient.h
rename to ampel-firmware/src/lib/PubSubClient/src/PubSubClient.h
diff --git a/src/lib/SparkFun_SCD30_Arduino_Library/LICENSE.md b/ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/LICENSE.md
similarity index 100%
rename from src/lib/SparkFun_SCD30_Arduino_Library/LICENSE.md
rename to ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/LICENSE.md
diff --git a/src/lib/SparkFun_SCD30_Arduino_Library/README.md b/ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/README.md
similarity index 100%
rename from src/lib/SparkFun_SCD30_Arduino_Library/README.md
rename to ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/README.md
diff --git a/src/lib/SparkFun_SCD30_Arduino_Library/documents/Sensirion_CO2_Sensors_SCD30_Preliminary-Datasheet.pdf b/ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/documents/Sensirion_CO2_Sensors_SCD30_Preliminary-Datasheet.pdf
similarity index 100%
rename from src/lib/SparkFun_SCD30_Arduino_Library/documents/Sensirion_CO2_Sensors_SCD30_Preliminary-Datasheet.pdf
rename to ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/documents/Sensirion_CO2_Sensors_SCD30_Preliminary-Datasheet.pdf
diff --git a/src/lib/SparkFun_SCD30_Arduino_Library/keywords.txt b/ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/keywords.txt
similarity index 100%
rename from src/lib/SparkFun_SCD30_Arduino_Library/keywords.txt
rename to ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/keywords.txt
diff --git a/src/lib/SparkFun_SCD30_Arduino_Library/library.properties b/ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/library.properties
similarity index 100%
rename from src/lib/SparkFun_SCD30_Arduino_Library/library.properties
rename to ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/library.properties
diff --git a/src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.cpp b/ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.cpp
similarity index 100%
rename from src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.cpp
rename to ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.cpp
diff --git a/src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.h b/ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.h
similarity index 100%
rename from src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.h
rename to ampel-firmware/src/lib/SparkFun_SCD30_Arduino_Library/src/SparkFun_SCD30_Arduino_Library.h
diff --git a/util.cpp b/ampel-firmware/util.cpp
similarity index 88%
rename from util.cpp
rename to ampel-firmware/util.cpp
index c32a5c561d717539d8ff0809724d381461131deb..31df19dd856e5c3f17b5eb929979660eb27db715 100644
--- a/util.cpp
+++ b/ampel-firmware/util.cpp
@@ -38,16 +38,6 @@ namespace ntp {
   }
 }
 
-void resetAmpel() {
-  Serial.print(F("Resetting"));
-#ifdef AMPEL_CSV
-  FS_LIB.end();
-#endif
-  LedEffects::LEDsOff();
-  delay(1000);
-  ESP.restart();
-}
-
 uint32_t max_loop_duration = 0;
 
 //FIXME: Remove every instance of Strings, to avoid heap fragmentation problems. (Start:  "Free heap space : 17104 bytes")
diff --git a/util.h b/ampel-firmware/util.h
similarity index 83%
rename from util.h
rename to ampel-firmware/util.h
index c9a8a943aaf0af03dc933e171070c56eb7a93eab..0ffe5eb4d35d2243512035c07e09c1d44464fea8 100644
--- a/util.h
+++ b/ampel-firmware/util.h
@@ -2,19 +2,17 @@
 #define AMPEL_UTIL_H_INCLUDED
 #include <Arduino.h>
 #include "config.h"
-#include "wifi_util.h" // To get MAC
-#ifdef AMPEL_CSV
-#  include "csv_writer.h" // To close filesystem before reset
-#endif
 
-#include <WiFiUdp.h> //required for NTP
+#include <WiFiUdp.h> // required for NTP
 #include "src/lib/NTPClient-master/NTPClient.h" // NTP
 
 #if defined(ESP8266)
 #  define BOARD "ESP8266"
+#  include <ESP8266WiFi.h> // required to get MAC address
 #  define get_free_heap_size() system_get_free_heap_size()
 #elif defined(ESP32)
 #  define BOARD "ESP32"
+#  include <WiFi.h> // required to get MAC address
 #  define get_free_heap_size() esp_get_free_heap_size()
 #else
 #  define BOARD "Unknown"
@@ -42,6 +40,4 @@ namespace util {
 extern uint32_t max_loop_duration;
 const extern String SENSOR_ID;
 
-void resetAmpel();
-
 #endif
diff --git a/web_server.cpp b/ampel-firmware/web_server.cpp
similarity index 100%
rename from web_server.cpp
rename to ampel-firmware/web_server.cpp
diff --git a/web_server.h b/ampel-firmware/web_server.h
similarity index 100%
rename from web_server.h
rename to ampel-firmware/web_server.h
diff --git a/wifi_util.cpp b/ampel-firmware/wifi_util.cpp
similarity index 87%
rename from wifi_util.cpp
rename to ampel-firmware/wifi_util.cpp
index 2da3d1884f19e9c9a0cdaeed34439d244ab99e06..5160b52b5365e77fc31e5bfda24198ac02284515 100644
--- a/wifi_util.cpp
+++ b/ampel-firmware/wifi_util.cpp
@@ -16,7 +16,7 @@ namespace config {
 void WiFiConnect(const String &hostname) {
   //NOTE: WiFi Multi could allow multiple SSID and passwords.
   WiFi.persistent(false); // Don't write user & password to Flash.
-  WiFi.mode(WIFI_STA); // Set ESP8266 to be a WiFi-client only
+  WiFi.mode(WIFI_STA); // Set ESP to be a WiFi-client only
 #if defined(ESP8266)
     WiFi.hostname(hostname);
 #elif defined(ESP32)
@@ -29,16 +29,16 @@ void WiFiConnect(const String &hostname) {
 
   // Wait for connection, at most wifi_timeout seconds
   for (int i = 0; i <= config::wifi_timeout && (WiFi.status() != WL_CONNECTED); i++) {
-    LedEffects::showRainbowWheel();
+    led_effects::showRainbowWheel();
     Serial.print(".");
   }
   if (WiFi.status() == WL_CONNECTED) {
-    LedEffects::showKITTWheel(color::green);
+    led_effects::showKITTWheel(color::green);
     Serial.println();
     Serial.print("\nWiFi connected, IP address: ");
     Serial.println(WiFi.localIP());
   } else {
-    LedEffects::showKITTWheel(color::red);
+    led_effects::showKITTWheel(color::red);
     Serial.println("\nConnection to WiFi failed");
   }
 }
diff --git a/ampel-firmware/wifi_util.h b/ampel-firmware/wifi_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..7520ed78e070cf552500441f4828bb7d339392b8
--- /dev/null
+++ b/ampel-firmware/wifi_util.h
@@ -0,0 +1,10 @@
+#ifndef WIFI_UTIL_H_INCLUDED
+#define WIFI_UTIL_H_INCLUDED
+
+#include "config.h"
+#include "util.h"
+#include "led_effects.h"
+
+void WiFiConnect(const String &hostname);
+
+#endif
diff --git a/platformio.ini b/platformio.ini
index 37408192cce461fd4605ba150237ec318a72d209..becf69fc263e19f956d1cf7a7ff4701dd7322247 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -8,7 +8,7 @@
 ; http://docs.platformio.org/page/projectconf.html
 
 [platformio]
-src_dir = ./
+src_dir = ampel-firmware
 
 [env:esp8266]
 platform = espressif8266
diff --git a/wifi_util.h b/wifi_util.h
deleted file mode 100644
index d6303fbf0c50f7ff62d2c0f583767c40bc912eda..0000000000000000000000000000000000000000
--- a/wifi_util.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef WIFI_UTIL_H_INCLUDED
-#  define WIFI_UTIL_H_INCLUDED
-#  if defined(ESP8266)
-#    include <ESP8266WiFi.h>
-#  elif defined(ESP32)
-#    include <WiFi.h>
-#  endif
-
-#include "led_effects.h"
-#include "config.h"
-void WiFiConnect(const String &hostname);
-
-#endif