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:
-
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. His sketch was the initial basis of this sketch.
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. |
You need the Arduino IDE in order to compile and flash the sketch to the ESP8266.
Follow the instructions on the ESP8266 github project page or from ct magazine to setup your environment.
As additional dependencies you need:
-
ESP8255 board support, Version 2.7.4
-
IotWebConf, Version 2.3.0 for general WiFi setup and WebUI
-
PubSubClient, Version 2.7.0 for MQTT support
Install these libraries via the Arduino IDE.
The pulse-counting feature stores the number of counted impulses in flash. To reserve flash, use the following layout:
4MB FS 1MB, OTA
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].
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].
- 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).
- 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.
- 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.
> mosquitto_sub -v -t "#" sml2emeter/data {"PowerIn":297.32,"EnergyIn":4059843.70,"PowerOut":0.00,"EnergyOut":0.00}
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. |
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}
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.
Check the documentation from 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 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. |
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
For faster and more comfortable development it is possible to use Visual Studio or a GNU toolchain for compiling the sketch and running it on a PC. To create a solution, you need to run 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.
SML { transactionId groupNo abortOnError messageBody crc16 endOfMsg }
Reference: p. 17
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