Forum: Mikrocontroller und Digitale Elektronik Prozessor bleibt bei case switching hängen


von Laurin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Ich habe ein Problem mit einem Roboter. Er läuft jeweils ein paar 
Sekunden gut (macht das, was ich per Joystick vorgebe), dann bleibt er 
jeweils plötzlich in einem case hängen. Das heisst die zwei Motoren 
laufen kontinuierlich, auch noch wenn ich den Sender ausschalte. Ich 
kann dann jeweils nur den Reset drücken oder einen power down machen. 
Die Motoren habe ich bereits mit je drei 100nF Kondensatoren bestückt - 
ohne Erfolg. Auch die Commands habe ich mit dem Serial Monitor 
(Serial.print(cmd)) empängerseitig überprüft. Es kommen genau die 
characters an, die ich schicke.

Auf der Empfängerseite: Arduino Uno mit dem Motortreiber Pololu VNH5019, 
zwei DC-Motoren und HC-12 RF-Modul. Stromversorgung: 11.1 Volt Lipo

Sender: Arduino Mini Pro, X/Y Joystick, HC-12 RF-Modul. Stromversorgung: 
4 x 1.5 Volt AAA

Danke für Eure Hilfe!

von Wolfgang (Gast)


Lesenswert?

Laurin schrieb:
> ... dann bleibt er jeweils plötzlich in einem case hängen.

Und das wäre welcher?

von Laurin (Gast)


Lesenswert?

Kein bestimmter. Ist immer mal wieder ein anderer case.

von Dieter F. (Gast)


Lesenswert?

Laurin schrieb:
> Kein bestimmter. Ist immer mal wieder ein anderer case

Da wirkt manchmal ein "default:" im Switch-Case Wunder :-) (mit dem man 
z. B. die Motore abschaltet)

von Laurin (Gast)


Lesenswert?

Oh ok. Wie müsste denn ein case aussehen mit einem default? Die Lösung 
für mein Problem scheint ja sehr simpel zu sein. Sorry ich bin ein 
Neuling in Sachen Programmieren ;)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> Danke für Eure Hilfe!

 Ja, ein delay(0) ist für mich überaus sinnvoll und nützlich.

von Laurin (Gast)


Lesenswert?

Die delay steht noch dort, weil ich mit verschiedenen delay-zeiten 
experimentiert habe. Mir ist klar, dass delay(0) nix bewirkt

von (prx) A. K. (prx)


Lesenswert?

Laurin schrieb:
> Auch die Commands habe ich mit dem Serial Monitor
> (Serial.print(cmd)) empängerseitig überprüft.

Mit dem gezeigten Code?

von Laurin (Gast)


Lesenswert?

Ja mit dem Xode, den ich gepostet habe.

von (prx) A. K. (prx)


Lesenswert?

Laurin schrieb:
> dann bleibt er jeweils plötzlich in einem case hängen.

Woran erkennst du das?

von (prx) A. K. (prx)


Lesenswert?

Laurin schrieb:
> Ja mit dem Xode, den ich gepostet habe.

In allen mir bekannten Programmiersprachen dieses Aussehens ist das 
toter Code. Daher die Frage.

von Laurin (Gast)


Lesenswert?

Am Verhalten der Motoren. Sie verhalten sich in punkto Geschwindigkeit 
und Drehrichtung jeweils entsprechend einem case, zb. schnell vorwärts 
oder schnell rückwärts

von (prx) A. K. (prx)


Lesenswert?

Dass dieser Code im bisherigen Zustand verharrt, wenn nichts mehr kommt, 
überrascht mich jetzt nicht so.

von Laurin (Gast)


Lesenswert?

Ok. Der Original-Code stammt nicht von mir sondern von instructables.com

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

1
    switch (cmd)
2
    {
3
      ...
4
        break;
5
      Serial.print(cmd);
6
    }

Das Serial.print(cmd) ist toter Code und wird nie ausgeführt. 
Vielleicht verleitet dich ds zur inkorrekten Folgerung, der Code stürze 
ab.

von Laurin (Gast)


Lesenswert?

Was würdet Ihr nun vorschlagen. Den ganzen Code neu und ohne switch 
case?

von Ausbilder (Gast)


Lesenswert?

Es gibt noch mehr Möglichkeiten
a)
bluetooth.available() liefert beständig 0 zurück.

b)
bluetooth.read() kehrt nicht zurück.

Laurin schrieb:
> Was würdet Ihr nun vorschlagen.

Mehr prints einbauen um herauszufinden wo das Programm genau "hängt".
z.B. einen, wenn bluetooth.available() 0 liefert, und je einen vor und 
nach bluetooth.read()

von Joachim B. (jar)


Lesenswert?

Laurin schrieb:
> Was würdet Ihr nun vorschlagen.

nach dem letzten case

default:
cmd=0;
break;

und vorher

if(isprint(cmd))

oder (besser?)

if( (cmd >= 'A' && cmd < 'J') || (cmd >= '0' && cmd < '6') )


{
switch (cmd)

und auf jeden Fall wenn nichts davon stimmt

im default: oder else

while(bluetooth.available()) bluetooth.read();

von Laurin (Gast)


Lesenswert?

Danke vielmals für deinen Input Joachim!

von Laurin (Gast)



Lesenswert?

Hallo Joachim

Habe erst folgendes, wie von Dir vorgeschlagen, nach den letzten Case 
eingebaut:

default:
cmd=0;
break;

Resultat: Die Motoren laufen nach dem power up, ohne dass ich Befehle 
gebe.

Dann:
if(isprint(cmd)) vor dem switch start

Resultat: Die Motoren bleiben nicht mehr hängen, drehen aber immer bei 
voller Geschwindigkeit, auch wenn ich ein slow speed Befehl gebe.

Der Code sieht jetzt so aus (siehe attachment)

von Laurin (Gast)


Lesenswert?

Stimmt leider nicht, sorry. Musste nach erneutem Aufstarten feststellen, 
dass die Motoren laufen gemäss den Befehlen. Leider bleiben sie immer 
noch hängen..

von Laurin (Gast)



Lesenswert?

Hier der Sketch mit beiden Änderungsvorschlägen von Joachim.

von Helmut H. (helmuth)


Lesenswert?

Dieter F. schrieb:

> Da wirkt manchmal ein "default:" im Switch-Case Wunder :-) (mit dem man
> z. B. die Motore abschaltet)
1
  default:
2
   md.setM1Speed(0); // stopped
3
   md.setM2Speed(0); // stopped
4
   break;

Das cmd=0 bringt hier nichts.

default ist auch üblicherweise die letzte Anweisung im switch, guckstdu 
https://www.arduino.cc/en/Reference/SwitchCase

von Dieter F. (Gast)


Lesenswert?

Helmut H. schrieb:
> default ist auch üblicherweise die letzte Anweisung im switch, guckstdu
> https://www.arduino.cc/en/Reference/SwitchCase

Nicht unbedingt - man muss "default:" schon angeben - von alleine wird 
das die letzte Anweisung im switch case nicht :-) (O.K. - böse ...).

Man muss sich das halt vor Augen führen. Der Compiler/Prozessor ist 
doof. Der Programmierer sagt: Wenn 1 dann A, Wenn 2 dann B, Wenn 3 dann 
C. Fertig.

Wenn 4, 5, 6, ... Sonstwas oder Unendlich kommt weiß der 
Compiler/Prozessor nicht was zu tun ist. Und was tut man im Normalfall: 
Nichts, man wartet auf den nächsten Befeht - und so lange macht man das, 
was zuletzt "befohlen" wurde ...
Man kann natürlich nach jeder Befehlsausührung den Befehl auf einen 
bestimmten "Default"-Wert setzen - aber das kann man sich halt durch die 
"default:"-Anweisung auch ersparen.

Aber die Suchbegriffe "Arduino" und "switch case" in Google helfen da 
ungemein - wenn man das da lesen mag. K. A., ob es entsprechende 
YouTube-Videos dazu gibt - das ist nicht so recht meine Generation.

Übrigens helfen C-Bücher (so etwas gab es mal / hat sich, glaube ich, in 
einigen Nischen auch noch gehalten) in dieser Beziehung auch weiter. Es 
gibt auch Kurse an der Volkshochschule etc. welche Grundlagen vermitteln 
- durchaus nicht zu verachten.

von Helmut H. (helmuth)


Lesenswert?

Dieter F. schrieb:

> Nicht unbedingt - man muss "default:" schon angeben - von alleine wird
> das die letzte Anweisung im switch case nicht :-) (O.K. - böse ...).
>

War sehr missverständlich von mir, gemeint war, dass es als letzte 
Selektion angegeben werden sollte und nicht - wie im Sketch - irgendwo 
mittendrin zwischen case 'I' und case '0'.

von Dieter F. (Gast)


Lesenswert?

Helmut H. schrieb:
> ar sehr missverständlich von mir, gemeint war, dass es als letzte
> Selektion angegeben werden sollte

Schon klar :-) - deswegen ja auch "böse" :-)

von Joachim B. (jar)


Lesenswert?

Helmut H. schrieb:
> Dieter F. schrieb:
>
1
>   default:
2
>    md.setM1Speed(0); // stopped
3
>    md.setM2Speed(0); // stopped
4
>    break;
5
>
>
> Das cmd=0 bringt hier nichts.

es schadet aber auch nichts und setzt das "ungültige" zurück

Laurin schrieb:
> Hier der Sketch mit beiden Änderungsvorschlägen von Joachim.

na ja so habe ich das nicht geschrieben

Joachim B. schrieb:
> nach dem letzten case

erkenne den Unterschied
ausserdem

> im default: oder else
>
> while(bluetooth.available()) bluetooth.read();

trotzdem sollte der BT serial in gelöscht werden

von Dieter F. (Gast)


Lesenswert?

Joachim B. schrieb:
> Helmut H. schrieb:
>> Dieter F. schrieb:
>>>   default:
>>    md.setM1Speed(0); // stopped
>>    md.setM2Speed(0); // stopped
>>    break;
>> >
>> Das cmd=0 bringt hier nichts.

Nein, das habe ich nicht geschrieben (obwohl so korrekt) - schau bitte 
nochmal nach.

Das war Helmut:
Beitrag "Re: Prozessor bleibt bei case switching hängen"

von Laurin (Gast)


Lesenswert?

Also, habe genau das eingebaut nach dem letzten case:

default:
md.setM1Speed(0); // stopped
md.setM2Speed(0); // stopped
break;

Leider hängt das blöde Ding immer noch nach wenigen Sekunden. Ich 
schmeiss das Teil jetzt dann ausm Fenster ;(

von Marco H. (damarco)


Lesenswert?

Nö logisch vorgehen hilft ;)

Erstmal muss man sich Gedanken machen was das Modul eigentlich zurück 
gibt bzw. bluetooth.read(); Gibt es die einzelnen ASCII Zeichen als int 
zurück ?


Bist du dir sicher das du genau das Zeichen auswertest was auch gewollt 
ist ? Auch die Codierung die gleiche ist ?

Was passiert wenn andere unerwartete Zeichen auftreten z.Bsp beim 
Einschalten oder durch andere Ereignisse die im Modul auftreten können.

Also wenn das Modul an anderen Seriellen Port hängt liefert diese meist 
Strings zurück.

Das weiterlaufen der Motoren bedeutet nur das die Switch Anweisung  A: 
nicht mehr ausgeführt wird. B: das der Vergleich negativ war.  Wenn 
default: nicht ausgeführt wird wäre wohl A: zutreffend.


Das kann aber auch daran liegen das Funktionen die in der Switch oder 
davor nicht zurückkehren. z.Bsp in einer while schleife hängen.  Einfach 
mal logisch vorgehen und testen bei welchen Befehl die Sache hängen 
bleibt und durch auskommentieren den Teil herausfiltern. Man kann sich 
auch per printf marker basteln um zu testen mit welchen values wo der 
code aufgerufen wird.  Oder auch nicht ;)

von Marco H. (damarco)


Lesenswert?

Hmm und das Modul hängt an einen Softwareserial Port. Wenn du auf der 
richtigen Seriellen was ausgibst bzw. dort ein Interrupt auf tritt geht 
das Zeichen ewt. verloren.  oder der Code hängt beim lesen in einer 
while schleife fest da er immer auf ein Zeichen am Software Serial 
wartet.

von Dieter F. (Gast)


Lesenswert?

Laurin schrieb:
> Leider hängt das blöde Ding immer noch nach wenigen Sekunden.

Dann hast Du wohl noch ein Verbindungsproblem. Probiere doch mal einen 
anderen Kanal oder eine geringere Baudrate. Hast Du Antennen dran?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> Leider hängt das blöde Ding immer noch nach wenigen Sekunden. Ich
> schmeiss das Teil jetzt dann ausm Fenster ;(

 Tja.
 Oder mit bisschen Debuggen versuchen...

 Anstatt:
1
  md.setM1Speed(xx);  //* xx = Wert
2
  md.setM2Speed(yy);  //* yy = Wert
 einfach:
1
      Serial.print("M1:"); Serial.println(xx);
2
      Serial.print("M2:"); Serial.println(yy);
 einsetzen.

 Vor switch..case noch ein:
1
      Serial.print("CMD:"); Serial.println(cmd);

 Wenn das Ganze noch nach 2 Minuten oder Stunden funktioniert,
 "md.SetMxSpeed(xx);" eins nach dem anderen wieder auskommentieren,
 sehen wo und wann es nicht mehr funktioniert...

von Laurin (Gast)


Lesenswert?

Hallo Marc

Du meinst so, oder?

void loop() {

  if (bluetooth.available()) {
    cmd = bluetooth.read();
    Serial.write(cmd);
    Serial.print("CMD:"); Serial.println(cmd);
    switch (cmd)
    {
      case 'C':
        Serial.print("M1:"); Serial.println(0);
        Serial.print("M2:"); Serial.println(0);
        // md.setM1Speed(0); // stopped
        // md.setM2Speed(0); // stopped
        break;

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> Du meinst so, oder?

 Ja.

von Laurin (Gast)


Lesenswert?

Ok, das Ding läuft jetzt seit ner Stunde, ohne Fehler.

Ohne Joystick-Ausschlag sehe ich im Serial Monitor immer:

CCMD:67
M1:0
M2:0

Würdest Du jetzt mit dem Auskommentieren beginnen?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> Würdest Du jetzt mit dem Auskommentieren beginnen?

 Nein.
 Erst mal eine Weile mit dem Joystick rumspielen, sehen ob auch
 alles übertragen wird.

von Laurin (Gast)


Lesenswert?

Habe hatte alle commands geprüft. War alles so wie gedacht. Jetzt habe 
ich begonnen, Auszukommentieren.
Bei der Reaktivierung des case 'F' hängt er nun wieder und im Serial 
Monitor kommt:

oCMD:111

Er printet die Motor Speed auch nicht mehr

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> oCMD:111
>
> Er printet die Motor Speed auch nicht mehr

 Dann hast du bei "default:" kein print, dein Program fällt einfach
 durch.

 Auf jeden Fall schickt dein Mini Pro ein "o" (kleines o), es wird
 also falsch gesendet.

 Was dies aber mit "F" zu tun hat, verstehe ich nicht - hast du
 vielleicht unmittelbar vorher ein "F" gesendet, in der Zwischenzeit
 etwas am Program geändert ?

 Ohne ein vollständiges Debug Print wird das sowieso nix.

von Joachim B. (jar)


Lesenswert?

du solltest endlich mal auf Input prüfen und alles was nicht

if( (cmd >= 'A' && cmd < 'J') || (cmd >= '0' && cmd < '6') )

ist verwerfen

auch regelmäßig leeren denn wenn dein Inputbuffer überläuft kommt nur 
noch Mist oder reset raus.

Wie ist denn deine Endeerkennung?
Zählst du die Zeichen die einlaufen? damit der Buffer nicht überläuft?

von Laurin (Gast)


Lesenswert?

Joachim B. schrieb:
> du solltest endlich mal auf Input prüfen und alles was nicht

Habe ich probiert. Das Resultat ist, dass die Kommandos verzögert 
ankommen und die Motoren trotzdem hängen bleiben.

void loop() {

  if (bluetooth.available()) {
    cmd = bluetooth.read();
    Serial.write(cmd);
    if ((cmd >= 'A' && cmd < 'J') || (cmd >= '0' && cmd < '6'))
    {
    switch (cmd)
    {
      case 'C':
        md.setM1Speed(0); // stopped
        md.setM2Speed(0); // stopped
        break;

und so weiter..

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> Joachim B. schrieb:
>> du solltest endlich mal auf Input prüfen und alles was nicht

 Dafür gibt es "default:"


> Habe ich probiert. Das Resultat ist, dass die Kommandos verzögert
> ankommen und die Motoren trotzdem hängen bleiben.

 Na ja, ich arbeite zwar nicht mit Arduino IDE, aber die Verzögerung
 sollte doch nicht so merkbar sein.

 Was ist mit einem Output, etwa so:
 CMD_Gesendet   CMD_Empfangen  CMD_Ausgeführt  Resultat

von Laurin (Gast)


Angehängte Dateien:

Lesenswert?

Bevor wir uns alle den Kopf zerbrechen über die Empfänger-Seite poste 
ich mal noch den Sketch der Sender-Seite. Vielleicht ist da etwas nicht 
koscher.
Danke an alle, die helfen!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> Bevor wir uns alle den Kopf zerbrechen über die Empfänger-Seite poste
> ich mal noch den Sketch der Sender-Seite. Vielleicht ist da etwas nicht
> koscher.

 Das ist der Sketch für Empfänger.

von Laurin (Gast)


Lesenswert?

Nein ist der Sketch für den Sender. Habs grad nochmals überprüft.

Beitrag #4933576 wurde von einem Moderator gelöscht.
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Laurin schrieb:
> Nein ist der Sketch für den Sender. Habs grad nochmals überprüft.

 Ja, sorry.
 Hab die ganze Zeit den vorletzten Sketch angeschaut.


 P.S.
 Auf jeden Fall ist es, wenn nicht falsch, dann aber auch nicht
 richtig.

 "F" bis "I" wird nur gesendet wenn x zwischen 400 und 500 liegt,
 also unabhängig von y.

 LED wird gleich hintereinander geschickt (ohne Pause).
 Für LED zwischen 51 und 199 wird erst "0" und dann gleich
 danach eine "1" gesendet.
 Für Werte wie 200, 400, 600, 800 wird nichts gesendet.
 Wert 1050 als ADC-WERT gibt es nicht.

 Usw.

von Laurin (Gast)


Lesenswert?

Hallo alle

Es gibt News: die Ursache ist gefunden. Es ist eine Ursache, die mir 
immer mal wieder im Kopf rumschwirrte, aber der ich trotzdem zu wenig 
Aufmerksamkeit schenkte. Die Ursache ist Noise von den DC-Motoren (beide 
entkoppelt mit je drei 100nF caps) die in das RF-Modul gelangte. Und 
zwar über Ground, also dem Alu-Chassis. Ich habe alles HF entkoppelt und 
seit da hängt nichts mehr.

Ich danke Euch allen für die vielen Inputs!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.