Hallo liebe Gemeinde,
erstmal zum Projekt:
LED Strip neopixel 60/m
- Schranke geschossen konsant Rot
- Schranke öffnet Lauflicht von 0 bis 239 in rot ( 10Block ) bis geöffnet
- Schranke geöffnet konsant Rot
- Schranke schlisst Lauflicht 239 auf 0 in rot ( 10Block ) bis geschlossen
- Schranke geschossen konsant Rot
diese wird von Senoren überwacht.
Diese funktioniert auch siehe Sketch.
jetzt soll wenn die Schranke oben(geöffnet) ist, nach Taster(input) und einer Zeit das LED auf Blau blinken und wieder nach einer Zeit zurück auf rot, diese funktioniert leider nicht.
#include <Adafruit_NeoPixel.h>
#define LED_PIN 6 // Anschluss für den Neopixel-Streifen
#define NUM_PIXELS 239 // Anzahl der LEDs im Streifen (Index 0 bis 239)
#define SWITCH_BOTTOM 9 // unterer Endschalter: normal geschlossen (read HIGH)
#define SWITCH_TOP 10 // oberer Endschalter: normal offen (read LOW)
#define TRAFFIC_SIGNAL 2 // Ampelsignal-Taster an Pin 2 weil wegen interrupt 0
Adafruit_NeoPixel strip(NUM_PIXELS, LED_PIN, NEO_RGB + NEO_KHZ800);
// Zustandsdefinitionen
enum BarrierState {
FULL_CLOSED, // Schranke voll geschlossen – statisch Rot
OPEN_RUNNING, // Schranke im Öffnungsprozess – Lauflicht (roter Block von 10 LEDs)
FULL_OPEN, // Schranke voll geöffnet – statisch Rot
CLOSE_RUNNING // Schranke im Schließprozess – Lauflicht (roter Block von 10 LEDs)
};
BarrierState state = FULL_CLOSED;
// Variablen zur Erkennung von Zustandsänderungen an den Schaltern
int prevBottomState;
int prevTopState;
unsigned long previousMillis = 0;
const unsigned long interval = 25; // Animationsgeschwindigkeit in ms (doppelt so schnell)
int animIndex = 0; // Verschiebungsindex für das Lauflicht
unsigned long signalStartTime = 0;
bool signalActive = false;
bool blinking = false;
const unsigned long blinkInterval = 500; // 500 ms für Blinken
unsigned long lastBlinkTime = 0;
bool blinkState = false;
unsigned long blinkStartTime = 0; // Zeitpunkt, an dem das Blinken startet
unsigned long currentMillis = millis();
// Hilfsfunktion: Setzt alle LEDs auf die angegebene Farbe
void setAllPixels(uint32_t color) {
for (int i = 0; i < NUM_PIXELS; i++) {
strip.setPixelColor(i, color);
}
strip.show();
}
// Animationsroutine für das Öffnen (Lauflicht von LED 239 bis 0)
void animateOpen() {
// Alle LEDs ausschalten
for (int i = 0; i < NUM_PIXELS; i++) {
if (((i + animIndex) / 10) % 2 == 0) {
strip.setPixelColor(i, strip.Color(255, 0, 0)); // Rot
} else {
strip.setPixelColor(i, 0); // Aus
}
}
strip.show();
animIndex = (animIndex + 1) % 20; // Schrittweise verschieben (max. 20 für 10er-Muster)
}
// Animationsroutine für das Schließen (Lauflicht von LED 0 bis 239)
void animateClose() {
for (int i = 0; i < NUM_PIXELS; i++) {
if (((i - animIndex) / 10) % 2 == 0) {
strip.setPixelColor(i, strip.Color(255, 0, 0)); // Rot
} else {
strip.setPixelColor(i, 0); // Aus
}
}
strip.show();
animIndex = (animIndex + 1) % 20;
}
void setup() {
// Schalter als INPUT_PULLUP, sodass definierte Zustände vorliegen:
// - SWITCH_BOTTOM: Normalerweise geschlossen (HIGH), wechselt zu LOW beim Öffnen.
// - SWITCH_TOP: Normalerweise offen (LOW), wechselt zu HIGH beim Schließen.
pinMode(SWITCH_BOTTOM, INPUT_PULLUP); // unterer Endschalter
pinMode(SWITCH_TOP, INPUT_PULLUP); // oberer Endschalter
pinMode(TRAFFIC_SIGNAL, INPUT); // Taster mit Pulldown-Widerstand //INPUT
attachInterrupt(0, pin_ISR, RISING); //interrupt verbinden CHANGE, LOW, FALLING, RISING,
// Initialisierung des LED-Streifens
strip.begin();
strip.show();
// Startzustand: Schranke voll geschlossen (statisch Rot)
setAllPixels(strip.Color(255, 0, 0));
state = FULL_CLOSED;
Serial.begin(9600);
// Initiale Schalterzustände speichern
prevBottomState = digitalRead(SWITCH_BOTTOM); // unterer Endschalter
prevTopState = digitalRead(SWITCH_TOP); // oberer Endschalter
}
void loop() {
// Aktuelle Schalterzustände auslesen
int bottomState = digitalRead(SWITCH_BOTTOM);
int topState = digitalRead(SWITCH_TOP);
currentMillis = millis();
Serial.println(signalActive);
// Zustandswechsel: Schranke öffnen
if (state == FULL_CLOSED) {
// Wenn der untere Schalter, der normalerweise geschlossen ist, öffnet (Wechsel von LOW zu HIGH)
if (prevBottomState == LOW && bottomState == HIGH) {
state = OPEN_RUNNING;
animIndex = 0; // Animation zurücksetzen
}
}
if (state == OPEN_RUNNING) {
// Führe die Animation aus, sofern das Intervall erreicht ist
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
animateOpen();
}
// Wenn der obere Schalter schließt (wird LOW), gilt die Schranke als voll geöffnet.
if (topState == LOW) {
state = FULL_OPEN;
setAllPixels(strip.Color(255, 0, 0)); // LED-Band dauerhaft rot
}
}
// Zustandswechsel: Schranke schließen
if (state == FULL_OPEN) {
// Wenn der obere Schalter, der geschlossen war, wieder öffnet (Wechsel von LOW zu HIGH)
if (prevTopState == LOW && topState == HIGH) {
state = CLOSE_RUNNING;
animIndex = 0;
}
}
if (state == CLOSE_RUNNING) {
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
animateClose();
}
// Wenn der untere Schalter wieder schließt (wird LOW), ist die Schranke voll geschlossen.
if (bottomState == LOW) {
state = FULL_CLOSED;
setAllPixels(strip.Color(255, 0, 0)); // LED-Band dauerhaft rot
}
}
// Aktualisiere die vorherigen Schalterzustände
prevBottomState = bottomState;
prevTopState = topState;
// Nach 20 Sekunden Blinken starten
if (signalActive && !blinking && prevTopState == 0 && (currentMillis - signalStartTime >= 21000)) {
blinking = true;
blinkStartTime = currentMillis; // Zeitpunkt speichern, ab dem das Blinken startet
}
// Blinken steuern
if (blinking) {
if (currentMillis - lastBlinkTime >= blinkInterval) {
lastBlinkTime = currentMillis;
blinkState = !blinkState;
uint32_t color = blinkState ? strip.Color(0, 0, 255) : strip.Color(0, 0, 0); // blau blinken
setAllPixels(color);
}
// Blinken nach 20 Sekunden stoppen (nach Beginn des Blinkens)
if (currentMillis - blinkStartTime >= 28000) {
blinking = false;
setAllPixels(strip.Color(255, 0, 0)); // Zurück zu rot
}
signalActive = false; //geaendert, signal muss wieder false sein
}
}
void pin_ISR()
{
if(!signalActive)
{
signalActive = true;
signalStartTime = currentMillis;
}
}
wo liegt der Fehler?
VG Sascha