Hallo zusammen, ich bräuchte mal wieder eine Anregung zur Lösung eines kleinen Softwareproblems. Am Start ist ein ATMega2560@16MHz, dessen Software einen ganzen Schwung an Datensätzen verwaltet und anlegen, löschen und ändern ermöglicht. Auf Grund der beschränkten Anzeigemöglichkeiten des Geräts (LCD 20 x 2) ist es nicht möglich, alle Daten eines Datensatzes (ca. 1kB binär) gemeinsam anzuzeigen. Um etwas mehr Komfort anzubieten, soll ein PC für diese Funktionen genutzt werden. Die Verbindung zwischen Controller und PC wird über eine UART und einen FTDI FT232RL@38400bd hergestellt, über die auch ein Bootloader genutzt werden kann. Die Funktionen „Löschen eines Datensatzes“ und „Übertragen eines Datensatzes an den PC“ habe ich umgesetzt, wobei das Übertragen in Richtung PC einfach durch sequentielles Lesen der Daten eines Datensatzes, Umwandeln in ASCII mit Trennzeichen „;“ und interruptgesteuertes Senden über einen 32 Byte Sendepuffer erfolgt. Zeitprobleme gibt es keine, der PC wartet halt auf das Endekennzeichen, egal wie lange der Controller dazu braucht. Bis jetzt gibt es keine Sicherung der Datenübertragung durch CRC – bisher aber auch keine Probleme. Nun kommt der andere Weg, also die Übertragung eines Datensatzes vom PC an den Controller. Die Übertragung erfolgt im gleichen Format, allerdings über den gleichen Puffer von 32 Byte wie beim Senden, mehr gibt es nicht dafür – ich kann also keinen ganzen Datensatz in ASCII puffern, das würde wohl auch so um die 4kB benötigen. Da der Controller noch mehr zu tun hat, steht auch nicht die gesamte Rechenleistung für die Separierung und Umwandlung zur Verfügung. Also muss ich einen Mechanismus implementieren, der das „Überfahren“ des Controllers durch den PC und den damit verbundenen Datenverlust vermeidet. Wie fängt man das jetzt am besten an? Entweder über eine flow control in Software (xon-xoff) oder Hardware (RTS/CTS) und untersuchen der Daten im Puffer, umwandeln und abspeichern oder zerlegt man den Datensatz von vorn herein in Häppchen, die in den Puffer passen? In diesem Fall könnte man auch eine einfache CRC-Sicherung einbauen, muss dann aber auch jeden Schnipsel einzeln quittieren. Wartet man den ganzen Satz ab, kann man erst am Ende erkennen, ob es einen Fehler gegeben hat. Irgendwie sehe ich den Wald vor lauter Bäumen nicht und finde keine richtig brauchbare Lösung. Hat da jemand eigene Erfahrung und kann ein sinnvolles Vorgehen hier mal kurz skizzieren? Danke Thomas
Wenn der Empfangspuffer so klein ist muss man halt in kleineren Häppchen senden. Handshake in Hardware oder Software ist ja eher so eine Protokoll-unabhängige Einrichtung, hat sicherlich in vielen Szenarien seine Berechtigung. Wenn du sowieso von Datensätzen sprichst, kann man das Protokoll sicherlich in sinnvollen Häppchen aufteilen. Eine Checksumme ist auch eine gute Idee, wenn es einmal läuft tut die nicht weiter weh. Was ich immer gerne einbaue ist eine Synchronisation für die Pakete. Jedes Paket beginnt mit einem bestimmten Zeichen, der Empfänger wartet nach einer beliebigen Situation (Warte auf neues Paket, Fehler, unklarer Zustand, Neustart etc.) auf dieses Zeichen und definiert damit den Beginn eines neues Frames. Dann folgt z.B ID, Länge, Daten, Checksumme. Wichtig ist, dass das Zeichen für Synchronisation in JEDER Situation IMMER den Beginn eines neuen Frames darstellt. Also wird jedes eingehende Byte geprüft. Damit kann alles passieren, z.B. fehlende Zeichen durch Wackelkontakt oder z.B. Empfang einer ungültige Länge. Der Sync fängt das Protokoll stets wieder sauber ein. Falls man ohne Sync arbeitet, kann ein aus dem Tritt gekommenes Protokoll unter Umständen recht lange brauchen, bis es wieder in der Spur ist. Bei reinen ASCII Daten ist der Sync recht einfach, man nimmt ein Zeichen, was sonst nicht vorkommt. Aber selbst bei binären Daten klappt das, dann muss man nur eine spezielle Sequenz finden, die die Übertragung des „speziellen Zeichens“ ermöglicht. Ein schönes Beispiel für so etwas findet man beim Framing Modus der XBee Funkmodule. Beim ersten Studium des Mechanismus mag man noch denken, dass das etwas kompliziert zu programmieren ist, in der tatsächlichen Umsetzung sind es aber dann nur sehr wenige Zeilen extra. Belohnt wird man durch ein extrem robustes Protokoll. Benutze ein solches System in beide Richtungen, der Empfänger quittiert dann jedes korrekt empfangene Paket. Schön ist es dann auch, wenn jedes fortlaufende Paket einfach eine laufende Nummer zwischen 0..255 bekommt, dann kann der Empfänger genau mitteilen, bei welcher Paketnummer ein evtl. Fehler vorlag.
Hier ist der Framing Mode am Beispiel XBee beschrieben https://www.digi.com/resources/documentation/Digidocs/90002002/Content/Reference/r_api_frame_format_900hp.htm Ignoriere den Funkmodul-spezifischen Teil, es geht mir nur um den API Frame mit dem Delimiter und der Escape-Sequenz.
32 Byte ist wenig, aber OK. Wenn die Daten auch binär ausgetauscht werden können, nimm ruhig binär oder hexadezimal. Bei Hex hast Du sehr viele Steuerzeichen frei. Nimm halt 32 Byte-blocke mit Start, Sequenz, anzahl, Daten, Stop, also 14 Byte Nutzdaten. Flow-control über HW finde ich schlecht, da nicht für alle Strecken verfügbar. Einfach ein paar Steuerzeichen: nochmal/von vorne/Pause/vorletzten Satz/weiter. Der PC wartet halt auf "weiter" etc.
Hallo Harald A., danke für den Hinweis, das werde ich mir mal zu Gemüte führen. Da in meinem Anwendungsfall immer ein Bediener beteiligt ist, kann ich eine fehlgeschlagene Übertragung immer mit einem Fehler abbrechen, muss dann eben manuell neu gestartet werden. @Achim S. Von dem Austausch von Binärdaten war ich abgekommen, da ich Probleme mit notwendigen Steuerzeichen befürchte und auch ein notwendiges Debugging einfacher ist. Auf einer Seite muss ich Daten ohnehin umwandeln und auf der Controllerseite tue ich mich leichter damit. Aber warum ist HW-flow-control schlecht? Sicher, die Schnittstelle auf PC-Seite muss entsprechend eingestellt sein und nur so kann sich doch der Controller gegen ein Überfahren wehren. Bedenken hätte ich eher wegen Latenzen zwischen dem Erkennen "Puffer voll", Senden oder Einschalten des xoff und dessen Wirksamwerden. Keine Ahnung, wieviele Zeichen da noch ankommen können, bis der PC das geschnallt hat und das Senden einstellt. Thomas
Serielle Daten hat man auch früher schon per Upload / Download übertragen. Ich würde mir Mal xmodem anschauen. Ev auch zmodem. Das sind standardisierte einfache Protokolle die auch in jedem Terminal Programm verfügbar sind. Thomas
Thomas P. schrieb: > Von dem Austausch von Binärdaten war ich abgekommen, da ich Probleme mit > notwendigen Steuerzeichen befürchte und auch ein notwendiges Debugging > einfacher ist. Übliche Verfahren sind i.A. auf eine 'sparsame' Bandbreitennutzung ausgelegt und versuchen mit möglichst wenig Extradaten auszukommen, was andererseits eine etwas kompliziertere Codierung beinhaltet. In deinem Fall hast du aktuell ca.3-fache Bandbreite (relativ zu den Binärdaten) sodass eine 'großzügige'/einfach debugbare/einfach (de)codierbare Symbolcodierung bspw. 8-bit-binär<--> 2*(4bit-meta+4bit-nib) [ rrns.dddd r(eserved) (n)ibble l/h (s)start/stop (d)ata] immer noch weniger Bandbreite (eh nur Thema in anderen Situationen)benötigen würde, aber vor allem extrem extrem einfach und µC-Last-schonend implementierbar wäre. Praktisch keine µC-Leistung-->aufwendige/fehlerträchtige Flusssteuerung kann entfallen (der µC kann sicher empfangene Daten verarbeiten (evtl. die Leistung/Speicher für eine Tetris-Anwendung nutzen) und die Daten sind aufgrund der einfachen, etwas verschwenderischen Codierung immer noch bequem mit einfachsten Programmen decodierbar. > Auf einer Seite muss ich Daten ohnehin umwandeln und auf > der Controllerseite tue ich mich leichter damit. wenn du nicht gerade selbstgebastelte interne Formate verwendest dürfte die Umwandlung Wert <--> Text eine einstellige Zeilenanzahl betreffen und praktisch 1:1 vom µC übernommen werden können. Als Hobby kann debugging von Zeitabläufen natürlich Spass machen, aber leichter wird ein (zeitvariabler) Overhead wohl nicht wenn 'feste' (also praktisch nur Daten) Übertragungen ohne spezifische Zustände als Alternative möglich sind.
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.