Einfaches binäres Protokoll



  • Q schrieb:

    Das macht das Problem doch noch schlimmer, wenn wir noch mehr Steuerzeichen verwenden.

    Hä? Hast du dir eben überhaupt meinen ganzen Beitrag durchgelesen? Ich sehe kein Problem mehr, das funktioniert so.



  • Hä? Hast du dir eben überhaupt meinen ganzen Beitrag durchgelesen? Ich sehe kein Problem mehr, das funktioniert so.

    cooky451 schrieb:

    read(b, sizeof(char))
    switch (b)
    {
    case 'a':
      beginBlock(); 
      ...
    }
    

    Jedem Buchstaben könnt ihr dann ein "Steuerzeichen" zuweisen.

    Das Problem ist, der Microkontroller sendet permanent über die serielle Schnittstelle Daten.

    Man kann also zu jedem Zeitpunkt das Kabel einstecken und Daten empfangen.
    Woher weiß man dann, wann der header losgeht, ohne einen speziellen code dafür zu benutzen, was die schon erwähnten Probleme bereitet?

    Funktioniert das dann immer noch?
    Wenn ja, dann erklär das bitte nochmal.
    Ich denke nämlich das es das nicht tut, wenn man zu jedem beliebigen Zeitpunkt einstecken kann.
    Dann kann es nämlich sein, dass gerade eine Zahl übertragen wird. Das Bytemuster der Zahl enthält dann Steuerzeichen, die fälschlicherweise als Steuerzeichen interpretiert werden und dann hat man den Salat.

    Ethon schrieb:

    Das ist ein Argument. Dann würde ich mit einer möglichst großen MagicNumber arbeiten. Ein

    0xDEADDEADDEADDEAD

    sollte da schon sehr zuverlässig sein. 😉

    Jo sowas werd ich dann auch nehmen, falls wir keine anderen Methoden finden, ist bestimmt sicherer als 2003 oder sowas^^



  • Q schrieb:

    Funktioniert das dann immer noch?

    Klar.

    readBlock()
    {
      TYPE type = 0;
      while (type != 'e')
      {
        switch ((type = readType()))
        {
        case 'e':
          break;
        case 'f':
          readFloat();
          break;
        case 'i':
          readInt();
          break;
        default:
          throw "ALLES_KAPUTT";
          break;
        }
      }
    }
    

    Drüber liegt natürlich eine Funktion, die dann irgendwelche anderen Daten liest, bis ein 'b' kommt, dann wird diese Funktion aufgerufen. Falls eh nur solche Blocks empfangen werden, kann man das natürlich alles in eine Funktion packen etc., ist nur pseudo-Code. Allerdings sollte klar werden, dass das Programm zu jeder Zeit in einem klar definierten Zustand ist und immer weiß, worauf es warten muss bzw. was als nächstes kommt. Ich sehe kein Problem, wann die Daten übertragen werden, oder wie zerstückelt die sind, spielt eigentlich keine Rolle.



  • Ich verstehe leider nicht, warum das funktioniert.

    Ich rufe die funktion auf, der Microkontroller ist gerade dabei, eine Zahl zu senden, kein Steuercode.

    Das char, dass du einlist ist etwas, was weder 'e', noch 'f' noch 'i' ist.
    Und schon fliegt dir die exception um die Ohren.

    Vielleicht habe ich das nicht klar genug gesagt.
    Der Microkontroller sendet IMMER, auch wenn gar kein Computer angeschlossen ist.
    Zu jedem beliebigen Zeitpunkt kannst du den Stecker einstecken und Daten empfangen, aber du weißt erstmal nicht, ob das, was gerade gesendet wird eine Zahl oder ein Steuerzeichen ist.

    Falls das dennoch funktioniert, bitte ich nochmals um eine Erklärung.

    Vielen Dank für deine Hilfe.



  • Q schrieb:

    ..

    Ich dachte bis jetzt ja auch, dass man selbst etwas an den Microcontroller sendet. Natürlich dürfen keine Daten innerhalb eines Blocks verloren gehen. Das kannst du mit keinem Protokoll ausbügeln. Das Protokoll ist ja gerade dafür da, um Regeln für die Übertragung aufzustellen. So wird ja auch gar nicht garantiert, dass du überhaupt Anfangs/End Zeichen erhälst. Wie stellst du dir das vor? Wie hat das denn mit Text geklappt bis jetzt?



  • Mit text wars so, dass '\n' bedeutet, dass ein neuer block kommt, ' '(leerzeichen) heißt neue zahl und dazwischen sind die zahlen asci kodiert.
    Da die Zahlen nur aus 0-9 Punkt und e^ oder sowas bestehen und kein '\n' oder ' '(leerzeichen) enthalten, war das kein Problem.



  • Q schrieb:

    Mit text wars so, dass '\n' bedeutet, dass ein neuer block kommt, ' '(leerzeichen) heißt neue zahl und dazwischen sind die zahlen asci kodiert.
    Da die Zahlen nur aus 0-9 Punkt und e^ oder sowas bestehen und kein '\n' oder ' '(leerzeichen) enthalten, war das kein Problem.

    Aha? Microcontroler sendet die Zahl "5533", Kabel wird nach "55" eingesteckt. Oups, komplett falsche Zahl. :p

    Edit: Und wie habt ihr das mit Blockanfang gemacht? Eben war es doch noch so wichtig, an welcher Stelle die Zahl im Block steht.



  • cooky451 schrieb:

    Q schrieb:

    Mit text wars so, dass '\n' bedeutet, dass ein neuer block kommt, ' '(leerzeichen) heißt neue zahl und dazwischen sind die zahlen asci kodiert.
    Da die Zahlen nur aus 0-9 Punkt und e^ oder sowas bestehen und kein '\n' oder ' '(leerzeichen) enthalten, war das kein Problem.

    Aha? Microcontroler sendet die Zahl "5533", Kabel wird nach "55" eingesteckt. Oups, komplett falsche Zahl. :p

    Edit: Und wie habt ihr das mit Blockanfang gemacht? Eben war es doch noch so wichtig, an welcher Stelle die Zahl im Block steht.

    Na, da hätten sie doch einfach alles bis zum ersten newline verwerfen können.



  • Ein Block fängt nach \n an.

    Das mit 5533 ist auch kein Problem.
    Solange bis das erste mal \n kommt wird alles ignoriert, also kann da nichts passieren.



  • Q schrieb:

    Ein Block fängt nach \n an.

    Das mit 5533 ist auch kein Problem.
    Solange bis das erste mal \n kommt wird alles ignoriert, also kann da nichts passieren.

    Ignorieren ist also erlaubt, ok. Dann braucht man also irgendwelche Steuerzeichen, die nicht in Daten vorkommen können. "Echte" binäre Übertragung fällt somit also weg, ihr müsst euch ein Kodierverfahren einfallen lassen. Base64 würde sich z.B. anbieten. Dann könnt ihr Steuerzeichen von Daten eindeutig unterscheiden.



  • D.h. es wird immer ein char empfangen, sodass das Steuerzeichen dann aus einem char bestehen müsste? Oder werden immer ints empfangen? Oder kann man gar bei verschiedenen Bits einstecken?



  • wxSkip schrieb:

    D.h. es wird immer ein char empfangen, sodass das Steuerzeichen dann aus einem char bestehen müsste?

    Jo. Allerdings lohnt die ganze Aktion natürlich wirklich erst, wenn die ASCII Darstellung sehr teuer ist. Es ist wesentlich billiger eine "5" als String zu übertragen, als als int. Wenn die Zahlen also gar nicht so groß sind, lohnt vielleicht auch mal ein Blick auf
    http://de.wikipedia.org/wiki/LZ77



  • Base64 würde sich z.B. anbieten. Dann könnt ihr Steuerzeichen von Daten eindeutig unterscheiden.

    Was wohl schon wieder länger wäre als die ASCII-Darstellung.



  • Hm das mit der Base64 kodierung sieht ziemlich kompliziert aus...
    Aber falls es da was gutes fertiges zu gibt, würde das natürlich gehen.

    Evtl. ignorier ich das Problem auch einfach, weil die Wahrscheinlichkeit relativ gering ist, oder ich überprüf vorm senden, ob ich was problematisches sende und wenn ja, passe ich es minimal an.

    Edit: Wir haben inzwischen auch gemerkt, dass binär gar nicht soviel wengier ist als ascii und außerdem sind wir uns nicht mehr ganz sicher, ob die menge der daten das hauptproblem ist.
    Wir werden das erstmal ein wenig weiter "erforschen" und dann mal schaun, was wir tun.

    Weitere Vorschläge sind natürlich trotzdem willkommen.



  • Q schrieb:

    Edit: Wir haben inzwischen auch gemerkt, dass binär gar nicht soviel wengier ist als ascii und außerdem sind wir uns nicht mehr ganz sicher, ob die menge der daten das hauptproblem ist.
    Wir werden das erstmal ein wenig weiter "erforschen" und dann mal schaun, was wir tun.

    cooky451 schrieb:

    Jo. Allerdings lohnt die ganze Aktion natürlich wirklich erst, wenn die ASCII Darstellung sehr teuer ist. Es ist wesentlich billiger eine "5" als String zu übertragen, als als int. Wenn die Zahlen also gar nicht so groß sind, lohnt vielleicht auch mal ein Blick auf
    http://de.wikipedia.org/wiki/LZ77



  • Das LZ77 guck ich mir gleich an, aber dazu muss ich folgendes sagen:
    Ich kenne LZW und vermute, dass das so ähnlich ist.
    Da wird nach und nach ein Wörterbuch aufgebaut, was hier aber nicht praktikabel ist, weil man zu jedem Zeitpunkt sich einklinken kann.
    Außerdem muss man wenn man sich zu jedem Zeitpunkt einklinken kann trotz kompression den "Anfang" finden (der früher nach dem ersten \n los ging).
    Ich hoffe mal, dass das damit möglich ist.



  • Wenn ihr ein bisschen Rechenzeit für binäre Operationen übrig habt, könnt ihr ja auch einfach je nach Datenpaket abwechselnd eine 1 und eine 0 ins High-Bit jedes chars setzen - und die anderen 7 Bits für die Codierung nutzen. Dann nehmt ihr halt 5 chars statt 4 für eine 32-bit-Zahl und lasst die restlichen 3 Bit leer oder wenn die euch reichen, schreibt ihr dort den Typ rein (int, unsigned int, float, ...).



  • 1. Falls man das Ding zu jedem Zeitpunkt reinstecken kann und die vorherigen Daten eh egal sind, kann man die Synchronisierung auch sehr viel später machen.
    Einmal pro Sekunde, einmal pro Minute, wie auch immer.

    2. Hauptsache ist der Magic-String ist länger als jede potentielle vorkommende erlaubte Zeichenkette.
    Wenn 4 Byte für die Input-Werte erlaubt sind, dann macht doch einfach 16 Byte Magic Sequence.



  • nurf schrieb:

    2. Hauptsache ist der Magic-String ist länger als jede potentielle vorkommende erlaubte Zeichenkette.
    Wenn 4 Byte für die Input-Werte erlaubt sind, dann macht doch einfach 16 Byte Magic Sequence.

    Nö. Es könnte ja sein, dass zufällig 4 Input-Werte à 4 Bytes ankommen, die zusammen genau den Magic String ergeben. Außer, du willst nach jedem Input-Wert den Magic-String senden. Dann ist es aber mit der Ersparnis dahin.



  • Ein Vorschlag ohne den ganzen Thread gelesen zu haben.

    Q schrieb:

    2003 3 iff XXXX XXXX XXXX 2058

    • Du startest jede Übertragung mit vier Einsen (Praembel): 1111. Wenn du das bekommst, geht eine Übertragung los.
    • Danach kommt ein Wechsel auf 0 als Startbit um einzuleiten, dass die Typinformationen kommen.
    • Anschließend folgt deine Typcodierung. Hier muss ich aber von dir erfahren, wieviele Typen du haben kannst. Vielleicht kann man dort die Anzahl und die Typen zusammen kodieren.
    • Jetzt das interessante. Du benutzt folgende Codierung. Eine 1 als 10 und eine 0 als 01. ZB ist die Zahle 5 = 0101 in dieser Kodierung (habe vergessen wie diese heißt) = 01100110. Mit dieser Kodierung wirst du nie mehr als zwei aufeinanderfolgende Einsen bzw Nullen haben. Dh, dort werden nie vier 1 wie im Praembel erscheinen. Also sollte das Praembel mindestens drei gleiche Bits haben, wieso ich vier habe, habe ich dummerweise waehrend des Schreibens vergessen 🙂 Da war irgendwas mit Startbit und Typkodierung.

    Somit werden vier Einsen - jetzt weiß ich auch wieso, weil ich im Kopf hatte die Typen als drei Bit zu kodieren und da 111 drin sein könnte, aber dafür brauche ich ja ehe noch Informationen von dir - nie in deinem Daten vorkommen. Du musst dann von den reinen Daten doppelt soviel Übertragen, wie du gern haettest, aber vllt stört dich das ja nicht.

    Wenn du den Stecker mittendrin einsteckst, wartest du einfach auf die vier Einsen. Und stell dir mal vor du würdest das Startbit (0) nicht haben, und bei der letzten Praembel-1 einstecken und dann würden nochmal drei Einsen wegen des Types kommen und du würdest das als Praembel dann faelschlicherweise interpretieren. Aber genau dafür ist der Wechsel auf 0 da. Also einfach auf vier Einsen und dann den Wechsel auf 0 warten und du weißt, dass es jetzt startet.

    Edit: Manchester-Codierung war es 🙂


Anmelden zum Antworten