#include #include #include // --- NeoPixel-Definition --- #define LED_PIN 1 // D1 = GPIO1 #define NUM_LEDS 40 Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800); // --- Sensor-Definition --- #define MQ135_PIN A0 // --- ESP-NOW-Peer-MAC (Empfänger) --- uint8_t peerMAC[] = { 0xE4, 0xB0, 0x63, 0x41, 0xD1, 0x18 }; // --- Status-Codes --- // 0 = Kalibrieren, 1 = gut, 2 = okay, 3 = schlecht uint8_t state = 0; uint32_t baseAvg = 0; // Basiswert aus Kalibrierung uint8_t failCount = 0; uint16_t spinnerPos = 0; // Callback: Sendestatus -> failCount void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { if (status == ESP_NOW_SEND_SUCCESS) { failCount = 0; } else { failCount++; } } // „Breathing“ in Weiß (gesamte Dauer in ms) void breatheWhite(uint16_t durationMs) { const int steps = 50; const int halfMs = durationMs / 2; const int delayMs = halfMs / steps; // fade up for (int i = 0; i <= steps; i++) { strip.setBrightness(map(i, 0, steps, 0, 255)); strip.fill(strip.Color(255,255,255), 0, NUM_LEDS); strip.show(); delay(delayMs); } // fade down for (int i = steps; i >= 0; i--) { strip.setBrightness(map(i, 0, steps, 0, 255)); strip.fill(strip.Color(255,255,255), 0, NUM_LEDS); strip.show(); delay(delayMs); } strip.setBrightness(255); } // Spinner-Animation bei Verbindungsproblemen void showSpinner() { strip.clear(); for (uint8_t i = 0; i < 3; i++) { strip.setPixelColor((spinnerPos + i) % NUM_LEDS, strip.Color(255,255,255)); } strip.show(); spinnerPos = (spinnerPos + 1) % NUM_LEDS; delay(100); } void setup() { Serial.begin(115200); // NeoPixel initialisieren + weißes Aufleuchten strip.begin(); strip.fill(strip.Color(255,255,255), 0, NUM_LEDS); strip.setBrightness(255); strip.show(); // WLAN & ESP-NOW init WiFi.mode(WIFI_STA); if (esp_now_init() != ESP_OK) { // Endlosschleife mit White-Flash while (true) { strip.fill(strip.Color(255,255,255), 0, NUM_LEDS); strip.show(); delay(100); strip.clear(); strip.show(); delay(100); } } esp_now_register_send_cb(onDataSent); esp_now_peer_info_t peer = {}; memcpy(peer.peer_addr, peerMAC, 6); peer.channel = 0; peer.encrypt = false; esp_now_add_peer(&peer); Serial.println("Starte Kalibrierung (60s)..."); // Kalibrierung: 60 Messungen im 1s-Takt uint32_t sum = 0; for (int i = 0; i < 60; i++) { int raw = analogRead(MQ135_PIN); sum += raw; // Sende Kalibrierungs-Status state = 0; esp_now_send(peerMAC, &state, 1); // Weißes „Breathing“ breatheWhite(1000); } baseAvg = sum / 60; Serial.printf("Kalibrierung fertig, Basis = %u\n", baseAvg); // LEDs aus nach Kalibrierung strip.clear(); strip.show(); delay(500); } void loop() { // 1) Sensor auslesen int raw = analogRead(MQ135_PIN); // 2) Klassifikation relativ zum Basiswert if (raw <= baseAvg) state = 1; // gut else if (raw <= baseAvg * 1.2f) state = 2; // okay else state = 3; // schlecht // 3) Status senden esp_now_send(peerMAC, &state, 1); // 4) Animation / Farblegende if (failCount >= 10) { showSpinner(); } else { strip.clear(); switch (state) { case 1: // gut → Grün jede zweite LED for (int i = 0; i < NUM_LEDS; i += 2) strip.setPixelColor(i, strip.Color(0,150,0)); break; case 2: // okay → Gelb for (int i = 0; i < NUM_LEDS; i += 2) strip.setPixelColor(i, strip.Color(150,150,0)); break; case 3: // schlecht → Rot for (int i = 0; i < NUM_LEDS; i += 2) strip.setPixelColor(i, strip.Color(150,0,0)); break; } strip.show(); delay(1000); } }