Problem Switch-Case

Danke für die Antwort.

Ich habe mir durch die Ausgabe mal die Integer-Ausgabe, als auch das Zeichen an sich (char) ausgeben lassen. Die passen soweit.

Er wiederholt automatisch den Switch... Obwohl ich durch "break" beende. Im Anhang ist mal ein Bild von der Ausgabe.

Unbenannt.GIF

Hi

Wäre PDF oder gar ein exotisches Format hier nicht noch unsinniger?
Du hast Da einen TEXT ... was ist so schwer daran, den Text zu markieren und hier - ALS TEXT - einzufügen?

MfG

Diesen TEXT bitte auch in Codetags.

Gruß Tommy

Hallo,

d.h Dein Problem ist nicht Switch case sondern If ELSE ?

Heinz

Du schreibst Dir deinen Speicher kaputt. Offensichtlich überschreibst Du was im Speicher der seriellen Schnittstelle, denn dein 'a' wird mehrfach gelesen.

Verwende sprechende Namen für die Variablen und kommentiere deinen Sketch, und zwar so dass Du beschreibst, was das jeweilige Codesegment tun soll ( kommentiere die Semantik, und nicht die Syntax). Vielleicht findest Du dann solche verqueren Fehler schon durch das Nachdenken, was Du als Kommentar da hinschreiben sollst.

Hier:

        // WEICHENLAGE_UEBERPRUEFEN_EINSTELLEN_VERSCHLIEßEN
          int Weichen_r[4] = {28, 30, 33, 35};
          int Weichen_f[4] = {29, 31, 32, 34};
          for (int i = 0; i <= 3; i++)
          {
            Weichen_stellen(4, Weichen_r[i], Weichen_f[i]);
          } // Ende "for (int i = 0; i <= 3; i++)"

rufst Du dein Weichen_stellen() mit Parameterwerten auf, die überhaupt nicht zu der Funktion passen. Ich nehme mal an, das sollen Pin-Nummern sein. In der Funktion verwendest Du sie aber als Indizes in deinem Array 'weichen':

void Weichen_stellen(int k, int j, int h)
{
  for (int i = 0; i <= k - 1; i++)
  {
    if (Weichen[j] = LOW)  // <- das ist eine Zuweisung, und keine Abfrage
    {
      digitalWrite(Weichen[j], HIGH);
    } // Ende "if (Weichen[j] == LOW)"

    else
    {
      digitalWrite(Weichen[h], LOW);
      digitalWrite(Weichen[j], HIGH);
    } // Ende "else"

  } // Ende "for (int i = 0; i <= k-1; i++)"

} // Ende "void Weichen_stellen(int i = 0; i <= k; i++)"

Dein Array Weichen hat nur 4 Elemente, aber Du übergibst viel höhere Zahlen als Parameter. Mit der markierten Zeile schreibst Du dann auch noch irgendwo in den Speicher rein.
Wenn Du vernünftige Variablennamen verwendest, merkst Du evtl. eher, dass Du Werte übergibst, die nicht den erwarteten Variableninhalten entsprechen.

Und deine while-Schleife ist überflüssig, loop() ist bereits eine Schleife.

P.S. Es macht auch überhaupt keinen Sinn, solche Konstante wie Pinnummern mitten im Code zu definieren. Das gehört ganz an den Anfang, und sinnvollerweise noch mit dem Schlüsselwort 'const'. Dann würdest Du auch merken, dass Du Überschneidungen bei den Pin-Nummern für die Weichen und die Leds hast. Pin1 ( und auch 0) solltest Du garnicht verwenden, der wird für die serielle Schnittstele gebraucht.

Hallo,

erstmal danke für die Antworten. Ich habe nochmal drüber geguckt und dort sind mir auch teils ein paar Fehler aufgefallen, welche ich aber beseitigt haben sollte. Anbei der Quellcode als PDF.

Das Problem mit dem Auskommentieren der "Weichenfreimeldung()" im zweiten Switch konnte ich beheben.

Zur besseren Übersicht habe ich den jetzt mal entfernt. Folgendes Problem tritt nun auf. Nach der Durchführung des Switch 'a' springt er sofort in 'default'. Jemand Ideen warum das so sein könnte?

//// DEFINIERUNG DER VARIABLEN
// Pinbelegung
const int LEDS [30] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,    // Pinbelegung am Arduino
                       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31     // Pinbelegung am Arduino
                      };

// Weichen
int Status_Weichen [4] = {0, 0, 0, 0};

// Gleisfreimeldeabschnitte
int Status_Gleis1 [9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
int Status_Gleis2 [3] = {0, 0, 0};

// Rest
char State = ' ';
int Gleis_1_Frei = 0;
int Gleis_1_Besetzt = 0;
int Gleis_2_Frei = 0;
int Gleis_2_Besetzt = 0;
int W_Frei = 0;
int W_Besetzt = 0;


//// UNTERPROGRAMME
//void Start()
void Start()
{
  Serial.println("Bitte geben Sie die Fahrstraße ein!");
} // Ende "void  Start()"


// void Grundstellung()
void Grundstellung()
{
  for (int i = 0; i <= 29; i++)
  {
    digitalWrite(LEDS[i], LOW);   // alles LEDs Status "LOW"
  } // Ende "for (int i = 0; i <= 29; i++)"

  digitalWrite(LEDS[1], HIGH);
  digitalWrite(LEDS[3], HIGH);
  digitalWrite(LEDS[7], HIGH);
  digitalWrite(LEDS[9], HIGH);
  digitalWrite(LEDS[12], HIGH);
  digitalWrite(LEDS[14], HIGH);
  digitalWrite(LEDS[18], HIGH);
  digitalWrite(LEDS[20], HIGH);

  for (int i = 0; i <= 3; i++)
  {
    Status_Weichen[i] = 0;
  } // Ende "for (int i = 0; i <= 3; i++)"

  for (int i = 0; i <= 8; i++)
  {
    Status_Gleis1[i] = 0;
  } // Ende "for (int i = 0; i <= 8; i++)"

  for (int i = 0; i <= 2; i++)
  {
    Status_Gleis2[i] = 0;
  } // Ende "for (int i = 0; i <= 2; i++)"

} // Ende "void Grundstellung()"


// void Blinken()
void Blinken(int k)
{
  int off = 500;    // Definierung Integer-Variable "off" (Wert: 500 "ms")
  int on = 500;     // Definierung Integer-Variable "on" (Wert: 500 "ms")

  int blinkPhase = millis() % (off + on);   // Definierung Integer-Variable "blinkPhase" als Rest aus Division

  for (int i = 1; i <= 20; i++)   // fuere 20 mal aus (10x aus & 10x an -> ca. 10s)
  {
    if (blinkPhase < off)   // wenn Variable kleiner als 500 "ms"
    {
      digitalWrite(k, LOW);   // setze Zustand der LED auf "LOW"
    } // Ende "if (blinkPhase < off)"

    else    // Variable "blinkPhase" groeßer als 500 "ms"
    {
      digitalWrite(k, HIGH);    // setze Zustand der LED auf "HIGH"
    } // Ende "else"

  } // Ende "for (int i = 1; i <= 20; i++)"

} // Ende "void Blinken()"


// void LEDs_on()
void LEDs_on(int k, int j)
{
  for (int i = 0; i <= k - 1; i++)
  {
    digitalWrite(LEDS[j], HIGH); 
  } // Ende "for (int i = 0; i <= k-1; i++)"

} // Ende "void LEDs_on()"


// Weichen_stellen()
void Weichen_stellen(int k, int j, int h)
{
  for (int i = 0; i <= k - 1; i++)
  {
    if (LEDS[j] == LOW)
    {
      digitalWrite(LEDS[j], HIGH);    // setze Zustand LEDS[j] zu "HIGH"
      digitalWrite(LEDS[h], LOW);     // setze Zustand LEDS[h] zu "HIGH"
    } // Ende "if (LEDS[j] == LOW)"

  } // Ende "for (int i = 0; i <= k-1; i++)"

} // Ende "void Weichen_stellen(int i = 0; i <= k; i++)"


// void Gleisfreimeldung_1()
void Gleisfreimeldung_1(int j, int k)
{
  for (int i = j; i <= k; i++)
  {
    if (Status_Gleis1[i] == 0)
    {
      Gleis_1_Frei = Gleis_1_Frei + 1;
    } // Ende "if (Status_Gleis1[i] == 0)"

    else
    {
      Gleis_1_Besetzt = Gleis_1_Besetzt + 1;
    } // Ende "else"

  } // Ende "for (int i = j; i <= k; i++)"

} // Ende "void Gleisfreimeldung_1(int j, int k)"


// void Gleisfreimeldung_2()
void Gleisfreimeldung_2(int j, int k)
{
  for (int i = j; i <= k; i++)
  {
    if (Status_Gleis2[i] == 0)
    {
      Gleis_2_Frei = Gleis_2_Frei + 1;
    } // Ende "if (Status_Gleis2[i] == 0)"

    else
    {
      Gleis_2_Besetzt = Gleis_2_Besetzt + 1;
    } // Ende "else"

  } // Ende "for (int i = j; i <= k; i++)

} // Ende "void Gleisfreimeldung_2(int j, int k)"


// void Weichenfreimeldung()
void Weichenfreimeldung(int j, int k)
{
  for (int i = j; i <= k; i++)
  {
    if (Status_Weichen[i] == 0)
    {
      W_Frei = W_Frei + 1;
    } // Ende "if (Status_Weichen[i] == 0)"

    else
    {
      W_Besetzt = W_Besetzt + 1;
    } // Ende "else"

  } // Ende "for (int i = j; i <= k; i++)"

} // Ende "void Weichenfreimeldung()"




//// VOID SETUP()
void setup()
{
  // Serielle Verbindung
  Serial.begin(9600);

  // Unterprogramm oeffnen
  Start();

  // Definierung der LEDs als Ausgang
  for (int i = 0; i <= 29; i++)
  {
    pinMode(LEDS[i], OUTPUT);
  } // Ende "for (int i = 0; i <= 35; i++)"

  Grundstellung();

} // Ende "void setup()"




//// VOID LOOP()
void loop()
{
  if (Serial.available() > 0)
  {
    State = Serial.read();
    switch (State)
    {
      // FAHSTRAßE_13A.(13N1)_MIT_D1

      case 'a':

        // GLEISFREIMELDEPRUEFUNG
        Gleisfreimeldung_1(0, 7);

        // WEICHENFREIMELDEPRUEFUNG
        Weichenfreimeldung(0, 3);

        // EINSTELLUNG_DER_FAHRSTRAßE
        if ((Gleis_1_Frei == 8) && (W_Frei == 4))
        {
          // WEICHENLAGE_UEBERPRUEFEN_EINSTELLEN_VERSCHLIEßEN
          int Weichen_r[4] = {22, 24, 27, 29};
          int Weichen_f[4] = {23, 25, 26, 28};
          for (int i = 0; i <= 3; i++)
          {
            Weichen_stellen(4, Weichen_r[i], Weichen_f[i]);
          } // Ende "for (int i = 0; i <= 3; i++)"

          for (int i = 0; i <= 3; i++)
          {
            Status_Weichen[i] = 1;
          } // Ende "for (int i = 0; i <= 3; i++)"

          // GLEISABSCHNITTE_BESETZEN
          for (int i = 0; i <= 7; i++)
          {
            Status_Gleis1[i] = 1;
          } // Ende "for (int i = 0; i <= 7; i++)"

          // SIGNALISIERUNG_EINSTELLEN
          int benoetigte_LEDS[3] = {0, 5, 7};
          for (int i = 0; i <= 2; i++)
          {
            LEDs_on(3, benoetigte_LEDS[i]);
          } // Ende "for (int i = 0; i <= 2; i++)"

          // FAHRSTRAßE_EINGESTELLT
          Serial.println("13A.(13N1) mit D1");

          // WARTEN_BIS_FAHRSTRAßENAUFLOESUNG
          delay(10000);   // 10s warten

          // GRUNDSTELLUNG_DER_SIGNALE
          digitalWrite(LEDS[0], LOW); digitalWrite(LEDS[1], HIGH);
          digitalWrite(LEDS[5], LOW); digitalWrite(LEDS[3], HIGH);

          // GLEISABSCHNITTE_FREI_MELDEN
          for (int i = 0; i <= 7; i++)
          {
            Status_Gleis1[i] = 0;
          } // Ende "for (int i = 0; i <= 7; i++)"

          // ZIELGLEISABSCHNITT_BESETZEN
          Status_Gleis1[4] = 1;

          //***** WEICHENVERSCHLUSS_AUFHEBEN
          Status_Weichen[0] = 0;
          Status_Weichen[1] = 0;
          Status_Weichen[2] = 0;
          Status_Weichen[3] = 0;

          // MELDUNG_FAHRSTRAßE_AUFGELOEST
          Serial.println("Fahrstraße aufgelöst!");

        } // Ende "if ((Gleis_1_Frei == 8)&&(W_Frei == 4))"

        else
        {
          Serial.println("Gleis besetzt");
        } // Ende "else"


        Gleis_1_Frei = 0; Gleis_1_Besetzt = 0;
        Gleis_2_Frei = 0; Gleis_2_Besetzt = 0;
        W_Frei = 0; W_Besetzt = 0;
        State = ' ';
        break;


      default:
        Serial.println("Fehler");
        Gleis_1_Frei = 0; Gleis_1_Besetzt = 0;
        Gleis_2_Frei = 0; Gleis_2_Besetzt = 0;
        W_Frei = 0; W_Besetzt = 0;
        State = ' ';
        break;

    } // Ende "switch (State)"

  } // Ende "if (Serial.available() > 0)"

} // Ende "void loop()"

Danke für die Hilfe!

Liebe Grüße

Sebastian

Quellcode.pdf (59.3 KB)

Warum hängst Du den Quelltext nicht als Zip ran? Hast Du Dir Dein PDF mal selbst angeschaut? Meinst Du das liest einer in dem schrecklichen Format?

Gruß Tommy

Tommy56:
Warum hängst Du den Quelltext nicht als Zip ran? Hast Du Dir Dein PDF mal selbst angeschaut? Meinst Du das liest einer in dem schrecklichen Format?

Gruß Tommy

Klar habe ich mir die angeschaut. Fand die Qualität eigentlich nicht schlecht. Hier halt nochmal als Zip.

Quellcode.zip (2.87 KB)

Nach der Durchführung des Switch 'a' springt er sofort in 'default'. Jemand Ideen warum das so sein könnte?

Am Ende von case 'a' ist state = ' ' .
Und das wird von default behandelt.
Oder hab ich was übersehen?

pdf und zip hab ich natürlich nicht angeschaut.

michael_x:
Am Ende von case 'a' ist state = ' ' .
Und das wird von default behandelt.
Oder hab ich was übersehen?

pdf und zip hab ich natürlich nicht angeschaut.

Habe State = ' ' mal auskommentiert. Geändert hat sich nichts. Muss ich nicht die Eingabe (indem Fall 'a') zurücksetzen für eine neue Eingabe?!

Muss ich nicht die Eingabe (indem Fall 'a') zurücksetzen für eine neue Eingabe?!

Nein. Der Sketch macht doch nur etwas, wenn Serial.available() was hat.
Und setzt dann state neu.

Kommt da evtl. ein newline oder so?

michael_x:
Nein. Der Sketch macht doch nur etwas, wenn Serial.available() was hat.
Und setzt dann state neu.

Kommt da evtl. ein newline oder so?

Ahh okay, ergibt Sinn!

Er schreibt "Fehler" halt in eine neue Zeile oder was meinst du mit "newline"?!

NL/CR
NewLine/CarrigeReturn
Steuerzeichen für 'neue Zeile' (0x0A) und 'Wagenrücklauf' (0x0D).
Kann man im Terminal angeben, welches Zeilenende gesendet werden soll - oder ob überhaupt ein Zeilenende kommen soll.
Früher hüstel war Das dafür da, daß der Drucker (LPT ... Line Printer) das Blatt eine Zeile hoch schob (new line) und den 'Wagen' an den Zeilenanfang zurück schon (Wagenrücklauf).
Und schon war man in der nächsten Zeile ganz links und konnte eine neue Zeile ausdrucken - so war Das früher Mal ... mit 9 Nadeln auf Papier rumkratzend schwarze Punkte zu Text und Grafik machen.

MfG

Wie gesagt, hab ich mir nur den Skech in #7 angeguckt, und wenn auf Serial mehr als nur ein einzelnes 'a' ankommt, und sei es nur ein kaum sichtbares neueZeile - Zeichen '\n' , wird auch der default - Zweig ausgeführt.

Er braucht sich doch einfach nur alle gelesenen Zeichen mal als HEX auszugeben, dann sieht er ja, was ankommt.

Gruß Tommy

Tommy56:
Er braucht sich doch einfach nur alle gelesenen Zeichen mal als HEX auszugeben, dann sieht er ja, was ankommt.

Gruß Tommy

Hab das jetzt mal ausgeben lassen, siehe Bild im Anhang.

Die ersten beiden Ausgaben von 'a' kann ich noch nachvollziehen. Danach scheitert es, weil ich nicht weiß, woher er nun die zwei "leeren" Eingaben und anschließend eine "10" (Dezimal) nimmt. Ich habe lediglich 'a' eingegeben.

Tommy meinte, Du sollst das in HEX ausgeben. Nur dann siehst Du, was da wirklich ankommt.
Füge mal unmittelbar hinter das Serial.Read diese print Anweisungen ein:

   State = Serial.read();
    Serial.print(">>> ");Serial.println(State,HEX);
    switch (State)

Dann bekommst Du etwa so eine Ausgabe:

Bitte geben Sie die Fahrstraße ein!
>>> 61
13A.(13N1) mit D1
Fahrstraße aufgelöst!
>>> D
Fehler
>>> A
Fehler

Hex '61' ist dein eingegebenes 'a'.
Das Hex 'D' und Hex 'A' sind die oben schon angesprochenen 'Carriage Return' und 'New Line'. Die fügt der serielle Monitor automatisch an deine Eingaben an. Im seriellen Monitor unten in dem dropDown Menü links neben der Baudrate kannst Du das abschalten ( 'Kein Zeilenende' )

Alternative wäre, diese Zeichen explizit zu behandeln (nichts tun), und nicht als Fehler zu sehen. Dann bist Du von der Einstellung im seriellen Monitor unabhängig.

P.S. Texte bitte immer hier als Text (in code-Tags) einstellen, und nicht als Bild.

MicroBahner:
Tommy meinte, Du sollst das in HEX ausgeben. Nur dann siehst Du, was da wirklich ankommt.
Füge mal unmittelbar hinter das Serial.Read diese print Anweisungen ein:

   State = Serial.read();

Serial.print(">>> ");Serial.println(State,HEX);
    switch (State)




Dann bekommst Du etwa so eine Ausgabe:


Bitte geben Sie die Fahrstraße ein!

61
13A.(13N1) mit D1
Fahrstraße aufgelöst!
D
Fehler
A
Fehler



Hex '61' ist dein eingegebenes 'a'.
Das Hex 'D' und Hex 'A' sind die oben schon angesprochenen 'Carriage Return' und 'New Line'. Die fügt der serielle Monitor automatisch an deine Eingaben an. Im seriellen Monitor unten in dem dropDown Menü links neben der Baudrate kannst Du das abschalten ( 'Kein Zeilenende' )

Alternative wäre, diese Zeichen explizit zu behandeln (nichts tun), und nicht als Fehler zu sehen. Dann bist Du von der Einstellung im seriellen Monitor unabhängig.

P.S. Texte bitte immer hier als Text (in code-Tags) einstellen, und nicht als Bild.

Danke, das hat geholfen! Wie wäre denn ein möglicher Ansatz um die Eingabe unabhängig von der Einstellung im DropDown-Menü zu realisieren?

   case 0xa:
   case 0xd:
     // nichts tun
     break;

    default:    // wenn keine Uebereinstimmung mit "State"  <--- Dein Default

Gruß Tommy