Forum: Mikrocontroller und Digitale Elektronik Operation "Caruso"


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Felix V. (led35)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

von Rene Z. (renezimmermann)


Bewertung
1 lesenswert
nicht lesenswert
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ß

von Felix V. (led35)


Bewertung
0 lesenswert
nicht lesenswert
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 ?

von Rene Z. (renezimmermann)


Bewertung
0 lesenswert
nicht lesenswert
Hi,

sendest du am Zeilenende "\r\n" ? Du liest ja einen String ein.

"Xr255l34X\r\n" oder nur "Xr255l34X\n"

Gruß

: Bearbeitet durch User
von Felix V. (led35)


Bewertung
0 lesenswert
nicht lesenswert
Ich sende nur "Xr255l34X" ohne derartige Zusätze.
Dann müsste ich doch eigentlich keinen Zeilenumbruch senden oder ?

von Rene Z. (renezimmermann)


Bewertung
1 lesenswert
nicht lesenswert
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 Felix V. (led35)


Bewertung
0 lesenswert
nicht lesenswert
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 ;-)

von Rene Z. (renezimmermann)


Bewertung
1 lesenswert
nicht lesenswert
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
von Felix V. (led35)


Bewertung
0 lesenswert
nicht lesenswert
Kann ich dann einfach in der App folgenden String versenden:
"Xr255l255X\n" ?
Oder wird dann "\n" zu '\' und 'n' und somit zu 2 Bytes ?

von Rene Z. (renezimmermann)


Bewertung
1 lesenswert
nicht lesenswert
"Xr255l255X\n" ist korrekt.

von Felix V. (led35)


Bewertung
0 lesenswert
nicht lesenswert
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

von Neverever (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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.

von STK500-Besitzer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
> Bei Rs232 z.B. sind es meines Wissens bei 9600bps 2400baud.

Bei RS232/UART ist die Baudrate gleich der Bitrate.

von S. R. (svenska)


Bewertung
0 lesenswert
nicht lesenswert
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.

von Felix V. (led35)


Bewertung
0 lesenswert
nicht lesenswert
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

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
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).

von Felix V. (led35)


Bewertung
0 lesenswert
nicht lesenswert
Das würde ja heißen, dass meine 38400 Baud locker ausreichen sollten 
oder ?

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
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.

von Felix V. (led35)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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).

von Felix V. (led35)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.