sml2emeter
sml2emeter copied to clipboard
A D0-SML to SMA Energy Meter converter for the ESP8266 and Raspberry Pi
= D0-SML to SMA Energy Meter converter Joern Tuemmler v1.6, October 2023: Final :doctype: article :encoding: utf-8 :lang: en :toc: left :toclevels: 3 :sectnums: :icons: font :source-highlighter: coderay
== Introduction
This sketch reads SML telegrams from an infrared D0 interface of a smart meter and sends them as SMA energy-meter telegrams via UDP. Alternatively the telegrams can also be published via MQTT or polled via the REST interface of the integrated WebUI.
So far it has been tested with the following meters:
- https://www.dzg.de/fileadmin/dzg/content/downloads/produkte-zaehler/dvs74/dzg_dvs74_handbuch.pdf[DWS74] from Deutsche Zählergesellschaft Oranienburg mbH
As hardware you need:
- an ESP8266 (tested with NodeMCUv2 and WeMos D1 mini)
- or a Raspberry Pi (tested with a Raspberry Pi 2)
- a BPW40 phototransistor
- and optionally a 1 KOhm resistor (only needed with a Raspberry Pi)
[CAUTION]
The source-code and the information in this document is provided as is. Use it at your own risk!
Thanks to Frank Carius for sharing his work. https://www.msxfaq.de/sonst/bastelbude/smartmeter_d0_sml.code.htm[His sketch] was the initial basis of this sketch.
== Setup
=== ESP8266
==== Hardware
Attach the BPW40 transistorize to your ESP8266:
- Short leg (collector, anode) to RxD
- Long leg (emitter, cathode) to GND
[NOTE]
TxD is used to print debug-output.
==== Software
You need the https://www.arduino.cc/en/Main/Software[Arduino IDE] in order to compile and flash the sketch to the ESP8266.
Follow the instructions on the https://github.com/esp8266/Arduino[ESP8266 github project page] or from https://www.heise.de/ct/artikel/Arduino-IDE-installieren-und-fit-machen-fuer-ESP8266-und-ESP32-4130814.html[ct magazine] to setup your environment.
As additional dependencies you need:
- ESP8255 board support, Version 2.7.4
- https://github.com/prampec/IotWebConf[IotWebConf, Version 2.3.0] for general WiFi setup and WebUI
- https://github.com/knolleary/pubsubclient[PubSubClient, Version 2.7.0] for MQTT support
Install these libraries via the Arduino IDE.
.Flash layout
The pulse-counting feature stores the number of counted impulses in flash. To reserve flash, use the following layout:
4MB FS 1MB, OTA
.Configuration After compiling and flashing the software, the ESP8266 provides a WiFi access point with the name sml2emeter. To configure the software, connect to this access point with the password sml2emeter. If supported by your mobile device, you will automatically be redirected to the web-server of the ESP. If not, open a web-browser and enter the IP-address 192.168.4.1.
If everything works you should see an image like in [1].
image::images/configuration.png[]
To configure the ESP, press the [Configuration] button.
[NOTE]
If the device was already configured, you are asked for a username and password. The username is admin and the password the current AP password.
The configuration page is divided into four sections: WiFi configuration [2], meter configuration [3], MQTT configuration [4] and finally pulse-counting configuration [5].
.WiFi configuration [2]
Thing name:: Name of the device. This name is also used when in AP mode. AP password:: Password to connect to the device when in AP mode (mandatory). This password needs to be changed once the configuration of the device is done. WiFi SSID:: The name of the WiFi network (mandatory). WiFi password:: The password to connect to the WiFi network (mandatory).
.Meter configuration [3]
Unicast address 1/2:: Up to two unicast addresses may be specified as destination for energy-meter telegrams. If none is set, the default SMA energy meter multicast address (239.12.255.254) is used. Port:: Destination port for the energy-meter telegrams (default 9522). If any other port greater than 0 is set, raw SML packets will be send. If this value is set to 0, sending of energy-meter telegrams is turned off. Serial number:: The serial number which is used in the energy-meter telegrams.
.MQTT configuration [4]
Broker address:: Hostname of the MQTT broker. Broker port:: Port of the MQTT broker (default 1883). If this value is set to 0, publishing MQTT data is turned off.
If MQTT is enabled, the sketch publishes each telegram received from the energy-meter as JSON object on topic {thing name}/data.
.Example using the mosquitto_sub command to print out received data ....
mosquitto_sub -v -t "#" sml2emeter/data {"PowerIn":297.32,"EnergyIn":4059843.70,"PowerOut":0.00,"EnergyOut":0.00} ....
.Pulse counting configuration [5]
The pulse-counting may be used to count impulses from a gas-meter. For this, a reed-sensor must be attached to GPIO D1.
Debounce time:: This value defines, how long (in ms) the signal of the reed-contact must be LOW until it is counted as an impulse. If this value is 0, pulse-counting is turned off. Factor for m3 calculation:: This value defines a factor to translate the impulses into a volume.
[NOTE]
If pulse-counting is enabled, then the MQTT messages contains two additional fields: ....
mosquitto_sub -v -t "#" sml2emeter/data {"PowerIn":297.32,"EnergyIn":4059843.70,"PowerOut":0.00,"EnergyOut":0.00,"Impulses":123,"m3":1.23} ....
It's possibe to attach an LED to D5 to get a visual feed-back when the software has detected a LOW signal.
.REST interface
Received energy-meter data can also be polled via HTTP: http://[hostname]/data
The returned JSON object is similar to the data published via MQTT:
.... {"PowerIn":90.59,"EnergyIn":4062453.10,"PowerOut":0.00,"EnergyOut":0.00,"Ok":468934,"ReadErrors":0,"ParseErrors":2} ....
=== Raspberry Pi
The software was originally developed for an ESP8266. Experimental support for the Raspberry Pi has been added and tested with a RaspberryPi 2. This version comes without a WebUI, MQTT and pulse-counting support.
==== Hardware
Check the documentation from https://pgoergen.de/de/2018/05/build-a-smartmeter-reading-head-for-1e/[Paul Görgen] for settings up the Raspberry Pi and the hardware. In short:
- Short leg (collector, anode) of the BPW40 to RxD
- Long leg (emitter, cathode) of the BPW40 to GND
- Put the resistor between RxD and 3,3V
[NOTE]
In Paul Görgens https://pgoergen.de/de/2018/05/build-a-smartmeter-reading-head-for-1e/[tutorial] the BPW40 is used without a resistor. In my case this didn't work and only fragments were received. Adding the resistor fixed that problem.
==== Software
You can compile the code directly on a Raspberry Pi. First run CMake to create a makefile, then use make to compile the application:
.... mkdir build cd build cmake .. make ....
Please note that you have to configure your Raspberry Pi to use the serial interface for an own application (see documentation above) and to setup communication parameters to 9600 8N1.
Start the application by specifying the port, e.g.:
.... ./sml2emeter /dev/ttyAMA0 ....
== Background information
=== Developing on a PC
For faster and more comfortable development it is possible to use https://visualstudio.microsoft.com/de/[Visual Studio] or a GNU toolchain for compiling the sketch and running it on a PC. To create a solution, you need to run https://cmake.org[CMake] first.
The python-script in the tools folder may be used to simulate a SML meter and to test everything without a real meter.
=== Links
- https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03109/TR-03109-1_Anlage_Feinspezifikation_Drahtgebundene_LMN-Schnittstelle_Teilb.pdf?__blob=publicationFile[Technische Richtlinie BSI TR-03109-1 / SML]
- https://www.bundesnetzagentur.de/DE/Beschlusskammern/BK06/BK6_83_Zug_Mess/835_mitteilungen_datenformate/Mitteilung_26/Anlagen/Codeliste_OBIS_24a.pdf?__blob=publicationFile&v=1[OBIS-Kennzahlen-System]
- https://www.promotic.eu/en/pmdoc/Subsystems/Comm/PmDrivers/IEC62056_OBIS.htm[OBIS codes]
- https://developer.sma.de/fileadmin/content/global/Partner/Documents/SMA_Labs/EMETER-Protokoll-TI-de-10.pdf[SMA ENERGY METER Zählerprotokoll]
=== Example SML message
.General structure of a SML message .... SML { transactionId groupNo abortOnError messageBody crc16 endOfMsg } .... Reference: p. 17
.Example message
....
76 list SML message
05 52 f1 58 00 string = R.X. transactionId
62 00 uint = 0 groupNo
62 00 uint = 0 abortOnError(0 == continue, p.19)
72 list messageBody (p.20)
63 01 01 uint = 257 SML_PublicOpen.Res (p.22)
76 list
01 optional, not used codepage
01 optional, not used clientId
02 31 string = 1 reqFileId
0b 0a 01 44 5a 47 00 ff 00 ff 00 string = ..DZG..... serverId
72 list refTime
62 01 uint type of time(1 == unsigned)
64 1d a6 aa uint = 1943210
62 02 uint = 2 smlVersion
63 d4 f4 uint = 54516 crc16
00 endOfMessage
76 list SML message
05 53 f1 58 00 string = S.X. transactionId
62 00 uint = 0 groupNo
62 00 uint = 0 abortOnError(0 == continue, p.19)
72 list messageBody (p.20)
63 07 01 uint = 1793 SML_GetList.Res (p.36)
77 list
01 optional, not used clientId
0b 0a 01 44 5a 47 00 ff 00 ff 00 string = ..DZG..... serviceId
07 01 00 62 0a ff ff string = ...... listName
72 list actSensorTime
62 01 uint = 1
64 1d a6 aa uint = 1943210
75 list valList
77 list
07 01 00 60 01 00 ff octed obis:Hardware version
01 optional, not used
72 list
62 01 uint = 1
62 00 uint = 0
62 00 uint = 0
52 00 int = 0
04 44 5a 47 string = DZG
01 optional, not used
77 list
07 01 00 60 01 00 ff octed obis:Device identification
01 optional, not used
72 list
62 01 uint = 1
62 00 uint = 0
62 00 uint = 0
52 00 int = 0
0b 0a 01 44 5a 47 00 ff 00 ff 00 string = ..DZG.....
01 optional, not used
77 list
07 01 00 01 08 00 ff octed obis:Positive active energy (A+) total [Wh]
64 1c 01 04 uint = 1835268
72 list
62 01 uint = 1
62 00 uint = 0
62 1e uint = 30 Unit
52 ff int = 255 Scale 10 ^ -1 = 0,1
64 26 78 f4 uint = 2521332 252133,2 Wh -> 252,1332 kWh -> 907679520 Ws
01 optional, not used
77 list
07 01 00 02 08 00 ff octed obis:Negative active energy (A+) total [Wh]
01 optional, not used
72 list
62 01 uint = 1
62 00 uint = 0
62 1e uint = 30 Unit
52 ff int = 255 Scale 10 ^ -1 = 0,1
62 00 uint = 0
01 optional, not used
77 list
07 01 00 10 07 00 ff octed obis:Sum active instantaneous power (A+ - A-) [W] (must be split to 1.4.0 and 2.4.0)
01 optional, not used
72 list
62 01 uint = 1
62 00 uint = 0
62 1b uint = 27 Unit
52 fe int = 254 Scale 10 ^ -2 = 0,01
53 48 7a int = 18554 185,54 W
01 optional, not used
01 optional, not used listSignature
01 optional, not used actGatewayTime
63 9a 1e uint = 39454 crc16
00 endOfMessage
76 list SML message
05 54 f1 58 00 string = T.X. transactionId
62 00 uint = 0 groupNo
62 00 uint = 0 abortOnError(0 == continue, p.19)
72 list messageBody (p.20)
63 02 01 uint = 513 SML_PublicClose.Res (p.23)
71 list
01 optional, not used signature
63 60 79 uint = 24697 crc16
00 endOfMessage
00 endOfMessage
....