-
        

Ergebnis 1 bis 10 von 10

Thema: 5 Bytes per UART zwischen 2 µCs übertragen...

  1. #1
    Erfahrener Benutzer Roboter Genie Avatar von Willa
    Registriert seit
    26.10.2006
    Ort
    Bremen
    Alter
    37
    Beiträge
    1.269

    5 Bytes per UART zwischen 2 µCs übertragen...

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Hallo,
    ich müsste mal wieder auf eure Erfahrung zurückgreifen... Ich habe zwei µCs die per UART kommunizieren. Der Sender errechnet aus GPS, Kompass und Drucksensor allerlei buntes Zeugs, dass er dann als vier fertige Bytes an den Empfänger schickt.

    Der Empfänger läuft in einem Dauerloop mit 500 Hz und guckt bei jedem Durchlauf nach ob der Sender etwas geschickt hat. Falls ja, dann bezieht er die empfangenen Daten in seine weiteren Berechnungen mit ein. Falls nein, dann macht er einfach weiter wie bisher. Der Empfänger soll möglichst wenig Rechenzeit für das Abfragen des UARTS benötigen.

    Um die Sicherheit zu erhöhen habe lasse ich beide eine Checksumme berechnen. Jedenfalls glaube ich, dass ich das mache - ich habe mit CRC8 noch keine Erfahrungen.

    Das Problem bzw. meine Befürchtung: Falls mal ein Byte vom Sender oder Empfänger verschluckt wird, sind dann die Daten nicht dauerhaft verschoben? Also Externalinput(1) entspricht nicht mehr Command(1) ; Externalinput(2) nicht mehr Command(2) und so weiter. Das müsste ich unbedingt verhindern. Vielleicht mit einer Art Marker am Ende des Arrays?

    z.B. so:
    Wenn die letzten drei Bytes das spezifische Muster 0; 255; 0 haben, dann sind die vorherigen 4 Bytes richtig empfangen worden. Gibt es so eine Möglichkeit? CRC8 macht ja so etwas ähnliches, aber wie bringe ich dem Empfänger bei, dass er bei Unstimmigkeiten wieder richtig synchronisiert (so dass Externalinput(1) wieder aus Command(1) gezogen wird)?

    Einen Interrupt möchte ich nicht verwenden, mir wäre es viel lieber, wenn der Empfänger regelmäßig mit 500 Hz guckt ob etwas da ist, und sich bei seinen restlichen Berechnungen nicht unterbrechen lässt.

    Hier mal der vereinfachte Code:

    Sender (dieser Code läuft in einem Loop mit 5 Hz)
    Code:
    Clear Serialout
    Command(1) = OutputPID_height_integer
    Command(2) = OutputPID_heading_integer
    Command(3) = OutputPID_roll_integer
    Command(4) = OutputPID_nick_integer
    Command(5) = Crc8(command(1) , 4)
    Printbin Command(1) ; 5
    Empfänger (dieser Code läuft in einem Loop mit 500 Hz)
    Code:
    If Ischarwaiting() > 0 Then
       Inputbin Externalinput(1) , 5
       Crc = Crc8(externalinput(1) , 4)
       If Crc = Externalinput(5) Then
          Heighthold_int = Externalinput(1)
          Heading_int = Externalinput(2)
          Gps_roll = Externalinput(3)
          Gps_nick = Externalinput(4)
       End If
    Else
       'do nothing
    end if
    Wäre wunderbar wenn mir jemand Tipps geben könnte....
    Viele Grüße, William
    -> http://william.thielicke.org/

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    30.12.2008
    Beiträge
    1.418
    ich habe das einfach mit einem startbyte gemacht
    255
    dieser wert wird bei mir z.b. nie erreicht

  3. #3
    Erfahrener Benutzer Roboter Genie Avatar von Willa
    Registriert seit
    26.10.2006
    Ort
    Bremen
    Alter
    37
    Beiträge
    1.269
    ...und dann im Empfänger so?
    Code:
    If Ischarwaiting() > 0 Then
       Inputbin startbyte
       if startbyte = 255 then
          inputbin externalinput(1),4
       end if 
    end if
    Viele Grüße, William
    -> http://william.thielicke.org/

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    30.12.2008
    Beiträge
    1.418
    in meinem konkretenfall so
    ist zwar c aber dennoch find ich gut verständlich
    ich werde das auch noch optimieren müssen
    ich habe hier noch den fall das keine daten kommen bedacht das war bei mir besonders wichtig
    ansonsten bei treppe und keine verbindung treppe: robo ade
    if ((time+500)<millis()){
    analogWrite(5,0);
    analogWrite(6,0);
    analogWrite(11,0);
    analogWrite(3,0); //HALT!!!
    digitalWrite(13,0);
    der teil immer wieder

    Code:
    #include <Servo.h> 
    int byte1;
    int byte2;
    int byte3;
    int byte4;
    int byte5;
    int byte6;
    int byte7;
    int startbyte;
    unsigned long time;
    Servo myservo;
    void setup() {
      // initialize serial communications at 9600 bps:
      Serial.begin(9600); 
    myservo.attach(9);
    
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      pinMode(3, OUTPUT);
      pinMode(11, OUTPUT);
      pinMode(13, OUTPUT);
      digitalWrite(13,1);
    }
    
    
    void loop() {
      digitalWrite(13,1);
      time = millis();
    
      do {
    
    
        if (Serial.available() ==1) {
          startbyte=byte(Serial.read());  //serial eingang prüfen ob "post 
        }
    
       // startbyte=0;
        if ((time+500)<millis()){
          analogWrite(5,0);
          analogWrite(6,0);
          analogWrite(11,0);
          analogWrite(3,0);          //HALT!!!
          digitalWrite(13,0);
    //myservo.write(byte5-1);
        }
    
      } 
      while (startbyte<254);
    startbyte=0;
    
    
    
      digitalWrite(13,1);
      time = millis();
    
      do{ 
        if (time+1000<millis()){
          analogWrite(5,0);
          analogWrite(6,0);
          analogWrite(11,0);
          analogWrite(3,0);          //HALT!!!
    //myservo.write(byte5-1);
        } 
      }
      while (Serial.available() ==0); //warten bis was ankommt
    
      byte1=Serial.read();
    
      do{ 
        if (time+1000<millis()){
          analogWrite(5,0);
          analogWrite(6,0);
          analogWrite(11,0);
          analogWrite(3,0);          //HALT!!!
    //myservo.write(byte5-1);
        } 
      }
      while (Serial.available() ==0); //warten bis was ankommt
    
      byte2=Serial.read();
    
      do{ 
        if (time+1000<millis()){
          analogWrite(5,0);
          analogWrite(6,0);
          analogWrite(11,0);
          analogWrite(3,0);          //HALT!!!
    //myservo.write(byte5-1);
        } 
      }
      while (Serial.available() ==0); //warten bis was ankommt
    
      byte3=Serial.read();
    
      do{ 
        if (time+1000<millis()){
          analogWrite(5,0);
          analogWrite(6,0);
          analogWrite(11,0);
          analogWrite(3,0);          //HALT!!!
    //myservo.write(byte5-1);
        } 
      }
      while (Serial.available() ==0); //warten bis was ankommt
    
      byte4=Serial.read();
    
    
      do{ 
        if (time+1000<millis()){
          analogWrite(5,0);
          analogWrite(6,0);
          analogWrite(11,0);
          analogWrite(3,0);          //HALT!!!
    //myservo.write(byte5-1);
        } 
      }
      while (Serial.available() ==0); //warten bis was ankommt
    
      byte5=Serial.read();
    
      analogWrite(5, byte1-1);           
      analogWrite(6, byte2-1);           
      analogWrite(3, byte3-1);           
      analogWrite(11, byte4-1);           
    myservo.write(byte5-1);
    }

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von Vitis
    Registriert seit
    06.01.2005
    Ort
    Südpfalz
    Alter
    43
    Beiträge
    2.240
    für wenig Rechenzeitverbrauch nicht pollen, sondern urxc-Interrupt benutzen und Daten in nen Ringpuffer / oder Array speichern. Dann n Flag setzen und in der Mainloop nur nach dem Flag suchen für die Verarbeitung.
    Vor den Erfolg haben die Götter den Schweiß gesetzt

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    15.08.2004
    Ort
    Graz
    Beiträge
    342
    So etwas war Teil meines hier vorgestellten Projekts, für dich von Interesse dürfte L0_Serial.bas sein.

    mfg

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.02.2006
    Beiträge
    982
    Ich schreibe in meinen Projekten immer jedes ankommende Byte in einen Buffer, solange bis CR-LF (asc 10 & 13) empfangen wird oder der Buffer voll ist.
    Ist das der Fall pruefe ich ob die Daten im Buffer sinnvoll sind und verarbeitet oder verworfen werden.
    Nam et ipsa scientia potestas est..

  8. #8
    Erfahrener Benutzer Roboter Genie Avatar von malthy
    Registriert seit
    19.04.2004
    Ort
    Oldenburg
    Beiträge
    1.379
    Hallo William!

    Ich habe den Thread nur überflogen, ich hoffe dass ich Deine Frage richtig verstanden habe. Falls ja:

    Ich mache sowas in der Tat mit einem Ringpuffer (das Schlagwort ist ja schon gefallen). Jedes empfangene Zeichen wird einfach an den aktuellen Index des Puffers geschrieben, dann durchsuche ich den Puffer nach einer Startbedingung (die in den Daten natürlich nicht vorkommen darf). Wenn ich sie finde, lese ich ab dort die Daten und verwende sie. Ich hab das vor einiger Zeit mal quick-and-dirty gemacht, nämlich so:

    Code:
    Do
       If Ischarwaiting() <> 0 Then
          Toggle Led2
          Circ_buf(circ_buf_i) = Inkey()
          If Circ_buf_i < 34 Then
             Incr Circ_buf_i
          Else
             Circ_buf_i = 1
          End If
       End If
       '
       ' puffer nach datenstartbedingung (&HFFFF) durchsuchen
       For Ub1 = 1 To 34
          If Circ_buf(ub1) = &HFF Then
             ' ein &HFF gefunden, evnt. datenstartbedingung?
             Ub2 = Ub1 + 1
             If Ub2 = 35 Then Ub2 = 1                           ' pufferende erreicht
             If Circ_buf(ub2) = &HFF Then
                ' zwei &HFF in folge gefunden -> datenstartbedingung
                Incr Ub2                                        ' datenbeginn in circ_buf
                For Ub3 = 1 To 32
                   ' datan in arr_buf einlesen
                   If Ub2 = 35 Then Ub2 = 1
                   Arr_buf(ub3) = Circ_buf(ub2)
                   Incr Ub2
                Next Ub3
                Exit For
             End If
          End If
       Next Ub1
       
       'hier kann man dann was mit den Daten in Arr_buf machen 
    Loop
    Ich behaupte nicht, dass das schön programmiert ist, es funktioniert aber gut .

    Achso, was ich dann vielleicht noch nachtragen sollte: eine CRC hab ich jetzt natürlich nicht integriert, das könntest Du ja aber zusätzlich natürlich noch machen. Aber - wenn ich das jetzt richtig sehe - das bringt Dir natürlich auch keine 100%ige Sicherheit, denn es kann immerhin sein, dass ein Fehler aufgetreten ist, der zur gleichen CRC geführt hat wie die richtigen Daten. In meinem Falle war es so, dass es zu verkraften gewesen wäre, wenn mal ein "falscher" Datensatz dazwischen wäre - hauptsache der nächste wird dann wieder korrekt im Leseraster interpretiert...

    Vielleicht kannst ja was damit anfangen...


    Viele Grüße
    Malte

  9. #9
    Erfahrener Benutzer Roboter Genie Avatar von Willa
    Registriert seit
    26.10.2006
    Ort
    Bremen
    Alter
    37
    Beiträge
    1.269
    Hi, danke für die Tipps. Ich habe jetzt erstmal die einfachste Variante gewählt:
    Code:
        
    'Empfänger   
    If Ischarwaiting() > 0 Then
       Inputbin startbyte
       if startbyte = 255 then
          inputbin externalinput(1),4
       end if
    end if
    Das ist doch eine ganz praktikable Methode die sich bei Bedarf selbst synchronisiert, aber eben nur bei Bedarf.
    Nach meinen Tests vorhin funktioniert das sehr gut. In Datensätzen von ca. 1000 Werten war kein einziger Fehler, obwohl beide µCs nebenbei jede Menge andere Dinge machen.
    Viele Grüße, William
    -> http://william.thielicke.org/

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.556
    Hmm schau Dir einmal bei www.shop.robotikhardware.de/ die Beispielprogramme von z.B. Motorcontrol an. die machen das mit Strings gelegentlich auch mit CRC. Ich habe damit auch schon etwas "gespielt" und konnte mit MIDstring(x,y,z) die Daten (Hier Motor Tick's )aus dem String holen.

    Gruß Richard

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •