TwinBus Analyse

Ich empfinde es immer etwas störend, wenn ich durch ein Klingeln an der Haustür aus einer konzentrierten Tätigkeit gerissen werde. Besonders lästig und frustrierend ist es jedoch, wenn ich mich zur Türsprechanlage begebe, und dort feststellen muß, daß der Besucher überhaupt nicht zu mir will, sondern gleich mehrere Klingeltaster betätigt hat, in der Hoffnung, daß irgendein Trottel einfach den Türöffner betätigt, und ihn ins Haus lässt (aus welchen Gründen auch immer).
 
Eine kurze Recherche auf der Webseite des Herstellers der hier verbauten Klingelanlage ergab, daß alle "Wohntelefone" (Bezeichnung laut Bedienungsanleitung) mit einem Zweidrahtbus miteinander (und der Klingelanlage) verbunden sind. Das müsste bedeuten, daß jegliche Betätigungen der Klingelknöpfe an jedem Wohnungsanschluß signalisiert werden, und erst das Wohntelefon enscheidet, ob daraufhin ein akustisches Signal erzeugt wird oder nicht. Damit sollten sich die unerwünschten "Mehrfachklingler" doch erkennen lassen ...

Der "TwinBus"

Über den vom Hersteller der Klingelanlage "TwinBus" genannten Zweidrahtbus, der die Komponenten der Anlage miteinander verbindet, waren nur sehr wenig konkrete Angaben zu beschaffen. In einem herunterladbaren "Systemhandbuch" wurde nur erwähnt, daß dieser Bus u.a. eine Betriebsspannung von ca. 24V liefert, der Schleifenwiderstand maximal 20Ω betragen darf, und maximal 30 Stationen an jedem der maximal drei Bussegmente angeschlossen werden dürfen. Aber Angaben über das Verfahren, wie Daten über den Bus übertragen werden, fehlten natürlich. Auch Recherchen in Bastlerforen ergaben fast nur (wenig hilfreiche) Aussagen wie "Lass die Finger davon, das ist hochempfindlich. " oder "Kauf dir lieber eine Anlage von einem anderen Hersteller. " Nur ein Teilnehmer machte grobe Angaben zu Taktraten, schrieb aber nichts zu verwendeter Schaltung oder Protokoll. Naja, vermutlich möchte er seine eigenen kostenpflichtigen Platinen verkaufen ... Also blieb mir nichts anderes übrig, als selber ein wenig "nachzuforschen" ...

Erste Messungen

erste Messung
Aus dem Systemhandbuch war zu erfahren, an welchen Anschlüssen des Wohntelefons die beiden Adern des Busses ("a" und "b" genannt) zu finden sind. Also schloß ich dort zwei Drähte an, um die beiden Signale außerhalb des Geräts verfügbar zu haben, und dort einige Messungen anzustellen. Ein Multimeter zeigte die erwarteten ca. 24V ("a" negativ, "b" positiv). Um die Datensignale sichtbar zu machen, verwendete ich ein batteriebetriebenes digitales Speicheroszilloskop, denn bei einem netzbetriebenen Oszilloskop ist meist der Masseanschluß mit der Potentialerde verbunden, was zu (tunlichst zu vermeidenden) Kurzschlüssen an den Busleitungen führen könnte. Die Auslösung eines Klingelsignals ergab nebenstehendes Oszillogramm, welches zwei Impulspakete (Request und Response?) von etwa 40ms im Abstand von etwa 10ms mit ca. 4Vss zeigt. Damit ergaben sich schonmal ein paar Parameter zum Entwurf einer Schaltung, die ein solches Signal in ein Eingangssignal für einen Mikrocontroller umwandelt.

Das Mikrocontroller-Interface

Um die Busleitungen möglichst gering zu belasten wählte ich eine kapazitive Entkopplung beider Busleitungen (2x100nF). Damit sich die Koppelkondensatoren auch wieder entladen können, musste ich noch einen 1MΩ Widerstand vorsehen. Ich denke, diese zusätzliche Last sollte gering genung sein, um den Bus nicht weiter zu beeinflussen. Zur Stromversorgung wählte ich ein separates Steckernetzteil mit etwa 5V, um die Betriebsspannung des Busses nicht noch mit einem Spannungswandler zu belasten.
 
Zur Optimierung der Schaltung und der Bauteilwerte verwendete ich eine Simulation mittels ngspice, welches es u.a. erlaubt, eine Spannungsquelle mit einem vorgegebenen Signalverlauf zu simulieren. Somit konnte ich meine Schaltung gleich mit den bisher ermittelten Messdaten simulieren.
Interface-Schaltung

Das "Erdungsproblem"

Interface-Ausgangssignal
Leider zeigten die ersten Messungen am Ausgang der Interface-Schaltung (noch ohne den Mikrocontroller) Signale, die instabil wirkten, und weder mit den Ausgangssignalen der Simulation, noch mit dem Eingangssignal Ähnlichkeiten aufwiesen. Nach einigen Messungen stellte sich heraus, daß die Ausgangsspannung des verwendeten Steckernetzteils mit einer hochohmigen/kapazitiven Sinusschwingung von 50Hz und etwa 150V (gegenüber der "a"-Leitung des Busses) überlagert war. Da das Stecker(schalt)netzteil ja nur zweipolig an der Netzspannung angeschlossen ist, ist davon auszugehen, daß sich darin zwei Kondensatoren befinden, die von den beiden Netzspannungsanschlüssen zur "Ausgangsmasse" führen, und damit ein "Referenzpotenzial" bilden sollen. Das Netzteil der Kingelanlage wird zwar (laut Systemhandbuch) auch nur zweipolig angeschlossen, verwendet aber vermutlich die Potenzialerde als Referenzspannung. Somit ergab sich eine gehörige Brummspannung zwischen dem Steckernetzteil und den Busleitungen, die mein Interface störte.
 
Da ich keine Ausgleichsströme auf dem Busleitungen (und damit ggf. Störungen) verursachen möchte, konnte ich das bisherige Steckernetzteil nicht für diese Anwendung einsetzen. Aber glücklicherweise fand ich noch einen kleinen Transformator und das Gehäuse eines defekten Steckernetzteils in meinen Vorräten. Mit ein paar weiteren Bauteilen konnte ich mir daraus ein klassisches Trafonetzteil bauen, dessen Ausgangsspannung wirklich potenzialfrei ist. Dieses Netzteil benötigt zwar etwas mehr "Standby-Leistung", aber damit liefert die Interface-Schaltung die erwünschten Signale, und ich konnte mich der weiteren Analyse der Bussignals widmen.

Die Signalcodierung

Jedes Impulspaket besteht aus einer Startfolge (Preamble), gefolgt von mehreren (meist vier) Datenpaketen. Das Ende eines Impulspakets wird durch ein oder zwei Impulse von mindestens 400µs signalisiert. Danach kehrt das Signal in den Ruhezustand (hier: ca. 5V) zurück.
 
Die Preamble dient meist der Synchronisation von Sender und Empfänger. Hier besteht sie aus mindestens 70 Impulsen von ca. 60µs in einem Abstand von ca. 70µs.
 
Die Datenpakete codieren hier jeweils ein Datenbyte, welches aus acht Bits besteht, gefolgt von einem Parity-Bit, welches zur Prüfung auf fehlerfreie Datenübertragung verwendet wird und die Anzahl der "1"-Bits in einem Datenbyte immer auf eine gerade Anzahl ergänzt ("Even Parity"). Dieses Verfahren erkennt zwar nur einzelne Bitfehler sicher, scheint aber für die vorgesehene Anwendung ausreichend zu sein. Die Interpretation der Reihenfolge/Wertigkeit der einzelnen Bits in einem Byte obliegt dem Anwender, daher habe ich mal "LSB first" angenommen.
 
Die einzelnen Bits in einem Datenpaket sind durch eine Folge von "kurzen" (ca. 28/35µs) und "langen" (ca. 64/69µs) Impulsen codiert: Jede Bitzelle beginnt mit mehreren kurzen Impulsen, denen mehrere lange Impulse folgen. Das Ende der Parity-Bitzelle (und damit des Datenbytes) signalisiert ein langer Impuls von ca. 195µs. Die Anzahl von kurzen und langen Impulsen definiert, ob eine Bitzelle ein "0"-Bit oder ein "1"-Bit darstellt. Die meisten betrachteten Bitzellen enthielten entweder 8 kurze und 2 lange Impulse, oder 4 kurze und 4 lange Impulse. Vermutlich wird diese Codierung verwendet, um den Gleichspannungsanteil des Signals möglichst gering zu halten, und somit eine kapazitive Auskopplung zu ermöglichen. Die Interpretation, welche der beiden Pulsfolgen denn nun eine "0" oder eine "1" bedeutet, ist dem Anwender überlassen, daher sehe ich eine Bitzelle mit weniger als 6 kurzen Impulsen als "1" an.
 
Anmerkung: Diese Decodierung der Signale basiert auf Daten, die mit einer Abtastrate von 10µs gewonnen wurden, und die Flankensteilheit der Interface-Schaltung ist auch nicht beliebig gering. Daher sind die angegebenen Zeiten teilweise gemittelte Werte, und mit einer gewissen Ungenauigkeit behaftet. Für die Decodierung eines solchen Signals mit Hilfe eines Microcontrollers sollte die Genauigkeit jedoch ausreichen.
 
Da die Übertragungung eines Bytes mit diesem Verfahren mindestens 7ms benötigt, liegt die Datenrate deutlich unter 150 Byte/s, was für eine digital codierte Audio-Übertragung (Gespräch zwischen Wohntelefon und Türsprechstelle) sehr wahrscheinlich nicht ausreicht. Daher ist davon auszugehen, daß auf dem Bus außer den Daten auch Audiosignale auf den Busleitungen übertragen werden. Eine solche Übertragung habe ich zwar bisher noch nicht aufzeichnen können, aber eine Microcontroller-Firmware sollte mit dem Umstand umgehen können, daß auch Impulse auf dem Bus erscheinen können, die nicht dem beschriebenen Schema entsprechen.
Signalcodierung

Die aktuelle Firmware

Um auch die kürzesten Impulse (28µs) der Datenübertragung sicher erkennen zu können, sollte der entsprechende Portpin deutlich schneller eingelesen werden. Bei der Verwendung eines Systemtakts von 4MHz entspräche diese Zeit maximal 27 Zyklen/Instruktionen. Für die Abhandlung eines (Port Changed-) Interrupts (incl. Einlesen der Portdaten und Kopieren eines Timers) würden m.E. mindestens 16 Zyklen benötigt, sodaß dem eigentlichen Programm nur noch 11 Zyklen/Instruktionen zur Verarbeitung der gewonnenen Daten zur Verfügung stehen.
 
Mittels einer Zählschleife gelang es mir, Impulse in einem Interval von 7µs abzutasten, und die Länge von Pulspausen in Schritten von 11µs zu bestimmen, was ausreicht, um kurze Impulse von langen Impulsen sicher zu unterscheiden. Außerdem werden die Überläufe des "Pausenzählers" verwendet, um die Dauer der Inaktivität auf dem Bus zu bestimmen. Die gewonnenen Bitdaten werden am Ende einer Bitzelle in ein Byte eingefügt, welches am Ende eines Datenbytes (nach Prüfung des Paritiy-Bits) in einen Zwischenpuffer geschrieben wird.
 
Am Ende des Impulspakets werden die gesammelten Daten zusammen mit der Anzahl der Bytes im Impulspaket, einem Bit für evtl. aufgetretene Parity-Fehler, und einer Zeitangabe (in 180ms-Intervalen) zur vorhergehenden Inaktivitätsdauer in einen Ringpuffer übertragen. Außerdem wird die am Microcontroller angeschlossene LED aktiviert, um zu signalisieren, daß Daten empfangen wurden. Solange sich der Bus im Ruhezustand befindet, wird der Ringpuffer auf enthaltene Daten geprüft, und ggf. vorhandene Daten in das EEPROM des Controllers geschrieben, von wo aus sie mittels eines Prommers wieder ausgelesen und weiter analysiert werden können.
 
Die hier vorgestellte Version der Firmware stellt einen reinen Datenlogger dar, der ausschließlich Daten empfängt, und im EEPROM ablegt. Eine weitergehende Analyse der Daten findet nicht statt.
 
Nach eingehender Analyse der mit dieser Version gewonnenen Busdaten möchte ich die Firmware so weit erweitern, daß bei einem Klingelbefehl an mein Wohntelefon geprüft wird, ob weitere Klingelsignale in den letzten Sekunden erfolgt sind oder noch folgen, und dieser Umstand entsprechend (akustisch) signalisiert wird. Dieses Signal zeigt mir dann an, ob es sinnvoll ist, mich zu Wohnungstür zu begeben, oder ich das Klingeln getrost ignorieren kann.

Das Datenformat im EEPROM

Da das EEPROM des verwendeten Controllers nur 128 Byte aufnehmen kann, sind die Daten darin als Ringpuffer strukturiert, sodaß die letzten empfangenen Daten verfügbar sind, und ältere Daten überschrieben werden.
Adresse "00" des EEPROMs enthält die Adresse des aktuellen Anfangs der aufgezeichneten Datensätze im EEPROM. Diese Adresse ändert sich jedesmal, wenn ein neuer Datensatz in das EEPROM geschrieben wird, der u.U. einen älteren Datensatz überschreibt.
Jeder Datensatz beginnt mit einem Controlbyte, welches u.a. die Anzahl der Datenbytes enthält, gefolgt von einem Wert, der die Dauer der Inaktivität des Busses vor dem Impulspaket angibt. Danach folgen die aufgezeichneten Datenbytes. Direkt nach dem letzten Datenbyte folgt das Controlbyte des nächsten Datensatzes.
Die unteren 4 Bit des Controlbytes enthalten die Anzahl der Datenbytes (Bytecount), ein gesetztes Bit in den oberen 4 Bit zeigt einen Parity-Fehler beim Empfang der Daten an. Ist der Bytecount "0", signalisiert das Controlbyte das Ende der aufgezeichneten Datensätze. Bei den folgenden Daten handelt es sich in diesem Fall um ältere, ggf. unvollständige oder überschriebene Datensätze.
Die Dauer der Bus-Inaktivität vor den aufgezeichneten Daten ist in Schritten von ca. 180ms angegeben. Dieser Wert erlaubt eine Abschätzung, ob zwei aufeinander folgende Datensätze ggf. in einem Zusammenhang stehen. Ein Wert von "00" weist z.B. auf eine automatische Antwort eines Wohntelefons auf ein Klingelsignal hin. Ein Wert zwischen "1B" und "A6" (ca. 5-30s) könnte z.B. die Reaktion eines Bewohners sein, der den Hörer nach einen Klingelsignal abnimmt, oder den Türöffner betätigt. Ein Wert von "FE" oder "FF" (>45s) zeigt an, daß wahrscheinlich kein Zusammenhang mit dem vorherigen Daten besteht.
Die Anzahl der Datenbytes ist variabel und im Bytecount des Controlbytes am Anfang des Datensatzes angegeben.
Überschreitet die fortlaufende EEPROM-Adresse den Wert "7F" (Größe des EEPROM-Bereichs), beginnt sie wieder bei "01", da die Adresse "00" des EEPROMs für die Anfangsadresse der Datensätze benötigt wird (→ Ringpuffer).
Ein beispielhafter Dump von EEPROM-Daten ("xx" zeigt irrelevante Bytes an):
 
:00  7C 33 44 15 00 44 55 66
:08  77 88 00 xx xx xx xx xx
     ...
:78  xx xx xx xx 04 FE 11 22

 
Das Byte "7C" an der EEPROM-Adresse "00" signalisiert, daß die Datensätze an der EEPROM-Adresse "7C" beginnen, wo das erste Controlbyte (04) zu finden ist. Das Controlbyte gibt an, daß der Datensatz vier Datenbytes enthält, und fehlerfrei empfangen wurde. Das folgende Byte (FE) gibt die Inaktivitätszeit vor dem Empfang der Daten an (>45s), danach folgen die vier Datenbytes 11, 22, 33, und 44. Da die höchstmögliche EEPROM-Adresse ("7F") überschritten wird (und EEPROM-Adresse "00" für die Anfangsadresse der Datensätze verwendet wird), sind die letzten zwei Datenbytes auf den EEPROM-Adressen "01" und "02" zu finden. Den Datenbytes folgt das Controlbyte des nächsten Datensatzes (15), welches anzeigt, daß dieser Datensatz fünf Datenbytes enthält, und beim Empfang eine Parity-Fehler aufgetreten ist. Die Inaktivitätszeit (00) vor dem Datenempfang beträgt hier <180ms, was auf eine automatisch erzeugte Antwort auf das vorherige Datenpaket hinweist. Dann folgen die fünf Datenbytes 44, 55, 66, 77, und 88. Das folgende Controlbyte des nächsten Datensatzes ist hier 00, was das Ende der aufgezeichneten Daten signalisiert.

Das Material

Das hier angebotene Material unterliegt der Creative Commons Lizenz "CC BY-NC-SA".
In diesem Archiv befinden sich die KiCad-Dateien für die verwendete Schaltung (Schaltplan und Layout).
In dieser Datei befindet sich das Hexfile, welches zur Programmierung des Microcontrollers notwendig ist.
In diesem Archiv befindet sich der Quellcode, um die Firmware (→Hexfile) für den Controller herzustellen. Diese Dateien werden nur benötigt, wenn Änderungen an der Firmware des Controllers vorgenommen werden sollen. Zur Herstellung eines neuen Hexfiles ist die Installation des Pakets "gputils" z.B. aus dem "Raspbian"-Repository (oder von gputils.sourceforge.net ) notwendig.

Hinweise für Nachbauwillige

Wer diese Konstruktion nachbauen möchte, sollte über etwas Kenntnisse von dem Umgang mit Mikrocontrollern verfügen. Es handelt sich hierbei nicht um einen Bausatz, sondern eher um eine Anregung für eigene Konstruktionen. Alles, was ich dazu anbieten kann, befindet sich auf dieser Seite, d.h. Nachfragen nach fertigen Geräte oder Bausätzen sind zwecklos → Ich "produziere" ausschliesslich für den Eigenbedarf.


Für die Funktionalität und Nachbausicherheit dieser Konstruktion, sowie der Richtigkeit meiner Protokoll-Analyse kann ich keinerlei Verantwortung übernehmen. Ich verkaufe weder fertige aufgebaute Schaltungen, noch komplette Geräte oder Bausätze. Eine kommerzielle Verwertung des hier angebotenen Materials (Schaltpläne, Layouts, Quell- und Hexcodes) oder auch Teilen davon ist nur mit meiner ausdrücklichen Genehmigung zulässig.


Startseite  Hardware  Rechtliches  Kontakt

HTML und Design: DK1RM erstellt: 9.6.2025 - letzte Änderung: 9.6.2025