LED Programmierbar Lauflicht

Da ich vom Bau komme, haut mich nichts so schnell um. und da du im selben Atemzug mit einem verbesserungsvorschlag gekommen bist, habe ich es auch nicht so aufgefasst, sondern habe mich um den vorschlag gefreut und mich sofort in das Aray wieder eingearbeitet weil ich das wahrscheinlich übernehmen werde insofern ich raus habe wie ich das lauflich mithilfe des arays zum laufen bekomme. dabei hilft evtl auch die PDF.
Keine sorge habe es mehr überlesen als darauf einzugehen.
Schätze es aber deine Entschuldigung.

Dann mal hier nochmal meine Analyse:
Du definierst hier:

Einen tasterPin.
Aber gleichzeitig:

Der PIN macht zwei Dinge. Die beissen sich.

Ich würde erstmal (!) mit einem Pin anfangen. Eine taste - ein Stripe.
Wenn das läuft, dann mit einem Array anfangen.

mein Einstieg: - ungetestet

#include <FastLED.h>

const byte LEDs_Anzahl = 20;
// Taster
const byte Taster = 22;
// LED Stripes
const byte LED_Stripe = 30;
CRGB leds[LEDs_Anzahl];

void setup()
{
  //Zuweisung Taster auf Pins des Arduinos
  pinMode( Taster, INPUT);
  pinMode( LED_Stripe, OUTPUT);
//  FastLED.addLeds<WS2812B, Taster , GRB>(leds, LEDs_Anzahl); Nein nicht Taster!
  FastLED.addLeds<WS2812B, LED_Stripe , GRB>(leds, LEDs_Anzahl);

}

void loop()
{
  for (unsigned int Lauflicht = 0; Lauflicht < LEDs_Anzahl; Lauflicht++)
  {
    leds[Lauflicht] = CRGB:: Green;
    FastLED.show();
    delay(200);
    leds[Lauflicht] = CRGB::Black;
  }
}

Da ist nichts mit Taster bei - Den darfst Du selbst abfragen. Mal sehen. Morgen ist ein neuer Tag :wink:

Tatsächlich habe ich das die ganze Zeit übersehen. Da war dann doch der Tag zu lange.

zwecks dem Taster hatte ich selber schon nen Ansatz den ich getestet hatte heute nachmittag dieser aber nicht Funktioniert hat. ob das mit dem entprellen zu tun hat?
Folgendes hab ich schon mehrfach in verschiedenen konstellationen aufgeschrieben wobei ich bei einer schon ein thread fand auf englisch der mir sagte, dass man das so nicht machen kann.
mein Ansatz für den Taster ( an deinem Einstiegsbsp.:

for(unsigned int Lauflicht1 = 0; Lauflicht1 < LEDs_Anzahl; Lauflicht1++)
      {
        if( digitalRead (Taster) == HIGH)
          {
          leds[Lauflicht1] = CRGB:: Green;
          FastLED.show();
          delay(200);
          leds[Lauflicht1] = CRGB::Black;
          }
      }

oder:

 for(unsigned int Lauflicht1 = 0; Lauflicht1 < LEDs_Anzahl; Lauflicht1++)
      {
        if( digitalRead (Taster) == HIGH)
          {
           digitalWrite(LED_Stripe, HIGH);
          leds[Lauflicht1] = CRGB:: Green;
          FastLED.show();
          delay(200);
          leds[Lauflicht1] = CRGB::Black;
          }
      }

oder:

for(unsigned int Lauflicht1 = 0; (Lauflicht1 < LEDs_Anzahl) && ( digitalRead(Taster)== HIGH); Lauflicht1++)
      {
          leds[Lauflicht1] = CRGB:: Green;
          FastLED.show();
          delay(200);
          leds[Lauflicht1] = CRGB::Black;
          
      }

aus einem Einsteiger Artikel habe ich die Syntax mit Read und Write und aus C halt die Bedingungen WANN die LEDs an gehen dürfen. weshalb die vorher ohne Taster und JETZT mit taster funktionieren.
ich war ebenfalls der meinung, dass alle 3 Varianten funktionieren sollten, da aber keiner davon funktioniert hat, würde ich mal sagen, dass es evtl. am entprellen liegen kann? dahingehend habe ich noch nichts da ich hardwareseitig noch nicht entprellen kann ( fehlende teile). Außer der Syntax ist schon mehr als falsch, die Option ist natürlich weiterhin offen und beschäftigt mich seid dem Mittagessen.

Irgendwie ist ja heute schon morgen...

Las dir ein wenig Zeit.
Geh Bett.
Das wird.

Hallo,

@ TO:
mein Vorschlag wäre, konzentriere dich erstmal auf einen Taster und eben dem Umgang mit millis um diesen entprellt einzulesen. Die IDE bringt ein Bsp. BlinkWithoutDelay mit. Lösche die ganzen Kommentare raus, dann wird der auch lesbar. Dann sollte man verstehen was der wie macht.

Oder du liest dir das einmal durch.
Theseus erklärt millis()
GuntherB - BlinkwithoutDelay - Die Nachtwächtererklärung

Im Grunde braucht man sich nur vorstellen, dass millis die ewig laufende Armbanduhr ist die eben aller 49 Tage statt 12/24h überläuft. Dennoch stellt man damit unbewusst irgendwelche Zeitdifferenzen auf wenn man auf irgendwas wartet und kann nebenbei andere Dinge machen und wiederum warten. Du musst das Prinzip verstehen, dann kannst du das auf alles andere anwenden. Am Ende kannst du ganze Arrays damit abarbeiten uvm.

Inhaltlich weiß ich Deine Beiträge durchaus zu schätzen, mir geht es nur um Deine, wie ich finde, übertriebene Ausdrucksweise:

  • Ich möchte keine Fäkalsprache in diesem Forum lesen.
  • Wer höflich fragt, darf auch eine höfliche Antwort erwarten, egal wie schlecht ein Programm in Deinen Augen auch ist.

Glücklicherweise bin ich nicht der Moderator dieses Forums, weshalb ich meine Meinung einfach so schreiben kann und Du darfst machen, was Du für richtig erachtest :slightly_smiling_face:

möchtest du
a) nur einen Pin Abfragen und abhänig davon ob dieser HIGH oder LOW ist soll der zugeteilte Strip laufen

b) mit einem TASTER (der nur kurz kontaktiert) umschalten zwischen Lauflicht Läuft - Lauflicht Läuft nicht?

im Falle von b) schlage ich dir vor du schaust dir mal das IDE Beispiel

  1. Digital / StateChangeDetection

Wenn das bei dir funktioniert, dann kann man sich den nächsten Schritt ansehen.

Im #15 hat er geschrieben das nach Tastendruck die Animation ca. 2 Minuten laufen soll.

Also im loop

  • Tastendruck auswerten,
  • Status setzen,
  • solange Status gesetzt Animation ausführen
  • nach Ablauf der Zeit Staus zurücksetzen

@spes91
hätte da einen Vorschlag.
Das "Lauflicht" umgebaut nach "BlinkWithoutDelay",
Die Kombination Pixel und Buttons ergeben ein eigenes Objekt.
Jedes Objekt kümmert sich selber um das ganze Time-Management.

nur mal als Beispiel mit 4 Stripes:

// https://forum.arduino.cc/t/led-programmierbar-lauflicht/917480
// by noiasca
// 2021-10-23

#include <Adafruit_NeoPixel.h>

class Strip {
    uint8_t actual = 0;                // for strips up to 255 pixels
    uint16_t interval = 500;           // speed of running light
    uint16_t runningSeconds = 30;      // running time when startetd
    uint32_t onColor = pixels.Color(0, 150, 0);  // color for pixels which are on
    uint32_t offColor = 0x00;          // color for pixels which are off
    uint32_t previousMillis = 0;       // time management for movement
    uint32_t startMillis = 0;          // time management for total running time
    bool isRunning = false;            // flag if running light is activ
    const byte numPixel;               // how many pixels has this strip
    const byte pixelPin;               // on which GPIO are the pixels connected
    const byte buttonPin;              // which button operates this pixels
    Adafruit_NeoPixel pixels;          // the pixels hardware (using the Adafruit library)

  public:
    Strip (byte numPixel, byte pixelPin, byte buttonPin) :
      numPixel (numPixel),
      pixelPin (pixelPin),
      buttonPin (buttonPin),
      pixels(numPixel, pixelPin, NEO_GRB + NEO_KHZ800)
    {}

    void begin()
    {
      pixels.begin();
      pixels.clear();
      pinMode(buttonPin, INPUT_PULLUP);
    }

    void start()
    {
      if (isRunning == false)
      {
        actual = 0;
        isRunning = true;
        startMillis = millis();
        update();
      }
    }

    void update()
    {
      uint32_t currentMillis = millis();
      // movements
      if (isRunning && (currentMillis - previousMillis > interval))
      {
        previousMillis = currentMillis;
        pixels.setPixelColor(actual, offColor);
        actual++;
        if (actual >= numPixel)
        {
          actual = 0;
        }
        pixels.setPixelColor(actual, onColor);
      }
      // check if time has passed - switch off
      if (isRunning && (currentMillis - startMillis > runningSeconds * 1000UL))
      {
        isRunning = false;
        pixels.setPixelColor(actual, offColor);
      }
      pixels.show();   // Send the updated pixel colors to the hardware.

      //check the button - switch on
      if (!isRunning && digitalRead(buttonPin) == LOW)
      {
        start();
      }
    }
};

// numPixels, pixelPin, buttonPin
Strip strip[] {
  {16, 12, A0},
  {16, 11, A1},
  {16, 10, A2},
  {16,  9, A3}
};

void setup() {
  Serial.begin(115200);
  for (auto &i : strip)
  {
    i.begin();
  }
  strip[0].start();          // start once on startup as "on test"
}

void loop() {
  for (auto &i : strip)
  {
    i.update();             // check if change is necessary & read button
  }
}

kann man nun natürlich noch erweitern und setter machen um unterschiedliche Farben, Geschwindigkeiten etc. zu definieren, aber ich wollte das Beispiel auf 100 Zeilen begrenzen.

2 Likes

Das hatte ich befürchtet, aber ich wollte die Möglichkeiten zumindest mal erwähnt haben :roll_eyes:

Von mir daher noch eine ganz einfache Variante, getestet mit Mega2560 und WS2815:

#include <FastLED.h>
#include <Bounce2.h>  // https://github.com/thomasfredericks/Bounce2

// LED Stripes
#define LEDs_Anzahl_1 20 // Anzahl von LEDs auf dem Stripe
#define LEDs_Anzahl_2 20 // Anzahl von LEDs auf dem Stripe
#define LEDs_Anzahl_3 20 // Anzahl von LEDs auf dem Stripe
#define LEDs_Anzahl_4 20 // Anzahl von LEDs auf dem Stripe
#define LEDs_Anzahl_5 20 // Anzahl von LEDs auf dem Stripe
#define LEDs_Anzahl_6 20 // Anzahl von LEDs auf dem Stripe
#define LEDs_Anzahl_7 20 // Anzahl von LEDs auf dem Stripe

// Taster
const byte Taster1 = 22; // Taster1 auf Pin22
const byte Taster2 = 23; // Taster2 auf Pin23
const byte Taster3 = 24; // Taster3 auf Pin24
const byte Taster4 = 25; // Taster4 auf Pin25
const byte Taster5 = 26; // Taster5 auf Pin26
const byte Taster6 = 27; // Taster6 auf Pin27
const byte Taster7 = 28; // Taster7 auf Pin28

Bounce button1 = Bounce(Taster1, 100);  // 100 = 100 ms debounce time
Bounce button2 = Bounce(Taster2, 100);
Bounce button3 = Bounce(Taster3, 100);
Bounce button4 = Bounce(Taster4, 100);
Bounce button5 = Bounce(Taster5, 100);
Bounce button6 = Bounce(Taster6, 100);
Bounce button7 = Bounce(Taster7, 100);

// LED Stripes
const byte LED_Stripe1 = 30; // LED_Stripe1 auf Pin 30
const byte LED_Stripe2 = 31; // LED_Stripe2 auf Pin 31
const byte LED_Stripe3 = 32; // LED_Stripe3 auf Pin 32
const byte LED_Stripe4 = 33; // LED_Stripe4 auf Pin 33
const byte LED_Stripe5 = 34; // LED_Stripe5 auf Pin 34
const byte LED_Stripe6 = 35; // LED_Stripe6 auf Pin 35
const byte LED_Stripe7 = 36; // LED_Stripe7 auf Pin 36

CRGB leds1[LEDs_Anzahl_1];
CRGB leds2[LEDs_Anzahl_2];
CRGB leds3[LEDs_Anzahl_3];
CRGB leds4[LEDs_Anzahl_4];
CRGB leds5[LEDs_Anzahl_5];
CRGB leds6[LEDs_Anzahl_6];
CRGB leds7[LEDs_Anzahl_7];

bool merker1;
bool merker2;
bool merker3;
bool merker4;
bool merker5;
bool merker6;
bool merker7;

byte lauflicht1;
byte lauflicht2;
byte lauflicht3;
byte lauflicht4;
byte lauflicht5;
byte lauflicht6;
byte lauflicht7;

const uint32_t Intervall1 = 100;
const uint32_t Intervall2 = 100;
const uint32_t Intervall3 = 100;
const uint32_t Intervall4 = 100;
const uint32_t Intervall5 = 100;
const uint32_t Intervall6 = 100;
const uint32_t Intervall7 = 100;

uint32_t vorhin1;
uint32_t vorhin2;
uint32_t vorhin3;
uint32_t vorhin4;
uint32_t vorhin5;
uint32_t vorhin6;
uint32_t vorhin7;

void setup()
{
  //Zuweisung Taster auf Pins des Arduinos
  pinMode( Taster1, INPUT_PULLUP);
  pinMode( Taster2, INPUT_PULLUP);
  pinMode( Taster3, INPUT_PULLUP);
  pinMode( Taster4, INPUT_PULLUP);
  pinMode( Taster5, INPUT_PULLUP);
  pinMode( Taster6, INPUT_PULLUP);
  pinMode( Taster7, INPUT_PULLUP);

  button1.attach(Taster1);
  button2.attach(Taster2);
  button3.attach(Taster3);
  button4.attach(Taster4);
  button5.attach(Taster5);
  button6.attach(Taster6);
  button7.attach(Taster7);

  button1.interval(100); // interval in ms
  button2.interval(100); // interval in ms
  button3.interval(100); // interval in ms
  button4.interval(100); // interval in ms
  button5.interval(100); // interval in ms
  button6.interval(100); // interval in ms
  button7.interval(100); // interval in ms

  FastLED.addLeds<WS2812B, LED_Stripe1 , GRB>(leds1, LEDs_Anzahl_1);
  FastLED.addLeds<WS2812B, LED_Stripe2 , GRB>(leds2, LEDs_Anzahl_2);
  FastLED.addLeds<WS2812B, LED_Stripe3 , GRB>(leds3, LEDs_Anzahl_3);
  FastLED.addLeds<WS2812B, LED_Stripe4 , GRB>(leds4, LEDs_Anzahl_4);
  FastLED.addLeds<WS2812B, LED_Stripe5 , GRB>(leds5, LEDs_Anzahl_5);
  FastLED.addLeds<WS2812B, LED_Stripe6 , GRB>(leds6, LEDs_Anzahl_6);
  FastLED.addLeds<WS2812B, LED_Stripe7 , GRB>(leds7, LEDs_Anzahl_7);

  FastLED.show();
}

void loop()
{
  uint32_t jetzt = millis();
  bool neu = false;

  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();

  if (button1.fell())
  {
    merker1 = !merker1;
  }
  if (button2.fell())
  {
    merker2 = !merker2;
  }
  if (button3.fell())
  {
    merker3 = !merker3;
  }
  if (button4.fell())
  {
    merker4 = !merker4;
  }
  if (button5.fell())
  {
    merker5 = !merker5;
  }
  if (button6.fell())
  {
    merker6 = !merker6;
  }
  if (button7.fell())
  {
    merker7 = !merker7;
  }

  if (jetzt - vorhin1 >= Intervall1)
  {
    neu = true;
    if (merker1)
    {
      vorhin1 = jetzt;
      leds1[lauflicht1] = CRGB::Black;
      leds1[LEDs_Anzahl_1 - lauflicht1 - 1] = CRGB::Black;
      lauflicht1++;
      if (lauflicht1 >= LEDs_Anzahl_1) lauflicht1 = 0;
      leds1[lauflicht1] = CRGB::Green;
      leds1[LEDs_Anzahl_1 - lauflicht1 - 1] = CRGB::Red;
    } else {
      for (lauflicht1 = 0; lauflicht1 < LEDs_Anzahl_1; lauflicht1++)
      {
        leds1[lauflicht1] = CRGB::Black;
      }
    }
  }

  if (neu) FastLED.show();
}

Eine Frage dazu. &i ist ja eine Adresse von der Variable i und über : wird die Adressen von strip zugewiesen? Und for wird solange ausgeführt, wie es weitere Adressen von dem strip Array gibt?

Gibt es dazu Lektüre oder Google Stichworte?

c++ for (auto &i :

1 Like

Range-Based For Loop
Bereichsbasierende For Schleife

Danke :slight_smile:

Edit: Passend dazu ein Video was das ausführlich erklärt. Mir hat es geholfen.

1 Like

Vorteil: Die Anzahl der Elemente eines Feldes wird automatisch ermittelt. Aber auto steht für den automatisch ermittelten Typ, hier Strip. Also gleich zwei Automatismen.

Jein. Das heißt dass es eine Referenz ist. Wenn man das nicht macht wird eine Kopie angelegt. Das ist bei primitiven Datentypen in Ordnung, aber nicht bei Objekten von Klassen. Es stimmt schon dass das mit Adressen implementiert ist, aber direkt sollte man da nicht so denken.

Generell darfst du hier nicht den "Adresse von" Operator (wie er z.B. bei Zeigern verwendet wird) mit einer Referenz verwechseln. Das sind zwei ähnliche und verwandte aber unterschiedliche Dinge.

Dieses Konstrukt ist in C++ relativ neu. C++11 gibt es zwar jetzt auch schon ein paar Jahre, aber andere Sprachen kannten das vorher schon lange als "for each". Das ist aber der Grund weshalb man es in vielen grundlegenden Tutorials nicht findet und es immer noch oft als etwas spezielles behandelt wird.
Das liest man einfach als "für jedes Element i im Array mache folgendes"

1 Like

Eher so:
Das & kennzeichnet i als Referenz ( auf das jeweilige Element von strip )

lol.
Ich hab grad in meinem Archiv gegraben und einen meiner Mustersketche gefunden der da heißt: "20180618_foreach". Darin auch der Link auf die (für mich) auslösende Diskussion: https://forum.arduino.cc/index.php?topic=553441.30

1 Like

Danke. Lesenswerter Thread.

gut das ist wirklich ein einfacher programmteil.
Leicht zu verstehn, nur darauf zu kommen ist ne andere Hausnummer

Was auch immer @agmue damit bezwecken wollte, aber das ist weder einfach noch zu verstehen.

Bedenke: Du musst für jeden Stripe alles ab Zeile 159 neu schreiben - davon abgesehen, das in #8 doch schon klar war, das die Abarbeitung via array ganz einfach und zielführend ist.
Benummerte Variablen ...

Ist gelöst. Mehr war ja nich.