/*   Optischer_Abstandswarner     - TESTAUFBAU -         v1.21           Juli 2026
----------------------------------------------------------------------------------
Distanzmessung mit dem VL53L1X Laser Sensor bis 4 Meter.
Inspiriert durch: https://github.com/pololu/vl53l1x-arduino
Anzeige der Distanz auf einem kleinen 0,96"- SSD1306 Display.
11.10.2024 https://www.film-werk56.de/linux.html von Peter Klingbeil
17.07.2026 erweitert durch "Heimwerker Leopoldi" zur Abstandswarnung Garage
    Test-Hardware: Arduino Nano, vl53l1x, 0,96" SSD1306 Display, Ampelmodul, 
                   LED-Stripe WS2812B (100uF, 220E), Summer 5V <40mA     
v1.21 Texte STOP und ENDE                    */

#define Abstand_ROT        15 // < cm  | änderbare TESTaufbau werte  -------------
#define Abstand_ROT_blink  30 // < cm  | Garagenabstände ausmessen ---------------
#define Abstand_GELB       40 // >= cm | und eintragen !!!------------------------
#define Abstand_GRUEN  (Abstand_GELB+1) // Modul fkt. bis 400cm
#define RotAusZeit       2000 // alles abschalten wenn ROT für xxx Millisek.------
#define NUMPIXELS   17  // TEST: Wegen Stromversorgung über USB- Port ------------
#define BRIGHTNESS  50  // ====  Set BRIGHTNESS to about 1/5 (max = 255) ---------

#include <Wire.h>              // Funktion: Distanzauswertung in cm
#include "VL53L1X.h"           // Distanzanzeige: gruen, gelb, rot-blink, rot
#include <Arduino.h>           // Summer wenn rot-blink und rot
#include <Adafruit_GFX.h>      // Nach "RotAuszeit" ausschalten der Anzeigen.
#include <Adafruit_SSD1306.h>  
#include <Adafruit_NeoPixel.h>

#define PIN          6   // Digitalpin Neopixel Data
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

bool flag = true;     // für blink wechsel
int8_t dis = 1;       // case distanz: 1= Grün, 2= Gelb, 3= Rot-Blink, 4= ROT

// LED-Ampelmodul und Summer -PIN - Definitionen
const int PIN_LED_GRUEN = 12;
const int PIN_LED_GELB  = 11;
const int PIN_LED_ROT   = 10;
const int PIN_Summer    =  2;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // datasheet Address; 0x3D for 128x64, 0x3C for 128x32

unsigned int Distance;
unsigned long startZeit;

VL53L1X sensor;
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire); 

void setup()
{
 while (!Serial) {}
 Serial.begin(9600);
 Wire.begin();
 Wire.setClock(400000); // use 400 kHz I2C Bus

// LED Strip vorbereiten - alle auf weiss
 pixels.begin();
 pixels.setBrightness(BRIGHTNESS);
 pixels.fill(pixels.Color(100, 100, 100)); 
 pixels.show(); // Befehl zum Senden der Daten an die LEDs
 delay(500);

// LED PIN's vorbereiten
  pinMode(PIN_LED_GRUEN,OUTPUT);
  pinMode(PIN_LED_GELB,OUTPUT);
  pinMode(PIN_LED_ROT,OUTPUT);
  pinMode(PIN_Summer,OUTPUT);
// Ausgangszustand herstellen
  digitalWrite(PIN_LED_GRUEN,HIGH);  //evtl. weiß
  digitalWrite(PIN_LED_GELB,LOW);
  digitalWrite(PIN_LED_ROT,LOW); 
  digitalWrite(PIN_Summer,LOW);

  sensor.setTimeout(5); //500
  if (!sensor.init())
  {
    Serial.println("Fehler Initialisierung Sensor!");
    while (1);
  }

  // Init Display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x64
  display.clearDisplay();

  // Clear Display Puffer.
  display.clearDisplay();
  display.display();

  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,20);    //display.setCursor(0,20);
  display.print("Laser V1.2\n");
  display.display();  // Anzeigen
  Serial.println("Laser Version 1.2");

  sensor.setDistanceMode(VL53L1X::Long);
  sensor.setMeasurementTimingBudget(50000);
  sensor.startContinuous(50);
 
  delay(1500);   // Version anzeigen, delay für VL531X
}

void loop()
{
  Distance = sensor.read();
  Distance = Distance/10;       // kill mm
  //Serial.print(Distance);
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

  // Anzeige Abstand
     display.clearDisplay();
     display.setTextSize(4);  //4
     display.setCursor(24,20);  //8,0
     Serial.print("Abstand: ");
   
  if (Distance >= Abstand_GRUEN) dis = 1;   //Switch case Variable
  if (Distance <= Abstand_GELB)  dis = 2;   //nach Abstand
  if (Distance <= Abstand_ROT_blink) dis = 3;
  if (Distance <= Abstand_ROT) dis = 4;

  switch (dis) {    
     case 4:
        digitalWrite(PIN_Summer,HIGH);
        digitalWrite(PIN_LED_GRUEN,LOW);  
        digitalWrite(PIN_LED_GELB,LOW);
        digitalWrite(PIN_LED_ROT,HIGH);           // ROT
        pixels.fill(pixels.Color(255, 0, 0)); 
        pixels.show(); // Befehl zum Senden der Daten an die LEDs
        Serial.println(Distance);
        //display.print(Distance);
          display.clearDisplay();
          display.setTextSize(4);  //4
          display.setCursor(16,20);  //8,0
          display.print("STOP");
          display.display();  // Refrech Display
        delay(50);

        if (millis() - startZeit >= RotAusZeit) {     // nach 5s ROT ausschalten
          digitalWrite(PIN_Summer,LOW);
          digitalWrite(PIN_LED_GRUEN,LOW);  
          digitalWrite(PIN_LED_GELB,LOW);             // Pixels und LEDsaus aus
          digitalWrite(PIN_LED_ROT,LOW);   //ROT
          pixels.clear();
          pixels.show(); // Befehl zum Senden der Daten an die LEDs 
          display.clearDisplay();
          display.setTextSize(4);  //4
          display.setCursor(16,20);  //8,0
          display.print("ENDE");
          display.display();  // Refrech Display
          while(true) {
            // Der Arduino tut ab hier nichts mehr
          }
        }
        break;
     case 3:
        startZeit = millis();                // Millis neu starten 
        if (flag) {                               // ROT- Blinken
          digitalWrite(PIN_Summer,HIGH);  
          digitalWrite(PIN_LED_GRUEN,LOW);  
          digitalWrite(PIN_LED_GELB,LOW);
          digitalWrite(PIN_LED_ROT,HIGH);              // ROT an
          pixels.fill(pixels.Color(255, 0, 0)); 
          pixels.show(); // Befehl zum Senden der Daten an die LEDs
          Serial.println(Distance);
          display.print(Distance);
          flag= false;
          delay(50);}
        else {
          digitalWrite(PIN_Summer,LOW);
          digitalWrite(PIN_LED_GRUEN,LOW);  
          digitalWrite(PIN_LED_GELB,LOW);             // Pixels aus
          digitalWrite(PIN_LED_ROT,LOW); //ROT
          pixels.clear();
          pixels.show(); // Befehl zum Senden der Daten an die LEDs
          Serial.println(Distance);
          display.print(Distance);
          flag = true;
          delay(50); } 
          break;
     case 2:
        startZeit = millis();                // Millis neu starten
        digitalWrite(PIN_Summer,LOW);
        digitalWrite(PIN_LED_GRUEN,LOW);          //GELB
        digitalWrite(PIN_LED_GELB,HIGH);
        digitalWrite(PIN_LED_ROT,LOW);
        pixels.fill(pixels.Color(252, 244, 0)); 
        pixels.show(); // Befehl zum Senden der Daten an die LEDs
        Serial.println(Distance);
        display.print(Distance);
        break;
     case 1:
        startZeit = millis();                // Millis neu starten
        digitalWrite(PIN_Summer,LOW);
        digitalWrite(PIN_LED_GRUEN,HIGH);        //GRUEN 
        digitalWrite(PIN_LED_GELB,LOW);
        digitalWrite(PIN_LED_ROT,LOW);
        pixels.fill(pixels.Color(0, 91, 9)); 
        pixels.show(); // Befehl zum Senden der Daten an die LEDs
        Serial.println(Distance);
        display.print(Distance);
        break;
     } 
     display.display();  // Refrech Display
     delay(200); // 0,2 Sekunden Pause, um die Anzeige ruhig zu halten
}     