WS2812B zwei Programme mit Taster umschalten

Hallo,

nach langer Suche im www frage ich nun euch was ich nicht bedacht habe bei meinem kleinen Code.
Ich bin neu in der Arduino-Szene und kenne mich sogut wie gar nicht mit dem Programmieren von dem kleinen aus.

Vorhanden ist folgendes:
-Arduino Nano
-1m 144LEDs WS2812B Strip
[mehr brauch ich nicht]

Ziel:
-ein Programm mit einem Lauflicht mit Schweif in eine Richtung und ein weiteres mit allen LEDs, welche gleichzeitig langsam aufleuchten und wieder abdunkeln. Beides in Dauerschleife bis ein Taster betätigt wird.

Der Taster soll die beiden Programme umschalten können und einen “Aus”-Zustand davor haben.

Heißt:
Stromquelle AN-> Arduino AN Licht AUS
Taster drücken ->Programm 1 (Hier:Lauflicht) EIN
Taster drücken ->Programm 2 (Hier:langsam aufhellen/abdunkeln) EIN
Taster drücken ->Licht AUS

und das dann so oft ich will. Bei mir scheiterts am letzten Punkt. Er will nicht wieder in den ersten Schritt meiner Abfolge springen in der das Licht AUS sein soll und ich wieder erneut starten kann.

PS.: Falls jemand Verbesserungen zu allem anderen hat, nehme ich dies gerne mit!

#include "FastLED.h"
#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
#warning "Requires FastLED 3.1 or later; check github for latest code."
#endif
// Konstanten
const int tasterPin = 13;           // Taster an Pin 2 angeschlossen
// Variablen
int lmode           = 0;           // Variable für die verschiedenen festgelegten Farben
int tasterStatus    = LOW;         // Variable zu speichern des Tasterstatus

#define DATA_PIN    3
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    144

#define BRIGHTNESS         64

CRGB leds[NUM_LEDS];

void setup() {
  pinMode(tasterPin, INPUT);      // Setzt den TasterPin als Eingang
  delay(1000);                    // 1 second delay for recovery
  Serial.begin(9600);
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
}

void loop()
{ 
  // Abfrage ob der Taster gedrückt ist
  tasterStatus = digitalRead(tasterPin);
   
  // Wenn Taster gedrückt ist...
  if (tasterStatus == HIGH)
  {
    lmode++;          // Lichtmodus +1
    delay(300);       // 300ms warten
  }
   
  //+++++++++++++++ LEUCHTPROGRAMME +++++++++++++++++
   
  // Modus 0 = Licht aus  
  if (lmode == 0)
  {
{
  EVERY_N_MILLISECONDS(20)
  {
    
    FastLED.show();
  }
}    
  }
   
  // Modus 1 = Blau  
  else if (lmode == 1)
  {
{
  EVERY_N_MILLISECONDS(20)
  {
    fade2();
    FastLED.show();
  }
}    
  }
   
  // Modus 2 = Rot  
  else if (lmode == 2)
  {
{
  EVERY_N_MILLISECONDS(20)
  {
    FadeInOut(0x00, 0x00, 0xff);    
    FastLED.show();
  }
}
  }
 
  // Anzahl der Leuchtmodi auf 3 begrenzen. (0 bis 2)
  else
  {
    lmode = 0;
  }
}

void fade2()
{
  fadeToBlackBy( leds, NUM_LEDS, 10);
  byte pos = (beat8(10)*NUM_LEDS) / 255;
  leds[pos] = CHSV( 160, 255, 255);
}

void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
      
  for(int k = 0; k < 256; k=k+1) { 
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
     
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue); 
  }
  showStrip();
}
void showStrip() {
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifndef ADAFRUIT_NEOPIXEL_H 
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

Ich sehe nicht, wo du die LED komplett aus schaltest.

const int tasterPin = 13; // Taster an Pin 2 angeschlossen

Da gibt es Verbesserungspotential :wink:

Sauberer wäre auch, nicht darauf zu hoffen, dass der Taster kürzer als 300 ms gedrückt wird, und erst danach wieder.

Daran könnte es liegen. Ich bin davon ausgegangen dass der erste Zustand nach einschalten (also lmode==0) diese Wirkung hat. Habe mir alles mögliche zusammenkopiert aus verschiedensten Foren und doch nicht so viel kapiert.
Wie ist denn der Befehl zum ausschalten der LEDs?
Also wenn ich den Taster nach dem 2. Programm erneut drücke passiert nix. das Programm läuft einfach weiter.

Das "debouncen" wollte ich erst richtig einbauen wenn der Rest so läuft wie ich es will.

Was genau kann ich an dem tasterPin verbessern?

Was genau kann ich an dem tasterPin verbessern?

Den Kommentar weglassen oder korrigieren?

Wie ist denn der Befehl zum ausschalten der LEDs?

z.B. setAll(0,0,0);

Das ist übrigens kein Befehl, sondern eine Funktion, die du geschrieben hast.

Danke schonmal dafür, hätte man selber drauf kommen können :roll_eyes:

Allerdings komme ich gar nicht mehr zu lmode==0 zurück. Auch nicht mit <if(lmode>2){lmode=0}

}
}
}

Mach das mal noch schöner, dann sieht man evtl., wann aus lmode = 3 wieder lmode = 0 wird,
oder warum nicht.
Oder mach die lmode-Berechnung an einer zentralen Stelle.

  if (tasterStatus == HIGH)
  {
    lmode++;          // Lichtmodus +1
    if (lmode >= 3) lmode = 0;
    delay(300);       // Ersatz für eine Zustandsführung und entprellen
  }

lmode darf sonst nirgends verändert werden.

GK-ken:
Vorhanden ist folgendes:
-Arduino Nano
-1m 144LEDs WS2812B Strip
[mehr brauch ich nicht]

Ich vermisse da ein ordentliches Netzteil. Wenn alle LED an sind dann ziehen sie ca 8,7A

Grüße Uwe

Also im moment arbeite ich nur mit 5-10% der gesamthelligkeit um es direkt am usb betreiben zu können, aber am Einbauort werden sie mit 25% Helligkeit arbeiten an einem 75W Netzteil, 15A Max bei 5V also.

Wenn die drei { untereinander wegmache oder nur eines davon geht gar nix mehr und ich bekomme schon beim kompilieren an anderer Stelle. Mit dem Aufzählen an Zentraler stelle geht es komischerweise nach dem ersten mal nach dem AUS Zustand von lmode=2 nach einer sequenz automatisch in lmode=1 und das jedes mal wenn man in lmode=1 den Taster betätigt

GK-ken:
Also wenn ich den Taster nach dem 2. Programm erneut drücke passiert nix. das Programm läuft einfach weiter.

Die Funktion FadeInOut ist blockierend programmiert, weshalb ein Tastendruck nicht erkannt wird. Abgesehen davon funktioniert das Programm, wenn man zum richtigen Zeitpunkt den Taster drückt.

Hilfreich ist eine Testausgabe:

    lmode++;          // Lichtmodus +1
    Serial.println(lmode);
    delay(300);       // 300ms warten

Was genau blockiert davon die Tastereingabe?

GK-ken:
Was genau blockiert davon die Tastereingabe?

In FadeInOut hast Du zwei for-Schleifen, die wiederum in setAll eine for-Schleife aufrufen. FastLED.show braucht auch Zeit. Das scheint in der Summe zu viel zu sein, ist meine Vermutung.

Kannst du mir eine Lösung bzw. eine funktionierende/s Funktion/Programm geben?

GK-ken:
… eine Lösung …

Eher drei, die mir spontan einfallen:

  • Tastenabfrage mittels Interrupt; anfängerunfreundlich, unnötig.
  • Tastenabfrage in die Schleifen integrieren; anfängerfreundlich, wenn es “irgendwie” funktionieren soll :smiling_imp:
  • Schleifen blockadearm zu loop, “der” Schleife, öffnen; aufwendig zu ändern aber gut.

Dein Programm habe ich mal, weil es schnell geht und Spaß macht, entsprechend 2 geändert. Ich verwende einen Nano mit APA102 (DotStar) LEDs an SPI, weil die besser sind als WS2812 (NeoPixel). Daher ist die Initalisierung anders, die kannst Du einfach durch Deine ersetzen:

#include "FastLED.h"
FASTLED_USING_NAMESPACE
//#define DATA_PIN    4      // MOSI Pin11
//#define CLK_PIN     5      // ACK  Pin13
#define LED_TYPE    APA102
#define COLOR_ORDER BGR
#define BRIGHTNESS  25
#define NUM_LEDS    120

CRGB leds[NUM_LEDS];

const int tasterPin = 2;           // Taster an Pin 2 angeschlossen
// Variablen
byte lmode           = 0;           // Variable für die verschiedenen festgelegten Farben
bool tasterStatus    = LOW;         // Variable zu speichern des Tasterstatus

void setup() {
  FastLED.addLeds<LED_TYPE, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
  LEDS.showColor(CRGB(0, 0, 0));

  Serial.begin(9600);
  Serial.println(F("Anfang"));
  pinMode(tasterPin, INPUT_PULLUP);      // Setzt den TasterPin als Eingang
}

void taster()
{
  // Abfrage ob der Taster gedrückt ist
  tasterStatus = digitalRead(tasterPin);

  // Wenn Taster gedrückt ist...
  if (tasterStatus == HIGH)
  {
    lmode++;          // Lichtmodus +1
    Serial.println(lmode);
    delay(300);       // 300ms warten
  }
}
void loop()
{
  //+++++++++++++++ LEUCHTPROGRAMME +++++++++++++++++

  // Modus 0 = Licht aus
  if (lmode == 0)
  {
    taster();
    {
      EVERY_N_MILLISECONDS(20)
      {

        FastLED.show();
      }
    }
  }

  // Modus 1 = Blau
  else if (lmode == 1)
  {
    taster();
    {
      EVERY_N_MILLISECONDS(20)
      {
        fade2();
        FastLED.show();
      }
    }
  }

  // Modus 2 = Rot
  else if (lmode == 2)
  {
    {
      EVERY_N_MILLISECONDS(20)
      {
        FadeInOut(0xff, 0x00, 0x00);
        FastLED.show();
      }
    }
  }

  // Anzahl der Leuchtmodi auf 3 begrenzen. (0 bis 2)
  else
  {
    lmode = 0;
  }
}

void fade2()
{
  fadeToBlackBy( leds, NUM_LEDS, 10);
  byte pos = (beat8(10) * NUM_LEDS) / 255;
  leds[pos] = CHSV( 160, 255, 255);
}

void FadeInOut(byte red, byte green, byte blue) {
  float r, g, b;

  for (int k = 0; k < 256; k = k + 1) {
    r = (k / 256.0) * red;
    g = (k / 256.0) * green;
    b = (k / 256.0) * blue;
    setAll(r, g, b);
    FastLED.show();
  }

  for (int k = 255; k >= 0; k = k - 2) {
    r = (k / 256.0) * red;
    g = (k / 256.0) * green;
    b = (k / 256.0) * blue;
    setAll(r, g, b);
    FastLED.show();
  }
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
  taster();
  // FastLED
  leds[Pixel].r = red;
  leds[Pixel].g = green;
  leds[Pixel].b = blue;
}