Von einem Freund habe ich einen M-Bus (Meter-Bus) Wasserzähler und einen Wärmemengenzähler bekommen. Der M-BUS ist ein Feldbus der über eine Zweidrahtleitung über sehr lange Strecken genutzt werden kann. Ein M-BUS Master fragt dabei alle Slaves im Strang oder Stern ab. Die Slaves werden teilweise vom M-Bus-Master mit Spannung versorgt. Mehr Details im Wiki.
Der M-Bus-Master sollte in meinem Fall aus dem Raspberry und einem Pegelwandler bestehen. Pegelwandler gibt es fertig von verschiedenen Herstellen (Relay, Wachendorff). Diese sind aber, je nachdem für wieviele Slaves sie ausgelegt sind, relativ teuer.
Mein erster Ansatz war daher der Selbstbau eines Pegelwandlers inkl. RS232-Schnittstelle zum Anschluss an den Raspberry Pi. Im Netz gibt es verschiedene Beschreibungen einer einfachen Schaltung und einige wenige Forumseinträge die sich mit dem Selbstbau eines Pegelwandlers bzw. generell mit M-Bus beschäftigen. Leider habe ich in keinem Forum eine Diskussion gefunden die bis zu einem funktionierenden System verfolgt wurde. Egal, ich habe es trotzdem mal versucht…
Selbstbau Pegelwandler
Auf der Platine ist der Pegelwandler inkl. einer RSA232 Schnittstelle die aus einem MAX3232 besteht. Die +/-15 Volt für den Pegelwandler habe ich mittels DCDC-Wandler IH0515S der Fa. XP Power erzeugt. Dieses Bauteil kann man z.B. bei Farnell beziehen. Dann das Ganze auf Lochraster zusammen gelötet und mit dem Raspi und dem Wärmemengenzähler verbunden.
Damit der Raspberry das M-Bus Protokoll versteht bzw. auch den Pegelwandler korrekt anspricht, habe ich die Bibliotheken von rSCADA genutzt. Die Quellen liessen sich problemlos auf dem Raspberry kompilieren. Im Ergebnis wurden verschiedene Binaries erzeugt um mit Slaves im Bus zu kommunizieren.
Meine ersten Versuche waren jedoch nicht von Erfolg gekrönt. Es wurde kein M-Bus-Gerät gefunden. Bei der Fehlersuche habe ich zuerst die serielle Schnittstelle separat getestet und mit Minicom über den Raspberry mit einem anderen Linux-Rechner kommuniziert. Das hat funktioniert. Die weitere Fehlersuche z.B. am M-Bus-Ausgang sind allerdings am fehlenden Oszilloskop gescheitert, da das Multimeter mich nicht wirklich weiter brachte.
Etwas niedergeschlagen habe ich dann nach drei Tagen erfolgloser Fehlersuche nochmal nach fertigen Pegelwandlern gesucht und ein relativ preiswertes Gerät gefunden und kurzerhand gekauft. Damit fiel die Fehlerquelle “Pegelwandler” schon mal weg.
Versuch mit gekauftem Pegelwandler
Der neue Pegelwandler benötigt zum Anschluss an den Raspberry Pi auch eine RS232 Schnittstelle. Um mir diesmal das Löten zu ersparen, hab ich erstmal den kompletten Versuchsaufbau auf einem Breadboard gesteckt. Der Pegelwandler läuft mit einer Spannung von 12-24 V DC weshalb ich den DCDC-Wandler aus dem ersten Versich auch nicht benötige.
Die Binaries von rSCADA unterscheiden zwischen TCP- und seriell angeschlossenen M-Bus-Pegelwandlern. Da meiner seriell angeschlossen ist, benutze ich “mbus-serial-scan” um nach angeschlossenen Slaves im Bus zu suchen.
Als Argumente übergebe ich “-d” für den Debugmodus, “-b 2400” um 2400 Baud zu nutzen und “/dev/ttyAMA0” als serielle Schnittstelle des Pi.
Zu meiner Überraschung wurde direkt ein Slave (der Wasserzähler) erkannt. Sehr schön…
pi@raspberry2 ~/libmbus-0.8.0/bin $ ./mbus-serial-scan -d -b 2400 /dev/ttyAMA0 Scanning primary addresses: 0 [2014-12-13 13:59:21] SEND (005): 10 40 00 40 16 [2014-12-13 13:59:21] RECV (001): E5 Found a M-Bus device at address 0 1 [2014-12-13 13:59:22] SEND (005): 10 40 01 41 16 2 [2014-12-13 13:59:22] SEND (005): 10 40 02 42 16 3 [2014-12-13 13:59:22] SEND (005): 10 40 03 43 16 4 [2014-12-13 13:59:22] SEND (005): 10 40 04 44 16 5 [2014-12-13 13:59:23] SEND (005): 10 40 05 45 16 6 [2014-12-13 13:59:23] SEND (005): 10 40 06 46 16 7 [2014-12-13 13:59:23] SEND (005): 10 40 07 47 16 ...
Hat man alle angeschlossenen M-Bus-Geräte per Scan identifiziert, können mit einem weiteren Programm die Daten des Gerätes ausgelesen werden. Auch hier gibt es wieder das Argument “-d” für den Debugmodus, “-b” zur Einstellung der Baudrate, das Device der seriellen Schnittstelle und die vom Scan ermittelte Device-Nummer. Im Fall meines Wasserzählers ist das die “0”. Die Daten der Slaves werden in einer einfachen XML-Struktur zurück geliefert.
./mbus-serial-request-data -d -b 2400 /dev/ttyAMA0 0 [2014-12-13 14:06:46] SEND (005): 10 5B 00 5B 16 [2014-12-13 14:06:47] RECV (084): 68 4E 4E 68 08 00 72 12 37 16 46 68 50 49 07 B6 00 00 00 0C 14 53 42 00 00 8C 10 12 35 53 42 00 0B 3B 00 00 00 8C 20 14 53 42 00 00 8C 30 14 00 00 00 00 04 6D 21 0F CD 1C 4C 14 02 00 00 00 42 6C BF 1C 42 EC 7E DF 1C 0A 92 2A 00 10 0A 92 2B 00 10 3E 16 mbus_frame_print: Dumping M-Bus frame [type 4, 84 bytes]: 68 4E 4E 68 08 00 72 12 37 16 46 68 50 49 07 B6 00 00 00 0C 14 53 42 00 00 8C 10 12 35 53 42 00 0B 3B 00 00 00 8C 20 14 53 42 00 00 8C 30 14 00 00 00 00 04 6D 21 0F CD 1C 4C 14 02 00 00 00 42 6C BF 1C 42 EC 7E DF 1C 0A 92 2A 00 10 0A 92 2B 00 10 3E 1646163712 TCH 73 Water 182 00 0000 Instantaneous value Volume (1e-2 m^3) 4253 2014-12-13T14:06:47 ... Instantaneous value Volume (1e-4 m^3) 425335 2014-12-13T14:06:47
Da es auf Anhieb funktioniert hat, habe ich die serielle Schnittstelle auf Lochraster gebannt und der Pegelwandler wird mittels kleinem 12V-Netzteil betrieben. Dann Raspberry Pi, Pegelwandler und Platine im Netzwerkschrank verstauen…
Software
Den Stand des Wasserzählers protokolliere ich nun einmal täglich um 23:59 Uhr. Das wird per Cronjob und einem kleinen PHP-Script erledigt. Warum PHP? Weil ich zu ungeduldig war und das schnell umsetzen wollte und schon das ein oder andere ähnliche PHP-Script fertig hatte.
Das Script ruft das Binary wie oben erklärt per shell_exec auf. Ab dem XML-Teil parse ich die Ausgabe und extrahiere die relevanten Informationen die dann in eine MySQL-Tabelle geschrieben werden.
[cc lang=”php”]
//***********************************
//Wasserzaehler mit der ID:0 auslesen
//***********************************
$output = shell_exec("sudo /home/odroid/libmbus-0.7.0/bin/mbus-serial-request-data -d -b 2400 /dev/ttyS1 0");
$xmloutput=substr($output,strpos($output,'
$xmloutput = new SimpleXMLElement($xmloutput);
$zaehlerID=$xmloutput->SlaveInformation->Id;
$zaehlerStand=$xmloutput->DataRecord[1]->Value/10000;
$mysqlhost=””;
$mysqluser=””;
$mysqlpwd=””;
$connection=mysql_connect($mysqlhost,$mysqluser,$mysqlpwd) or die (“Verbindungsversuch fehlgeschlagen”);
$mysqldb=””;
mysql_select_db($mysqldb,$connection) or die(“Konnte die Datenbank nicht waehlen.”);
$sql = “INSERT INTO wasserzaehler (timestamp,zaehlerid,zaehlerstand) VALUES (CURRENT_TIMESTAMP,$zaehlerID,$zaehlerStand)”;
$query = mysql_query($sql) or die(“Anfrage 1 nicht erfolgreich”);
?>;
[/cc]
Da ich auf meiner Webseite aber nicht nur den absoluten Wasserverbrauch darstellen möchte sondern auch den Tagesverbrauch, kommt folgendes SQL zum Einsatz. Hier werden die Einträge aus zwei aufeinanderfolgenden Zeilen subtrahiert um die Differenz zum Vortag zu bestimmen.
SELECT CASE DATE_FORMAT(wz1.timestamp,'%w') WHEN 0 THEN 'Sonntag' WHEN 1 THEN 'Montag' WHEN 2 THEN 'Dienstag' WHEN 3 THEN 'Mittwoch' WHEN 4 THEN 'Donnerstag' WHEN 5 THEN 'Freitag' WHEN 6 THEN 'Samstag' ELSE 'fehler' END, wz1.zaehlerstand - IFNULL(wz2.zaehlerstand, 0) AS verbrauch FROM wasserzaehler wz1 LEFT JOIN wasserzaehler wz2 ON wz2.timestamp = ( SELECT MAX(timestamp) FROM wasserzaehler wz3 WHERE wz3.timestamp < wz1.timestamp ) ORDER BY wz1.timestamp
Das Ergbnis sieht dann wie folgt aus. Ich war etwas erschreckt wieviel Wasser man an machen Tagen verbraucht!
Selbstgebauter Pegelwandler
Da ich ja nun weiß das es generell funktioniert und der Fehler meiner ersten Lösung definitiv im selbstgebauten Pegelwandler liegt, werde ich den Versuch mit dem Selbstbau demnächst nochmal angehen.
Sobald der Wärmemengenzähler in den Wasserlauf des Kachelofens eingebaut ist, werde ich nochmal einen kurzen Beitrag schreiben. Das Prinzip des Auslesens ist ja analog zum Wasserzähler aber vielleicht gibt es in den zurückgelieferten Daten unterschiede.
Viel Spaß mit dem M-Bus!
Chris
Pingback: Vorlauf- und Rücklauf vom Kachelofen mittels 1-wire Temperatursensoren | bubuxblog
Hallo Chris,
das klingt eigentlich genau, nach dem was ich suche – abgesehen davon, dass ich vermeiden wollte nochmal 100 EUR für so einen fertigen Pegelwandler auszugeben.
Mir ist jetzt nicht ganz klar, ob Du den Fehler in Deiner DIY-Lösung inzwischen gefunden hast und es jetzt auch ohne das teure Zusatzgerät funktioniert bzw. funktionieren würde.
(Quote: “Da ich ja nun weiß das es generell funktioniert und der Fehler meiner ersten Lösung definitiv im selbstgebauten Pegelwandler liegt, werde ich den Versuch mit dem Selbstbau demnächst nochmal angehen.”)
Solltest Du eine funktionierende DIY-Lösung haben, wäre ich sehr daran interessiert.
Habe gerade noch den Link in Deinem Artikel zu http://www.m-bus.de/pw1.html entdeckt. Ist es denn diese Schaltung die Du nachgebaut hast?
Was Deinen Schaltplan angeht: “1” und “2” sind die beiden Adern des M-Bus Anschluß, oder? Ist es da egal wie ich meinen Sensor anschließe? Laut Datenblatt des Herstellers geht “grün” an GND und “Weiss” an einen “NPN” Eingang in einer SPS.
VG
Markus
Hallo Markus,
wie das oft so ist wenn man eine funktionierende Lösung hat, bin ich noch nicht dazu gekommen nach dem Problem mit der DIY-Platine zu schauen. Vielleicht diesen Winter…
Ja, im Prinzip ist es diese Schaltung. Die gibt es mit kleinen Variationen auf verschiedenen Seiten im Internet.
Ich habe noch die Stromversorgung für den M-Bus und den Maxim Pegelwandler für den Anschluss an den Raspberry Pi mit verbaut.
Beim Anschluss der Geräte an den M-Bus wäre mir nicht bekannt, das man auf eine Polung achten müsste (zumindest nicht bei dem gekauften Pegelwandler).
Bei meiner Platine könnte ich das nochmal testen!
Gruß
Chris
Hallo Chris
auf der suche nach einer Möglichkeit meinen M-Bus E-Zähler auszulesen bin ich auf deine Seite gestoßen.
Bei dem bestellen der benötigten Teile, um deine Schaltung zu realisieren, bin ich vermutlich auf dein Fehler gestoßen warum deine Lochrasterplatine nicht funktioniert.
Vorausgesetzt du bist noch auf der suche…
Schau dir mal dein DC/DC Wandler an laut deinem Schaltbild wird dein Bus nur mit 15V betrieben. Da am Ausgang 0V mit GND zusammen geführt und nur die -15V beschaltet hast. Jetzt könntest du ja versuchen die -15V mit GND zusammen zu führen und den +15V auf den Bus zu geben (0V bleibt frei) jetzt sollte dein Bus mit 30V arbeiten was gerade so in der Spec. liegt (Logisch Null = 24V; Logisch High=36V)
Wenn ich alles zusammen habe kann ich es selber testen aber vielleicht hast die die Platine noch nicht begraben und kannst es versuchen.
Grüße Martin
Hallo Martin,
danke für den Tip. die Platine liegt noch auf meinem Werktisch und ich werde es mal testen. Im Keller ist es schön kühl 🙂
Gruß
Chris
Hallo Martin & Chris,
habt ihr die Schaltung zwischenzeitlich aufgebaut und getestet?
Ich hab bei mir den Volkszähler am laufen und würde neben DMLS, S0 und W1therm auch gerne M-Bus Zähler anbinden, der Preis für kommerzielle M-Bus Master schreckt mich allerdings ab. Sollte die Schaltung funktionieren, wäre das eine geniale Alternative zu den kommerziellen Produkten.
Schöne Grüße
Michael
Hallo Michael,
ich bin leider noch nicht dazu gekommen und da ich eine funktionierende Variante habe, ist mein Antrieb auch leider nicht so groß. Die Platine liegt aber noch hier.
Widme mich gerade meinem Holzbackofen-Projekt. Da bleibt nicht so viel Zeit für anderes.
Gruß
Chris
Schau dir mal die Schaltung hier an: https://github.com/rscada/libmbus/blob/master/hardware/MBus_USB.pdf . Ich hatte diese mal nachgebaut, allerdings ohne Step-Up-Spannungswandler und und ohne FTDI-Teil. Den Spannungswandler habe ich ersetzt durch einen Printrtrafo mit 2x12V + B80-Diodenbrücke und 220uF/50V Elko; den FTDI durch ein fertiges Kabel TTL-232R-3V3 (mit bereits integriertem FTDI).
Zum Zähler-Auslesen unter Windows kannst du den auf win portierten libmbus benutzen: https://github.com/xaelsouth/libmbus-winport/tree/master/msvc/libmbus/Release
Wenn du COM-Port > 9 benutzen musst, dann in der Commandline \\.\\COM99 eingeben.
Hallo Chris
Bei mir läuft unter Windows mein Energiezähler (gleicher Pegelwandler wie du hast). Ich möchte jetzt das ganze auf dem Raspberry PI2 laufen lassen. Ich habe jedoch meine Probleme bei der Installation von libmbus. Kannst du mir schrittweise erklären, wie ich den Installieren muss? Ich habe es noch nicht so mit Linux.
Hallo,
danke für deinen hilfreichen Beitrag!
Ich hätte aber eine Frage, wie würde es aussehen, wenn man versucht die Ausgabe in Python zu verwerten?
Habe dazu mal versucht:
!/usr/bin/python
from xml.dom import minidom
from pdb import set_trace as bkp
import subprocess
bashCommand = “mbus-serial-request-data -d -b 2400 /dev/serial0 10”
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
Ich erhalte eine Antwort versuche ich das nun aber in xml zu parsen klappts nicht… auch sieht die Ausgabe anders aus.
Wenn ich den Befehl direkt in der BASH ausführe wird eine XML Formatierung zusätzlich ausgegeben…bei indirekten Aufruf von Python aus leider nicht…
Vieleicht hast du eine Idee…
Danke!
Hallo Daniela,
das XML sieht etwas “zerhackt” aus aber grundsätzlich kommt die MBUS-Antwort zurück.
Schick doch auch mal den Rest des Scripts wo Du die XML-Ausgabe parst.
Gruß
Chris
Mein Script sieht derzeit so aus:
`#!/usr/bin/python
from xml.dom import minidom
from pdb import set_trace as bkp
import subprocess
bashCommand = “mbus-serial-request-data -d -b 2400 /dev/serial0 10”
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
#mbusdata = minidom.parseString(output)
Ich erhalte allterdings eine Fehlermeldung:
Traceback (most recent call last): File “test.py”, line 13, in mbusdata = minidom.parseString(output) File “/usr/lib/python2.7/xml/dom/minidom.py”, line 1928, in parseString return expatbuilder.parseString(string) File “/usr/lib/python2.7/xml/dom/expatbuilder.py”, line 940, in parseString return builder.parseString(string) File “/usr/lib/python2.7/xml/dom/expatbuilder.py”, line 223, in parseString parser.Parse(string, True) xml.parsers.expat.ExpatError: syntax error: line 1, column 0
Wobei ich vermute dass es sich dabei um keine ordnungsgemäße Antwort handelt (XML) Format handelt …
Hallo Daniela,
ich denke Deine Vermutung ist richtig. In “output” nicht nur XML, sondern auch noch Text und ein HEX-Frame. Das müsstest Du zuerst beschneiden indem Du den Start des XMLs raus suchst. Im PHP z.B. so:‘));
$xmloutput=substr($output,strpos($output,’
Das ist in meinem Beispielcode im Artikel durch das WYSIWYG verloren gegangen. Habe das korrigiert.
Gruß
Chris
Hallo Chris,
ich bekomme bei dem Aufbau leider keine Antwort des Pegelwandlers. Anstelle des Max3232 verwende ich den KY-051 Voltage Translator. Wie sind denn die Einstellungen deiner seriellen Schnittstelle?
Gruß
Martin
Hi Martin,
Du meinst bei der Selbstbau-Platine?
Das weiß ich leider nicht mehr. Gefühlt habe ich alles 10x durchprobiert.
Gruß
Chris
Die meisten Zähler werden mit 2400 baud mit 8E1 (parity even!) ausgelesen.
Hi an Alle!
Ich habe die Schaltung
http://m-bus.de/pw1.html
schon mehrfach aufgebaut. Es funktioniert. Bei einer Änderung von R10 Widerstand lassen sich sogar mehr als 20 M-Bus Zähler auslesen. Selbst habe ich mit 22 Zählern ausprobiert. Man muss halt für gute Kühlung bei Transistor T5 achten. Die Schaltung hat aber keine galvanische Trennung, was zu Problemen bei langen Busleitungen führen kann – Überspannungen die zum Beispiel bei Gewitter entstehen. Eine Supresor-Diode von 50-60 Volt am Ausgang wäre nicht schlecht.
Einen teuren Server würde ich da aber nicht anschließen.
Die Versorgung Spannung kann auch +/- 12 Volt betragen.
Jetzt mal abseits der inhaltlichen Diskussion:
Können wir mal kurz festhalten, dass ich begeistert bin von der professionellen Gestaltung Deiner Lochrasterplatine und wie unverschämt gut Du die Komponenten verlötet hast? 🙂
Hallo Christian,
danke danke! Ich bin da etwas pedantisch 😉 und habe es auch vor längerer Zeit mal in der Ausbildung gelernt.
Also immer schön den Draht vorher strecken und auf glänzende konkave Lötstellen achten.
Gruß
Chris