Wir erhalten Daten von Mercury 203.2T-Zählern auf RS-485



Das Organisieren einer Fernerfassung von Messwerten von Stromzählern ist keine schwierige Aufgabe, die Zähler sind jedes Jahr intelligenter und müssen alles selbst senden, aber nein, natürlich gibt es Informationen, aber sie sind verstreut. Gerätehersteller wollen offenbar auch mit dem Verkauf ihrer Software Geld verdienen. Ich schreibe diesen Artikel, um Zeit für alle zu sparen, die ähnliche Aufgaben haben.

Starten Sie


Das Unternehmen musste die Erfassung von Messwerten von Stromzählern, etwa zwanzig Stück, automatisieren. Dazu war dies schnell und möglichst kostengünstig erforderlich. Aus diesem Grund haben sie beschlossen, Daten mit dem bereits bereitgestellten Zabbix zu sammeln. Um jedoch eine Verbindung zum Zähler herzustellen, musste ein kleines Skript geschrieben werden, mehr dazu weiter unten. Es stellte sich heraus, dass die Erfassung von Messwerten nur einer der Parameter ist, die erfasst werden müssen. Der PC mit Debian an Bord ist für den Rest verantwortlich, sodass es nicht schwierig war, über den COM-Port eine Verbindung zum Zähler herzustellen. Für die meisten ist es natürlich bequemer, ein lokales Netzwerk zu verwenden und Informationen von einem industriellen Switch oder Schnittstellenkonverter abzurufen.

Von den Verbindungsoptionen können Sie auch einen optischen Anschluss in Betracht ziehen, obwohl Sie ein zusätzliches Gerät kaufen müssen. Andererseits müssen Sie die Dichtung nicht entfernen.



Die Klemmen zum Anschluss an das Messgerät befinden sich unter der versiegelten Abdeckung.
Daher mussten wir uns auf ein Netzwerkunternehmen einigen, dass wir die Dichtungen entfernen, Arbeiten ausführen und die Zähler wieder versiegeln müssen. Am Ende wurden jedoch Vereinbarungen getroffen, und es war möglich, die Lösung des Hauptproblems ruhig zu behandeln.



Problemlösung


Wie aus der offiziellen Dokumentation hervorgeht.

Der Zähler nimmt eine Eingabezeichenfolge von Bytes des ADDR-CMD-CRC-Formats und gibt die ADDR-CMD-DATA-CRC an, wobei:

  • ADDR - Zählername (für Mercury 203.2T - wie Seriennummer)
  • CMD - Code Befehl
  • DATA - Daten hängen von der Anfrage ab
  • CRC - zyklischer 2-Byte-Redundanzcode, berechnet für alle vorherigen Bytes dieses Pakets. Aus dieser Erklärung geht nicht hervor, was in das Prüfsummenfeld geschrieben werden soll.

Ein Bindestrich in einer Sequenz wird nicht verwendet, hier wird er verwendet, um logische Blöcke zu trennen.

Stellen Sie zunächst mit dem Standardkonfigurator-Programm eine Verbindung zum Zähler her und sehen Sie sich mit einem Sniffer die übertragenen Pakete an, um herauszufinden, welche Prüfsumme am Ende hinzugefügt werden soll. Unten die vom Zähler empfangene Zeile.



Mit dem CRC-Online-Rechner finden wir heraus, was wir zur Berechnung von CRC-16 (Modbus) mit dem Polynom 0xA001 benötigen.

Ein bisschen Python


Es gibt genügend Links zum Berechnungsalgorithmus, daher werde ich nicht weiter darauf eingehen. Für die Entwicklung habe ich Python 3 verwendet

def crc16(data): crc = 0xFFFF l = len(data) i = 0 while i < l: j = 0 crc = crc ^ data[i] while j < 8: if (crc & 0x1): mask = 0xA001 else: mask = 0x00 crc = ((crc >> 1) & 0x7FFF) ^ mask j += 1 i += 1 if crc < 0: crc -= 256 result = data + chr(crc % 256).encode() + chr(crc // 256).encode('latin-1') return result 

Versuchen wir nun, die Seriennummer vom Zähler zu erhalten und die CRC zu überprüfen. Sie müssen das Pyserialmodul installieren

 import serial import struct import time sn = 26222790 #   ser = serial.Serial('/dev/ttyUSB0', 9600, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE) print ('Connected:', ser.isOpen()) # \x2f -      chunk = struct.pack('>L', int(sn)) chunk += b'\x2f' chunk = crc16(chunk) #          ser.write(chunk) time.sleep(1) out = ser.read_all() ser.close() print ('Check CRC:', out[-2:] == crc16(out[:-2])[-2:]) print ('Result string:', ':'.join('{:02x}'.format(c) for c in out)) 

Großartig! Jetzt erhalten wir die Werte für die verbrauchte Energie beim ersten und zweiten Tarif. Tatsächlich müssen wir nur noch das Teamfeld ändern und das Ergebnis analysieren.

 chunk += b'\x27' t1 = ''.join('{:02x}'.format(c) for c in out[5:9]) t2 = ''.join('{:02x}'.format(c) for c in out[9:13]) print ('T1 =', float(t1)*0.01, '(*)', 'T2 =', float(t2)*0.01, '(*)') 

Alles arbeitet. Die endgültige Version des auf git veröffentlichten Skripts. In Zukunft möchte ich Unterstützung für die Arbeit im lokalen Netzwerk hinzufügen.

Für die Entwicklung wurde der Mercury-221 USB -> COM-Adapter verwendet, aber Sie können den Zähler direkt an den COM-Anschluss anschließen.



Referenzen:

Nützliche Informationen zum Anschließen von Zählern finden Sie hier.
Dokumentation auf der offiziellen Website
Website für technischen Support
Über CRC auf Wikipedia

Source: https://habr.com/ru/post/de418209/


All Articles