So nennt sich mein kürzlich eingeweihtes Roboterprojekt. In diesem Projekt möchte ich Hobby mäßig einen Roboter gestalten und programmieren. Dieser soll lebensgroß sein. Auf diesem Weg versuche ich zurzeit erst einmal die Steuerung des Fahrwerkes mit einer Bluetooth App (selbst programmiert) herzustellen. Dies klappte bisher auch einwandfrei. Die Baudrate liegt bei meinem HC-05 bei 38400 Baud und die serielle Kommunikation zwischen diesem und einem Arduino UNO läuft auch über 38400 Baud. Ich versende einen String, welcher (z.b.) wie folgt aussieht: Xr255l34X Er setzt sich aus dem char 'X' zusammen, welcher hier die Funktion einer Überprüfung, der korrekten Übertragung des Strings, symbolisiert. Das 'r' steht für den rechten Motor und das 'l' für den Linken. Zahlen stellen das PWM-Signal dar (von 0 - 255). Der String wird über die Arduino IDE zerlegt, sodass ich die oben genannten Rohinformationen für die einzelnen Motoren erhalte. Nun aber endlich zu meinen Fragen: 1. Die Kommunikation bzw. die Auswertung ist sehr stark Verzögert (rund 1 Sekunde). 2. Der Befehl: if(Serial.available() > 0){ state = Serial.readString(); Serial.println(state); } agiert zu langsam, sodass die von der App kommenden Strings so aussehen: Xr255l34XXr255l33XXr255l32XXr255l25XXr255l22XXr255l20XXr255l20X statt: Xr255l20X Dies macht die Strings für mich nicht auswertbar... Hat jemand eine Lösung dafür ? Ist die Baudrate immer noch zu langsam ? (Ich vermute nicht) Im Anhang befindet sich ein Bild der App-Oberfläche und die .ino Datei. Eine Vorgabe möchte ich meinerseits noch machen: Es muss ein String dieser Länge versendet werden. Dies macht die Weiterentwicklung komfortabler. Danke im Vorraus für Ihre Hilfe. Für Vorschläge und Ideen Caruso betreffen werden gerne akzeptiert und sind neben den Fragen sogar erwünscht. Weitere Updates können zum Projekt folgen. led35
Hallo
>Dies macht die Strings für mich nicht auswertbar...
Warum nicht? Musst nur auf die 'X' parsen. Keiner zwinkt dich alles
angekommene auf einmal einzulesen. Immer nur ein Teilstück holen dann
bearbeiten und dann das nächste. Oder auf Handshake umbauen.
Gruß
Danke erstmal für die sehr schnelle Antwort. Die Idee mit dem "Handshake"-Vefahren klingt gut. Damit würde, wenn ich das recht verstehe die ganze Stringzerlegung wegfallen. Ich werde es gleich mal testen. Aber eine Frage bleibt trotzdem noch offen, warum reiht der Mikrocontroller (Arduino UNO) trotz der eigentlich schnellen Baudrate die Strings aneinander ? Liegt das an der Stringzerlegung ?
Hi, sendest du am Zeilenende "\r\n" ? Du liest ja einen String ein. "Xr255l34X\r\n" oder nur "Xr255l34X\n" Gruß
:
Bearbeitet durch User
Ich sende nur "Xr255l34X" ohne derartige Zusätze. Dann müsste ich doch eigentlich keinen Zeilenumbruch senden oder ?
Nein musst du nicht. War nur ein Vorschlag um das Befehlsende zu Kennzeichnen. Schau das: Serial.readString() reads characters from the serial buffer into a string. The function terminates if it times out (see setTimeout())." Man kann auf Serial.readBytes umbauen. Immer ein Byte einlesen und auf '\n' testen. Kommt das Zeichen ist der Befehl vollständig und kann weiter verarbeitet werden.
Von dem Befehl hab ich noch nie was gehört. Ich find es aber Klasse, dass so einen gibt und das es noch hilfsbereite Menschen gibt. An dieser Stelle nochmals vielen Dank, ich bin fast verzweifelt... Dennoch habe ich noch ein paar Fragen: Wenn ich eine Baudrate von 38400 Baud benutze, wie lang muss das Timeout mindestens sein ? Ich hab mal gelesen, dass man Baud nicht mit Bits/s gleichsetzten kann ... Ist da etwas dran ? Würde es Sinn machen meine Idee mit dem String zu verwerfen und stattdessen das Handshake-Verfahren zu nutzen ? Jetzt erklärt sich auch die rund eine Sekunde Verzögerung ... Man lernt nie aus. Vor allem ich noch nicht ;-)
Hi, Handshake ist manchmal sinnvoll, manchmal aber auch nicht. Du kannst z.B. sowas verwenden um immer einen Befehl zu bekommen.
1 | bool auswerten = false; |
2 | String befehl = ""; |
3 | |
4 | void loop() { |
5 | if (Serial.available() > 0) { |
6 | char empfangenesByte = Serial.read(); |
7 | if(empfangenesByte == '\n'){ |
8 | auswerten = true; |
9 | }else{ |
10 | befehl += empfangenesByte; |
11 | }
|
12 | }
|
13 | if(auswerten){ |
14 | |
15 | // hier die Befehlsauswertung hin
|
16 | |
17 | befehl = ""; |
18 | auswerten = false; |
19 | }
|
20 | }
|
Allerdings muss die App das '\n' dann auch senden. Aber das Timeout spielt hier keine Rolle mehr. Gruß
:
Bearbeitet durch User
Kann ich dann einfach in der App folgenden String versenden: "Xr255l255X\n" ? Oder wird dann "\n" zu '\' und 'n' und somit zu 2 Bytes ?
Ich werde es dann mal mit Ihren Ratschlägen und Tipps ausprobieren. Kann sein, dass ich mich hier nochmal melden muss weil ich wieder verzweifle :-|. Ich wünsche Ihnen eine gute Nacht und einen guten Start in den Sonntag. Mfg led35
Felix V. schrieb: > Wenn ich eine Baudrate von 38400 Baud benutze, wie lang muss das Timeout > mindestens sein ? Ich hab mal gelesen, dass man Baud nicht mit Bits/s > gleichsetzten kann ... Ist da etwas dran ? Ja. Baudrate ist die Anzahl der Schrittwechsel pro Sekunde (vergleichbar Frequenz). Je nach Modulationsverfahren können aber mehrere Bits pro Schrittwechsel übertragen werden, daher ist die Bitrate im Allgemeinen höher als die Baudrate. Bei Rs232 z.B. sind es meines Wissens bei 9600bps 2400baud.
Felix V. schrieb: > Wenn ich eine Baudrate von 38400 Baud benutze, wie lang muss das Timeout > mindestens sein ? Ich hab mal gelesen, dass man Baud nicht mit Bits/s > gleichsetzten kann ... Ist da etwas dran ? Es werden 38400 Bits pro Sekunde übertragen. Bei 8 Datenbits, einem Startbit, einem Stopbit und keinem Paritätsbit (insgesamt 10 Bits/s) kannst du also die Baudrate einfach durch 10 teilen, um die Anzahl der Bytes pro Sekunde zu errechnen. Den Lösungsansatz mit einem Timeout halte ich für bedingt gelungen. Sinnvolle wäre es, den Stream byte-/zeichenweise einzulesen und gleich das Start- und Endezeichen auszuwerten (für beide 'X' zu wählen ist ungünstig). Zeichenweise auslesen kann man mit "Read". Was soll außer den Motor-Richtungen noch alles übertragen werden? Deine Unterscheidungskennzeichen der Information sind ja momentan 'r' und 'l'. Man muss nur verhindern, dass die beiden Zeichen noch anderes auftreten können. Ansonsten muss man nach "Xr" oder "Xl" gucken und dann die Befehlsdekodierung starten. Felix V. schrieb: > Oder wird dann "\n" zu '\' und 'n' und somit zu 2 Bytes ? Nö, das '\' leitet ein Sonderzeichen in einem String in C/C++ ein.
> Bei Rs232 z.B. sind es meines Wissens bei 9600bps 2400baud.
Bei RS232/UART ist die Baudrate gleich der Bitrate.
Neverever schrieb: > Bei Rs232 z.B. sind es meines Wissens bei 9600bps 2400baud. Falsch. RS232 überträgt keine modulierten Daten. Du verwechselst das mit analogen Telefonmodems, da ist das tatsächlich so.
Erstmal wieder ein dickes Dankeschön für die Antworten. Ich habe die App aber in Java programmiert und in xml. Aber hier wird auch mit '\' ein Sonderzeichen eingeleitet. Sollte also passen denk ich mal. Später sollen noch die Arme und der Kopf, sowie Stimme über die App gesteuert werden. Die Zeichen treten nirgendwo sonst auf. Darauf hab ich schon geachtet, da sonst die Befehlsauswertung vorn Baum geht. Bisher wird noch mit "XstopX" ein Notaus veranlasst. Ich hab mich jetzt aber glaub ich auf das Handshake-Verfahren eingeschossen. Sollte ich bei irgendwas Bedenken oder Vorsicht walten lassen ? Schönen Sonntag allen. Mfg led35
Stefanus F. schrieb: > Bei RS232/UART ist die Baudrate gleich der Bitrate. Man muss nur berücksichtigen, daß pro übertragenem Byte (das sich i.d.R. aus 8 Bits zusammensetzt) noch mindestens zwei zusätzliche Bits übertragen werden, das Start- und das Stopbit. Damit werden also bei 2400 Baud nur 240 Byte pro Sekunde übertragen (2400/10) und nicht 300 (2400/8).
Daß die Datenrate zu hoch ist, ist nicht Dein Problem. Es sieht so aus, als würdest Du beim Empfang Zeichen verschlucken. Reduziere die Datenrate auf einen deutlich niedrigeren Wert, dann sollte das nicht passieren. Abhilfe für den verschluckfreien Empfang auch bei höheren Datenraten bietet interruptgesteuertes Empfangen, d.h. die Daten werden nebenläufig in Deinem Programm empfangen und aufgehoben, auch wenn das Programm gerade an einer anderen Stelle als dem Aufruf von Serial.readString steckt.
Hallo an alle, Ich habe die vorgeschlagenen Tipps und Empfehlungen gestern in die Tat umgesetzt. Es klappte wie geschmiert. "Caruso" reagierte sofort. Es gab mittels des Handshake-Verfahrens auch keinen Überlauf mehr an Ereignissen. Sie haben dabei mitgewirkt, "Caruso" leben einzuhauchen und ihm laufen beizubringen. Dafür ein fettes Dankeschön an alle. Mfg led35 PS: Im Anhang ist "Caruso" zu sehen (Fahrwerk).
Hallo Progger und Proggerinnen, ich hatte in meinem Thread Operation "Caruso" gesagt, dass Statusupdates folgen werden. Daran möchte ich mich auch hiermit halten. Alle die schon einmal ein so ähnlich großes Projekt hatten, wissen wenn Probleme gelöst wurden so treten neue auf. Deshalb wird auch dieses Update nicht ohne Fragen ausfallen. Im Anhang sind aktuelle App-Oberfläche, Arduino Code und ein Teil des Java-Programmes hinterlegt. Bei Caruso funktioniert jetzt sowohl vorwärts als auch rückwärts fahren. Des Weiteren ist ein Notaus Knopf in der App eingebunden, welcher an jeder beliebigen Stelle ausgelöst werden kann und Caruso SOFORT zum stehen bringt. Die Geschwindigkeit kann reguliert werden, indem man sich mit dem Finger vom Zentrum des Radar-ähnlichen-Kreises entfernt (0 - 255). Aber nun zu meiner Frage: Wenn Sie sich den Anhang angeguckt haben ist Ihnen sicher das nebenläufige Logscript aufgefallen (Textfeld rechts). Dieses Script schreibt alle Daten mit, welche der Arduino UNO R3 sendete. Dies funktioniert auch in gefühlter Echtzeit. ABER: Ich versende mit dem Arduino einen String welcher folgenden Bau aufweist: "XTE". (Gerne kann der Lösungsvorschlag auch für die Form sein: "XbusyE".) Dabei ist X das Anfangsbyte und E das Endbyte. Nur leider erscheint im Log manchmal diese Form: (Datum über Java hingeschrieben): X (Datum über Java hingeschrieben): TE Damit kann ich nur nichts anfangen, da dies bedeutet, dass der InputStream diesen String zerhackt in die Log geschrieben hat. Da ich aber während des schreibens in den Log nichts verändere, ist das so eingelesen worden, da ich dieses String eigentlich am Arduino als ganzes sende. Ich benutze nach wie vor das HC-05 Modul und eine Baudrate von 38400. Kann mir bitte jemand bei diesem Problem weiter helfen ? Ich weiß keinen Rat mehr und im Internet wird man bei so spezifischen Sachen nicht fündig. PS: Durch diese Fehler kommt es zu Störungen im Motorbetrieb (kaum auffällig, aber dennoch nervig). Bitte Kommentare in der .ino Datei ignorieren.
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.