artikel:w-bus:w-bus_lib_selbst_entwickeln

W-Bus Bibliothek selbst entwickeln

Ziel dieses Tutorials ist es darzulegen, was man beim entwickeln einer eigenen Kommunikationsbibliothek für den W-Bus beachten muss und wie man dies umsetzt. Dies soll helfen, eigene Software in der favorisierten Programmiersprache umzusetzen.

Auf dem W-Bus werden Nachrichten (Frames) immer zusammenhängend am Stück übertragen. Es ist keine Pause zwischen dem Beginn einer Übertragung und deren Ende vorgesehen. Ein Sync-Signal um den Beginn eines Frames anzuzeigen, ist nicht vorgesehen.

Da W-Bus ein Eindraht-Bus ist, sind die RX- und TX-Leitungen miteinander verkoppelt. Jeder Teilnehmer liest gleichzeitig auch was er sendet. Vor dem senden sollten die Busteilnehmer prüfen ob die Leitung frei ist. Dies kann angenommen werden, wenn innerhalb einer Zeit X keine Bytes am eigenen Eingang einlaufen.

Dennoch kann es zu Kollisionen kommen, wodurch Datenpakete „verstümmelt“ übertragen/empfangen werden. Hiergegen schützt zum einen das Paritäts-Bit innerhalb eines jeden Bytes während der Übertragung, aber auch das Prüfsummen-Byte (CHK) am Ende eines Frames. Ein Empfänger muss eine Nachricht verwerfen, wenn beim Empfang eines Bytes ein Paritätsfehler auftritt, oder wenn die Prüfsumme des Frames nicht stimmt. Um die Prüfsumme zu berechnen muss ein Frame vollständig empfangen worden sein. Hier gilt es aus dem empfangenen Datenstrom das Frame zu ermitteln. Da ein Empfänger nicht zwangsläufig den Beginn einer Kommunikation mitbekommt, muss er seinen Eingangspuffer auf mögliche Frames untersuchen.

Der W-Bus wird über einen Pegelwandlerbaustein mit dem UART eines Controllers verbunden. Die UARTs besitzen meist nur einen kleinen Eingangspuffer (FIFO) von wenigen Bytes. Die übertragenen Daten (Frames) sind in der Regel größer als dieser Hardware-Puffer. Um einen Überlauf und damit einen Datenverlust zu vermeiden, müssen die eingehenden Bytes regelmäßig in einen weiteren Eingangspuffer im (größeren) Arbeitsspeicher des Controllers umgeladen werden.

Diese Aufgabe übernimmt eine Serviceroutine, die idealerweise unabhängig von anderen Abläufen im Hintergrund über einen Interrupt aufgerufen wird. Das auslösende Signal kann ein einfacher Timer ab auch eine Eingangserkennung oder Puffer-Voll-Meldung vom UART sein.

Um nun innerhalb des Eingangsdatenstromes ein gültiges Frame zu finden geht man wie folgt vor:

  1. Sind mind. 4 Bytes im Empfangsbuffer vorhanden?
    • Nein ⇒ Dann Rücksprung (warte bis mehr Bytes eintreffen)
  2. Lese zweites Byte im Eingangspuffer als LEN-Byte. Ist dieses >= 2?
    • Nein ⇒ Ungültige Länge, vermutlich ist die kein LEN-Byte. Entferne das erste Byte aus dem Eingangspuffer und starte erneut bei 1.
  3. Enthält der Eingangsbuffer mindesten LEN + 2 Bytes?
    • Nein ⇒ Wurde länger als X Millisekunden nichts mehr empfangen?
      • Ja ⇒ Vermutlich ist das gelesene Byte kein LEN-Byte. Entferne das erste Zeichen aus dem RX-Buffer und starte erneut bei 1.
      • Nein ⇒ Rücksprung (warte bis mehr Bytes eintreffen)
  4. Lese das CHK-Byte am Ende des Frames (Position LEN + 2 - 1). Berechne die Prüfsumme des Frames (alle Bytes, beginnend mit dem ADDR-Byte, jedoch ohne das CHK-Byte selbst miteinander XOR verknüpfen). Stimmt die berechnete Prüfsumme mit dem CHK-Byte überein?
    • Nein ⇒ Ungültiges Frame empfangen oder falsche Bytepositionen angenommen. Entferne das erste Byte im RX-Buffer und starte erneut bei 1.
  5. Gültiges Frame empfangen. Parse ADDR, CMD, Datenrichtung (Anfrage oder Antwort) und DATA in eine interne MSG-Struktur und entferne die verarbeiteten Bytes aus dem RX-Buffer.

Irgendwann hat man damit dann mal ein gültiges Frame erkannt und kann es verarbeiten!

Ihre Aufgabe ist es, auf die empfangenen Nachrichten zu reagieren, ggf. Aktionen auszulösen, Messwerte zu ermitteln, Parameter zu lesen und eine der Anfrage entsprechende Antwort zurückzusenden.

Setzt man die W-Bus Bibliothek zum Beispiel dafür ein, einen Standheizung zu simulieren und erhält diese einen Einschaltbefehl, so ist es Aufgabe dieser Routine das zu erkennen, die Parameter (Heizzeit) zu prüfen, den internen Betriebszustand (Inaktiv, Aktiv, Störung, etc.) zu ermitteln und eine Antwort zu formulieren. Diese könnte z.B. lauten „Heizbefehl für 30 Minuten akzeptiert. Heizung läuft“.

Die Antworten werden in den Nachrichtenausgangspuffer geschrieben von wo aus sie eine Service-Route an den W-Bus in Form von Bytes übermittelt.

Sie wir innerhalb der Bibliothek mit Kommandos und Parametern aufgerufen und erzeugt daraus ein gültiges W-Bus Nachrichtenpaket (Frame), welches sie anschließend in den Ausgangspuffer für die Senderoutine anfügt.

Um ein 25/25ms Break-Signal zu erzeugen gibt es grundsätzlich 3 Möglichkeiten:

  1. Per Hardware, z.B. Transistor, wird beim eintreffen einer speziellen Nachricht oder einem Schaltsignal am W-Bus Interface die TX-Leitung 25 ms auf GND gezogen. Die BREAK-Zeit kann entweder rein durch Software (Dauer der Signalansteuerung bzw. Timer bei Kommunikationspaket) gesteuert werden, oder aber auch durch entsprechende Hardware (Monoflop, oder R/C-Glied).
  2. Setzt man die Baudrate auf den niedrigsten Wert (z.B. 300 Baud) und sendet dann den Bytewert 0x00 (idealerweise mit der Einstellung 7N1), dann ergibt dies eine LOW-Phase auf TX für ca. 25 ms. Anschließend stellt man die Baudrate wieder auf 2400 Baud zurück (8E1) und sendet die Bytes. Wichtig ist, das zwischen den beiden Transfers eine Ruhephase von 25 ms zustande kommt.
  3. Unterstützt der W-Bus Interface-Treiber die Methoden BREAK_ON und BREAK_OFF (POSIX-IOCTL oder NVT-CMDs), kann BREAK per Software erzeugt werden. Dabei wird die TX-Leitung bei BREAK_ON auf GND gezogen und bei BREAK_OFF wieder durch den UART beschrieben.

Während des BREAK ist keine Kommunikation auf dem Bus möglich, bzw. wird laufende Kommunikation verstümmelt! Daher muss man vor der Generierung sicher sein, das keine Kommunikation läuft. Hierzu am besten prüfen wie lange der letzte Datenempfang her ist.

Diese Routine muss in regelmäßigen Abständen (Timer/Interrupt) aufgerufen werden um zum senden bereitstehende Nachrichten auf den W-Bus zu übermitteln. Hierzu werden die Bytes jeder Nachricht zusammenhängend über das Interface gesendet.

Der Ablauf ist dabei wie folgt:

  1. Liegt im Ausgangspuffer eine vollständige Nachricht (Frame) zum Versand bereit?
    • Nein ⇒ Rücksprung
  2. Ist der Bus frei? (letzte empfangene Nachricht, die nicht von uns selbst kam, länger als 100 ms her?)
    • Nein ⇒ Rücksprung (warte bis der andere Teilnehmer fertig gesendet hat)
  3. Ist die letzte Busaktivität (Senden/Empfangen) länger als 30 Sekunden her?
    • Ja ⇒ Sende BREAK
  4. Sind noch Bytes zu senden? (Bufferzeiger == Ende der Nachricht)
    • Ja ⇒ Signalisiere Nachricht als vollständig gesendet. Entferne die Bytes des Frame aus dem Ausgangspuffer. Rücksprung.
  5. Sende das Byte im Ausgangspuffer der Nachricht, auf welches der Bufferzeiger zeigt
  6. Wurde in den letzten 1 ms ein Byte Empfangen?
    • Nein ⇒ Busfehler. Die W-Bus Leitung ist nicht terminiert, nicht angeschlossen, oder kurzgeschlossen. Abbruch der Kommunikation.
  7. Ist das empfangene Byte identisch mit dem gesendeten?
    • Nein ⇒ Busfehler oder verstümmelte/vermischte Kommunikation durch Überlagerung mit anderem Teilnehmer
  8. Erhöhe den Bufferzeiger um eins und springe zurück zu 4.
  • artikel/w-bus/w-bus_lib_selbst_entwickeln.txt
  • Zuletzt geändert: Mon. 03.05.2021 19:54
  • von wikiadmin