// NanoLight V1.02 [© 01.03.2025 by Gucky]
// Schaltet mit einem HC-SR501 Infrarotsensor Licht (per WS2812B) für eine eingestellte Zeit ein.
//
// History:
// - v1.00: Erste unveröffntlichte Version.
// - v1.01: Zweite unveröffentlichte Version.
// - v1.02: Ersteveröffentlichte Version.
#include <Adafruit_NeoPixel.h> // RGB Stripe WS2812B einbinden
#define sensorPin 2 // 2 = Sensor Pin (Interrupt 0)
#define ledPowerPin 3 // 3 = Power LED
#define ledStripePin 4 // 4 = Datenpin WS2812B
#define ldrPin A0 // A0 = LDR Pin
#define ledNum 100 // Anzahl der RGB LEDs
Adafruit_NeoPixel pixels(ledNum, ledStripePin, NEO_GRB + NEO_KHZ800); // Anzahl der LEDs, Dataenpin, Typ)
unsigned long lightTime; // Zeit, zu der die LEDs eingeschaltet wurden.
unsigned long lightDuration = 180; // Zeit in Sekunden, die die LEDs eingeschaltet bleiben sollen.
unsigned long ldrTime; // Dienst zum Messen der Helligkeit alle 10 Sek. (siehe 'void checkLdr()').
bool lightIsOn = true; // Ist true. solange das Licht brennt.
volatile bool triggered = false; // Ist true, wenn vom Sensor ein High Signal kommt und wird false, wenn ein Low Signal kommt.
int ldr = 0; // Zur Spannungsmessung reichen Integerwerte, daher int (spart etwas Speicher).
int ldrThreshold = 150; // LDR Schaltschwelle (0 = dunkel | 1023 = hell)
int maxBrightness = 255; // Max. Helligkeit der LEDs (Spart ggf. etwas Energie).
void setup()
{
pinMode(sensorPin, INPUT); // Sensorpin
pinMode(ledStripePin, OUTPUT); // WS2812B Datenpin
pinMode(ledPowerPin, OUTPUT); // Power LED
lightOff(); // Alle LEDs einschalten und bis auf 0 faden (Selbsttest).
for(byte y = 0; y < 30; y++) // Schleife 30 x wiederholen (1/2 Minute), damit der Sensor sich einpegeln kann.
{
for(byte x = 0; x < 3; x++) // Schleife 3x wiederholen.
{
digitalWrite(ledPowerPin, HIGH); // Power LED ausschalten.
delay(30); // 30 mS warten.
digitalWrite(ledPowerPin, LOW); // Power LED einschalten.
delay(170); // 170 mS warten.
}
delay(400); // Insgesamt dauert ein Schleifendurchlauf rund 1 Sekunde
}
checkLdr(); // Helligkeit messen
attachInterrupt(digitalPinToInterrupt(sensorPin), interruptOn, RISING); // Interrupt für HIGH Signal starten
ldrTime = millis(); // Zeit für LDR Messung speichern
Serial.begin(115200); // Die serielle Schnittstelle wird nur zum Debuggen benutzt.
}
void loop() // Haupt Programmschkeife
{
if(triggered) // Wenn der Sensor getrigert wurde (= Bewegung), ...
{
if(lightIsOn == false) // und das Licht aus ist, ...
lightOn(); // LEDs einschalten (faden), ...
triggered = false; // Trigger löschen und ...
lightTime = millis(); // die Zeit des Einschaltens merken.
}
if(millis() >= lightTime + (lightDuration * 1000) && lightIsOn == true) // Prüfen, ob LED Einschaltdauer erreicht und das Licht an ist?
{
lightOff(); // Wenn ja, LEDs ausschalten (faden).
checkLdr(); // Aktuelle Helligkeit messen.
}
if(millis() >= ldrTime + 10000) // Alle 10 Sekunden prüfen, ...
{
if(!lightIsOn) // ob das Licht eingeschaltet ist...
checkLdr(); // und wenn nicht, dann die Helligkeit messen, um "Selbsthaltung" zu unterdrücken.
}
}
void interruptOn() // Interrupt an Pin 2 wird bei jeder ansteigenden Flanke des Sensors ausgeöst.
{
if(ldr < ldrThreshold) // Licht nur einschalten, wenn es dunkler ist, als die Schaltschwelle.
{
detachInterrupt(0); // Interrupt löschen.
triggered = true; // Trigger setzen, damit wenn das Licht an ist, nachgetriggert wird.
attachInterrupt(digitalPinToInterrupt(sensorPin), interruptOff, FALLING); // Neuen Interrupt starten, der auf LOW Signal des Bewegungsmelders wartet.
}
}
void interruptOff() // Interrupt an Pin 2 wird bei jeder abfallenden Flanke des Sensors ausgeöst.
{
detachInterrupt(0); // Interrupt löschen.
triggered = false; // Trigger löschen.
attachInterrupt(digitalPinToInterrupt(sensorPin), interruptOn, RISING); // Neuen Interrupt starten.
}
void lightOn() // Setzt die Hellligkeit von 0 auf maxBrightness, um das Licht einzuschalten.
{
for(byte v = 0; v < maxBrightness; v++) // Werte für Helligkeit von 0 bis maxBrightness zählen.
{
for (byte x = 0; x <= ledNum; x++) // RGB LEDs setzen
pixels.setPixelColor(x, pixels.ColorHSV( 20000, 0, v)); // Hue, Sat , Val | Weisses Licht einschalten. Val darf zwischen 0 und 65535 liegen. Bei Sättigung 0 ist das Licht weiss.
pixels.show(); // Alle LEDs aktualisieren.
delay(5); // Kurze Pause, damit es nicht zu schnell fadet.
}
lightIsOn = true; // Speichern, dass das Licht eingeschaltet ist.
}
void lightOff() // Setzt die Hellligkeit von maxBrightness auf 0, um das Licht auszuschalten)
{
for(int v = maxBrightness; v >= 0; v--) // Werte für Helligkeit von MaxBrightness bis 0 zählen.
{
for (byte x = 0; x <= ledNum; x++) // RGB LEDs setzen.
pixels.setPixelColor(x, pixels.ColorHSV( 20000, 0, v)); // Hue, Sat , Val | Weisses Licht einschalten. Hue darf zwischen 0 und 65535 liegen.
pixels.show(); // Alle LEDs aktualisieren.
delay(5); // Kurze Pause, damit es nicht zu schnell fadet.
}
lightIsOn = false; // Speichern, dass das Licht wirder ausgeschaltet ist.
}
void checkLdr() // Helligkeit mit LDR an AO messen.
{
ldr = 0; // Messwert des LDR zurücksetzen.
for(byte x = 0; x < 10; x++) // Schleife 10x durchlaufen, um Duchschnittswert zu erhalten.
{
ldr += analogRead(ldrPin); // Spannung an AO messen und Werte aufaddieren...
digitalWrite(ledPowerPin, !digitalRead(ledPowerPin)); // LED, wenn ausgeschaltet, dann einschalten und umgekehrt.
delay(25); // Kurz warten.
}
ldr = ldr / 10; // Zuletzt durch 10 teilen (Durchschnittswert bilden).
Serial.println(ldr); // Zum Debuggen Wert ausgeben.
ldrTime = millis(); // Zeit für nächste Messung speichern.
}
Ein