Prozessor bleibt bei case switching hängen

Gast #4932014
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!
Angehängte Dateien:
Gast #4932173
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()
Gast #4932227
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)
Gast #4932315
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.
#4932375
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
Gast #4932418
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 ;(
#4932582
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 ;)
#4932589
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.
(Firma: Vescomp) #4932754
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...
Gast #4932813
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;
Gast #4933204
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
(Firma: Vescomp) #4933249
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.
#4933260
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?
Gast #4933509
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..
(Firma: Vescomp) #4933544
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
Beitrag #4933576 wurde von einem Moderator gelöscht.
(Firma: Vescomp) #4933582
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.
Gast #4938766
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!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren