while schleife hängt sich auf

hi Leute,
weiß einer von euch warum ich im "Loop" nicht aus der Schleife komme. Den anderen Code müsst ihr nicht beachten, da ich erst mit dem Projekt angefangen habe und vor dem Problem stehe.
Die While schleife soll eine Start Sequenz für eine gewisse zeit darstellen. Dannach soll der bool Startup = LOW und dann die Funk. BlinkSystem();

#include <Arduino.h>
//PINS
//Trigger = 0; Echo = 1; LED_Red 2; LED_Green = 3; LED_Blue = 4; Buzzer = 5; Relay = 6;
const byte Pin[7] = {2,3,4,5,6,7,8};
//LED
enum Phase_Blue {ON1, OFF1, ON2, OFF2, ON3, OFF3, ON4, OFF4};
const int d[8] = {100, 20, 40, 100, 50, 300, 800, 1002};
Phase_Blue Phase_Blue;
bool state;
unsigned long millisMem_System;
unsigned long millisMem_Startup;
unsigned long millisMem_Serial = millis();
const int delayStartUp = 3000;
bool Startup = false;
//ULTRASCHALL
long time = 0;
long distance = 0;

void blinkSystem(){
      switch (Phase_Blue) {
        case ON1:
          if(state = LOW){
            if(millis() - millisMem_System >= d[0]){
              state = HIGH;millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 1");
              break;
          }
        }
        case OFF1:
        if(millis() - millisMem_System >= d[1]){
          state = HIGH; millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 2");
            break;
      }
        case ON2:
        if(millis() - millisMem_System >= d[2]){
          state = HIGH;millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 3");
          break;
      }
        case OFF2:
        if(millis() - millisMem_System >= d[3]){
          state = LOW;  millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 3");
            break;
      }
        case ON3:
        if(millis() - millisMem_System >= d[4]){
          state = HIGH;millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 4");
            break;
      }
        case OFF3:
        if(millis() - millisMem_System >= d[5]){
          state = LOW;millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 5");
            break;
      }
        case ON4:
        if(millis() - millisMem_System >= d[6]){
          state = HIGH;millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 6");
            break;
      }
        case OFF4:
        if(millis() - millisMem_System >= d[7]){
          state = LOW;millisMem_System = millis();digitalWrite(Pin[4], state);Serial.print("State = 7");
            break;
      }
  }
}

void setup() {
  Serial.begin(9600);
  millisMem_System = millis();
  millisMem_Startup = millis();
  Startup = LOW;
  pinMode(Pin[0], OUTPUT);
  pinMode(Pin[1], INPUT);
  pinMode(Pin[2], OUTPUT);
  pinMode(Pin[3], OUTPUT);
  pinMode(Pin[4], OUTPUT);
  pinMode(Pin[5], OUTPUT);
  pinMode(Pin[6], OUTPUT);
}

void loop() {
  if(Startup = HIGH){
  while (Startup = HIGH) {
    if(millis() - millisMem_Startup <= delayStartUp){
      Startup = HIGH;
      digitalWrite(Pin[4], HIGH);
      digitalWrite(Pin[3], HIGH);
      digitalWrite(Pin[2], HIGH);
      Serial.println("Startup");
    }else{
      Startup = LOW;
      digitalWrite(Pin[4], LOW);
      digitalWrite(Pin[3], LOW);
      digitalWrite(Pin[2], LOW);
      Serial.println("Startup END");
      //Er bleibt Startup END "Serial Monitor"
      break;
      delay(50);
    }
 }
}else{
  Startup = LOW;
   //blinkSystem();
}
}

Hi

Jupp

Statup=HIGH - Das ist ein ZUWEISUNG - Du weist Statup den Zustand HIGH zu - und Das ist außerdem 'true', somit wird sowohl die IF, wie die WHILE ausgeführt.
Scheinbar wird die Anweisung innerhalb der While-Klammer auch bei jedem Durchlauf ausgeführt - da Du ja auch Statup innerhalb der While auf LOW setzt.

Davon ab ist eine WHILE eine gaaanz schlechte Idee, um auf etwas zu warten.
Ok, zum Warten ist vll. falsch - aber sobald Du Mal was Anderes noch nebenbei machen möchtest, fällt Dir Das auf die Füße.
Daher rate ich Dir zu dem Beispiel Blink_without_delay aus der IDE und der Nachtwächtererklärung hier im Forum.

MfG

Auch STRG+T solltest Du in der IDE Mal gedrückt haben - macht die Sache übersichtlicher und 'direkt untereinander stehende Klammern' sollten dann der Vergangenheit angehören.

Edit
blink_without_millis ... ich sollte ins Bett :confused:
Ist korrigiert, danke :slight_smile:

postmaster-ino:
... Blink_without_millis aus der IDE und der Nachtwächtererklärung hier im Forum.

Du meinst „blink without delay:slight_smile:

Gruß

Gregor

postmaster-ino:
Daher rate ich Dir zu dem Beispiel Blink_without_millis

insider:
delay(apokalypse)

:wink:
Peer

gregorss:
Du meinst „blink without delay:slight_smile:

Der Hinweis läuft in dieser Form wohl ins Leere.
Der OP kennt das.

 if(millis() - millisMem_System >= d[0]){

Peer

Hi

my_xy_projekt:
Der Hinweis läuft in dieser Form wohl ins Leere.
Der OP kennt das.

Er zieht Es aber nicht durch.
Oder wie würdest Du die WHILE-Schleife erklären, Die so lange aktiv bleibt, bis die Status-Variable LOW wird?
(Diese wird durch einen millis-Vergleich gesetzt)
Kann so passen, bei Erweiterungen wird Das aber auf den Füßen zu spüren sein!

mfG

postmaster-ino:
Oder wie würdest Du die WHILE-Schleife erklären, Die so lange aktiv bleibt, bis die Status-Variable LOW wird?

Erwischt.
Code kopiert wäre eine (simple und nicht belastbare) Erklärung.
Evtl. hat der OP auch nur einfach das gemacht, was ich auch kenne: erstmal gedanklich erfasstes Soll in Codezeilen umsetzen, das genau Dieser Teil so funktioniert, wie gewünscht.

Sicher nicht Code der zeigenswert, aber funktional ist.

Besser geht immer.

Gruß

Peer

Aktiviere die Warnungen in der IDE! Solche Sachen werden angezeigt auch wenn es kein Fehler ist:

warning: suggest parentheses around assignment used as truth value [-Wparentheses]

Für eine Abfrage auf eine Zuweisung gibt es auch Anwendungen. Man kann so abfragen ob ein ausgelesener Wert gleich oder ungleich Null ist. Meistens will man es aber nicht

Die Warnungen zeigen dir übrigens auch dass die breaks bei switch/case außerhalb der if-Abragen gehören

Serenifly:
Aktiviere die Warnungen in der IDE!

Das mag für diesen State gültig sein, aber wenn Compiler-Warnungen schon allein aus den integrierten Funktionen herrühren, Mal als Zitat:

arduino-1.8.10/hardware/arduino/avr/libraries/Wire/src/utility/twi.c: In function '__vector_39':
arduino-1.8.10/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:447:49: warning: this statement may fall through [-Wimplicit-fallthrough=]
twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
^
arduino-1.8.10/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:448:5: note: here
case TW_MR_SLA_ACK: // address sent, ack received
^~~~
arduino-1.8.10/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:529:9: warning: this statement may fall through [-Wimplicit-fallthrough=]
if(0 == twi_txBufferLength){
^
arduino-1.8.10/hardware/arduino/avr/libraries/Wire/src/utility/twi.c:534:5: note: here
case TW_ST_DATA_ACK: // byte sent, ack returned
^~~~

dann schaltet man doch wieder ganz schnell die Compilerausgabe ab...

Peer

.. Noch als Nachtrag bevor jemand den Grund sucht: am I2C ist eine RTC dran.

(Wenn ich meinen Post editiere fehlt die Formatierungsanzeige - darum ohne hyperlink)

Hi

Naja - Das heißt 'Da ist kein break; drin'.
Kein Problem, mache ich auch.
Der Kompiler meldet ja auch nur, daß Das ein Problem sein kann.
Es ist halt möglich, in einem case einzuspringen, und zum Nächsten 'durchzufallen'.

Wenn man die Warnung ernst genommen, begutachtet und als unbegründet eingestuft hat, ist doch wieder Alles ok.
Wenn man die Warnung nicht gesehen hat und eben leider doch nicht 'zum nächsten case durch fallen wollte', sucht man halt länger - auch eine Lösung - dauert zwar länger, ist dann aber halt so.

MfG

my_xy_projekt:
dann schaltet man doch wieder ganz schnell die Compilerausgabe ab...

Au weia.

Wer auch nur einigermaßen etwas auf Codequalität gibt, beachtet alle Fehlermeldungen und Warnungen und schraubt so lange am Code, bis derlei nicht mehr auftaucht.

Wenn es einem nichts ausmacht, für den Müll zu arbeiten, kann man es natürlich auch machen wie Du.

Gruß

Gregor

... auch konnte man (irgendwie) die fallthrough auch abschalten oder Bereiche einstellen, wo Diese nicht angemeckert werden (da Diese von Einem selber so gewünscht sind) ...
Ich meine, combie hatte die Lösung dazu irgend wo hier mal gepostet, gab Da wohl zwei Schreibweisen, wovon nur noch Eine gültig ist.

Zumindest in den MoBaTools hat unser microbahner
[[fallthrough]]; // supress warning
verwendet - scheint dann die korrekte Schreibweise zu sein.
Man müsste sich anschauen, in welchen Bereichen Das wirkt.

postmaster-ino:
... auch konnte man (irgendwie) die fallthrough auch abschalten oder Bereiche einstellen, wo Diese nicht angemeckert werden (da Diese von Einem selber so gewünscht sind) ...

[[fallthrough]] gibt es seit C++17
https://en.cppreference.com/w/cpp/language/attributes/fallthrough

Ist hier allerdings irrelevant, da das nicht in diesem Fall gewünscht ist. Er wird sicher korrekt abbrechen, nur dem Compiler passt es es nicht so recht

Danke an alle, die hier auf den Hinweis eingestiegen sind.

@Gregor
Wenn es einem nichts ausmacht, für den Müll zu arbeiten, kann man es natürlich auch machen wie Du.

Schade, das Du Dir so ein vorurteilbehaftetes Bild von mir gemacht hast.

Damit bin ich raus. Die Wanne ruft. Und nachdem mir der DSLer hier zum xten Mal abge... ist und die Formatierungsleiste nicht mehr wieder kommt, solls heute nicht sein.

An alle trotzdem und gerade darum: Danke fürs Feedback
Grüße

Peer

Ich meine, combie hatte die Lösung dazu irgend wo hier mal gepostet, gab Da wohl zwei Schreibweisen,

3 Varianten...

[[fallthrough]] gibt es seit C++17

Gcc wertet schon seit einiger Zeit Kommentare aus.

Statt [[fallthrough]] ein /* fall through */ vermeidet auch diese Warnung

Und dann gibts da noch das Gcc spezifische Attribut attribute((fallthrough))

Man kann beim GCC auch gezielt Warnungen unterdrücken, wenn die einem gerada mal 'im Wege' stehen:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
...
...
#pragma GCC diagnostic pop

Gerade wenn man Code für verschiedene Plattformen erstellt, kann das im Einzelfall einfacher sein, als eine weitere #ifdef Ebene einzuführen.

combie:
Statt [[fallthrough]] ein /* fall through */ vermeidet auch diese Warnung

Hatte ich auch zuerst nur so. Hat aber nicht immer bei allen Plattformen zuverlässig funktioniert. Deshalb habe ich wieder das 'offizielle' [[fallthrough]] reingesetzt.

Edit:

postmaster-ino:
müsste sich anschauen, in welchen Bereichen Das wirkt.

Das wirkt genau da wo es steht. Wenns für einen ganzen Bereich gelten soll, muss man die #pragma Variante nutzen.

my_xy_projekt:
Das mag für diesen State gültig sein, aber wenn Compiler-Warnungen schon allein aus den integrierten Funktionen herrühren,
dann schaltet man doch wieder ganz schnell die Compilerausgabe ab...

Nein!

Auf sowas kann man nur kommen, wenn man die Schuld lieber bei anderen sucht, als selber Verantwortung zu übernehmen.

Wie ich solche Probleme angehe, kann ich dir gerne zeigen:
Hier wird genau das Thema abgehandelt.
Die Korrektur ist in den Arduino Core übernommen worden, steht also in Kürze JEDEM Arduino Nutzer weltweit, zur Verführung.

Zusammenfassung:
Das abschalten der Warnungen ist ein zuverlässiges Mittel, sich selber Knüppel zwischen die Beine zu werfen. Das im Forum dann auch zu propagieren geht gegen unsere Linie.

Wie soll denn jemand seine Programmierkenntnisse verbessern, wenn er die Augen verschließt und auftauchende Warnungen ignoriert?

Anstelle MicroBahners

#pragma GCC diagnostic ignored "-Wunused-parameter"

würde ich das eher so lösen:

void foo(int param); // Deklaration einer Funktion mit Parameter ( macht Arduino IDE für uns )

void setup() {
    Serial.begin(9600);
    foo(1234);  // Aufruf der Funktion
}

void foo (int) {
   // Die Funktion hat zwar einen Parameter, der wird aber nicht gebraucht
   // Wir lassen den Variablennamen hinter dem Datentyp weg
   // und kriegen so keine Warnung wegen "unused parameter" 
   Serial.println("foo");
}

Combie hat Recht: Warnungen soll man nicht ignorieren.
Und wenn Libraries Warnungen erzeugen, zeigt einem dies, dass man auf einem toten ungepflegten Pferd reitet.

Alternativ, für Kompiler, welche das weglassen des Bezeichners nicht mögen:

void foo (int wert) 
{
  (void)wert;
   // Die Funktion hat zwar einen Parameter, der wird aber nicht gebraucht
   // und kriegen so keine Warnung wegen "unused parameter"
   Serial.println("foo");
}

Sollte mit allen C und C++ Kompilern der letzten 30 Jahre funktionieren.