LAN-Anbindung für BSB-Bus (Brötje, Elco Thision etc.)

Begonnen von justme1968, 29 November 2014, 19:50:40

Vorheriges Thema - Nächstes Thema

freetz

Auch hier habe ich wieder den Eindruck, dass Du die Anleitung bzw. die FAQ kein Stück gelesen hast, denn das ist gleich der zweite Punkt:
https://github.com/fredlcore/bsb_lan/blob/master/FAQ_de.md#ich-nutze-fhem-und-möchte-die-daten-meines-heizungssystems-darin-weiter-verarbeiten-wie-kann-ich-dies-tun

Da frage ich mich schon, warum Ulf und ich uns die Mühe machen, diese Texte zu schreiben. Für uns ist das ein Hobby-Projekt, bei dem wir gerne helfen, wenn es Probleme gibt, aber so macht das keine Spaß. Weitere Fragen, die sich direkt aus der Anleitung oder der FAQ ergeben, werde ich daher nicht beantworten.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

Schotty

Moin Elektroblitz,
ein fertiges Modul gibt es für den Adapter m.W. noch nicht.
Schätzungsweise werden die Störungsmeldungen per RegExp ausgelesen, wie im Beispiel hier: https://github.com/fredlcore/bsb_lan/blob/master/FAQ_de.md#ich-nutze-fhem-und-m%C3%B6chte-die-daten-meines-heizungssystems-darin-weiter-verarbeiten-wie-kann-ich-dies-tun
Gruß

EDIT: Freetz war schneller.. ;)
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

justme1968

und noch etwas ganz anderes: ich weiß nicht wie alt dein kessel ist und wie es mit wartung und garantie ausschaut. aber du solltest drauf bestehen das es in ordnung gebracht wird.

ich habe mit der heizungs überwachung auch angefangen weil mein brenner immer wieder aus gegangen ist und ich es nicht erst unter der kalten dusche merken wollte.

ich habe aber den installateur so lange genervt bis es dann endlich zuverlässig ging. am ende wurde über etwa ein jahr so ziemlich jedes teil bis hin zur saugleitung und tankentlüftung getauscht. hat alles nichts geholfen. am ende wurde der hersteller selber hinzugezogen. der hat die komplette anlage am stück getauscht. seit dem ist ruhe. das ganze hat ein 'sondereinsatz' mitarbeiter gemacht der scheinbar genau für solche unerklärlichen probleme da ist und ganz deutschland bereist.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Elektroblitz

Da kann ich mich nur entschuldigen! Danke für den direkten Hinweis auf die Hilfe und eure Mühe dies zuerstellen.
Meine Heizungsanlage ist von 2008 und das Problem der Brennerstörung habe ich jetzt seit über 2 Jahren. Es haben sich schon einige Installateure versucht unter anderem von Brötje Werkskundendienst. Nun ist wieder eine neue Firma dran, mal sehen was passiert. Da ich 4 Mietparteien im Haus habe will ich nun wissen ob der Brenner auf Störung ist, bevor die Mieter kaltes Wasser haben.

freetz

Ok, kann ja auch mal passieren. Aber bitte das nächste Mal dann wenigstens die 10 Minuten investieren, in den beiden Hauptdokumenten nachzulesen. Wenn es dann Fragen zu konkreten Problemen gibt, helfen wir hier ja gern, so ist das ja nicht ;)...
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

Schotty

Moin allerseits!

Ich habe mal aus den deutschen Versionen von FAQ, Readme und HowTo jeweils ein PDF erstellt, so kann man sich das besser ausdrucken und dann auch offline im Keller oder wo-auch-immer zur Hand haben.. ;)

@freetz: Vielleicht kannst du das bei GitHub mit reinstellen..?

Gruß
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

freetz

Hallo Schotty,

keine schlechte Idee - magst Du das dort einstellen? Es sind ja schließlich Deine Übersetzungen etc., und immer wenn sich an den Texten etwas ändert (was jetzt wohl nicht allzu oft, aber doch ab und an vorkommt), müssten ja auch die PDFs neu generiert werden. Da wäre es sicher gut, wenn das in einer Hand bleibt.

Danke!

F.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

Schotty

Moin zusammen,
ich habe das HowTo nochmal aktualisiert, nun sind u.a. auch die Änderungen ab v0.34 drin, die die neuen Sicherheitsfeatures und die Installation betreffen. Das PDF von gestern ist somit obsolet.
Gruß
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

freetz

Nach längerer Sommerpause ist mir aufgefallen, dass die mühsam eingepflegten Beschreibungen der diversen KonfigRGx und sonstigen Bit-basierten Parameter nicht angezeigt wurden (ich glaube, jemand von Euch hatte mich auch darauf hingewiesen, aber ich dahchte, dass das mit dem Read-Only-Flag zu tun hatte). Ich hatte die Änderungen nur an einer älteren Version gemacht, so dass die nicht in dem normalen Prozess aktualisiert wurde.

Dabei ist mir gleichzeitig aufgefallen, dass es noch ein paar Speicherprobleme gab, die mitunter zu unvorhersehbaren Ergebnissen geführt haben. Diese habe ich (hoffentlich zumindest größtenteils) beseitigt, so dass ich jedem das Update auf Version 0.36, das jetzt bei GitHub liegt, empfehlen würde.

Gruß,

F.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

freetz

So, inzwischen ist die Dekodierung des LPB-Protokolls so weit fortgeschritten, dass eine rudimentäre Anbindung auch mit BSB_LAN möglich ist. Wenn Ihr Euch den aktuellen Master(!)-Branch herunterladet und in der _config.h die folgenden Zeilen hinzufügt
#define DEBUG
#define LPB

dann kann man mit dem URL-Kommando /Yxx,aabbccdd eine LPB-CommandID aabbccdd mit dem Nachrichtentyp xx absetzen und bekommt die Antwort von der Therme dann in der Weboberfläche zurückgemeldet.

Mit http://..../Y06,0500021F wird z.B. die Außentemperatur abgefragt und mit http://..../Y06,0500021D die Kesseltemperatur. Die jeweiligen Antworten sind noch nicht dekodiert, das ließe sich aber bei einer Anbindung über FHEM relativ einfach machen (im obigen Beispiel müssten die fünft- bis drittletzten Bytes, die das Datenpaket darstellen, durch 64 geteilt werden, um auf die entsprechende Temperatur zu kommen).

Was jetzt benötigt würde, wäre jemand mit einem OZW672 oder anderem Gerät, mit dem man der Therme Befehle/Parameter/Abfragen schicken kann. Das Teil müsste man dann zusammen mit einem BSB-Lan-Adapter an den LPB-Bus anschließen und könnte dann die Telegramme belauschen, um die CommandIDs herauszufinden. Für eine sinnvolle Regelung der Therme wären vermutlich schon die Übermittlung der Komfort- und Reduzierttemperatur und des Betriebsmodus ausreichend. Wenn dann noch jemand einen Raumtemperaturfühler hat, den man an ein LPB-Gerät anschließen könnte, wäre das ebenfalls noch sehr hilfreich.

Hier nun noch die inzwischen bekannte Entschlüsselung des LPB-Telegrammaufbaus:

01. Magic Byte, (immer?) 0x78
02. Länge des Telegramms inkl. Prüfsumme, aber ohne Magic Byte
03. Zieladresse (MSB = Segment, LSB = Geräteadresse minus 1)
04. Absendeadresse (MSB = Segment, LSB = Geräteadresse minus 1)
05. noch unbekannt, bei Sende- und Empfangstelegrammen meist C0 beim Senden und 0C beim Empfangen, bei Broadcasts auch CC oder FC
06. - 08. noch unbekannt, aber bisher immer 02 00 14
09. Message-Type, identisch mit den Werten bei BSB (*)
10. - 13. CommandID, beim Abfragen von Parametern werden wie bei BSB die ersten beiden Bytes vertauscht.
14. - xx. optionales Datenpaket, Codierungen ähnlich wie bei BSB (Kesseltemperatur z.B. mit Mulitiplikator/Divisor 64)
Letzte beiden Bytes: Prüfsumme nach der Formel (255 - (Telegrammlänge ohne Prüfsumme - 1)) * 256 + Telegrammlänge ohne PS - 1 + Summe aller Telegrammbytes

(*) Beim Abfrage-Typ wird von den Geräten bei jedem Sendevorgang der Wert immer um 0x20 erhöht, also statt 06 für Query dann mal 0x46, 0x66 oder 0x86. Die Antwort erhält dann auch diese entsprechende Erhöhung des Typ-Wertes. Vielleicht eine weitere Form der Absicherung, dass der Empfägner weiß, dass die Nachricht für ihn bestimmt ist? Es macht aber keine Probleme, wenn man immer nur 0x06 sendet. Umgekehrt könnte man bei BSB auch mal prüfen, ob hier letztlich auch immer nur auf das LSB geachtet wird und das MSB vielleicht aus LPB-historischen Gründen ebenfalls keine Rolle spielt.

Große Unterschiede zum BSB-Protokoll gibt es daher nicht, das Magic-Byte ist anders, das Längenbyte ist bei BSB bei gleicher Nachrichtenlänge um eins höher (zählt also das Magic Byte mit), es gibt ein paar Füll-Byte und die Prüfsumme wird anders berechnet. Prinzipiell steht einem weiteren Einbau der LPB-Funktionalität also nichts entgegen, wenn es jemanden gibt, der wie gesagt die benötigten CommandIDs ausfindig machen kann...

Hier im Anschluss noch die bereits bekannten LPB-CommandIDs, die man mit obigem /Y-Befehl schon jetzt abrufen kann:
05 00 02 1D - Kesseltemperatur x 64 in 0,5 Grad-Schritten
05 00 02 1E - Kesselrücklauftemperatur x 64 in 0,5 Grad-Schritten
05 00 02 1F - Außentemperatur x 64 in 0,5 Grad-Schritten
05 05 00 0B - Uhrzeit
05 05 04 B3 - Beginn Sommerzeit
05 05 04 B2 - Ende Sommerzeit

Gruß,

F.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

miwi

ZitatWas jetzt benötigt würde, wäre jemand mit einem OZW672 oder anderem Gerät, mit dem man der Therme Befehle/Parameter/Abfragen schicken kann. Das Teil müsste man dann zusammen mit einem BSB-Lan-Adapter an den LPB-Bus anschließen und könnte dann die Telegramme belauschen, um die CommandIDs herauszufinden. Für eine sinnvolle Regelung der Therme wären vermutlich schon die Übermittlung der Komfort- und Reduzierttemperatur und des Betriebsmodus ausreichend. Wenn dann noch jemand einen Raumtemperaturfühler hat, den man an ein LPB-Gerät anschließen könnte, wäre das ebenfalls noch sehr hilfreich.
OK, I'll bite.

Zuerst einmal: Schoen, dass auch der LP-Bus etwas Aufmerksamkeit findet.  Das ist der Bus, an den das Wartungsinterface OCI700 angeschlossen wird.

Ist ein OCI700, das am LP-Bus haengt, das, was Du suchst?  Die Kommandos kaemen dann von einem BROEJE/SIEMENS ACS-Programm, mit dem der Fachmann die Anlagenparameter abfragt und setzt. 
Ich habe mein Bus-Interface schon einige Zeit nicht mehr im Einsatz gehabt und hoffe, dass es nach ein paar Basteleien noch immer das tut, was es frueher tat: Datenverkehr zwischen OCI700 und dem LP-Bus ueber einen RS-232 Anschluss ausgeben. Ich koennte diese seriellen Daten mit einem RS-232 Datenlogger mitschreiben und sie dann zur Verfuegung stellen.

A popo ;-) Datenlogger: Mein Sniffer legt jedem einzelnen Byte einen timestamp bei. Wenn ich nun in den Code schaue, wundern mich zwei Dinge: Die Implementierung des Parity in BSBSoftwareSerial.cpp und das timing in bsb.cpp.

Erstens: OK, die Methode void BSBSoftwareSerial::recv() in Datei BSBSoftwareSerial.cpp hat keine Moeglichkeit, einen Parity-Fehler an die Application zu melden. Dass aber der Code in Zeilen 234 - 238 keinen time slot fuer ein Parity-Bit vorsieht und nach den Daten gleich ein Stopbit liest, ist nicht im Sinn des Protokolls.


  } // endfor, receive 8 data bits

    // skip the stop bit
    tunedDelay(_rx_delay_stopbit *2);
    DebugPulse(_DEBUG_PIN2, 1);

Richtig waere

  } // endfor, receive 8 data bits

    // Skip the parity bit; we don't care what it is because this routine
    // is not designed to notify the application of parity errors.
    tunedDelay(_rx_delay_intrabit);
    DebugPulse(_DEBUG_PIN2, 1);

    // skip the stop bit
    tunedDelay(_rx_delay_stopbit *2);
    DebugPulse(_DEBUG_PIN2, 1);

Dass die Methode BSBSoftwareSerial::recv() keinen Rueckgabewert vorsieht, macht die Fehlerbehandlung beim Aufrufer unmoeglich. Notfalls koennte man vielleicht das _buffer_overflow flag auch fuer Parity-Fehler missbrauchen, aber das waere doppeldeutig und kein guter Entwurf. Was die Fehlerbehandlung beim Lesen angeht, scheint sowieso keiner das _buffer_overflow flag zu pruefen.

Zweitens, timing. Ich habe Mitschriebe von Datenverkehr auf dem BS-Bus und habe die Pausendauer zwischen bytes und zwischen Telegrammen analysiert.

1. Die Pausen zwischen bytes dauern mind. 2,291 us und bis zu 2,917 us,
   allerdings habe ich auch einen Mitschrieb mit max 3,334 us.  D.h.
   dass Pausen zwischen Datenbytes laenger sein koennen als die
   Dauer eines Datenbytes mit seinen 11 bits (=11,000/4,800 =
   2,292 us).
   Verweis auf bsb.cpp Zeilen 136-143, wo eine zusaetzl. Wartezeit
   nach dem Empfang eines Datenbytes eingefuegt wird.  Wahrscheinlich
   hat der Entwickler damals Empfangsprobleme, die wegen dieser Pausen
   vorkamen, durch das Einfuegen einer Wartezeit ueberwunden.

   Die Zahlen zeigen wiederum, dass man nach einer Wartezeit von 3 ms
   noch nicht eindeutig bestimmen kann, ob ein Telegram geendet hat.
   Nach einer Wartezeit von 4-5 ms ist es sehr wahrscheinlich, dass
   man das Ende eines Telegramms korrekt bestimmt.

   Anscheinend macht es den Geraeten auf dem Bus aber nichts aus,
   wenn ein Geraet wie dieses hier die Daten OHNE Pausen zwischen
   den Bytes sendet.

2. Die Pausen zwischen den Telegrammen dauern mindestens 59.6 ms,
   eine obere Grenze ist nicht bekannt und existiert vermtl. nicht.

   Da die Pausen zwischen Telegrammen MINDESTENS 59 ms dauern,
   warten ALLE Geraete so lange und laenger, bevor sie senden.
   Verweis auf Methode _sendLPB() in bsb.cpp: Wenn der Code dort
   nur 3 ms lang wartet, bevor er sendet, muss man sein Verhalten
   als aggressiv bezeichnen.  Er koennte sich durchaus an die Ge-
   pflogenheiten der anderen Geraete halten, ohne dadurch einen
   Nachteil zu erleiden.  Geschickt waere es, wenn der Code eine
   variable, zufaellig bestimmte Zeit auf einen stillen Bus warten
   wuerde, statt mit einer festen Zeit zu arbeiten. 
   Dann saehen die Zeilen 199 .. 217 in bsb.cpp so aus:

   /*
    Er wartet 11/4800 Sek ab, lauscht und schaut ob der Bus in dieser Zeit
    von jemand anderem benutzt wird. Sprich ob der Bus in dieser Zeit mal
    auf 0 runtergezogen wurde. Wenn ja - mit den warten neu anfangen.
   */
   unsigned long timeoutabort = millis() + 1000;  // one second timeout
   retry:
   // Select a random wait time between 60 and 79 ms
   unsigned long waitfree = random(1,20) + 59; // range 60 .. 79 ms
   { // block begins
     if(millis() > timeoutabort){  // one second has elapsed
       return false;
     }
     // Wait 59 ms plus a random time
     unsigned long timeout = millis() + waitfree;
     while (millis() < timeout) {
       if ( serial->rx_pin_read()) // inverse logic
       {
         goto retry;
       } // endif
     } // endwhile
   } // block ends


   Die zufaellige weitere Wartezeit von bis zu 20 ms ist "so aus dem Aermel
   geschuettelt". Man kann sie bei Bedarf justieren, aber man braucht sie. 
   Erst die Einfuehrung einer zufaelligen Groesse bewirkt, dass sich die
   Geraete nach einer Kollision nicht alle zu gleicher Zeit wieder auf den
   Bus stuerzen und sofort neu kollidieren.  EWG - Einer Wird Gewinnen.

Drittens, Datei BSB_lan_defs.h
Die Frage "WHO WROTE THIS?" kann ich beantworten: Ich; und zwar, als ich damals den Code von Gero komplett durchgearbeitet und mit mehreren BROETJE Handbuechern (die leider inkonsistent sind und - nicht nur deswegen - manchmal Fragen generieren statt sie zu beantworten) und auch mit dem Python-Code verglichen habe. Meine Intention war, hier in diesem Projekt eine erste konsistente Beschreibungsbasis aus allen verfuegbaren Quellen zu erzeugen.


freetz

Zitat von: miwi am 26 August 2017, 15:00:16
OK, I'll bite.

Danke :)!

Sorry, wenn ich das mit dem OCI und OZW verwechselt habe, es geht wie gesagt primär darum, die CommandIDs mitzuschneiden, die beim Aufruf von Parametern über den Bus gehen. Da ich u.a. bei der Entschlüsselung auf Deine Mitschnitte im Mikrocontroller-Forum zurückgegriffen habe, hatte ich die Hoffnung, dass Du da vielleicht auch mit anderen Parametern weiterhelfen könntest (damals hattest Du dort die Abfrage von Zeit und Zeitumstellung gepostet).

Was die hardwarebasierten Codes in bsb.cpp angeht, stammen diese ja alle noch von Gero - ich habe jetzt für LPB nur quasi Kopien angelegt und die unterschiedlichen Payload-Werte angepasst. Da die Interfaces aber bisher bei einem Dutzend Leuten ohne Probleme laufen, bin ich (als Ex-Serveradmin von dem Motto geprägt "never change a running system") etwas zurückhaltend, die Änderungen ungetestet zu übernehmen. Wenn Du die bsb.cpp/h-Dateien bei Dir so angepasst aber laufen hast, dann schicke sie mir gerne und ich übernehme das 1:1.

Danke auch für die Erklärung zu ProgNr 6030, dann notiere ich im Code mal "miwi" für den Fall, dass es da noch mal Fragen dazu gibt; nach der Übernahme des Codes war es teilweise nur mit mühsamer Sucher herauszufinden, wer was beigetragen hat, und das war eine der letzten Lücken...

Danke und Gruß,

F.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

freetz

Hallo miwi,

also ich habe die Änderungen an bsb.cpp und BSBSoftwareSerial.cpp jetzt mal so, wie von Dir beschrieben, übernommen. Leider mit dem Effekt, dass dann nur noch "query failed" zurück kommt, wenn man das Parity-Bit berücksichtigt. Keine Ahnung, warum, aber ich habe es dann erst einmal so belassen, wie es war. Wenn Du den Fehler lokalisieren kannst, dann sag' gern Bescheid.
Den zufälligen Timeout habe ich jetzt drin, da gab's keine Probleme, und das macht natürlich Sinn, so wie Du das erklärt hast.

Gruß,

F.
Alle Infos zur Anbindung von Heizungssystemen mit PPS-, LPB- bzw. BSB-Bus ans LAN gibt es hier:
https://github.com/fredlcore/bsb_lan

Alle Infos zum WLAN-Interface "Robotan" für Ambrogio/Stiga/Wolf und baugleiche Rasenmähroboter:
https://github.com/fredlcore/robotan

miwi

#913
ZitatDen zufälligen Timeout habe ich jetzt drin, da gab's keine Probleme, und das macht natürlich Sinn, so wie Du das erklärt hast.
Prima. Ja, das ist doch ein uebliches Verfahren bei CSMA/CA mit Listen-Before-Talk (LBT).

Wegen des Parity time slots kann ich ja mal mit dem Scope nachsehen, was die Geraete von BROETJE denn so senden.  Laut Bus spec muss auf acht empfangene Datenbits ein ODD parity bit folgen.  Ich hoffe, ich bin beim Betrachten der for-loop fuer die 8 Datenbits nicht in die alte 'off-by-one' Falle getappt und das delay ist schon in der for-loop.
Deinen Test kann ich nur mit einem Unterschied im Aufbau nachvollziehen: Meine low level I/O Routinen laufen auf einem Arduino micro direkt auf der Interface-Platine.  Der besorgt das Bus-konforme Senden und das Empfangen eines vollen Telegrams und somit eine low level Vorverarbeitung vor einem nachgelagerten Computer.
Alternativ waere es natuerlich schoen, auch das alles per Software in einem Raspberry zu machen.  Etwas Ueberlegung zur realtime Faehigkeit des Raspbian zeigt aber, dass das so einfach nicht geht. Evtl. bestuende noch die Moeglichkeit,  pigpio direkt im Raspberry diese Sende-Empfangsaufgaben zu uebertragen; pigpio kennt aber kein parity handling, das muesste im Benutzercode geschehen.  Da der Arduino Code schon besteht und alles das kann, faellt fuer mich das Kosten-Nutzen-Verhaeltnis zugunsten einer kleinen Arduino-HW aus.

miwi

#914
Ich habe meinen Fehler gefunden.

Nach der for-loop muss in der Tat ein _rx_delay_intrabit kommen, um zur Mitte des parity bits zu kommen, und ein _rx_delay_stopbit, um zur Mitte des Stopbits zu kommen.

Nun haben aber laut table _rx_delay_intrabit und _rx_delay_stopbit die selbe Zeitdauer und ein schlauer Mensch hat deshalb ein delay statement von (_rx_delay_stopbit *2)  nach der for-loop eingesetzt.  Der Kommentar "Skip the stop bit" muesste besser "Skip the parity bit and stop bit" lauten. 

Man kann den Code so wie von mir vorgeschlagen schreiben und zwei separate delays mit jeweils ihrem DebugPulse statement (hilft beim Testen mit dem Scope) belassen, muss dann aber die Multiplikation mit zwei entfernen.

Mystery solved.