Undefinierte bytes bei RS485

Hallo,

ich habe ein kleines Problem mit UART via RS485.
Als Master wird ein Arduino Leonardo verwendet, welcher über Serial die Daten empfängt und über Serial1 an RS485 weitergibt. So weit so gut.
Der UNO empfängt die Daten auch problemlos. Wenn er allerdings die gleichen Daten zurück sendet, zur Sicherheit, dass auch wirklich alles angekommen ist, geht etwas schief.
Wenn ich z. B.
1234567891 sende, kommt beim UNO 1234567891 an, beim Leonardo: 1234567891
123456789123 sende, kommt beim UNO 123456789123 an, beim Leonardo: R123456789123
12345678912345 sende, kommt beim UNO 12345678912345 an, beim Leonardo: 2312345678912345

man sieht, es kommt ab einer gewissen länge zu Problemen beim senden vom UNO zum Leonardo.

Code vom Leonardo:

String inputString = "";
String inputString1 = "";
boolean stringComplete = false;

int DirecControl = 3;

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  inputString.reserve(200);

  pinMode(DirecControl, OUTPUT);
}

void loop() {
  if (stringComplete) {
    digitalWrite(DirecControl, HIGH);
    Serial1.print(inputString);
    Serial1.flush();
    digitalWrite(DirecControl, LOW);
    inputString = "";
    stringComplete = false;
  }
  while (Serial.available()) {
    char inChar = (char)Serial.read(); 
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;
    } 
  }
  while (Serial1.available()) {
    char inChar = (char)Serial1.read(); 
    inputString1 += inChar;
    if (inChar == '\n') {
      Serial.print(inputString1);
      inputString1 = "";
    } 
  }
}

Code vom UNO:

int DirecControl = 3;

String inputString = "";
boolean stringComplete = false;

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

void setup() {
  Serial.begin(9600);
  pinMode(DirecControl, OUTPUT);

  lcd.clear();

  inputString.reserve(200);
}

void loop() {
  if (stringComplete) {
      delay(5);
      digitalWrite(DirecControl, HIGH);
      Serial.print(inputString);
      Serial.flush();
      digitalWrite(DirecControl, LOW);
  inputString = "";
  stringComplete = false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read(); 
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;

      lcd.clear();
      lcd.print(inputString);
    } 
  }
}

Die Verkabelung ist "ganz normal" zwischen A und B habe ich einen 120Ω Widerstand. Zu test zwecken ist die Verbindung nur etwa 4cm lang.

Ich würde mich über jeden Tipp sehr freuen.

Mit freundlichen Grüßen,

Valli

Wenn es eine Übung zum Zwischenspeichern und zu String-Objekten ist, fürchte ich, dass hier dein Problem liegt:

  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;  // kommt mit der anderen Verwendung von inputString durcheinander

Ansonsten geht es einfacher sicher besser:

Ohne String Objekte
Ohne serialEvent
Ohne while schleifen

die while-Schleife ist nicht das Problem. Das mache ich mit char Arrays auch mit einer Schleife. Die wird auch nur durchlaufen wenn mehrere Bytes im Eingangspuffer sind. Wenn die Bytes nur langsam nacheinander kommen wird nur ein Byte eingelesen, dann angebrochen und erst mal wieder loop() durchlaufen.

Die Kommunikation soll dafür ausgelegt sein, Strings zu senden und zu empfangen.
"InputString" wird nur einmal verwendet. Im Code wird unten "InputString1" verwendet.

Hmm, ja...

Könnte es sein, dass nach '\n' zu früh der nächste Text kommt ?

Abhilfe z.B. so (in deinem serialEvent):

   if (inChar == '\n') {
      stringComplete = true;

      lcd.clear();
      lcd.print(inputString);
      return;  // erst später, wenn stringComplete wieder false ist, weiterlesen.
   }

Wobei ich noch anmerken möchte:

  • serialEvent ist zum Glück gar keine Interrupt-Routine
  • es ist evtl. übersichtlicher, wenn du in loop schreibst, wie es abläuft, nämlich:

void loop () {
...
if (Serial.available()) serialEvent();
}

Ich habe heute das mit dem return ausprobiert, hilft auch nichts :confused:

Heute habe ich mal ausprobiert, nicht nur den Leonardo empfangen zu lassen, sondern parallel auch einen FTDI.
Wenn der FTDI angeschlossen ist, kommt beim Leonardo und beim FTDI das gleiche an. Sobald der FTDI wieder ausgesteckt wird, kommen beim Leonardo vor dem String wieder irgendwelche Bytes...

Ich würde mich sehr über weitere Tipps freuen!

Valli

Sobald der FTDI wieder ausgesteckt wird

Eigentlich wird blind gesendet. Ein µC merkt nicht, ob etwas serielles irgendwo ankommt oder nur HIGH-LOW Wechsel an irgendwelchen Pins erzeugt...

PC                  Leonardo            Uno
SerialMonitor  ----  Serial             LCD
                     Serial1  -----x-- Serial
                                   |
Terminal2      --------------------+

Hab ich das so richtig verstanden
Die Verbindung x solltest du evtl. genauer beschreiben ... ( Sende und Empfangsleitungen )

Wenn es durch Anstecken funktioniert, ist es wohl ein elektrischen Problem ?
Wenn du die RS485 Adapter weglässt ?

Hallo,

nur mal so als Verdacht: Könnte es sein daß es ein Problem mit dem Ruhepegel am RS485 Bus ist? Also Pull-Up / Pull-Down u.s.w.Z.B. so daß der Empfänger noch schnell ein weiteres Bit erkennt wenn der Bus auf den vorgegebenen Ruhepegel springt...

Christian

Eigentlich soll es so funktionieren:

PC-Serial ----> USB ---->Leonardo ---->RS485 ---->RS485 ---->Serial ---->UNO ..und das ganze wieder zurück.
Wenn ich hier: ||| RX und TX vom FTDI anschließe, geht alles perfekt...

Ich habe einfach die komplette Schaltung nochmal aufgebaut so: BILD aber das Phänomen tritt immer noch auf.

Wenn ich:
77777777 sende, kommt am UNO 77777777 an, am Leonardo: ºººººººR77777777

Das mit dem Pull-Up / Pull-Down ergibt sinn, allerdings scheint es ja z. B. auf dem Bild auch ohne zu funktionieren.

Hallo,

eventuell wirkt der Eingangswiderstand des verwendeten FTDI Modules bereits wie ein Pull Up/Down...

Oszilloskop & Logic Analyser hast Du vermutlich nicht zur Hand? Das wäre jetzt sehr pratisch um mal nachzusehen was wirklich wo passiert ;D

Bleibt also nur raten & probieren; mach mal einen mittleren Widerstand, vielleicht 10k oder so, an der Stelle wo der FTDI sitzt gegen Masse.

Christian