Switch case und loop function für Neopixel LED

Servus Leute,

leider komme ich mit meinen Kenntnissen nicht weiter und brauche dringend euren Rat und know-how.

kurz zum Project: Ich habe einen Neopixel 24 Bit RGB LED Ring, den ich über Arduino mini Pro und HC-06 BT Modul ansteuere. Die App zum BT steuern habe ich vom MIT Inventor 2 mir schnell und einfach zusammengebaut. Ich kann simple Sachen wie Farben wechseln (also vorher im Code generiert) und Funktionen ablaufen lassen ABER was ich noch nicht hinkriege ist, dass ich z.B. ein Case Fall z.B. Rainbowcycle solange laufen lassen kann, bis ich einen anderen Case durch BT auswähle. ICh habe mich schon durch google durchgewühlt aber mir fehlen die richtigen suchwörter oder einfach das Verständniss. Aus diesem Grunde bitte ich um eure Unterstützung, um in dem Projekt einfach mal Ruhe zu bekommen und mich auf die einzelnen Funktionen und Farbspiele zu konzentrieren.

Also nochmal die Konkrete Problemeatik. Ich möchte eine Schleife eines cases solange laufen lassen, bis ich etwas anderes über Bluetooth auswähle.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

#define PIN 6

#include <SoftwareSerial.h>
SoftwareSerial mySerial(0, 1); // RX, TX

Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, PIN, NEO_RGB + NEO_KHZ800);




void setup() {

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  pinMode(6, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  
  if (Serial.available() > 0) {
    char data;
    data = Serial.read();
    Serial.write(Serial.read());


    switch (data)
    {
      case 'E':
        colorSet(strip.Color(0, 0, 0), 0);//aus muss oben stehen, sonst wenn app geschlossen laufen alle funktionen durch
        break; // stoppt den Ablauf von case
      case 'A':
        rainbowCycle(20);  // erst läuft der Rainbow Cycle Zyklus ab
        colorSet(strip.Color(0, 0, 0), 0); // dann gehen die LEDs aus ansosnten würden sie nach ablauf vom  Rainbow Zyclus farbig stehen bleiben
        break;
      case 'B':
        // colorWipe(random(0, 100), 20);  //  colorWipe(random(0, 255), 20); // random Helligkeit


        do {  // verzweifelter Versuch mit do whole Schleife ohne Erfolg  // WAS WÄRE denn richtig?
          colorWipe(strip.Color(random(0, 100), random(0, 100), random(0, 100)), 50);
          delay(50);
          data = Serial.read();
                    Serial.write(Serial.read());
          
        }      while (data = 'B');

        break;
      case 'C':
        theaterChaseRainbow(20); // Die Zahl in der Klammer gibt an wie schnell die schleife drehen soll hier 20ms
        colorSet(strip.Color(0, 0, 0), 0);
        break;
      case 'D':
        //brighten();
        //  darken();
        break;
      case 'F':
        colorSet(strip.Color(0, 0, 30), 0);//Blue
        break;

      default:
        colorSet(strip.Color(0, 0, 0), 0);
        digitalWrite(6, LOW);
    }

  }

}


void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256 * 1; j++) { // 1 cycles of all colors on wheel
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}


void colorSet(uint32_t c, uint8_t wait) {     // From NeoPixel Library
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
  }
  strip.show();
  delay(wait);
}





// 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);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

ich hoffe ich habe keinen Admin oder jemanden sonst verärgert.

Und bedanke mich schon im voraus für alle Hinweise, die mich Konstruktiv weiter bringen.

Hi

void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256 * 1; j++) { // 1 cycles of all colors on wheel
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

Solange Du nicht innerhalb der Funktion, Die Du unterbrechen können möchtest, auf den gewünschten Abbruch prüfst (und dann die FOR per break; oder durch Setzen von i auf den Endwert) die Schleife verlässt - wird der Arduino Das auch nicht von selber machen.

Mir ist nicht bekannt, ob der BT-Kram 'durch kommt', wenn Du in einer Funktion 'gefangen' bist.
Wenn die BT-Funktionen ebenfalls regelmäßig dafür aufgerufen werden müssen - musst Du Die wohl regelmäßig aufrufen :wink:

MfG

Der bessere Weg dürfte es sein, keine Schleifen mit delay zu benutzen.
Die innere for-Schleife setzt die Farben, danach show() - das geht schnell und ist machbar.
Die äußere for-Schleife muss weg und sollte durch millis() ersetzt werden. Damit kann im Loop ganz normal auf andere Ereignisse geprüft werden (z.B. BT)

Gruß Tommy

postmaster-ino:
Hi

void rainbowCycle(uint8_t wait) {

uint16_t i, j;

for (j = 0; j < 256 * 1; j++) { // 1 cycles of all colors on wheel
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}



Solange Du nicht innerhalb der Funktion, Die Du unterbrechen können möchtest, auf den gewünschten Abbruch prüfst (und dann die FOR per break; oder durch Setzen von i auf den Endwert) die Schleife verlässt - wird der Arduino Das auch nicht von selber machen.

Mir ist nicht bekannt, ob der BT-Kram 'durch kommt', wenn Du in einer Funktion 'gefangen' bist.
Wenn die BT-Funktionen ebenfalls regelmäßig dafür aufgerufen werden müssen - musst Du Die wohl regelmäßig aufrufen ;)

MfG

Hi, diese Funktionen möchte ich auch gar nicht unterbrechen. Mir geht es darum diese Funktionen in einer Schleife in einem Case laufen zu lassen und bei bedarf durch BT Ansteuerung zu verlassen. Da hapert es mir aber noch an Verständnis.

 case 'B':
  
        do {  // verzweifelter Versuch mit do whole Schleife ohne Erfolg  // WAS WÄRE denn richtig?
          colorWipe(strip.Color(random(0, 100), random(0, 100), random(0, 100)), 50);
          delay(50);
          data = Serial.read();
                    Serial.write(Serial.read());
          
        }      while (data = 'B');

        break;

damit wollte ich z.B. das erreichen. Aber anscheinend geht es so nicht.

Ich habe keine Neopixel sondern 122 Dotstar, ich nutze Hardware SPI und den seriellen Monitor zur Buchstabeneingabe. Die entsprechenden Initilisierungen müßtest Du für Deinen Ring anpassen.

Hier ein Vorschlag:

#include <Adafruit_DotStar.h>
#include <SPI.h>         // COMMENT OUT THIS LINE FOR GEMMA OR TRINKET
#define NUMPIXELS 122 // Number of LEDs in strip

// Hardware SPI is a little faster, but must be wired to specific pins
// (Arduino Uno = pin 11 for data, 13 for clock, other boards are different).
Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DOTSTAR_BGR);

char animation = 'E';
uint32_t aktuell;

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  Serial.begin(9600);
  einefarbe(052545);
}

void loop() {
  aktuell = millis();
  if (Serial.available() > 0) {
    char data;
    data = Serial.read();
    Serial.write(data);

    switch (data)
    {
      case 'E':
        animation = 'E';
        break;
      case 'A':
        animation = 'A';
        break;
      case 'B':
        animation = 'B';
        break;
      default:
        break;
    }
  }

  switch (animation)
  {
    case 'E':
      einefarbe(0);
      break;
    case 'A':
      lauflicht(0x200000);
      break;
    case 'B':
      lauflicht(0x202020);
      break;
    default:
      break;
  }
}

void einefarbe(uint32_t farbe) {
  for (uint16_t led = 0; led < strip.numPixels(); led++) {
    strip.setPixelColor(led, farbe);
  }
  strip.show();
  animation = ' ';
}

void lauflicht(uint32_t farbe) {
  static uint32_t vorhin = 0;
  static uint16_t led = 0;
  if (aktuell - vorhin >= 20) {
    vorhin = aktuell;
    strip.setPixelColor(led, farbe);
    if (led > 0) {
      strip.setPixelColor(led - 1, 0);
    }
    led = (1 + led) % strip.numPixels();
    strip.show();
  }
}

Hi

WHILE ist, wenn Du immer überall sein willst, der falsche Weg.
Auch wird Deine Do-While-Schleife NIE beendet werden, da Deine Bedingung eine Zuweisung ist und keine Prüfung.
= != ==

MfG

agmue:
Ich habe keine Neopixel sondern 122 Dotstar, ich nutze Hardware SPI und den seriellen Monitor zur Buchstabeneingabe. Die entsprechenden Initilisierungen müßtest Du für Deinen Ring anpassen.

Hier ein Vorschlag:

#include <Adafruit_DotStar.h>

#include <SPI.h>         // COMMENT OUT THIS LINE FOR GEMMA OR TRINKET
#define NUMPIXELS 122 // Number of LEDs in strip

// Hardware SPI is a little faster, but must be wired to specific pins
// (Arduino Uno = pin 11 for data, 13 for clock, other boards are different).
Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DOTSTAR_BGR);

char animation = 'E';
uint32_t aktuell;

void setup() {
 strip.begin();
 strip.show(); // Initialize all pixels to 'off'
 Serial.begin(9600);
 einefarbe(052545);
}

void loop() {
 aktuell = millis();
 if (Serial.available() > 0) {
   char data;
   data = Serial.read();
   Serial.write(data);

switch (data)
   {
     case 'E':
       animation = 'E';
       break;
     case 'A':
       animation = 'A';
       break;
     case 'B':
       animation = 'B';
       break;
     default:
       break;
   }
 }

switch (animation)
 {
   case 'E':
     einefarbe(0);
     break;
   case 'A':
     lauflicht(0x200000);
     break;
   case 'B':
     lauflicht(0x202020);
     break;
   default:
     break;
 }
}

void einefarbe(uint32_t farbe) {
 for (uint16_t led = 0; led < strip.numPixels(); led++) {
   strip.setPixelColor(led, farbe);
 }
 strip.show();
 animation = ' ';
}

void lauflicht(uint32_t farbe) {
 static uint32_t vorhin = 0;
 static uint16_t led = 0;
 if (aktuell - vorhin >= 20) {
   vorhin = aktuell;
   strip.setPixelColor(led, farbe);
   if (led > 0) {
     strip.setPixelColor(led - 1, 0);
   }
   led = (1 + led) % strip.numPixels();
   strip.show();
 }
}

Jawohl! genau so ein Hinweis hat mir gefehlt, vielen lieben Dank für die Anregungen. Funktioniert einwandfrei, genau wie ich es mir gewünscht habe. Bester Mann! Und danke an alle die auch versucht haben zu helfen.

GELÖST !