Montag, 22. September 2014

Einen Bus mit RS485 aufbauen

[Under Construction] (Achtung, der Beitrag ist noch nicht ganz fertig!)


Wenn man mit Microcontrollern arbeitet, will man früher oder später mehrere Microcontroller miteinander reden lassen. Eine bewährte Möglichkeit ist die Serielle Schnittstelle (Auch UART oder RS232 genannt). Will man aber mehr als zwei Microcontroller miteinander kommunizieren lassen, kann es schnell kompliziert werden, zumal viele Microcontroller gerade mal eine einzige serielle Schnittstelle bieten. Prinzipell könnte man einfach mehrere Sender und Empfänger jeweils gleichzeitig auf ein und die selben TX und RX Leitungen hängen, allerdings muss man dafür sorgen, dass niemals zwei Teilnehmer gleichzeitig senden. Außerdem darf man niemals zwei GPIO Ausgänge zusammen schalten (Was bei mehreren Microcontrollern auf der gleichen TX-Leitung der Fall ist), da man sich damit seine Hardware zerschießen kann. Die Lösung des Problems liegt in einem Bussystem. In der Industrie ist der RS485 Bus sehr verbreitet. Das mag vielleicht kompliziert klingen, ist es aber eigentlich nicht. In diesem Beitrag gebe ich einleitende Informationen zu RS485 und zeige am Ende eine kleine Beispielschaltung zum nachbauen. Wer diese Seite also über google gefunden hat und es nicht abwarten kann, kann also Direkt zu Abschnitt 3 springen. Wer sich tiefer für die Materie interessiert, liest einfach weiter.

1. Was ist RS485? Wo ist der Unterschied zu RS232?

Bei RS485 handelt es sich um einen sogenannten Feldbus. Das Wort Feld bedeutet salopp gesagt, dass das Übertragungskabel nicht nur unter Laborbedingungen gut funktioniert, sondern dass man es getrost auch mal "in den dreck" schmeißen kann und auch bei Umgebungen mit Störeinflüssen immer noch eine saubere Datenübertragung hat. Der Grund, warum das bei RS485 funktioniert, ist die Differentialübertragung. D.h. Es werden zwei Leitungen für die gleiche Information genutzt, die sog. A und B Leitung. In einigen Bussystemen auch Busplus und Busminus genannt. Auf Kanal A wird die Information genauso wie bei RS232 übertragen. Auf Kanal B allerdings invertiert. Der Empfänger subtrahiert nun beide Signale und wertet das Ergebnis aus. Wenn jetzt von außen eine Störung einstreut (Gleichtaktstörung), rechnet sich der Fehler wieder heraus:



Im diesem Bild ist der Signalverlauf von Leitung A und B dargestellt. Der untere Signalverlauf ist das Ergebnis, was der Empfänger "sieht". Eine fehlerhafte Einstreuung ist in Rot dargestellt. (Sowas passiert z.B. wenn man das Licht einschaltet). Da der gleiche Fehler auf beiden Leitungen auftritt, wird der Fehler herausgerechnet und ist im resultierendem Signal praktisch nicht mehr vorhanden.

Hier ein etwas extremeres Beispiel:



Hierbei handelt es sich zwar nicht um RS485 sondern um den FlexRay Bus, dieser verwendet jedoch ebenfalls ein Differenzsignal. Grün ist hierbei Kanal A, Blau ist Kanal B. Und Rot ist das resultierende Signal, was nach Subtraktion von A und B herauskommt. Man sieht hier sehr deutlich ein unsauberes Eingangssignal. Und Obwohl die Kurven sehr verbogen aussehen, kommt am Ende ein sauberes Signal heraus, weil sich der Fehler herausrechnen lässt. Ohne Differenzsignal würde man hier unter Umständen Datenmüll erhalten.

2. Warum einen Bus verwenden?


Bei einem Bussystem werden mehrere Teilnehmer mit nur einer einzigen Leitung verbunden..Das ist sehr vorteilhaft, da man nicht jedes mal eine extra Leitung zu jedem Teilnehmer ziehen muss und somit GPIO Pins sparen kann. Ich habe derzeit ein Projekt, bei dem ich genau vor diesem Problem stehe. Ich habe einen Hauptcontroller und acht weitere Microcontroller (Slaves), denen ich Befehle geben möchte. In Zukunft plane ich noch mehr Slaves zu verwenden und so langsam entwickelt sich auf meiner Platine ein regelrechter Kabelsalat.

In diesem Abschnitt möchte ich erläutern, wie man einen RS485 Baustein verschalten muss und was es mit den merkwürdigen Pinbezeichnungen auf sich hat. Ich beziehe mich hierbei auf einen MAX485 Baustein. Schauen wir uns die Pins also einmal an:




Die Belegung der Pins ist:

1: RO (Receiver Output)
2: /RE (Receive Output Enable)
3: DE (Driver Outputs Enable)
4: DI (Driver Input)
5: GND (Masse)
6: A (Bus Plus)
7: B (Bus Minus)
8: Vcc (+5V)

Setzt man /RE auf low, wird der Transceiver in den Empfangsmodus versetzt. Sämtliche Busaktivitäten an den A und B pins wird dann an den RO pin weitergeleitet, der beim Microcontroller überlicherweise mit dem RX-Pin verbunden ist.

Ist analog dazu DE auf high gesetzt, wir der Transceiver in den Sendemodus versetzt. Daten die per TX-Pin vom Microcontroller am DI Pin angelegt werden, werden an den Bus weitergeleitet.

Ist /RE auf low und DE gleichzeitig auf high, so empfängt der sender seine soeben gesendeten daten gespiegelt zurück, da er gleichzeitig am Bus lauscht.

Setzt man /RE auf high und DE auf low, versetzt man den Transceiver in einen Sleep modus. Das ist sehr praktisch, wenn der verwendete Microcontroller nur über eine einzige UART Schnittstelle verfügt. Dann kann man immer noch bequem per printf() debuggen, ohne den Bus vollzumüllen bzw. den chip per FTDI flashen, ohne dass die Programmiersoftware bzw. der Bus dadurch gestört wird.

Während der DE Pin eines Teilnehmers auf high gesetzt ist, kann kein anderer Teilnehmer senden, da der Bus dann blockiert ist! Daher sollte man DE nach jedem Sendevorgang wieder zurück auf LOW setzen, um den Bus für die Anderen wieder freizugeben!

Im folgendem Beispiel sind zwei MAX485 Bausteine miteinander verschaltet. Der Linke ist dabei als Sender und der rechte als Empfänger konfiguriert:





Die Konfiguration geschieht über die /RE und DE pins. Praktischerweise sind /RE und DE komplementär ausgeführt. Die Pins vom linken MAX485 werden, wie man im Schaltplan sehen kann, direkt mit VCC (also +5V) verbunden. Dadurch befindet er sich im Sendemodus, aber lauscht nicht am Bus. Umgekehrt dazu liegen beim rechten MAX485 Baustein die Pins auf Masse (0V). Dadurch ist der Baustein im Empfangsmodus. Daten die auf den DI pin gehen, werden dann einfach ignoriert und nicht an den Bus weitergeleitet.

Selbstverständlich kann man die /RE und DE Pins auch einzeln an GPIO Pins des Microcontrollers hängen und im Betrieb entscheiden, ob man gerade Sender oder Empfänger oder beides sein will.
Es ist wichtig, dass an den jeweiligen RX pins ein pulldown Widerstand vorhanden ist! Legt man nämlich \RE auf high, wird der RO Ausgang elektrisch abgeschaltet und geht daher in einen undefinierten Zustand über. Ohne Pulldown Widerstand erhält man dann irgendwelchen zufälligen Datenmüll!


3. Eine Beispielschaltung


demnächst...

4. Und wo ist der Haken?


Bussysteme haben natürlich auch Nachteile. Einer davon sind Leitungsreflektionen. Bei kleinen Bussen mit nur zwei Microcontrollern fällt das noch nicht so doll auf. Je länger der Bus allerdings wird und je mehr Teilnehmer man dran hängt, desto stärker fallen diese Reflektironen ins Gewicht. Irgendwann kommt es dann zu fehlerhaftem Datenempfang. Um das zu vermeiden verbaut man sog. Abschlusswiderstände an beiden Leitungsenden. Bei RS485 sind das jeweils 120 Ohm.

[Bild mit Abschlusswiderständen]

Außerdem kann ein einziger Amoklaufender Microcontroller den gesamten Bus blockieren und somit die gesamte Kommunikation lahmlegen. (Beispielsweise wenn einer den DE Pin nicht mehr auf LOW setzt und den Bus somit nicht mehr freigibt!)

Und damit sind wir fertig! Bei bedarf können mehr Teilnehmer in den Bus gehängt, oder wieder entfernt werden. Bei den normalen Transceivern kann man maxmal 32 Teilnehmer in den Bus hängen. Es gibt jedoch auch Bausteine, bei denen mehr möglich ist. Diese werden dann z.B. mit 1/2 Load bezeichnet, bei denen dann 64 Teilnehmer möglich sind. Die mir maximal bekannten Bausteine können 1/8 load, mit denen 256 teilnehmer möglich sind. Solche Bausteine sind dann aber auch dementsprechend teurer.

Ich hoffe ich konnte dem ein oder Anderen mit diesem Beitrag helfen.
Bei Unklarheiten oder sonstigem Feedback könnt ihr gerne einen Kommentar hinterlassen. :)




Keine Kommentare:

Kommentar veröffentlichen