Benutzer-Werkzeuge

Webseiten-Werkzeuge


hardware:channels:meters:power:drs155m

Dies ist eine alte Version des Dokuments!


Hutschienenzähler DRS110M

Das Gerät ist ein Zähler mit einfacher Baubreite und Hutschinenmontage. Der Vorteil ist die integrierte RS485 Schnittstelle, die man elektronisch auslesen kann.

Das Gerät gibt es bei Amazon für 30EUR.

Anschluss an den Computer: RS485 - USB Wandler

Für den Anschluss am Computer benötigt man eine RS485-USB Adapter. Ich habe hierzu von Ebay einen Adapter für 15EUR gekauft.

Bei Ebay nach „RS-485 Adapter: USB auf RS485 Power One Aurora Inverter Web Data Logger“ oder „RS-485 Interface Konverter Adapter: USB auf RS485“ suchen.

Elektrisch wird der Adapter mit dem Stromzähler A↔A , B↔B und G↔G verbunden. Ich habe keine Terminierung verwendet, bei mir ist das Kabel aber auch nur 50cm lang.

Anschluss an den Computer: Software

Für den Zähler habe ich keine richtige Software zum auslesen gefunden. Im Internet kursieren einige Scripte in PHP und Python, um den Zähler auszulesen.

Da ich ein Perl-Fan bin, habe ich das ganze unter perl zum laufen gebracht.

Es wird noch ein perl-Paket für die serielle Schnittstelle benötigt:

„apt-get install libdevice-serialport-perl“

Das script gibt die Zählerdaten auf der Console aus, eine Speicherung in die Datenbank erfolgt auch. Zuvor muss über das Webinterface der Kanal angelegt sein.

Hier dann das Perl-script

Das Script abspeichern, ausführbar machen. Das Script kann zum testen manuell aufgerufen werden. Falls alles gut läuft kann das Script im Cron zyklisch aufgerufen werden ( crontab -e ).

Der serielle Port und die uuid(die uuid bekommt man über das Webinterface von volkszähler) müssen im Script angepasst werden.

#!/usr/bin/perl -w

# teile von http://www.ip-symcon.de/forum/threads/21407-Stromz%C3%A4hler-mit-RS485/page2 entnommen
# 20130802 : ollir

use Device::SerialPort;


my $port = Device::SerialPort->new("/dev/ttyUSB0") || die $!;
$port->baudrate(9600);
$port->databits(7);
$port->parity("even");
$port->stopbits(1);
$port->handshake("none");
$port->write_settings;

$port->purge_all();
$port->read_char_time(0);     # don't wait for each character
$port->read_const_time(100); # 100 millisecond per unfulfilled "read" call

my $serialID = "000000000000";        # auszulesende Zähler-ID (12 Stellen), Standard: "000000000000"
my $password = "00000000"; # Standartpasswort
my $uuid="84356400-f7b8-11e2-8431-07a5d66d6531" ;

my $verbose = 2 ;

# ========================================
sub sendgetserial {
  my ($cmd) = @_;
  my $count;
  my $saw;
  my $x;

  $port->lookclear;
  $port->write( $cmd );

  ($count,$saw)=$port->read(84);   # will read 84 chars
  $x=uc(unpack('H*',$saw)); # nach hex wandeln

  $cmd =~ s/\n/\\n/mg;
  $cmd =~ s/\r/\\r/mg;

  $saw =~ s/\n/\\n/mg;
  $saw =~ s/\r/\\r/mg;

  if ( $verbose>10 ) {
    printf "+++ sendserial\n" ;
    print  " CMD: $cmd \n";  # gibt den Befehl in ASCII aus
    print  " COUNT: $count \n";  # gibt die Anzahl der empfangenen Daten aus
    print  " HEX: $x \n";  # gibt die empfangenen Daten in Hex aus
    print  " ASCII: $saw \n";  # gibt die empfangenen Daten aus
    printf "--- sendserial\n" ;
  }

  return $saw;
}
# ========================================
sub decodeVAL {
  my ($val) = @_;

  if ( $verbose>10 ) {
    printf "+++ decodeVAL\n" ;
    print " val = ( $val ) \n" ;
  }

  if($val =~ m/\((\d+)\)/) {
    if ( $verbose>10 ) {
      print " decoded val = $1\n";
      printf " --- decodeVAL\n" ;
    }
    return $1;
  }

  print " val = ( $val ) \n" ;
  die "NICHTS gefunden!\n";
  print "NICHTS gefunden!\n";
  return -8888;
}
# ========================================


## Variablen
my $cmd;
my $res;
my %vals = ();

# Abfrage der Initialisierung: hier bekommt man die $serialID raus !!
print("# INIT 1 #############\n") if ($verbose>8);
sendgetserial("/?!\r\n");


# initalisierung ueberprüfen, jetzt mit ID, wenn die ID nicht passt, kommt keine Antwort!
print("# INIT 2 #############\n") if ($verbose>8);
sendgetserial("/?" . $serialID . "!\r\n");


# ACK / Option Select Message senden ('Programming Mode')
# der programming modus muss auch bei einer einfachen Strom,Spgs-Abfrage gesetzt werden
if (1) {
  print("# PROGRAMMING MODE #############\n") if ($verbose>8);
  $cmd = chr(0x06).chr(0x30).":".chr(0x31).chr(0x0D).chr(0x0A);
  sendgetserial( $cmd);
  $cmd = chr(0x01)."P1".chr(0x02)."(".$password.")".chr(0x03).chr(0x61);
  sendgetserial( $cmd);
}

# ****************** Werte lesen
print("# SPANNUNG #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000000()".chr(0x03).chr(0x63) );
$vals { 'Spannung' } = ( decodeVAL $res  ) / 10;

print("# STROM #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000001()".chr(0x03).chr(0x62) );
$vals { 'Strom' } = ( decodeVAL $res  ) / 10;

print("# FREQUENZ #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000002()".chr(0x03).chr(0x61) );
$vals { 'Frequenz' } = ( decodeVAL $res  ) / 10;

print("# Wirkleistung #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000003()".chr(0x03).chr(0x60) );
$vals { 'PWirk' } = ( decodeVAL $res  ) * 10;

print("# Blindleistung #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000004()".chr(0x03).chr(0x67) );
$vals { 'PBlind' } = ( decodeVAL $res  ) * 10;

print("# Scheinleistung #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000005()".chr(0x03).chr(0x66) );
$vals { 'PSchein' } = ( decodeVAL $res  ) * 10;

print("# Leistungsfaktor #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000006()".chr(0x03).chr(0x65) );
$vals { 'cosphi' } = ( decodeVAL $res  ) / 1000 ;

print("# Zaehlerstand 1 #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000010()".chr(0x03).chr(0x62) );
$vals { 'Zaehler1' } = ( decodeVAL $res  ) * 1 ;
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000011()".chr(0x03).chr(0x63) );
$vals { 'Zaehler1b' } = ( decodeVAL $res  ) * 1 ;

print("# Zaehlerstand 2 #############\n") if ($verbose>8);
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000020()".chr(0x03).chr(0x61) );
$vals { 'Zaehler2' } = ( decodeVAL $res  ) * 1  ;
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000021()".chr(0x03).chr(0x60) );
$vals { 'Zaehler2b' } = ( decodeVAL $res  ) * 1  ;

print("# Temperatur #############\n") if ($verbose>8) ;
$res = sendgetserial( chr(0x01)."R1".chr(0x02)."00000032()".chr(0x03).chr(0x62) );
$vals { 'Temperatur' } = ( decodeVAL $res  )  * 1.0 ;


# ****************** LOGOUT
print("# LOGOUT #############\n") if ($verbose>8);
$cmd = chr(0x01)."B0".chr(0x03).chr(0x71) . "/?!\r\n" ;
$res = sendgetserial( $cmd);



# ****************** Werte plotten
if ($verbose>1) {
  print("# Werte plotten #############\n");
  while ( my ($key, $value) = each(%vals) ) {
    print " --> $key = $value\n";
  }
}


# ****************** Wert in die Datenbank schreiben

use LWP::UserAgent;

$val =  $vals{ "Zaehler1" } ;
print "ZAEHLERSTAND: " . $uuid . " = " . $val . "\n";

my $server_endpoint = "http://localhost/middleware.php/data/${uuid}.json?value=" . $val;
print "serverget = " .  $server_endpoint . "\n";

my $ua = LWP::UserAgent->new;

# set custom HTTP request header fields
my $req = HTTP::Request->new(POST => $server_endpoint);
$req->header('content-type' => 'application/json');
$req->header('x-auth-token' => 'kfksj48sdfj4jd9d');

# add POST data to HTTP request body
$req->content(" ");

if (1) {
  my $ua = LWP::UserAgent->new;
  my $resp = $ua->request($req);
    if ($resp->is_success) {
      my $message = $resp->decoded_content;
      print "Received reply: $message\n";
    } else {
      print "HTTP GET error code: ", $resp->code, "\n";
      print "HTTP GET error message: ", $resp->message, "\n";
    }
}



Beispielausgabe

Falls das Script läuft, bekommt man folgende Ausgaben:

 --> Zaehler2b = 7450
 --> Temperatur = 22
 --> Zaehler1 = 3040
 --> Frequenz = 50
 --> Zaehler2 = 7450
 --> Zaehler1b = 3040
 --> cosphi = 0
 --> PWirk = 0
 --> PSchein = 0
 --> Spannung = 234.2
 --> PBlind = 0
 --> Strom = 0

Die Zählerangabe sind Wh.

offene Punkte

Ich habe mit meinem Zähler das Problem, dass der Zähler 1x am Tag für ca.80min nicht zählt. Die Datenkommunikation funktioniert, aber der Zähler sendet scheinbar immer die gleichen Daten.

–> Kann das Problem jemand bestätigen?

Todos

  • Werte in die Datenbank schreiben
  • prüfen, ob das script auch bei mehreren Zähler an einem RS485 läuft
  • die ID der Zähler setzen
  • die Passwörter der Zähler setzen
hardware/channels/meters/power/drs155m.1375555363.txt.gz · Zuletzt geändert: 2013/08/03 20:42 von ollir