Input während eines aktiven Loops

Hey!
Vorweg möchte ich mich erstmal entschuldigen, falls ich irgendwas übersehen haben sollte bzw. etwas fehlt.

Ich sitze aktuell an einem kleinen Testprogramm, welches einerseits den Input der seriellen Schnittstelle beachtet, aber bevor der Input ankommt, soll eine Animation durchlaufen. Das Programm soll irgendwann während eines Bootvorgangs laufen und mehrere Status anzeigen. Also z.B wenn er gerade das Betriebssystem installiert, leuchtet eine LED gelb und sofern die Installation abgeschlossen ist, wird diese grün und die nächste wird automatisch gelb.
Diesen Input gebe ich aktuell über die serielle Schnittstelle mit einer If-Schleife, aber alles sehr simpel gehalten.

Bevor nun der Bootvorgang läuft, sollen die LEDs eine kleinen "Ladebalken" anzeigen, bis der erste Input über die Schnittstelle ankommt. Der Balken funktioniert soweit auch sehr gut, nur leider glaube ich, dass das Programm die zweiten Schleife dauerhaft durchführt und währenddessen den Input gar nicht wahrnehmen kann.
Ich habe schon gelesen, dass man durch delay() das Programm daran hindert in der Zeit andere Aktionen durchzuführen und ich weiß auch, dass ich womöglich einen check durchführen muss und je nach Ergebnis nun der Ladebalken weiter läuft oder eben nicht. Ich hab allerdings nicht die leiseste Ahnung wie und bin auf dem Gebiet auch noch relativ unerfahren, daher wollte ich mal um Hilfe bitten.

Verwendet wird ein Arduino Nano Every mit einem Neopixel mit 8 LEDs

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


#define PIN       3
#define NUMPIXELS 8


Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, 3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);



void setup() {

  // put your setup code here, to run once:
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif

  pixels.begin();
  strip.begin();
  strip.setBrightness(50);
  strip.show();
  Serial.begin(9600);
}

void loop() {
  pixels.clear();
  colorWipe(strip.Color(40, 0, 20), 10);

  if (Serial.available() > 0) {
    String txt = Serial.readString();
    if (txt == "Yellow") {
      strip.setPixelColor(0, 50, 50, 0);
      strip.fill(pixels.Color(50, 50, 0), 0, 8);
      Serial.println("System is currently starting");
      strip.show();
    }
    
    else if (txt == "Red")  {
      strip.setPixelColor(0, 50, 0, 0);
      strip.fill(strip.Color(50, 0, 0), 0, 8);
      Serial.println("System error has occured!");
      strip.show();
    }

    else if (txt == "Green")  {
      strip.setPixelColor(0, 0, 50, 0);
      strip.fill(strip.Color(0, 50, 0), 0, 8);
      Serial.println("System has successfully started");
      strip.show();
    }
  }
}

  
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(500);
 }
  for(int i=0; i<NUMPIXELS; i++) {
  strip.setPixelColor(i, strip.Color(0,0,0));
  strip.show();
  delay(wait);
 }
}

Vielen Dank im Voraus!

Hallo,

das was du erreichen willst, ist eigentlich recht simpel.
Du brauchst eine Statusvariable, die im Anfang abgefragt wird, solange die z.B. HIGH ist, durchläuft es die Balkenanzeige.
Wird eine Info über die Serielle Schnittstelle erkannt, setzt du diese Variable auf LOW und er geht nicht mehr in die Balkenanzeige.

So sollte das funktionieren.

Im übrigen gibt es keine if-Schleife, es ist eine if-Abfrage.

(deleted)

Hallo tcchaise, auch ein willkommen von mir.

An sich hat Hotsystems die Antwort geschrieben. Da du aber schon geschrieben hast, dass du ein Anfänger bist (keine Schande, da waren wir alle Mal) empfehle ich dir das anschauen folgenden Beispiels.

Den Link habe ich von programming questions englischer Forum kopiert. Das ist der Basis von nicht blockierende delays, was du für die Umsetzung deines Vorhabens benötigst.

Sonst musst du dich an interrupts reinarbeiten. Damit habe ich aber in Arduino Umfeld gar keine Erfahrung. Sind hier nicht in 8051 Umfeld. Hat arduino überhaupt einen Timer und interrupter?

Hat er, mehrere.

Gruß Tommy

dr-o:
Hallo tcchaise, auch ein willkommen von mir.

An sich hat Hotsystems die Antwort geschrieben. Da du aber schon geschrieben hast, dass du ein Anfänger bist (keine Schande, da waren wir alle Mal) empfehle ich dir das anschauen folgenden Beispiels.

Arduino State Management Explained (BlinkWithoutDelay) - YouTube

Den Link habe ich von programming questions englischer Forum kopiert. Das ist der Basis von nicht blockierende delays, was du für die Umsetzung deines Vorhabens benötigst.

Sonst musst du dich an interrupts reinarbeiten. Damit habe ich aber in Arduino Umfeld gar keine Erfahrung. Sind hier nicht in 8051 Umfeld. Hat arduino überhaupt einen Timer und interrupter?

Bitte keine Tipps mit Interrupt. Das ist hier völlig fehl am Platz.
Genau so skeptisch finde ich Empfehlungen zu. YT-Videos, die meist fehlerhaft sind.
Die meisten User fragen hier, weil sie mit fehlerhaften YT-Videos nicht klar kommen.

Peter-CAD-HST:
Moin tcchaise
Herzlich Willkommen im Forum. Und hier kommt ein konstruktiver Vorschlag:
Im Sketch wird der Inhalt des Strings txt geprüft. Nach erfolgreicher Prüfung muss der Inhalt des Strings überschreiben werden, z.B. mit txt=" "; , damit die Prüfung in der loop() nicht noch einmal ausgeführt wird.
Viel Erfolg beim Testen
Gruß Peter
take care

Das ist hier nicht das Problem.
Als lokale Variable geht txt am Ende der loop() ins Nirvana.
Es gibt also keine Notwendigkeit zum löschen.

Hat arduino überhaupt einen Timer und interrupter?

Tipp: Datenblatt zu deinem konkreten µC lesen.
Alles was da drin steht kann auch dein, mein, oder des TO sein Arduino.

Tipp am Rande:
Ohne Interrupts, kein millis(), kein Serial, kein USB, kein I2C usw.

HotSystems:
Bitte keine Tipps mit Interrupt. Das ist hier völlig fehl am Platz.

Jo, habe gerade gelesen, dass arduino keine Software interrupts sondern nur Hardware interrupts hat. Dann rate ich davon ebenfalls ab.

HotSystems:
Genau so skeptisch finde ich Empfehlungen zu.

Deine Argumentationskette kann ich folgen. Dennoch habe ich diesen Link von der internationalen Forum kopiert :wink: es gibt auch zahlreiche, nicht auf YouTube Videos basierende Tutorials. Hier z.B.
https://forum.arduino.cc/index.php?topic=663607.0
Ich tendiere persönlich auf millis() basierende delays.

(deleted)

Peter-CAD-HST:
Warum? und Dann?

Versuchs doch mal mit einer vollständigen/verständlichen Frage!
Oder einem konkreteren Zitat.

Dann kann ich dir auch antworten.
Sonst nicht.

Es sei denn, das soll eine Provokation sein.
Dann ist das so schon ok.

(deleted)

Aus immer wieder dem gleichen Grund.
Auch ist die Abhilfe immer wieder die gleiche.
(ok, vielleicht nicht immer, aber zu 99,9%)

-> Wenn man einen bestimmten Ablauf wünscht, muss man sich eine Ablaufsteuerung bauen.

Hier, zum Beispiel:
Weg mit den ganzen Delays und auf endliche Automaten umrüsten.
Dann lassen sich auch Nebenläufigkeiten realisieren.

Auch Serial.readString() steht da etwas im Wege rum, denn es blockiert recht lange.

Hallo zusammen,

erstmal vielen Dank für die zahlreichen Antworten :smiley:

Ich habe heute leider nicht so viel Zeit um daran weiter zu arbeiten, aber werde mich auf jeden Fall
nochmal melden, wenn ich die Vorschläge umgesetzt habe.
Danke schon mal im voraus für die Tipps :slight_smile:

So, ich habe Neuigkeiten bzgl. meines Problems.

Ich habe es gelöst bekommen, aber auf eine andere Art

while (!Serial.available()) {
    colorWipe(strip.Color(40, 0, 15), 10);
  }
}

Mithile dieser Schleife läuft die Funktionen solange, bis über die serielle Schnittstelle eines der Textbeispiele gesendet wird.
Dadurch ist jetzt allerdings ein neues Problem entstanden.

Wenn ich nun über die Kommmandozeile ein Textbeispiel versende, dann funktioniert gar nichts (LEDs bleiben komplett aus). Wenn ich dasselbe über das Terminal versuche, dann resettet sich die Schleife mit der Animation.
Zwischendurch hat es auf Windows auch funktioniert, nachdem der Test auf Linux dann aber fehlgeschlagen ist, hat es auf Windows auch nicht mehr geklappt (Habe nichts am Code verändert). Bevor ich die Animation integriert hatte und lediglich die Textbeispiele vorhanden waren, hat es über beides funktioniert.

Man muss dazu sagen, dass ich das über VMs teste, da ich über einen Firmenlaptop daran arbeite, an dem ich aber nicht die kompletten Rechte besitze.

tcchaise:
Man muss dazu sagen, dass ich das über VMs teste, da ich über einen Firmenlaptop daran arbeite, an dem ich aber nicht die kompletten Rechte besitze.

Du kannst die portable Version der IDE installieren, das geht als normaler user.

@ElEspanol

Ne, geht leider nicht.
Durch das interne Netz der Firma kann ich anscheinend keine Bibliotheken herunterladen ::slight_smile:

Aber deine VM kann das?

Ja, dort verbinde ich mich per USB-Tethering mit meinem Handy (Leider sehr umständlich)
Am Laptop direkt verwenden wir allerdings Cisco AnyConnect, wodurch wir automatisch mit dem Firmennetz verbunden werden.

Wenn ich nun über die Kommmandozeile ein Textbeispiel versende, dann funktioniert gar nichts (LEDs bleiben komplett aus).

Wenn du über Serial was sendest, passiert das was du sonst programmiert hast.

Ist das noch dein

  if (Serial.available() > 0) {
    String txt = Serial.readString();
    ...
  }

Im Zweifelsfall liegt dort auch dein Problem...

Hab die Lösung gefunden
Warum auch immer wurde die Konfiguration des COM-Ports verändert und die Eingaben kamen gar nicht erst an.
In Linux habe ich jetzt mithilfe von minicom die config überarbeitet und abgespeichert, für Windows habe ich bis jetzt erst mal nur einen Befehl, den ich vor jeder neuen Verwendung durchführen muss.

Trotzdem danke für die Hilfe, aber eine Frage hätte ich dennoch :-X

void colorWipe(uint32_t c, uint8_t wait) {
   for(uint16_t i=0; i<strip.numPixels(); i++) {    
     strip.setPixelColor(i, c);
     Serial.println("Starting...");
     strip.show();
     delay(500);
    }
    for(int i=0; i<NUMPIXELS; i++) {  
     strip.setPixelColor(i, strip.Color(0,0,0));
     strip.show();
    }
  }

Diese Animation läuft momentan solange durch, bis der Arduino einen gewissen Text erhält.
Allerdings wird die Animation immer bis zum Ende durchgeführt und das würde ich gerne vermeiden.
Kann man das über count regeln und wenn ja, könntet ihr mir vllt. eine kleine Starthilfe anbieten?
Stehe da gerade etwas auf dem Schlauch ^^"

Danke im voraus und vorweg schon mal schöne Feiertage!