Problem mit If Abfrage

Hallo alle zusammen,

ich habe folgendes Problem:
Na meinem Arduino habe ich eine LED-Lichterkette mit WS2811 Chips angeschlossen. Ich möchte verschiedene Programme durch eine Eingabe im seriellen Monitor ändern. Das Funktioniert soweit, als das die Eingabe über den seriellen Monitor nur nach dem einschalten bzw. resetten funktiert. Ich möchte aber nicht jedes mal den Arduino resetten bevor ein neues Programm läuft. Ich vermute es hängt mit den Schleifen im Definitionsteil für die einzelnen Lichtprogramme zusammen.
Hier der Code:

#include <Adafruit_NeoPixel.h>
#define LEDPIN 6 // connect the Data from the strip to this pin on the Arduino
#define NUMBER_PIEXELS 50 // the number of pixels in your LED strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMBER_PIEXELS, LEDPIN, NEO_RGB + NEO_KHZ800);

int wait = 50; // how long we wait on each color (milliseconds)
int waitTime = 5;
int delayTime = 50;

void setup() {
  strip.begin();
  Serial.begin(9600);
}

void loop() {

  if (Serial.available() > 0) {

    for (int color = 0; color < 255; color++) {
      for (int i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, Wheel(color));
      }
      strip.show();
      delay(wait);
    }
  };

  if (Serial.available() > 1) {

    fadeInAndOut(255, 0, 0, waitTime); // Red
    fadeInAndOut(0, 255, 0, waitTime); // Green
    fadeInAndOut(0, 0, 255, waitTime); // Blue
  };


  if (Serial.available() > 2) {

    for (int i = 0; i < strip.numPixels() - 1; i++) {
      rainbow7(i, delayTime); // starting at i, draw the 7 color rainbow
    };




  }

}

//Definitionsteil der einzelnen Lichtprogramme

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
    WheelPos -= 170;
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
};

void fadeInAndOut(uint8_t red, uint8_t green, uint8_t blue, uint8_t wait) {

  for (uint8_t b = 0; b < 255; b++) {
    for (uint8_t i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, red * b / 255, green * b / 255, blue * b / 255);
    }
    strip.show();
    delay(wait);
  };

  for (uint8_t b = 255; b > 0; b--) {
    for (uint8_t i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, red * b / 255, green * b / 255, blue * b / 255);
    }
    strip.show();
    delay(wait);
  };
};

// a seven segment rainbow with red on the highest pixel
void rainbow7(uint16_t i, uint16_t wait) {
  int np = strip.numPixels();  // we use the modulo function with this
  strip.setPixelColor(i     % np, 0, 0, 0); // off
  strip.setPixelColor((i + 1) % np, 25, 0, 25); // violet
  strip.setPixelColor((i + 2) % np, 255, 0, 255); // indigo
  strip.setPixelColor((i + 3) % np, 0, 0, 150); // blue
  strip.setPixelColor((i + 4) % np, 0, 150, 0); // green
  strip.setPixelColor((i + 5) % np, 255, 255, 0); // yellow
  strip.setPixelColor((i + 6) % np, 110, 70, 0); // orange
  strip.setPixelColor((i + 7) % np, 150, 0, 0); // red
  strip.show();
  delay(wait);
};

Die Steuerung wird später zusammen mit einem Raspberry Pi und Alexa als Sprachsteuerung zur verschönerung meines Weihnachtsbaumes dienen :slight_smile:
Ich hoffe mir kann jemand helfen.
Danke im Vorraus, Oli.

Die fragst immer nur ab ob was im Eingangspuffer ist, aber liest nie etwas aus.

...und wenn Du - wie ich mal annehme - mit den Ziffern 0, 1 und 2 die jeweilige Aktion auswählen willst, solltest Du nicht prüfen, ob mehr als 0, 1 oder zwei Zeichen im Eingangspuffer sind, sondern (1) das erste vorhandene Zeichen auslesen und dann (2) auf Gleichheit prüfen und dann (3) den Rest Zeichen ignorieren (da sind u.U. noch Wagenrücklauf/Zeilenvorschub 0x0D/0x0A im Puffer) Wenn wir mal annehmen, dass jeweils das erste Zeichen das wichtige sein soll:

int incomingByte = 0;
...
void loop {
    if (Serial.available() > 0) {
        // read the incoming byte:
        incomingByte = Serial.read();

        if (incomingByte == (int)'0') {
             ...
        }
        if (incomingByte == (int)'1') {
             ... // fade
        }
        if (incomingByte == (int)'2') {
             ... // rainbow
        }

        // jetzt noch die überzähligen Bytes wegwerfen
        while (Serial.available() > 0) {
            incomingByte = Serial.read();
        }
        // und den Zeichenspeicher vorsichtshalber wieder auf Anfang setzen
        // das ist nicht nötig, aber eine nützliche Angewohnheit, wenn Programme mal
        // komplizierter werden
        incomingByte = 0;
    } // Zeichen vorhanden

Ich hab's jetzt nicht kompiliert, aber so etwa sollte es gehen.

Gruß Walter

Natürlich könnte man statt der drei 'if' auch mit switch(incomingByte) {...} arbeiten.

Den Cast kann man sich sparen. Character Literale sind schon Integer

Ja, kann man sparen.

Schadet aber auch nix. Ist eine dumme Angewohnheit von mir, hervorgerufen durch die Benutzung verschiedener Systeme (CPUs, Compiler und Betriebssysteme) :).
</OFF TOPIC>

  // und den Zeichenspeicher vorsichtshalber wieder auf Anfang setzen
   // das ist nicht nötig, aber eine nützliche Angewohnheit, wenn Programme mal
   // komplizierter werden
   incomingByte = 0;

Profis verwenden gern lokale Variable und den richigen DatenTyp, dann erledigen sich manche Sachen von selbst.

void loop {
    if (Serial.available() > 0) {
        // read the incoming byte:
        byte incomingByte = Serial.read();
        if (incomingByte == '0') {
             ...
        }
        ... 
        // bei ankommenden Zeichen, die egal sind, wird hier einfach nichts gemacht.
    } 
    // hier gibt es gar keine Variable namens incomingByte
}

Das Weglesen von "Schrott" ( Neue Zeile, Leerzeichen usw.) kann genausogut in folgenden loop() Durchläufen gemacht werden.

Meine Kommentare können natürlich raus, wenn man kapiert hat, wie einfach es geht ;)

Vielen Dank an alle, werde es heute Nachmittag ausprobieren, aber ich denke Mal das funktioniert

wno158:
Ja, kann man sparen.

Schadet aber auch nix. Ist eine dumme Angewohnheit von mir, hervorgerufen durch die Benutzung verschiedener Systeme (CPUs, Compiler und Betriebssysteme) :).
</OFF TOPIC>

Ja, ich denke auch dass “dumme Angewohnheit” die Sache auf den Punkt bringt.

Die alten C-Style Casts machen oft mehr Probleme, als sie lösen.
Und: Es geht IMMER ohne.