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

Hi Thomas,

super, vielen Dank!
Häufig wechseln werden die Leute nicht, aber es gibt immer wieder User, die es doch unbedingt mit dem Raspi machen wollen und dann merken, dass die Software eben nicht das Gleiche ist. Und es kann eben passieren, dass in ein paar Monaten (oder Jahren) ein Wechsel auf eine andere, dann 3.3V, Plattform ansteht. Da sollten auf jeden Fall die bisherigen Platinen prinzipiell weiter passen. Wenn der Schritt dann einmal vollzogen ist, kann man dann natürlich die Widerstandswerte optimieren. Aber da es bisher bei den Raspi-Usern grundsätzlich lief, würde ich für's Erste bei so einem Kompromiss bleiben wollen...

VG, 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

Zitat von: freetz am 02 Dezember 2019, 18:12:17
Eine Frage inbesondere an die Elektrotechnik-Affinen User hier:

Ich habe mich etwas mit der Frage beschäftigt, warum Gero damals auf SoftwareSerial gesetzt hat und nicht das HardwareSerial Interface des Mega nutzt, der davon ja vier Stück hat. Ich vermute, dass es damals nicht die Konfigurationsmöglichkeit gab, die etwas exotische Übertragungsart 8O1 zu nutzen. Inzwischen weiß ich aber aus einem anderen Projekt, das das geht und habe mich dann einmal daran gemacht, den Bus über das HardwareSerial Interface anzusprechen. Mit Erfolg:
Das S/W serial interface ist so programmiert, dass es Kollisionen mit anderen Geraeten, die auf dem Bus senden, vermeidet.  Das geht nur, indem es laufend den Pegel abfragt und nur auf Senden geht, wenn der fuer mindestens x ms im Ruhezustand verharrt hat.  Dazu kommt die random wait time, nachdem es doch einmal eine Kollision gesehen hat.  Dieses carrier-sense multiple access with collision detection (CSMA/CD) Verhalten erwarten die kommerziellen BS-Bus- und LP-Bus-Gerate voneinander.

Ich kann nicht erkennen, dass das H/W serial interface diese Faehigkeit hat; es sendet ohne Ruecksicht auf Kollisionen einfach drauflos (does not play well with others).  Uebersehe ich da etwas?  Wenn es doch funktioniert, dann deswegen, weil die restlichen Geraete sich gegenueber dem "hoppla, jetzt komm' ich" Teilnehmer hoeflich verhalten.  Hast Du untersucht, wie viele der  Telegramme wiederholt werden muessen, weil sie nicht bei der Gegenstelle empfangen und quittiert werden konnten?

Ich bin zuerst einmal den Weg gegangen, einen Arduino micro zwischen <Raspi, oder anderen Computernamen einsetzen> und BS-Bus zu schalten, der mit seinem S/W serial interface den Bus so bedient, wie es der Mega jetzt macht.  Das war der einfache Teil der Uebung, denn der CSMA/CD Code existiert ja schon in BSB_lan. Jetzt muesste nur BSB_lan auf dem Raspi oder sonst einem Computer existieren ...  vorzugsweise in einer portablen Sprache implementiert.  I have a dream ..

Schotty

Moin miwi!
Zitat von: miwi am 04 Dezember 2019, 13:08:42
Dieses carrier-sense multiple access with collision detection (CSMA/CD) Verhalten erwarten die kommerziellen BS-Bus- und LP-Bus-Gerate voneinander.
Sehr interessant - ist das dann der Grund dafür, dass Abfragen via HwSerial anscheinend etwas schneller über die Bühne gehen als via SwSerial? Bei einer Komplettabfrage /0-10000 beträgt der Unterschied ca. 26Sekunden.
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

freetz

Zitat von: miwi am 04 Dezember 2019, 13:08:42
Ich kann nicht erkennen, dass das H/W serial interface diese Faehigkeit hat; es sendet ohne Ruecksicht auf Kollisionen einfach drauflos (does not play well with others).  Uebersehe ich da etwas? 

Ja, denn auch die damals von Gero angepasste SoftwareSerial-Library unterstützt kein CSMA/CD. Diese hatte er nur hinsichtlich der fehlenden Parity-Unterstützung erweitert. Das, was vermeintlich CSMA/CD ist, findet sich in der bsb.cpp in der Funktion _send(). Dort wird ausschließlich vor dem Senden einmal der RX-Pin abgefragt, um zu schauen, ob dort gerade Aktivität auf dem Bus ist. Wenn das der Fall ist, wird, wie Du schreibst, eine zufällige Zeit gewartet und dann erneut geschaut.

Im zweiten Teil der Funktion steht dann zwar ein Kommentar (keine Ahnung von wem), in dem beschrieben wird, dass die Daten dann bitweise gesendet werden und gleichzeitig immer wieder geprüft wird, ob ein anderes Gerät zwischendrin den Bus nutzen will, um dann angeblich abzubrechen, aber der Code spricht eine andere Sprache:
Die Daten werden nämlich byteweise an die write()-Funktion von SoftwareSerial geschickt und dann wird der Rückgabewert überprüft, ob dieser "1" ist. Nach meiner Lesart der SoftwareSerial::write()-Funktion ist dieser aber eigentlich immer 1. Bei HardwareSerial::write() wird immerhin die Anzahl der gesendeten Bytes zurück gegeben. Eine 0 sagt hier aber noch gar nichts darüber aus, ob das Byte nun wegen einer Kollision oder aus anderen Gründen nicht gesendet werden konnte.

Bei dem Wechsel auf HardwareSerial wird letztlich nur die Referenz auf das Objekt von SoftwareSerial auf HardwareSerial geändert. Ansonsten fliegt nur das An- und Abschalten der Interrupts raus (weil es nicht mehr nötig ist), und statt der SoftwareSerial-Funktion rx_pin_read() frage ich den RX1-Pin direkt mit digitalRead() ab.

Somit ist die Funktionalität in dieser Hinsicht identisch mit dem, was bisher als CSMA/CD umgesetzt wurde. Und ich denke, dass diese bisherige Umsetzung auch völlig ausreichend ist, denn ein Abfragen vor dem Senden, ob der Bus frei ist, sollte reichen, denn wenn sich alle daran halten, würde auch kein Gerät auf die Idee kommen zu senden, wenn der Bus gerade belegt ist, sondern dann warten, bis er frei ist - so wie das BSB-LAN auch macht.*

VG, F.

* Ja, es kann natürlich sein, dass der Bus gerade eine logische 0 anzeigt, weil diese 0 Teil eines übertragenen Bytes ist. Um das zu verhindern müsste man nach dem Senden eines jeden Bytes die rx_pin_read()/digitalRead()-Abfrage wiederholen. Momentan wird aber wie gesagt nur der Rückgabewert von write() ausgewertet, und der ist wie gesagt bis auf wenige Ausnahmefälle immer 1. Aber man möge mich gerne korrigieren, wenn ich da etwas übersehen habe.
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

loetmeister

#4054
Hi freetz,

hab gesehen das die Änderungen für HardwareSerial im Github sind (https://github.com/fredlcore/bsb_lan/commit/77b59d10e1550af460546c82c400e6ca22f4d939).

Mit BSB bus(19,18); in BSB_lan_config.h aktiviere ich es. Die alte Schaltung funktioniert aber nicht mehr, da die Signale nicht invertiert werden dürfen - richtig?
Könnte man jedes empfange byte invertieren? Dann kann man die alte Schaltung weiter nutzen? (noch mehr #define / #ifdef?  ::))


Zitates kann natürlich sein, dass der Bus gerade eine logische 0 anzeigt, weil diese 0 Teil eines übertragenen Bytes ist.
Eventuell könntest so oft es geht im "main loop" den RX pin abfragen, wenn eine "1" erkannt wurde, dann mindestens eine Nachrichten/Telegramm länge warten?

(EDIT: pins vertauscht)

Gruß,
Thomas

freetz

@miwi: Ich habe jetzt die Senderoutine so angepasst, dass jetzt auch zwischen dem Senden von einzelnen Bytes geprüft wird, ob ein anderes Gerät senden will, und falls ja, zieht sich BSB-LAN für eine kurze, zufällige Zeit zurück. Bei einem kursorischen Vergleich beider Varianten und einer testweisen Ausgabe einer Meldung, wenn dies passiert, ist mir nur bei PPS ein nennenswerter Unterschied aufgefallen, bis beide Partner dann "in sync" waren. Da PPS aber kein Bus mit mehreren Teilnehmern ist, sondern, wie der Name schon sagt, ein Punkt-zu-Punkt-System, wäre es hier sogar nicht wirklich relevant. Aber da es ja auch nicht schadet, bleibt es jetzt so drin...
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

...ich war gerade dabei die Erklärung zu schreiben ;)...
Nur kurz zu Deinem Hinweis mit der Abfrage im main loop: Auch da wäre ja das Problem, dass eine logische 0 ja eben Teil eines gerade übertragenen Bytes sein kann, wo diese 0 eben Teil der Daten ist. Ich frage mich aber eh', wie diese Kollisionserkennung dieses Problem umgehen will, denn mehr, als auf einen "ruhigen" (= auf logische 0 testen) Bus prüfen, kann man da ja auch nicht. Das habe ich jetzt vor dem Senden eines jeden Bytes (und nicht wie bisher vor jedem Telegramm) umgesetzt. Mehr Möglichkeiten sehe ich da ehrlich gesagt 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

freetz

So, nachdem Schotty und ich nun einige Tests und letzte Änderungen am Code durchgeführt haben, können wir nun alle User ermutigen, auf HardwareSerial zu wechseln. Bei wem die bisherige Variante problemlos funktioniert, ist das natürlich nicht zwingend nötig, aber wer für eine mittelfristige Migration auf eine Hardware mit mehr Speicherplatz gewappnet sein will (es scheint dabei dann auf den Arduino Due hinauszulaufen, damit u.a. die BSB-Platinen weiter verwendet werden können), sollte es sich vielleicht trotzdem einmal überlegen.
User, die die Platine im PPS-Modus verwenden, bekommen auf jeden Fall eine stabilere Verbindung zur Heizung, die z.B. beim Komplettabruf der PPS-Kategorie nicht unterbrochen wird.

Was ist zu tun?

Software

1. Es muss die aktuellste Software aus dem Master-Repository verwendet werden.
2. In der BSB_lan_config.h müssen in der Zeile
BSB bus(68,69);
statt 68 und 69 die Pins 19 und 18 (in dieser Reihenfolge!) eingetragen werden.
3. Kompilieren und flashen.

Hardware

1. Wer die Platine bisher nur mit den Komponenten für den Arduino bestückt hat, muss die verbleibenden Teile nachträglich einlöten, also vier Widerstände und zwei Transistoren.
2. Dazu müssen zwei Pins eingelötet werden, die auf der Leiste, die auf der Platine mit "Raspi" beschriftet ist, in die Kontakte "08" und "10" kommen.
3. Die Lötbrücken bleiben unangetastet! D.h., nur SJ1 bleibt geschlossen, SJ2 und SJ3 bleiben offen.
4. Bei unseren Tests konnten auch die beiden Pins bisherigen RX/TX-Pins bestehen bleiben.
5. Nun wird die gesamte BSB-LAN-Platine um einen Pin in Richtung der Mitte des Arduino verschoben, d.h., dass die auf der Platine mit "08" und "10" beschrifteten Pins auf dem Arduino in die Pins TX1 und RX1 gehen. GND und 5V sind auf dem Arduino ja in zwei Reihen vorhanden, so dass diese weiterhin damit versorgt werden, nur eben um einen Pin verschoben. Die alten RX/TX-Pins gehen dann nicht mehr in A14 und A15, sondern in A13 und A14.
6. Fertig.

Das einzige Problem ist, dass bei dieser Variante die Bohrlöcher für die Haltestifte in manchen Gehäusen nicht mehr in die Platine passen. Das muss man dann entweder in Kauf nehmen oder die Platine in einem eigenen Gehäuse auf die Weise befestigen und die Verbindung zum Arduino dann mit Jumper (DuPont) Kabeln herstellen.
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

Hi,
drei kurze Anmerkungen von mir dazu:

1)
Zitat von: freetz am 06 Dezember 2019, 12:19:02
5. Nun wird die gesamte BSB-LAN-Platine um einen Pin in Richtung der Mitte des Arduino verschoben,
Also in Richtung des LAN-Shields, quasi 'an das LAN-Shield heranschieben'.

2)
Zitat
Das einzige Problem ist, dass bei dieser Variante die Bohrlöcher für die Haltestifte in manchen Gehäusen nicht mehr in die Platine passen. Das muss man dann entweder in Kauf nehmen oder die Platine in einem eigenen Gehäuse auf die Weise befestigen und die Verbindung zum Arduino dann mit Jumper (DuPont) Kabeln herstellen.
Oder einfach oben ein Stück von den Haltestiften abzwacken. Die Adapterplatine ist dann zwar nicht mehr durch die Stifte 'gesichert', sitzt aber i.d.R. trotzdem fest genug, da sie ja auf den Ardu gesteckt ist. 

3)
Zu guter Letzt bitte beachten, dass nun auch die stirnseitige (quer angeordnete) Pinreihe des Adapters in der vorderen (LAN-Shield-seitigen) der doppelten Reihe des Ardu eingesteckt ist und sich somit die Zuordnungen ändern!
Wenn also bspw jemand einen Sensor an Pin 53 oder 51 an der Pinreihe des Adapters angeschlossen hat (direkt neben GND), dann ist dieser Pin nun Pin 52 bzw 50 (also immer -1). Zum besseren Verständnis am besten einmal auf den Ardu sehen, dann sollte es klar werden, was ich meine. In dem Fall sind also die Pinbelegungen (z.B. in der Datei BSB_lan_config.h) entsprechend anzupassen!
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

freetz

Zu 3: Ja, wobei der Pin 53 zukünftig auch geschützt sein wird, weil der im neuen Schaltplan für die Stromversorgung zuständig sein wird. Und um das dann mit meiner Test-Platine hier simulieren zu können, brauche ich durch das Verschieben dafür auch noch Pin 52. Am sichersten ist es aber eh', zuerst die Pins der klassischen Uno-Pins zu nehmen, also die, die auch über die Shields herausgeführt werden. Haben vermutlich eh' die meisten gemacht, weil man dafür dann nicht noch extra eine ganze Leiste an die BSB-Platine anlöten muss...
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

#4060
Zitat von: freetz am 06 Dezember 2019, 14:40:35
Uno-Pins
-> Hier Uno=Mega2560 ;)

Achso, ok - ich habe natürlich meine Sensoren bspw an Pin31 angebrutzelt, da ich nichts mehr oben in die Pinbuchsenleiste einstecken wollte (wg der Höhe und etwaiger Wackelkontakte)..  ;D 
Handbuch zur BSB-LAN Hard- & Software (Anbindung v. Heizungsreglern, u.a. von Brötje & Elco):
https://1coderookie.github.io/BSB-LPB-LAN/

freetz

Nein, denn ich wollte auf die Pins hinweisen, die beim Uno-Layout ausgeführt sind, deswegen habe ich "Uno" geschrieben, also die, die auch bei allen Shields ausgeführt werden. Wenn ich Mega2560 geschrieben hätte, wäre das ja nicht klar gewesen.
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

#4062
Eine Verständnisfrage noch an die User, die hardwarenah programmieren:

SoftwareSerial wird ja über Interrupts realisiert, die auslösen, wenn auf dem angegebenen RX-Pin eine Veränderung registriert wird. In dem Moment wird das Hauptprogramm, wie der Name Interrupt ja schon sagt, unterbrochen und die Interrupt-Routine (in diesem Fall SoftwareSerial::recv() ) wird ausgeführt, dann wird das Hauptprogramm an der unterbrochenen Stelle fortgeführt. Korrekt?

Wie sieht das bei den Hardware-UARTs aus? Da läuft das Programm bei eingehenden Daten doch ununterbrochen weiter, und erst, wenn ich mit Serial1->available() oder Serial1->read() auf die Daten zugreife, weiß ich überhaupt, ob da was angekommen ist oder nicht. Vorher läuft alles in den Buffer, ohne dass das Hauptprogramm irgendwie davon betroffen wäre. Korrekt?

Ich frage deshalb, weil mich die unterschiedlichen Verzögerungen beim Warten auf das nächste Byte in der bsb.cpp wundern. Bei SoftwareSerial reicht das bisherige delay(1) aus, bei HardwareSerial muss ich 3ms warten. Letzteres macht auch Sinn, weil die Übertragung von 10 Bits (8O1) bei 4800bps ca. 2.2ms dauert. Erst dann bekomme ich eine Rückmeldung von Serial1->available(), dass Daten vorhanden sind.

Bei SoftwareSerial scheint delay(1) deswegen ausreichend zu sein, weil das Hauptprogramm schon beim Startbit unterbrochen wird und innerhalb des Interrupts die 10 Bit eingelesen werden und SoftwareSerial->available() danach sofort eine 1 zurück gibt.

Vom Prinzip her sind bei SoftwareSerial also auch schon 1ms viel zu hoch angesetzt, weil bei einem laufenden Datenstrom das nächste Startbit ja direkt auf das Stoppbit folgen würde, also maximal die Zeit gewartet werden müsste, die es braucht, um ein Bit zu übertragen, also 0,2ms (208 Microsekunden). Die momentane Routine prüft bei SoftwareSerial bis zu 30 Mal in einem Abstand von 15 Microsekunden, ob ein weiteres Byte folgt, was wohl dafür ausreichend dimensioniert zu sein scheint, aber für HardwareSerial bei weitem nicht ausreicht, weil da available() ja erst nach der Übertragungsdauer für ein ganzes Byte eine 1 zurück liefert.

EDIT: die BSB::Monitor() Funktion wartet schon in der ursprünglichen (SoftwareSerial-basierten) Variante drei ms auf ein weiteres Zeichen, und betrachtet das Telegramm dann als beendet an, wenn innerhalb dieses Zeitraums keine Daten mehr folgen. Seltsamerweise wird diese Zeitspanne aber in 15 µs Schritten abgewartet, in denen nach einem solchen Schritt keine weitere Überprüfung o.ä. stattfindet. Der Sinn dahinter erschließt sich mir leider ebenfalls nicht...

Sind meine Annahmen hier soweit korrekt? Ich bin beim Umsetzen auf HardwareSerial auf diese Timing-Probleme gestoßen und habe sie dann mit trail and error angepasst, aber vor dem Hintergrund ließe sich das ja dann genauer umsetzen.

Danke im Voraus und VG, 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

babajun

Hello,

ich brächte mal einen Tip.
Seit einigen Tagen wird das reading Aussentemperatur nicht mehr aktualisiert. Am BSB Adapter wird der Wert richtig angezeigt.
Das log zeigt updates, aber nicht für die Aussentemperatur.

019-12-06 22:23:15 HTTPMOD Heizung Brennerzeit: 100576
2019-12-06 22:23:15 HTTPMOD Heizung Trinkwasserpumpe: 0
2019-12-06 22:23:15 HTTPMOD Heizung Status_Radiatoren: Nachlauf aktiv
2019-12-06 22:23:15 HTTPMOD Heizung Status_Wandheizung: Nachlauf aktiv
2019-12-06 22:23:15 HTTPMOD Heizung Raumsollwert: 19.5
2019-12-06 22:23:15 HTTPMOD Heizung Radiatoren: 37.8
2019-12-06 22:23:15 HTTPMOD Heizung Wandheizung: 27.7
2019-12-06 22:23:15 HTTPMOD Heizung Warmwasser: 42.6
2019-12-06 22:23:15 HTTPMOD Heizung Kesseltemp: 40.7
2019-12-06 22:23:15 HTTPMOD Heizung KesselSoll: ---
2019-12-06 22:23:15 HTTPMOD Heizung Raumtemperatur: 21.7
2019-12-06 22:23:15 HTTPMOD Heizung HK1_soll: 48.8
2019-12-06 22:23:15 HTTPMOD Heizung HK2_soll: 29.3
2019-12-06 22:23:15 HTTPMOD Heizung Brennerlaufzeit: 1676


Regex hat bisher immer funktioniert:

reading0Regex 8700 .*:[ \t]+([-]?[\d\.]+)

loetmeister

Hi freetz,

Nach meinem Verständnis der Arduino Serial (software, als auch hardware) Implementierung, nutzt keins Interrupts zur Empfangssignalisierung. In beiden Fällen muß gepollt werden. Der Vorteil zum Hardware serial ist der empfangspuffer.
Hier steht was von 64 bytes, bin mir aber nicht sicher ob das für alle Arduino Prozessoren gilt.
https://www.arduino.cc/reference/en/language/functions/communication/serial/available/
Wenn der puffer das gesamte Telegram enthält, bräuchte man gar keine Wartezeit mehr zu beachten?


Gruß,
Thomas