Sensor mit Köpfchen (Linux-Magazin, August 2007)

Digitale Multimeter messen heutzutage nicht nur Strom und Spannung, sondern auch Kapazität und Temperatur. Und es gibt sogar welche in der 50-Euro-Preisklasse, die mit der seriellen Schnittstelle eines PCs reden. Mit einigen einfachen Perlskripts lassen sich die Daten auslesen und graphisch aufbereiten.

Beim Blättern im Katalog eines Elektronikversandhändlers sprangen mir neulich relativ preiswerte digitale Multimeter mit RS-232-Schnittstelle ins Auge. Auf Ebay fand ich dann das Modell MAS-345 von der Firma Mastech für $35 und drückte ruck-zuck den ``Buy-it-now'' Button.

Windows? Nein danke.

Natürlich wurde das Gerät dann nur mit einer Windows-CD angeliefert, aber eine kurze Suche auf dem Netz förderte das Marsh-Projekt [2] zutage, das mit etwas C-Code unter anderem das Mastech MAS-345 ansteuert. Das Protokoll auf der seriellen Leitung ist nicht weiter kompliziert: Nach einigen einleitenden Signalen zur Leitungsklärung schickt der PC ein Newline-Zeichen an das Messgerät. Dieses antwortet mit einem 14 Byte langen String, der nach dem eingestellten Multimeter- Modus den auf der LCD-Anzeige des Multimeters dargestellen Zahlenwert enthält. Optional wird dann noch die eingestellte Maßeinheit (Volt, Ampere, Ohm, Grad Celsius) gesendet.

Steht im zurückgelieferten String zum Beispiel V -120.3 mV, steht das Multimeter im Spannungsmodus (``V'' für ``Volt'') und zeigt -120.3 Millivolt an. Die Kommunikation mit dem Multimeter dauert etwa eine Sekunde, sodass der Computer maximal einen Messwert pro Sekunde von dort abholen kann.

Objektorientiertes RS-232

Listing 1 zeigt ein Testskript, das einen Wert vom Multimeter abholt. Das CPAN-Modul Device::SerialPort bietet eine komfortable objektorientierte Schnittstelle, um mit einem seriellen Port des Rechners zu kommunizieren. Dieser wiederum spricht das RS-232-Protokoll mit dem am anderen Ende der Leitung angeschlossenen Multimeter.

Listing 1: mmread

    01 #!/usr/bin/perl -w
    02 use strict;
    03 use Device::SerialPort;
    04 
    05 my $serial = Device::SerialPort->new(
    06      "/dev/ttyS0");
    07 
    08 $serial->baudrate(600);
    09 $serial->databits(7);
    10 $serial->purge_all();
    11 $serial->rts_active(0);
    12 $serial->dtr_active(1);
    13 
    14    # Send request
    15 $serial->write("\n");
    16    # Wait one second
    17 select(undef, undef, undef, 1);
    18 
    19    # Read response
    20 my($count, $data) = $serial->read(14);
    21 print "$data\n";

mmread verbindet sich zunächst mit dem ersten seriellen Port, dessen Device-Eintrag /dev/ttyS0 ist. Damit das Skript auch unter normalen User-Accounts läuft, sollten vorher mit chmod a+rw /dev/ttyS0 (als root) am Port Schreib- und Leserechte für die Allgemeinheit eingeräumt werden. Wessen neumodischer Computer keine serielle Schnittstelle mehr hat, kann diese mittels einer PCI-Karte für etwa 10 Euro nachrüsten.

Zunächst wird die Baudrate auf 600 und die Anzahl der Datenbits auf 7 eingestellt. Die nachfolgend aufgerufene Methode purge_all() nutzt intern die Unix-Funktion tcflush(2) mit dem Flag TCIOFLUSH und löscht damit etwaige noch herumgeisternde Daten. Mit dem anschließenden Klären der RTS-Leitung und dem Setzen der DTS-Leitung wird die Kommunikation mit dem Multimeter eingeleitet.

Die Methode write() schickt anschließend ein Newline-Zeichen an das Multimeter, welches dieses aufschnappt und nach kurzer Verzögerung mit den auf seinem Display dargestellten Daten antwortet. Das Skript wartet deswegen erst einmal eine Sekunde, bevor es mit read() die Daten von der seriellen Schnittstelle abholt. Das könnte man einfach mit sleep(1) machen, aber select() unterstützt auch Sekundenbruchteile, und während der Skriptentwicklung habe ich verschiedene Werte probiert, bin aber bei einer Sekunde als zuverlässiger Lösung hängengeblieben.

Da bereits bekannt ist, dass das Multimeter genau 14 Zeichen schickt, wird read angewiesen, exakt 14 Zeichen zu lesen. Die Ausgabe mit print bestätigt, dass in der Tat ein korrekt formatierter Datenstring zurückkommt.

Einer für Alle

Statt ständig mit diesen Einstellungen herumzupfrümeln, habe ich das Ganze in ein Modul verpackt und unter Device::MAS345 aufs CPAN gespielt. So können auch andere MAS345-Enthusiasten ihre Multimeter auslesen, ohne sich mit den technischen Details herumschlagen zu müssen. Ein weiterer Vorteil von CPAN-Modulen ist, dass sie von überall verfügbar und mit search.cpan.org leicht aufzustöbern sind.

Device::MAS345 bietet eine objektorientierte Schnittstelle auf höherem Abstraktionsniveau. Das Skript mmloop in Listing 2 zeigt, wie man in einer Endlosschleife Daten vom Multimeter abholt und mit den Unix-Sekunden des Messzeitpunkts zeilenweise in einer Textdatei ablegt. Device::MAS345 schnappt nicht nur den roh formatierten String des Multimeters auf, sondern liefert gleich Zahlenwert ($value), Einheit ($unit) und Modus ($mode) getrennt zurück. Vor Beginn der Endlosschleife schaltet das Skript die Pufferung mit print ab, damit auch jede Zeile sofort in die Ausgabedatei geschrieben wird. So lässt sich das Ergebnis ruckelfrei mit tail -f verfolgen, wenn etwa alle 10 Sekunden ein neuer Wert abgelegt wird.

Listing 2: mmloop

    01 #!/usr/bin/perl
    02 use strict;
    03 use warnings;
    04 use Device::MAS345;
    05 use Log::Log4perl qw(:easy);
    06 Log::Log4perl->easy_init($DEBUG);
    07 
    08 my $mas = Device::MAS345->new(
    09             port => "/dev/ttyS0");
    10 
    11 open FILE, ">>values.txt" or die;
    12 
    13   # Autoflush
    14 select FILE;
    15 $| = 1;
    16 
    17 while(1) {
    18     my($val, $unit, $mode) = $mas->read();
    19     die $mas->error() unless $mode;
    20     print FILE time(), " ", "$val\n";
    21     sleep 10;
    22 }

Vorsicht, Spannung!

Abbildung 1: Das Multimeter misst den Strom, der durch die Steckdose fließt und gibt den gemessenen Wert per RS-232 an den Rechner weiter.

Schon lange beschäftigt mich, wieviel Strom mein Tag und Nacht laufender Computer zieht und wie der zeitliche Verlauf aussieht. Schaltet er die Stromaufnahme bei Nichtbenutzung herunter? Ein Gerät wie das ``Kill-A-Watt'' [3] kann zwar den Gesamtverbrauch ausrechnen, aber schließlich wollen wir wissen, was der Rechner in der Nacht um Vier treibt, wenn keiner hinsieht. Das MAS-345 kann nicht nur Strom bis 10 Amperes messen, sonder auch noch Wechselstrom, was bei billigen Multimetern keineswegs selbstverständlich ist.

Misst man den Strom aus der Steckdose mit einem Multimeter, sollte man innerlich auf Alarmstufe Rot schalten und höchste Vorsicht walten lassen. In Amerika kommen zwar nur etwa 110V an, aber auch das reicht unter Umständen, um einen unvorsichtigen Expermentierer schwer zu verletzen. Unisolierte Bananenstecker, die bei Niedervoltexperimenten eingesetzt werden, haben im Netzspannungsbereich nichts verloren. Vor vielen, vielen Jahren musste einer meiner Physiklehrer tatsächlich einmal ins Krankenhaus eingeliefert werden, weil er aus Schusseligkeit einen Bananenstecker angefasst hatte, auf dem 220V anlagen!

Neue Messkabel für Multimeter werden gottlob schon mit isolierten Bananensteckern geliefert, und ich habe mir einfach noch ein Paar gekauft, um sie an eine Vielfachsteckdose anzuschließen.

Abbildung 2: Das Multimeter muss auf Strommessung eingestellt und in Reihe mit dem Verbraucher geschaltet werden.

Abbildung 3: Eine modifizierte Vielfachsteckdose mit isolierten Bananensteckern für den Anschluss eines digitalen Ampere-Meters.

Das Ampere-Meter muss dabei in Reihe zum Verbraucher geschaltet werden. Abbildung 2 zeigt das Schaltbild, Abbildung 3 die reale Verkabelung einer Billig-Vielfachsteckdose. Im Ampere-Modus ist der interne Widerstand des Multimeters fast gleich Null, deswegen wäre es fatal, es parallel zur Steckdose anzuschließen. In diesem Fall träte ein Wettlauf zwischen dem Rausfliegen der Sicherungen im Sicherungskasten und im Multimeter (falls vorhanden) oder einer Explosion des letzteren in Gang. Also Vorsicht.

Die Lötstellen der Made-in-China-Vielfachsteckdose waren übrigens erstaunlich hart. Ich musste mir extra einen 60W-Lötkolben kaufen (der bislang dritte in meiner Sammlung), denn meine bisherigen waren eher zum Herumzischen in kleinen elektronischen Geräten ausgelegt.

Nach doppelter Prüfung der so modifizierten Hardware kann man vorsichtig eingestöpseln und die Messungen starten. Im Perlmeisterlabor wurden der Stromverbrauch des heimischen Linux-PCs und des an eine Docking- Station angeschlossenen Laptops gemessen.

Graphisch auswerten

Eine Textdatei mit Zahlenkolonnen holt heutzutage keinen Hund mehr hinter dem Ofen hervor. Um die Daten graphisch aufzubereiten, liest sie das Skript mm2rrd in Listing 3 zeilenweise aus und trennt den Zeitstempel vom abgelegten Messwert. Mit rrdtool lassen sich daraus ohne viel Aufwand schöne Graphiken erstellen.

Abbildung 4: Stromverbrauch eines PCs über Nacht: Ab zwei Uhr setzt ein Cronjob ein, der um 7:00 beendet ist.

Abbildung 5: Stromverbrauch eines Laptops kurz vor und nach dem Einschalten.

Zur zeilenweisen Bearbeitung kommt die Methode plough (engl. ``pflügen'') aus dem CPAN-Modul Sysadm::Install zum Einsatz. Es nimmt eine Subroutinen- Referenz und eine Datei entgegen. Es öffnet die Datei, iteriert über die Zeilen und springt für jede die angegebene Funktion an, wobei es die Variable $_ auf den Inhalt der aktuellen Zeile setzt. mm2rrd extrahiert dort dann den Zeitstempel und den Messwert und schiebt beide als Arrayreferenz ans Ende des Arrays @points.

Die Ansteuerung von rrdtool ist etwas kryptisch, aber das Modul RRDTool::OO vom CPAN bietet eine übersichtliche Schnittstelle an und übersetzt die Eingaben intern in rrdtool-Kommandos. Die mit create() erzeugte Round-Robin-Datenbank mmdata.rrd wird mit 10.000 sogenannter Primary Data Points (PDPs) angelegt, die alle 30 Sekunden (Wert für step) fällig werden. Das Messskript hat die Messwerte im 10-Sekunden-Abstand geliefert, also mittelt rrdtool die Werte automatisch, um die PDPs zu erhalten.

rrdtool reagiert empfindlich, wenn man Werte einspeist, die vor dem Anfangszeitpunkt der RRD-Datenbank liegen, also wird der Parameter $start für die create-Methode einfach auf eine Sekunde vor dem ersten Messwert gesetzt.

Der Zeitraum des Graphs, den die Methode graph als PNG-Datei erzeugt, wird ähnlich festgelegt, nur dass der Endpunkt mit $points[-1]->[0] auf den Zeitstempel des letzten Messpunkts im Array @points gesetzt wird.

Listing 3: mm2rrd

    01 #!/usr/bin/perl -w
    02 use strict;
    03 use RRDTool::OO;
    04 use Sysadm::Install qw(:all);
    05 
    06 my @points;
    07 
    08 plough sub {
    09   chomp;
    10   my($time, $value) = split / /, $_;
    11   push @points, [$time, $value];
    12 }, "values.txt";
    13 
    14    # Constructor
    15 my $rrd = RRDTool::OO->new(
    16 	    file => "mmdata.rrd" );
    17 
    18    # Create a round-robin database
    19 $rrd->create(
    20   step        => 30,
    21   start       => $points[0]->[0] - 1,
    22   data_source => { name => "amps",
    23                    type => "GAUGE" },
    24   archive     => { rows => 10_000 });
    25 
    26 for(@points) {
    27   $rrd->update(time  => $_->[0], 
    28                value => $_->[1]);
    29 }
    30 
    31 $rrd->graph(
    32  width  => 600,
    33  height => 400,
    34  image          => "mmdata.png",
    35  vertical_label => "Amperes",
    36  start          => $points[0]->[0],
    37  end            => $points[-1]->[0],
    38  draw           => {
    39      type   => "line",
    40      color  => "0000FF",
    41      legend => "Laptop Power",
    42  }
    43 );

Abbildung 4 zeigt den Stromverbrauch des Linux-PCs über Nacht. Da das System auch gleichzeitig das Messskript steuerte, trat keine Ruhe ein, aber auffällig ist, dass der ab 2 Uhr Nachts einsetzende Backup- und Indizierungsprozess die drei eingebauten Festplatten forderte und den Stromverbrauch entsprechend in die Höhe trieb. Kurz vor 7:00 in der Frühe war schließlich Schicht im Schacht und der Stromverbrauch ging zurück auf den Ausgangswert.

In Abbildung 5 ist der Stromverbrauch des an die Dockingstation angekoppelten Laptops kurz vor und einige Minuten nach dem Einschalten zu sehen. Interessant ist, dass die Docking-Station auch im ausgeschalteten Zustand 40mA (Milli-Ampere) verbraucht. Das sind immerhin 4 Watt für nichts und wieder nichts! Nach dem Einschalten schnellt der Verbrauch erwartungsgemäß in die Höhe, denn die Festplatte muss auf Touren kommen und das Operationsysstem geladen werden. Nach einigen Minuten geht der Wert auf etwa 130mA zurück, der Laptop verbraucht also etwa 15 Watt, etwas mehr als ein Zehntel des PCs.

Da das Multimeter auch noch Temperatur und Kapazität misst und man außerdem im einschlägigen Fachhandel allerlei Sensoren mit Spannungsausgang erwerben kann, finden kreative Bastler bestimmt noch weitere Einsatzmöglichkeiten.

Infos

[1]
Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2006/09/Perl

[2]
Marsh-Projekt zur Ansteuerung des Mastech MAS-345: http://savannah.nongnu.org/projects/marsh/

[3]
Das Stromverbrauchsmessgerät ``Kill-A-Watt'', http://www.p3international.com/products/special/P4400/P4400-CE.html

Michael Schilli

arbeitet als Software-Engineer bei Yahoo! in Sunnyvale, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com.