Hallo Leute, ich baue gerade an einer kleinen Bluetoth-Fernsteuerung für Modellfahrzeuge. Es wird (vom Sender) ein Frame geschickt (über den UART 19,2kbaud) : Adresse des Empängers - Wert 1 - Wert 2 - Adresse des Empängers ohne Zeichen dazwischen 8 Bit - 1 Start - 1 Stop - kein Parity und das mindestens 24 mal pro Sekunde. Das Frame soll auch noch um ein paar Bytes erweitert werden, aber das hier muss erst funktionieren. Das ganze geht über UART und Bluetoothmodule (übertragung funktioniert). -> Wie identifiziere ich im Empfänger die beiden Werte und speichere sie in zwei Variablen ab? Hab schon ein paar Tage dran gearbeitet, funktioniert aber noch nicht. Im Forum gesucht hab ich auch schon. Ach ja, das ganze arbeitet mit 2 ATMega8L bei 8 Mhz und 2 Bluetoothmodulen BTM-112. Michael
Du wirst dir wohl selber eine kleine Protokoll überlegen müssen, sonst kannst du die bytes NIE unterscheiden. z.b. Länge, Daten, Daten, [,Prüfsumme] und dann wieder Länge ...
Gibts irgendwo etwas in der Richtung in C, wo man sich sowas mal anschauen könnte?
Wenn ich dir jetzt einfach mal die Zahlenfolge ..... 23 23 23 23 23 23 23 23 ..... vorwerfe, kannst du dann sagen, was denn nun was ist? Nein, das kannst du nicht! Du hast kein eindeutiges Kriterium, welche Zahl den die Empfängeradresse und welche Zahl ein dich interessierender Wert ist. Die Aufgabe eines Protokolls ist es, dies zu regeln. Und sowas musst du dir ausdenken! Du brauchst irgendein eindeutiges Kriterium, an dem du erkennen kannst, wo ein Datensatz anfängt. Dein Problem werden wahrscheinlich die beiden Werte sein, da dort alle möglichen Werte vorkommen können. Dafür musst du dir eine Lösung überlegen (zb. indem du mit dir selbst vereinbarst, dass bestimmte Werte einfach nicht vorkommen).
ach SO meint ihr das! also, als Startbyte/Adresse (momentan gibt es nur eine Adresse) sende ich ein kleines f, bei den Werten wird das rausgefiltert mit: if (a1 == 'f') a1++; if (a2 == 'f') a2++; aber es klappt irgendwie noch nicht so ganz, und deshalb frage ich nach einem Codebeispiel. Danke schonmal. Michael
das kann doch gar nicht so schwer ein. Beim empfänger musst du ja bloss auf das 'f' warten und das erste byte was genach konnt ist halt Byte1 das nächste ist Byte2. Für solche sachen wird mal kaum Beispielcode finden, weil es zum schluss bloss ein paar zeilen sind - und diese sind meist sehr individuell. Zeigt doch mal dein Code.
Also Sinnvolles Startbyte kommt von Haus aus nicht im Datenstrom vor. Ich verwende gerne so Zeichen wie < > @ # etc. Meine Nutzdaten sende ich in der Regel als Hexzahlen. Das erhöht zwar die Datenmenge, dafür brauch ich keine Verrenkungen wenn das Startbyte als Wert vorkommt. Wenns die Kanalbelegung zulässt, sende ich noch ein Ende byte. Wenn die Frames unterschiedlich lang sein sollen, dann muss entweder am Frametyp (Parameterkennung) oder am Endebyte die Datenlänge erkannt werden. Hübsch sind natürlich noch CRC-Summen und event Framenummern. Wenn man dann jedes Frame bestätigt, ist die Übertragung auch sicher. Bestätigen kann man auch falls ein Fehler vorliegt. Leider erkennt man ein ausgelassenen Frame dann erst beim nächsten guten (Es fehlt dann eine Framenummer)
Hier mal die Sende- und Empfangsroutinen. Zum Sender: Die Werte a1 + a2 werden natürlich entsprechend gefüllt und dann die Senderoutine aufgerufen. Zu den Kommentaren: lasst euch von mal DE mal EN nicht verwirren, ich kann mich nicht entscheiden, ob ich Kommentare auf DE oder EN schreiben soll... Michael
Deine Adresse ist beim Senden sicher immer 'f'? Vereinfach doch mal deine Empfangsroutine ein wenig. Das ist doch massig zu kompliziert. Im Endeffekt wird das wahrscheinlich sowieso alles ganz anders gelöst werden, weil du dir warten auf einen Empfang nicht leisten kannst :-)
1 | inSync = FALSE; // Empfänger ist nicht synchronisiert |
2 | |
3 | while( 1 ) { |
4 | |
5 | x = uart_rxd(); |
6 | |
7 | if( x == 'f' ) { |
8 | inSync = true; // Frame hat angefangen. Empfänger ist synchronisiert |
9 | nextByte = 0; |
10 | }
|
11 | |
12 | else if( inSync ) { // ein empfangenes Byte zählt nur dann, wenn |
13 | // der Empfänger sich auf ein Datenpaket
|
14 | // synchronisiert hat.
|
15 | if( nextByte == 0 ) |
16 | a1 = x; |
17 | |
18 | else if( nextByte == 1 ) { |
19 | a2 = x; |
20 | inSync = false; // Frame ist fertig. Gebe synchronisierung auf |
21 | |
22 | ... Verarbeite a1 und a2 |
23 | }
|
24 | |
25 | nextByte++; // kann auch dann gemacht werden, wenn die Synchronisierung |
26 | // aufgegeben wurde. Beim nächsten Framestart wirds
|
27 | // sowieso wieder auf 0 gesetzt
|
28 | }
|
29 | |
30 | .....
|
31 | }
|
Anstatt getrennter Variablen inSync und nextByte könnte man auch beide Aufgaben in eine Variable zusammenfassen. zb könnte ein nextByte Wert von -1 bedeuten, dass keine Synchronisierung besteht. Mit dem Empfang eines 'f' geht nextByte auf 0, 1. Byte führt zu 1, und beim 2. Wertbyte wird nextByte wieder zu -1 ( um dann mit dem nächsten 'f' wieder zu 0 zu werden, etc).
kannst du noch sagen, was genau nicht geht? Von code ist zwar nicht schön sollte aber gehen. Ich würde ihn aber gleich umschreiben, sonst bekommst du später Probleme wenn das Programm mal etwas mehr machen soll. Dein µC ist in der Main immer mit dem empfangen beschäftigt! Nutze die Interruptroutinge zum empfangen von Daten. Dort Merkst du dir bei welchen byte die bist. Jedes mal wenn du ein byte empfängst zählst du einfach hoch. Wenn ein 'f' kommt dann setzt du den zähler wieder auf 1. Das ganze sollte dann auch ein wenig übersichtlicher sein. Wo sendest du üerbaupt das 'f' das ist nicht ersichtlich?
Was tut nicht: Gute Frage. Also, es hat mal so halbwegs funktioniert. Aber in unregelmäßigen Abständen hat es plötzlich gestockt, d.h. das Fahrzeug ist einfach so weitergefahren, egal wie der Kreuzknüppel (Werte a1 + a2) stand. Ebenso plötzlich gings dann auch wieder, und ich hatte mich schon gefreut. Das war Mittags. Abends gings dann nicht mehr. Die Module haben sich (mit 99% iger Wahrscheinlichkeit) verbunden, aber das Fahrzeug hat komplett getan was es wollte. Da hab ich die Empfangenen Daten am PC angeschaut, aber die sind aber in Ordnung. Deshalb bin ich zu dem Schluss gekommen, dass meine Frame-auswertung nicht richtig funktioniert. Und seitdem es einmal so verrückt gespielt hat, tut es das jetzt immer. > Wo sendest du üerbaupt das 'f' das ist nicht ersichtlich? Oops, 'f' ist in der Variable adr_e gespeichert, Sorry. Dass der µC in main immer mit empfangen beschäftigt ist, ist momentan noch nicht schlimm, die Servos werden per HW-PWM angesteuert. @Karl Heinz Deinen Code müsste man nur in eine Interrupt-Routine packen. Was passiert aber, wenn ein Byte verloren geht(ich glaube, bei meinen BT-Modulen gehen ab und wann ein, zwei Bytes verloren). Wäre aber machbar. Zu dem "mehr machen": später soll noch ein Programmiermodus rein, um LED's dimmen zu können. Weils acht stück sind, muss es SW-PWM sein. Könnte noch tolle Timing-Probleme geben, um die ich mich mal jetzt noch nicht kümmere. Vielen Dank für eure Hilfe, Michael
Michael 93 wrote: > Deinen Code müsste man nur in eine Interrupt-Routine packen. Was > passiert aber, wenn ein Byte verloren geht(ich glaube, bei meinen > BT-Modulen gehen ab und wann ein, zwei Bytes verloren). Wäre aber > machbar. Spiels in Gedanken durch. Die eigentliche Anwendung der Daten passier erst, nachdem a2 empfangen wurde. Wenn zwischendurch ein 'f' eintrudelt, dann beginnt der Frame wieder von vorne und nextByte wird wieder auf 0 zurückgestetzt. So wie der Code aufgebaut ist, wird immer auf ein f gewartet und die nachfolgenden 2 Byte als Werte interpretiert (sofern nicht ein 'f' dabei war). Selbst wenn ein 'f' verloren geht, passiert auch nichts. Empfangene Bytes werden nur dann ausgewertet, wenn vorher ein 'f' kam. Und nach 2 empfangenen Bytes muss wieder ein 'f' kommen, damit die Auswertung der Bytes in Gang kommen kann. Die Variable inSync fungiert wie ein Torwächter. Nur wenn sie auf TRUE steht, werden die nächsten beiden Bytes als gültige Daten akzeptiert. Das Tor geht nur dann auf, wenn ein 'f' empfangen wird und schliesst sich selbsttätig nach 2 empfangenen Bytes wieder.
> Spiels in Gedanken durch. > Die eigentliche Anwendung der Daten passier erst, nachdem a2 empfangen > wurde. Wenn zwischendurch ein 'f' eintrudelt, dann beginnt der Frame > wieder von vorne und nextByte wird wieder auf 0 zurückgestetzt. ok, hatte ich übersehen. > So wie der Code aufgebaut ist, wird immer auf ein f gewartet und die > nachfolgenden 2 Byte als Werte interpretiert (sofern nicht ein 'f' dabei > war). Selbst wenn ein 'f' verloren geht, passiert auch nichts. > Empfangene Bytes werden nur dann ausgewertet, wenn vorher ein 'f' kam. > Und nach 2 empfangenen Bytes muss wieder ein 'f' kommen, damit die > Auswertung der Bytes in Gang kommen kann. > > Die Variable inSync fungiert wie ein Torwächter. Nur wenn sie auf TRUE > steht, werden die nächsten beiden Bytes als gültige Daten akzeptiert. > Das Tor geht nur dann auf, wenn ein 'f' empfangen wird und schliesst > sich selbsttätig nach 2 empfangenen Bytes wieder. nach einem 'f' folgen aber 2 Werte und noch ein 'f', sieht also i.e. so aus: f-126-126-f-f-134-123-f-f-.... ein Frame sieht schließlich so aus: f-wert1-wert2-f und das wird immer hintereinander gesendet. (- trennt die bytes) Oder hab ich schon wieder was falsch verstanden? Michael
Hallo. Ich habe folgendes Problem: Ich empfange eine Variable die einen 16Bit-Wert beinhaltet.Nur die oberen 10Bit(Zweierkomplement) sind letztendlich relevant. Diese 10Bit möchte ich über Uart an den Hyperterminal schicken und dort als Gleitkomma-Zahl mit einer Nachkommastelle angezeigt bekommen. Steh aber grad auf dem Schlauch wie ich das realisieren kann. Variable: int16_t temp = 0x1102; -> davon obere 10Bit: 0001 0001 00 -> diese Zahl möchte ich halt über Uart mit einer Nachkommastelle auf dem HyperTerminal sehen. Hat jemand ne Idee?Danke
Michael 93 wrote: > f-126-126-f-f-134-123-f-f-.... > > ein Frame sieht schließlich so aus: f-wert1-wert2-f > und das wird immer hintereinander gesendet. > > (- trennt die bytes) > > Oder hab ich schon wieder was falsch verstanden? Ooops. das hab ich in deiner Senderoutine übersehen. Das ist keine gute Idee! Sorge dafür dass Start und Endekennungen immer eindeutig sind! Beim Empfang eines der beiden (Start oder Ende-Kennung) muss immer eindeutig klar sein, welches der beiden es ist. Für beides, Start und Ende, dasselbe Zeichen zu nehmen, ist abolut keine gute Idee! Da ist es noch besser, wenn du zb. die Ende Kennung ganz weg lässt.
tommy776 wrote: > Variable: > int16_t temp = 0x1102; -> davon obere 10Bit: 0001 0001 00 -> diese Zahl > möchte ich halt über Uart mit einer Nachkommastelle auf dem > HyperTerminal sehen. http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
Tag, ok, ich lass das Stopp-Byte weg. Komme aber Momentan nicht zum Entwickeln, schreiben morgen und übermogen je eine Klassenarbeit, blöde Schule (bitte jetzt keine Diskussion über die Wichtigkeit der Bildung und ähnliches)!!! Michael
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.