Code Monkey home page Code Monkey logo

sml2emeter's Introduction

D0-SML to SMA Energy Meter converter

1. 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:

  • 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.

2. Setup

2.1. ESP8266

2.1.1. 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.

2.1.2. Software

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:

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].

configuration

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}

2.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.

2.2.1. Hardware

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.

2.2.2. 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

3. Background information

3.1. Developing on a PC

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.

3.3. 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

sml2emeter's People

Contributors

jtuemmler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

sml2emeter's Issues

http to emeter

Hi,

I am searching for a way to use a http meter (tasmota flashed sonoff pow) to be integrated into the sunnyportal/homemanager as a production counter. The idea behind this is, to integrate some one phase inverter.
Your software is the nearest I found. Maybe you can help me out.

Best Regards
Johannes

webserver inresponsive when serial data is missing

i.e. when there is no serial connection. I fixed this by allowing the readSerial() function to terminate if no data arrives.
I did insert the second "break;".

void readSerial() {
   Serial.print("W");
   ledOff();
   bool receiving = false;
   int waitCount = 0;
   do {
      int data = Serial.read();
      if (data >= 0) {
         if (!receiving) {
            Serial.print("R");
            ledOn();
            receiving = true;
            waitCount = 0;
         }
         uint8_t byte = (uint8_t)data;
         if (smlStreamReader.addData(&byte, 1) >= 0) {
            break;
         }
      }
      else {
         ++waitCount;
         if (waitCount == 195) {
            ledOn();
         }
         if (waitCount == 200) {
            Serial.print("T");
            ledOff();
            waitCount = 0;
            ++readErrors;
            break;
         }
         delayMs(10);
      }
   } while (true);
   ledOff();
}

IOTWebconf update 2.3 -> 3.2

I noticed that the IOTWebconf library has advanced to version 3.2. Using this version, build fails with
'HTTPUpdateServer' does not name a type

reverting to the version you used, 2.3, it works.

Error in sml2emeter.ino

The following code causes a WDT reset.

void readTestPacket() {
   Serial.print("W");
   ledOff();
   delayMs(1000 - TEST_PACKET_RECEIVE_TIME_MS);
   Serial.print("R");
   ledOn();
   delay(TEST_PACKET_RECEIVE_TIME_MS);
   smlStreamReader.addData(SML_TEST_PACKET, SML_TEST_PACKET_LENGTH);
   ledOff();
}

A fix is to replace the second delay with delayMs.

CRC check reads OK if no data is in the packet.

The bool parsePacket(const uint8_t *pPacket, int packetLength) { function does not check wether the packetLength parameter is 0. If an empty packet is passed (i.e. no serial connection ), the CRC is reported as okay.
packetLength needs to be larger than 10 or so.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.