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!
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:> 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
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..
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" :-)
>> 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...
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_GesendetCMD_EmpfangenCMD_AusgeführtResultat
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.
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!