Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
| www-fuer-alle:codeweek [2025/10/13 07:00] – [Workshop] biebl | www-fuer-alle:codeweek [2025/10/13 19:39] (aktuell) – biebl | ||
|---|---|---|---|
| Zeile 20: | Zeile 20: | ||
| 2024 | 2024 | ||
| {{: | {{: | ||
| - | ===== Möglichkeiten ===== | ||
| - | * 3D-Druck - Projektumsetzung | + | 2025 {{:www-fuer-alle:codeweek-2025-breadboardaufbau.jpeg? | 
| - | * CAD | + | |
| - | * Einstieg mit [[https://www.blockscad3d.com/ | + | |
| - | * Projektumsetzung mit [[https:// | + | |
| - | * Slicer | + | |
| - | * [[https:// | + | |
| - | * [[https:// | + | |
| - | * Druck | + | |
| - | * [[https:// | + | |
| - | * [[https:// | + | |
| - | * Filamente | + | |
| - | * [[https:// | + | |
| - | * ... | + | |
| - | * ARDUINO - Projektumsetzung | + | ===== Vollversion ===== | 
| - | * Software | + | |
| - | * [[https:// | + | |
| - | * [[https:// | + | |
| - | * Hardware | + | |
| - | {{:www-fuer-alle:fehlende-teile.png? | + | < | 
| - | * UNO | + | / | 
| - | * NANO | + | * ESP32 - Mobiles Messgerät (Workshop-ready, | 
| - | * (D1-mini) | + | * | 
| + | * Sensoren: | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + | * | ||
| + | * Anzeige: | ||
| + |  | ||
| + |  | ||
| + | * | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + |  | ||
| - | ===== Linkliste | + | // === WLAN / Geräte-Setup | 
| + | #define DEVICE_NAME " | ||
| + | #define WIFI_PASSWORD " | ||
| + | #define MEASUREMENT_INTERVAL_SEC 1 | ||
| + | // === Hardware-Pins ================================================= | ||
| + | #define OLED_SDA 23 | ||
| + | #define OLED_SCL 22 | ||
| + | #define ADC_PIN_LDR 34 | ||
| + | #define ADC_PIN_MIC 35 | ||
| + | #define LED_GREEN 15 | ||
| + | #define LED_YELLOW 2 | ||
| + | #define LED_RED 4 | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| - | ===== Geschichte | + | // === Objekte | 
| + | Adafruit_SSD1306 display(128, | ||
| + | Adafruit_BMP085 bmp; | ||
| + | WebServer server(80); | ||
| - | * ...[[www-fuer-alle: | + | // === Globale Messdaten ============================================= | 
| + | volatile int lastLdr = 0; | ||
| + | volatile int lastMic = 0; | ||
| + | volatile float lastTemp = 0.0; | ||
| + | volatile float lastPres = 0.0; | ||
| + | // === Ampelstatus =================================================== | ||
| + | bool autoAmpelMode = false; | ||
| + | bool lärmAmpelMode = false; | ||
| + | int ampelState = 0; // interner Zustand der Verkehrsampel | ||
| + | unsigned long ampelTimer = 0; // Timer für Ampelphasen | ||
| + | // === Zeit / Uhr ==================================================== | ||
| + | bool timeSynced = false; | ||
| + | uint64_t startEpoch = 0; | ||
| + | uint64_t startMillis = 0; | ||
| - | {{: | + | // === Zeit-Funktionen =============================================== | 
| - | {{: | + | String formatTime(uint64_t epochSec) | 
| - | {{: | + |  | 
| - | {{: | + |  | 
| - | {{: | + | char buffer[25]; | 
| - | {{:www-fuer-alle:2019-08-arduino-material-07.jpg? | + |  | 
| - | {{:www-fuer-alle: | + | return String(buffer); | 
| - | {{: | + | } | 
| + | String getCurrentTimeString() { | ||
| + | if (!timeSynced) return " | ||
| + | uint64_t elapsedMs = millis() - startMillis; | ||
| + | uint64_t epochNow = startEpoch + (elapsedMs / 1000ULL); | ||
| + | return formatTime(epochNow); | ||
| + | } | ||
| + | // === LDR lesen ===================================================== | ||
| + | int readLDR(int pin, int samples = 10) { | ||
| + | long sum = 0; | ||
| + | for (int i = 0; i < samples; i++) { sum += analogRead(pin); | ||
| + | return sum / samples; | ||
| + | } | ||
| - | ====== | + | // === Lautstärke mit automatischer Kalibrierung | 
| + | int readMicLevel(int pin) { | ||
| + | const int samples = 250; // Messzeit ~0,25s | ||
| + | long sum = 0; | ||
| + | for (int i = 0; i < samples; i++) { sum += analogRead(pin); | ||
| + | float mean = (float)sum / samples; | ||
| - |  | + |  | 
| - | ===== Workshop ===== | + | for (int i = 0; i < samples; i++) { | 
| + | int val = analogRead(pin); | ||
| + | float diff = val - mean; | ||
| + | sumSq += diff * diff; | ||
| + | delayMicroseconds(400); | ||
| + | } | ||
| + | float rms = sqrt((float)sumSq / samples); | ||
| - |  | + |  | 
| + | static float noiseCeil | ||
| - | * Wir melden uns zeitnah | + |  | 
| + | noiseFloor = 0.995f | ||
| + | noiseCeil | ||
| + | if (noiseCeil | ||
| + | float norm = (rms - noiseFloor) / (noiseCeil - noiseFloor); | ||
| + | if (norm < 0) norm = 0; if (norm > 1) norm = 1; | ||
| + | int level = 1 + roundf(norm * 8.0f); // Pegel 1..9 | ||
| - | {{:www-fuer-alle: | + | // Debug-Ausgabe zur Kontrolle | 
| - | ===== Möglichkeiten ===== | + | Serial.printf(" | 
| + | rms, noiseFloor, noiseCeil, level); | ||
| + | return level; | ||
| + | } | ||
| - | * 3D-Druck - Projektumsetzung | + | // === Sensoren einlesen ============================================= | 
| - | * CAD | + | void readSensors() { | 
| - | * Einstieg mit [[https://www.blockscad3d.com/ | + |  | 
| - | * Projektumsetzung mit [[https:// | + |  | 
| - | * Slicer | + | |
| - | * [[https:// | + | |
| - | * [[https:// | + | |
| - | * Druck | + | |
| - | * [[https:// | + | |
| - | * [[https:// | + | |
| - | * Filamente | + | |
| - | * [[https:// | + | |
| - | * ... | + | |
| - |  | + |  | 
| - |  | + |  | 
| - | * [[https:// | + |  | 
| - | * [[https:// | + | } else { lastTemp = NAN; lastPres = NAN; } | 
| - | * Hardware | + | } | 
| - | {{:www-fuer-alle: | + | // === OLED-Ausgabe ================================================== | 
| - | * UNO | + | void updateOLED() { | 
| - | * NANO | + | display.clearDisplay(); | 
| - |  | + |  | 
| + |  | ||
| + |  | ||
| - | ===== Linkliste ===== | + | if (!timeSynced) { | 
| + | display.print(DEVICE_NAME); | ||
| + | display.print(" | ||
| + | } else display.println(getCurrentTimeString()); | ||
| + | display.setTextSize(2); | ||
| + | display.setCursor(0, | ||
| + | display.printf(" | ||
| + | display.setCursor(0, | ||
| + | display.printf(" | ||
| - | ===== Geschichte ===== | + | display.setCursor(0, | 
| + | display.setTextSize(1); | ||
| + | display.printf(" | ||
| + | display.display(); | ||
| + | } | ||
| - | * ...[[www-fuer-alle: | + | // === LED-Steuerung ================================================= | 
| + | void setLEDs(bool g, bool y, bool r) { | ||
| + | digitalWrite(LED_GREEN, | ||
| + | digitalWrite(LED_YELLOW, | ||
| + | digitalWrite(LED_RED, | ||
| + | } | ||
| + | // === Lärmampe-Logik ================================================ | ||
| + | void updateLärmAmpel(int level) { | ||
| + | if (!lärmAmpelMode) return; | ||
| + | if (level <= 2) setLEDs(true, | ||
| + | else if (level <= 4) setLEDs(true, | ||
| + | else if (level <= 6) setLEDs(false, | ||
| + | else if (level <= 8) setLEDs(false, | ||
| + | else setLEDs(false, | ||
| + | } | ||
| + | // === Lärmwarnung (Blinksignal) ===================================== | ||
| + | void checkLärmWarnung() { | ||
| + | static unsigned long lastWarn = 0; | ||
| + | static bool blinking = false; | ||
| + | static unsigned long blinkStart = 0; | ||
| - | {{: | + | // Blinkphase aktiv | 
| - | {{: | + | if (blinking) | 
| - | {{:www-fuer-alle: | + | if (millis() | 
| - | {{:www-fuer-alle: | + | else if (millis() | 
| - | {{: | + | else blinking = false; | 
| - | {{: | + |  | 
| - | {{: | + | } | 
| - | {{: | + | |
| - |  | + | // Bei Pegel >= 8 und nach 2s Pause | 
| + | if (lärmAmpelMode && lastMic >= 8 && millis() - lastWarn > 2000) { | ||
| + | blinking = true; | ||
| + | blinkStart = millis(); | ||
| + | lastWarn = millis(); | ||
| + | Serial.println(" | ||
| + | } | ||
| + | } | ||
| - | {{:www-fuer-alle:wetterballo-blick-erde.png? | + | // === Verkehrsampel-Logik =========================================== | 
| + | void updateVerkehrsAmpel() | ||
| + | if (!autoAmpelMode) return; | ||
| + | unsigned long now = millis(), diff = now - ampelTimer; | ||
| + | switch (ampelState) | ||
| + | case 0: setLEDs(true, | ||
| + | case 1: setLEDs(false, | ||
| + | case 2: setLEDs(false, | ||
| + | case 3: setLEDs(false, | ||
| + |  | ||
| + | } | ||
| - | {{:www-fuer-alle:sas-ballonii-blick-von-hamburg-auf-die-ostsee-aus-30km-hoehe.jpg? | + | // === Webinterface (HTML + JS) ====================================== | 
| - | ===== Workshop | + | String generateHTML() | 
| + | // Weboberfläche mit allen Buttons und Balkenanzeige | ||
| + | String html = R" | ||
| + | < | ||
| + | < | ||
| + | <meta name=" | ||
| + | < | ||
| + | body{font-family:Arial; | ||
| + | h1{font-size:1.4em} | ||
| + | .vals{margin: | ||
| + | button{padding: | ||
| + | .g{background:# | ||
| + | .r{background:# | ||
| + | .b{background:# | ||
| + | .status{margin: | ||
| + | .green{background:# | ||
| + | .bar-container{width: | ||
| + | .bar{height: | ||
| + | @keyframes glow{0%{box-shadow:0 0 5px # | ||
| + | .glow{animation: | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | <p class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | function sendTime(){fetch("/ | ||
| + | function updateValues(){ | ||
| + | fetch('/ | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + |  | ||
| + | let s=document.getElementById(' | ||
| + |  | ||
| + | let bar=document.getElementById(' | ||
| + | let width=(obj.mic/ | ||
| + | let color=obj.mic<=3?'# | ||
| + |  | ||
| + |  | ||
| + | }); | ||
| + | } | ||
| + | function led(cmd){fetch('/ | ||
| + | window.onload=()=> | ||
| + | </ | ||
| + | return html; | ||
| + | } | ||
| - | * Anmeldung zum [[https: | + | // === Server-Endpunkte ============================================== | 
| + | void handleRoot(){ server.send(200," | ||
| - | * Wir melden uns zeitnah | + | void handleValue(){ | 
| + | String timeStr=getCurrentTimeString(); | ||
| + | String micText; | ||
| + | if(lastMic< | ||
| + | else if(lastMic< | ||
| + | else if(lastMic< | ||
| + | else if(lastMic< | ||
| + | else if(lastMic< | ||
| + | else micText=" | ||
| + | String modeText, | ||
| + | if(autoAmpelMode){modeText=" | ||
| + | else if(lärmAmpelMode){modeText=" | ||
| + | else{modeText=" | ||
| + | char buf[400]; | ||
| + | snprintf(buf, | ||
| + | " | ||
| + | " | ||
| + |  | ||
| + |  | ||
| + | server.send(200," | ||
| + | } | ||
| - | {{: | + | void handleLed(){ | 
| - | ===== Möglichkeiten | + | String cmd=server.arg(" | 
| + | if(cmd==" | ||
| + | else if(cmd==" | ||
| + | else if(cmd==" | ||
| + | else if(cmd==" | ||
| + | else if(cmd==" | ||
| + | else if(cmd==" | ||
| + | else if(cmd==" | ||
| + | server.send(200," | ||
| + | } | ||
| - | * 3D-Druck - Projektumsetzung====== Codeweek 2025 ====== | + | void handleSetTime(){ | 
| + | if(server.hasArg(" | ||
| + | double epochMs=server.arg(" | ||
| + | startEpoch=(uint64_t)(epochMs/ | ||
| + | startMillis=millis(); timeSynced=true; | ||
| + | server.send(200," | ||
| + | Serial.printf(" | ||
| + | updateOLED(); | ||
| + | } else server.send(400," | ||
| + | } | ||
| - | * [[https://|Auftaktveranstaltung 2025]] | + | // === Setup ========================================================= | 
| + | void setup(){ | ||
| + | Serial.begin(115200); | ||
| + | Serial.println(" | ||
| - | {{: | + | pinMode(LED_GREEN, | 
| + | analogReadResolution(12); | ||
| - | {{: | + | Wire.begin(OLED_SDA, | 
| - | ===== Workshop ===== | + |  | 
| + | display.clearDisplay(); | ||
| + | display.setCursor(0, | ||
| - |  | + |  | 
| + | setenv(" | ||
| - |  | + |  | 
| + | Serial.printf(" | ||
| + | server.on("/", | ||
| + | server.on("/ | ||
| + | server.on("/ | ||
| + | server.on("/ | ||
| + | server.begin(); | ||
| + | readSensors(); | ||
| + | } | ||
| - | {{: | + | // === Loop ========================================================== | 
| + | void loop(){ | ||
| + | server.handleClient(); | ||
| + | static unsigned long lastMillis=0; | ||
| + | if(millis()-lastMillis> | ||
| + | lastMillis=millis(); | ||
| + | } | ||
| + | if(autoAmpelMode) updateVerkehrsAmpel(); | ||
| + | if(lärmAmpelMode){ updateLärmAmpel(lastMic); | ||
| + | } | ||
| + | </ | ||
| ===== Möglichkeiten ===== | ===== Möglichkeiten ===== | ||
| Zeile 205: | Zeile 440: | ||
| - | |||
| - | ====== Weiter Informationen ====== | ||
| - | |||
| - | * [[LEHRER: | ||
| - | * CAD | ||
| - | * Einstieg mit [[https:// | ||
| - | * Projektumsetzung mit [[https:// | ||
| - | * Slicer | ||
| - | * [[https:// | ||
| - | * [[https:// | ||
| - | * Druck | ||
| - | * [[https:// | ||
| - | * [[https:// | ||
| - | * Filamente | ||
| - | * [[https:// | ||
| - | * ... | ||
| - | |||
| - | * ARDUINO - Projektumsetzung | ||
| - | * Software | ||
| - | * [[https:// | ||
| - | * [[https:// | ||
| - | * Hardware | ||
| - | |||
| - | {{: | ||
| - | * UNO | ||
| - | * NANO | ||
| - | * (D1-mini) | ||
| - | |||
| - | ===== Linkliste ===== | ||
| - | |||
| - | |||
| - | |||
| - | ===== Geschichte ===== | ||
| - | |||
| - | * ...[[www-fuer-alle: | ||
| - | |||
| - | |||
| - | |||
| - | {{: | ||
| - | {{: | ||
| - | {{: | ||
| - | {{: | ||
| - | {{: | ||
| - | {{: | ||
| - | {{: | ||
| - | {{: | ||
| - | |||
| - | |||
| - | |||
| - | ====== Weiter Informationen ====== | ||
| - | |||
| - | * [[LEHRER: | ||
| - | |||
| - | |||
| - | |||
| - | ====== Weiter Informationen ====== | ||
| - | |||
| - | * [[LEHRER: | ||



