Benutzer-Werkzeuge

Webseiten-Werkzeuge


hardware:channels:meters:power:vsm-103

VSM-103 von Conrad

Conrad hat einen preisgünstigen Drehstromzähler mit S0-Schnittstelle und Modbus in RS-485 Variante und Infrarot. Leider gibt es dazu kaum Doku.

Nach dem Kauf des Komplettsystems und etwas Schnittstellenauswertung und probieren gibt's dazu hier ein paar weitere Infos.

Bei weiteren Infos oder Fragen am Besten hier eintragen.

Allgemeines

  • Preisgünstig
  • Undokumentierte Schnittstelle
  • Hoher Eigenverbrauch: ca. 2W (relativ zu anderen Zählern, jeweils laut Datenblatt)

RS-485

Der Zähler hat eine RS-485 Schnittstelle zum Abfragen. Diese arbeitet in der Betriebsart 8e2. Bisher ist nur die Geschwindigkeit mit 1200 baud getestet worden. Laut Doku sollte es auch schneller gehen.

Modbus

Der Modbus wird binär nach RTU betrieben. Siehe dazu auch http://de.wikipedia.org/wiki/Modbus und insbesondere http://www.simplymodbus.ca/. Grundätzliche Idee: Es gibt einen Master und mehrere Slaves. Der Master schickt Anfragen an die Slaves die darauf antworten.

Anfrage

Der VSM-Zähler erkennt (mindestens und soweit bekannt) Anfragen nach dem Schema

ID Funktion Register Länge CRC
Beschreibung Für VMS-103: 1, 1 ByteFür VSM-103: 4, 1 Byte2 Byte, je nach gewünschtem Wert2 Byte, bei VSM-103 immer 2CRC, 2 Byte
Beispiel (hex)010400 9600 0291 e7Momentanen Wirk-Gesamtleistung?

Antwort

Auf erkannte Anfragen antwortet der Zähler dann mit einem Datentelegramm mit meist 8 Byte:

ID Funktion Daten-Laenge Daten CRC
BeschreibungFür VMS-103: 1, 1 ByteFür VSM-103: 4, 1 ByteAnzahl der Bytes der Antwort, 1 ByteDatenCRC
Beispiel (hex)0104043b a3 d7 0a d9 75Momentanen Wirk-Gesamtleistung: 0,05 kWatt

Datenformat

Die Antworten liegen (soweit bisher bekannt) in den 4 Byte als 32Bit Gleitkommazahl vor: http://de.wikipedia.org/wiki/IEEE_754. Wer damit bisher nicht zu tun hatte, hier gibt's eine Excel-Vorlage zum berechnen: http://www.simplymodbus.ca/FAQ.htm#Types

CRC

Auch hier http://www.simplymodbus.ca/FAQ.htm#CRC gibt's eine Excel-Vorlage um die 2-Byte CRC zu berechnen. Der VSM-103 beantwortet nur Anfragen mit korrekter CRC.

Bisher bekannte Register

Register hex Art Beschreibung Einheit Stellen(*) Bemerkung
160010U1Spannung zwischen N und L1[V]
180012U2Spannung zwischen N und L2[V]
200014U3Spannung zwischen N und L3[V]
78004eFFrequenz[Hz]2
800050I1Strom auf L1[A]
820050I2Strom auf L2[A]
840052I3Strom auf L3[A]
860054INStrom auf N[A] ?? IN und I geben gleiche Werte?!
880058IStrom gesamt[A]
1440090P1Wirkleistung auf L1[kW]3–>1 Watt Auflösung
1460092P2Wirkleistung auf L2[kW]3
1480094P3Wirkleistung auf L3[kW]3
1500096PWirkleistung gesamt[kW]3
20800d0S1Scheinleistung L1[kvar]3
21000d2S2Scheinleistung L2[kvar]3
21200d4S3Scheinleistung L3[kvar]3?? Bei mir immer Null?!
21400d6SScheinleistung ges[kvar]3
2720110Q1Blindleistung L1[kvar]3
2740112Q2Blindleistung L2[kvar]3
2760114Q3Blindleistung L3[kvar]3
2780116QBlindleistung ges[kvar]3
3360150LF1Leistungsfaktor L1
3380150LF2Leistungsfaktor L2
3400150LF3Leistungsfaktor L3
3420150LFLeistungsfaktor ges
3520160Z1Zaehlerstand Wirkenergiebezug[kWh]2–>0,01 kWh Auflösung
3540162Z2Zaehlerstand Blindenergiebezug? [kWh]2nur Vermutung, nicht bestätigt
3580160Z3Zaehlerstand Wirkenergieabgabe? [kWh]2nur Vermutung, nicht bestätigt
3600168Z4Zaehlerstand Blindenergieeinspeisung? [kWh]2nur Vermutung, nicht bestätigt
13180526??VSM Antwortet mit: 0x01040456341256275c
15600618??Zaehlerstand ?
65298ff12??
65314ff22??

Auch bei Einträgen ohne Fragezeichen ist die Beschreibung nicht absolut sicher, solange niemand das Bestätigt bitte die erhaltenen Werte auf Sinnhaftigkeit prüfen!

(*) Hier nur: Aussage über die Nachkommastellen, nicht über die Messgenauigkeit

S0-Schnittstelle

Der VSM-103 verfügt über zwei S0-Schnittstellen für Wirk- und Blindenergie mit einer Konstante von 400 Impulsen pro kWh. Ungetestet.

Infrarot-Schnittstelle

Per Infrarot soll ebenfalls eine Modbus-RTU Kommunikation mit 1200 baud möglich sein. Ungetestet.

Software

Bin kein guter Softwerker, aber es funktioniert ;-) Verbesserungen willkommen.

#!/usr/bin/perl
 
# Nur bischen Zeit fuer die Logdatei aufbereiten...
$unix_time = time;
($jahr, $monat, $tag, $stunde, $minute, $sekunde) = (localtime)[5,4,3,2,1,0];
$monat=$monat+1;
$jahr=$jahr+1900;
if ($tag<10) {$tag='0'.$tag;}
if ($monat<10) {$monat='0'.$monat;}
if ($stunde<10) {$stunde='0'.$stunde;}
if ($minute<10) {$minute='0'.$minute;}
if ($sekunde<10) {$sekunde='0'.$sekunde;}
 
# Anfrage an den Terminalserver (http://wut.de/e-58631-ww-dade-000.php )
# Sollte auch ueber normale Serielle gehen. Dann mit Adapter RS-232<-->RS-485
use IO::Socket;
    $socket = IO::Socket::INET->new(PeerAddr=> "192.168.1.23",    # Terminalserver
                PeerPort=> "8000",
                Proto   => "tcp")
    or die "Kaputt!";
 
# Vordefinierte Register, CRC ist da schon berechnet :-) Hier nur zwei, sonst wird's arg unuebersichtlich.
# Momentanleistung 150
$frage[0]=pack('H*',"01040096000291e7");
# Zaehlerstand >     352
$frage[1]=pack('H*',"01040160000fb1ec");
# Wie erhaelt man nochmal die Laenge eines Arrays? ;-)
$fragen=2;
 
# Nun fuer jeden Angfragestring durchlaufen
for ($anfrage=0; $anfrage < $fragen; $anfrage++) {
# Den Anfragestring an den Anschluss schicken.
print $socket $frage[$anfrage];
 
# Einlesen von 8 Byte
# Es werden stumpf 8 Byte erwartet, nix mit Timout oder so...
$i=-1;
while ($i < 8 ){
    sysread($socket, my ($byte), 1);
    $i++;
    $antwort[$i]=$byte;
}
$antwortcount=$i;
 
# In der Subroutine den Wert umrechnen.
# Es werden stumpf die Datenbits genommen, nix CRC-Pruefung oder so...
$wert[$anfrage]=parse32b($antwort[3],$antwort[4],$antwort[5],$antwort[6]);
}
close($socket);
 
# Jetzt werden die ermittelten Werte in einer Zeile die Logdatei angehaengt, mit ';' getrennt
open (LOG,">>/pfad/datei")
    or die "Logdatei kann nicht geschrieben werden";
print LOG $jahr.$monat.$tag."T".$stunde.$minute.$sekunde.';'.$unix_time.";";
for ($anfrage=0; $anfrage < $fragen; $anfrage++) {
    print LOG $wert[$anfrage].";"
}
print LOG "\n";
close(LOG);
 
 
 
sub parse32b # 32bit nach Dezimal wandeln, http://de.wikipedia.org/wiki/IEEE_754
{
($byte0, $byte1, $byte2, $byte3) = @_;
 
# So klappts nicht. Vielleicht irgend was falsch herum?
#print "Bytes: ". unpack('H*',$byte0) ." ". unpack('H*',$byte1) ." ". unpack('H*',$byte2) ." ". unpack('H*',$byte3). "\n";
#$ra = unpack('f*',$byte0. $byte1. $byte2. $byte3);
#print $ra."\n";
 
## So klappen's, wenn auch nicht so elegant
$bin=unpack('B*', $byte0.$byte1.$byte2.$byte3 );
 
$sign=substr($bin,0,1);
if ($sign==1){$sign=-1;}
if ($sign==0){$sign=+1;}
 
$exponent=substr($bin,1,8);
$exponent=oct("0b".$exponent);
$exponent=$exponent-127;
 
$mantisse=substr($bin,9);
$mantisse=oct("0b".$mantisse);
$mantisse=$mantisse/8388608;
$mantisse=1+$mantisse;
 
$wert= $sign * $mantisse * ( 2 ** $exponent ) ;
return($wert);
}

Beispiele

Verbrauch morgens

Momentanleistung der drei Phasen (linke y-Achse) und Zählerstand (rechte y-Achse), Abfrageintervall ca. 10 Sekunden.

hardware/channels/meters/power/vsm-103.txt · Zuletzt geändert: 2012/01/28 16:56 von stv0g