Switch Case spielt nur ersten Case ab

Guten Tag an die Gemeinde,
habe einen Sketch zum Steuern von Motoren, dabei wird eine Message geprüft und in eine Zahl umgewandelt, die Zahl entspricht dann dem Case. Es wird immer der erste Case in der Schleife abgespielt, egal wie er heißt. Also wenn case 1 am Anfang steht, dann wird nur case 1 abgespielt, wenn die Message 4 sendet, dann wird case 4 nicht abgespielt.

Wenn ich hingegen zB Case 3 an den Anfang der Schleife setze, wird case 3 abgespielt wenn die Message 3 sendet, alle anderen Cases werden wieder nicht abgespielt. Ich sehe leider die Ursache nicht - liegt es am break? liegt es am void Message?

Am seriellen Monitor wird BtnValue für jeden Case richtig ausgegeben.
Es handelt sich um einen Arduino Mega, an dem hängt ein ESP8266 der über eine Webseite das BtnValue sendet.

#include <Servo.h>

int in1 = 30;
int in2 = 31;
int in3 = 32;
int in4 = 33;
int in5 = 34;
int in6 = 35;

Servo myservo;
int pos = 0;

int BtnValue = 0;
long Speed = 90;
long Height, Width, Diagonale, HalfWidth, HalfHeight, HalfDiagonale;
long /*Bewegung*/ links, rechts, oben, unten;
String message = "";

void setup() {
  pinMode(in1, OUTPUT);    
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);    
  pinMode(in4, OUTPUT);
  pinMode(in5, OUTPUT);    
  pinMode(in6, OUTPUT);
  myservo.attach(10);
  Serial.begin(115200);
  while (!Serial) {
  }
}

void StopAllMotors() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(in5, LOW);
  digitalWrite(in6, LOW);
}

void Message() {
  if (message.substring(0, 9) == "BtnValue:") {
    String Split = message.substring(9);
    BtnValue = Split.toInt();
    Serial.println(BtnValue);
    links = Width * 100;
    rechts = Width * 100;
    oben = Height * 100;
    unten = Height * 100;
  }

  if (message.substring(0, 1) == "Q") {
    int PointPosition = message.indexOf(':');
    String messageA = message.substring(1, PointPosition);
    //Serial.println(String(messageA));
    String messageB = message.substring((PointPosition + 1));
    //Serial.println(String(messageB));
    Width = messageA.toInt();
    Height = messageB.toInt();
    Serial.println(Width);
    Serial.println(Height);
  }
}

void loop() { // run over and over
  if (Serial.available()) {
    message = Serial.readString();
    message.trim();
    Serial.println(message);
    Message();
  }
  Motors();
}

void Motors() {
  switch (BtnValue) {
    case 1: //FRONT
      Serial.println("Up");
      StopAllMotors();
        digitalWrite(in1, LOW);  // Motor 1 beginnt zu rotieren
        digitalWrite(in2, HIGH);
        delay(20);
     break;

    case 2: //BACK
      Serial.println("Down");
      StopAllMotors();
        digitalWrite(in2, LOW);  // Motor 1 beginnt zu rotieren
        digitalWrite(in1, HIGH);
        delay(20);
      break;

    case 3://Left
      Serial.println("Left");
      StopAllMotors();
        digitalWrite(in3, LOW);  // Motor 2 beginnt zu rotieren
        digitalWrite(in4, HIGH);
        delay(20);
      break;

    case 4://Right
       Serial.println("Right");
       StopAllMotors();
        digitalWrite(in4, LOW);  // Motor 2 beginnt zu rotieren
        digitalWrite(in3, HIGH);
        delay(20);
      break;

    case 5: //Stop
    Serial.println("Stopp");
      StopAllMotors();
      BtnValue = 0;
      break;

    case 9://Dc links
    Serial.println("Rein");
      StopAllMotors();
      digitalWrite(in5, HIGH);  // Motor 3 beginnt zu rotieren
      digitalWrite(in6, LOW);
      delay (20);
      //Motors();
      break;
      
    case 10://dc rechts
    Serial.println("Raus");
      StopAllMotors();
      digitalWrite(in5, LOW);  // Motor 3 beginnt zu rotieren
      digitalWrite(in6, HIGH);
      delay (20);
      break;
 

    case 11://Servo left
    Serial.println("Servo links");
      StopAllMotors();
      pos -= 1;
      myservo.write(pos);
      break;
    
    case 12://Servo right
    Serial.println("Servo rechts");
      StopAllMotors();
      pos += 1;
      myservo.write(pos);
      break;
  }
}

Auch, wenn du in Motors() springst?

Nur mit Mega2560 und manueller Eingabe am seriellen Monitor kann ich keinen Fehler entdecken. Ich würde daher den Fehler an anderer Stelle vermuten.

Hallo Paul, weiß leider nicht genau was du meinst... Sobald ich auf der Webseite eine Taste anklicke, zeigt der Serielle Monitor die dazugehörige Zahl, also 1 oder 3 oder 4
Im Falle 1 wird dann auch der case 1 von Motors() abgespielt, am seriellen Monitor erscheint dann "Up"
Im Falle 2 oder sonstetwas wird nichts abgespielt

Dann schau dir doch die Variable mal als Hex-Wert an.
Da stecken sicher noch Steuerzeichen drin.

Hallo,
nutzt Du als Schnittstelle zum ESP tatsächlich die selbe wie für den Monitor , das wird so Probleme geben. Der Mega hat doch mehrere Schnittstellen dann nutze die Doch auch.
Heinz

@HotSystems ich dachte, dass durch diese Zeile sichergestellt wird, dass nur die Zahl ankommt. Habe aber etwas recherchiert und werde das heute Abend austesten.
BtnValue = Split.toInt();
@agmue finde ich schon mal gut :slight_smile: auf welchen Fährten soll ich suchen?
@Rentner damit habe ich mich noch gar nicht befasst, habe leider gleich fürs erste ein ambitioniertes Projekt angefangen. Gemeint ist sicher, dass Serial.begin(115200); nur einmal definiert ist und aktuell darüber sowohl das Kommando ausgelesen wird, als auch die Darstellung auf den seriellen Monitor erfolgt?

Mein ESP32 sendet "BtnValue:1" und so weiter, der Mega2560 empfängt und wertet aus, das funktioniert.

Daher vermute ich wie @HotSystems, daß andere Inhalte übertragen werden, wie Du vermutest.

Eine Nutzung einer weiteren seriellen Schnittstelle erscheint zwar nicht zwingend, könnte aber Datenmüll vorbeugen.

"Up" sollte alle 20 ms wiederholt werden, also ca. 50 Zeilen pro Sekunde ausgeben.
Wenn's das täte, hättest du es sicher schon geändert, also vermute ich, dass da was anders ist als in deinem hier veröffentlichten Sketch. (Oder ich hab was falsch gesehen, dann ignoriere diesen verwirrenden Beitrag)

Sobald ich auf der Webseite eine Taste anklicke, zeigt der Serielle Monitor die dazugehörige Zahl.

Welche Webseite? Wenn der Serielle Monitor mit Serial verbunden ist, kannst du auch nur dort einen Text wie dein "BtnValue:4" eingeben.

Ich tippe mal drauf, dein Problem und der gezeigte Sketch sind unterschiedlich.

Hm, das habe ich jetzt folgendermaßen mal gemacht:

void Message() {
  if (message.substring(0, 9) == "BtnValue:") {
    String Split = message.substring(9);
    BtnValue = Split.toInt();
    Serial.println(BtnValue);
    Serial.println(BtnValue,HEX);
    links = Width * 100;
    rechts = Width * 100;
    oben = Height * 100;
    unten = Height * 100;

der rest wie gehabt. Ausgabe ist dann bei einstelligen Zahlen korrekt, bei zweistelligen kommt ein Buchstabe:
19:27:26.223 -> 4
19:27:26.223 -> 4
19:27:30.235 -> 3
19:27:30.235 -> 3
19:27:32.464 -> 11
19:27:32.501 -> B
19:27:45.778 -> 12
19:27:45.778 -> C

Es liegt also etwas im Argen, aber heißt das konkret, dass einstellige Values richtig sind und zweistellige nicht? Warum springen die Cases 2-9 dennoch nicht an?
@michael_x "Up" kommt tatsächlich öfter :slight_smile: das war Absicht um den laufenden Case zu identifizieren. Also Up kommt, leider aber Down und die anderen nicht. Zu Webseite habe ich den Aufbau am Anfang geschrieben. Der NodeMCU ist im lokalen WLAN über eine Webseite erreichbar und dort sitzt die Steuerung die BtnValues versendet.

Wen wunderts?
11 ist halt identisch mit 0x0B

Du schreibst das doch so - die Ausgabe stimmt mit dem zu erwartendem Ergebnis überein.

Hast Du Dir mal Gedanken gemacht, was Du z.B. hier gebaut hast:

 case 1: //FRONT
      Serial.println("Up");
      StopAllMotors();
        digitalWrite(in1, LOW);  // Motor 1 beginnt zu rotieren

Das läuft deinem Konstrukt vollkommen zuwider.

Wenn Du 1 übergibts -> beim ersten Durchlauf stoppst Du alles und fährst wieder an - beim nächsten Durchlauf versuchst Du das wieder. Da hat sich BtnValue nicht verändert.
Was denkst Du, wie oft pro Sekunde Du diesen Case durchläuft?

Meine Ausgbae auf dem SerMon sah teilweise auch eigenartig aus.
Mal kam ein nicht druckbares Zeichen mit, mal kein Zeilenumbruch.

Das switch case würde ich anders bauen.

Jetzt dämmerts mir auch, ich habe das missverstanden mit dem HEX.

Ich verstehe Deine Kritik an der Motorsteuerung, die soll aber gar nicht Thema sein. Ich kann da auch eine Servo-Funktion an erster Stelle setzten, oder eine Stepper-Bewegung, die funktionieren dann. Es geht also(in meinem Verständnis) nicht um den Code im Case, sondern der drum herum. Alle, außer dem der Reihe nach Erstem, werden gar nicht erst aufgerufen.

Ich habe übrigens die Cases isoliert an Schalter gelegt und die Schalter einen nach dem anderen aktiviert, die Codes haben funktioniert. Die Schleife geht nicht.

Die Schleife geht.
Deine Auswertung tut nicht was Du willst.

Und ja, die Codes haben wohl das case ausgelöst, aber nochmal: Du fährst bei jedem Durchgang stop - start.

Ersetze:

void StopAllMotors()
{
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(in5, LOW);
  digitalWrite(in6, LOW);
  Serial.println("Alle aus");
}

Doch auch.
Das ist Code, der da nicht hingehört.
Wenn Du das so willst, ist es Deine Entscheidung.
Der Code ist aber nicht zielführend.

Nachtrag:
Wie sieht denn die Übergabe aus?
Kommt der "String" als zeichenfolge oder mit einem NewLine oder CarrigeReturn? oder beides? Oder Keines?

Guten Abend, ich muss etwas richtigstellen - wie @michael_x bereits vermutet hat, ist der Code im Case ein anderer gewesen als hier präsentiert, viel komplexer und für einen anderen Anwendungsfall. Und wie der Teufel so will, lag es genau an dem code. Insofern war schon die Fragestellung etwas irreführend, um so bewundernswerter euere Antworten und den richtigen Riecher der Profis :slight_smile: Ich war mir(als Laie) natürlich sicher, dass es nicht an diesem Code liegen kann und hielt es nicht für nötig diesen auf den Prüfstand zu stellen.

Es lag an Folgendem: Der Code im Case war wohl fehlerhaft, es waren mathematische Berechnungen. Den Case 1 hat das System noch gemacht und wohl da bereits (laienhaft gesagt) zusammengebrochen. Zu Case 2 kam es nicht mehr. Über eine if-else Schleife bin ich dem Ganzen dann auf die Schliche gekommen. Die If Regel war einfach und richtig, insofern hat er sie ausführen können. Die else Regel hat er nicht gemacht. Nun ist das Ganze so gelöst worden, dass die jeder Case seine eigene Funktion aufruft. Also die Funktionen sind vorher definiert, im Case wird nur darauf verwiesen.

Danke an Alle und sorry für die Verwirrung.

1 Like

Es liegt immer an an dem was verheimlicht wird.

Danke für die ehrliche Rückmeldung :slightly_smiling_face:

Auch von mir ein Danke für die Ehrlichkeit.

Ungeachtet dessen würde mich der "richtige" Sketch interessieren.
Vielleicht fällt ja doch noch was ab :wink:

Ich vermute sehr stark, dass es an neuen Variablen lag. Hier ein Case, die anderen Cases sind dann das selbe, nur in andere Richtungen. Während oben+unten bereits vorher definiert waren, tauchen upBEFORE, upAFTER, upSTEP nur in diesem Case auf.
Mittlerweile befasse ich mich aber mit der AccelStepper.h, so dass der Code ganz anders wird.

void Motors() {
  
  switch (BtnValue) {
    case 1: //Up
        //Serial.println("UP");
        float upBEFORE = sqrt((oben * oben) + (links * links));
        oben -= 10;
        unten += 10;
        float upAFTER = sqrt((oben * oben) + (links * links));
        long upSTEP = upBEFORE - upAFTER;
        upStepper.step(upSTEP);
        delay(20);
     break;