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!
Kein bestimmter. Ist immer mal wieder ein anderer case.
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)
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 ;)
Laurin schrieb: > Danke für Eure Hilfe! Ja, ein delay(0) ist für mich überaus sinnvoll und nützlich.
Die delay steht noch dort, weil ich mit verschiedenen delay-zeiten experimentiert habe. Mir ist klar, dass delay(0) nix bewirkt
Laurin schrieb: > Auch die Commands habe ich mit dem Serial Monitor > (Serial.print(cmd)) empängerseitig überprüft. Mit dem gezeigten Code?
Laurin schrieb: > Ja mit dem Xode, den ich gepostet habe. In allen mir bekannten Programmiersprachen dieses Aussehens ist das toter Code. Daher die Frage.
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
Dass dieser Code im bisherigen Zustand verharrt, wenn nichts mehr kommt, überrascht mich jetzt nicht so.
Ok. Der Original-Code stammt nicht von mir sondern von instructables.com
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.
Was würdet Ihr nun vorschlagen. Den ganzen Code neu und ohne switch case?
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()
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();
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)
Stimmt leider nicht, sorry. Musste nach erneutem Aufstarten feststellen, dass die Motoren laufen gemäss den Befehlen. Leider bleiben sie immer noch hängen..
Hier der Sketch mit beiden Änderungsvorschlägen von Joachim.
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
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.
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'.
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" :-)
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
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"
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 ;(
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 ;)
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.
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?
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...
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;
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?
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.
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
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.
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?
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..
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
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!
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.
Nein ist der Sketch für den Sender. Habs grad nochmals überprüft.
Beitrag #4933576 wurde von einem Moderator gelöscht.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.