EAC 1Wire/S0-Stick

Hinweis: Diese Seite beschreibt ein kommerzielles Produkt.

Eigentlich ist ein eigener Computer zum Zählen von Impulsen wirklich überzogen. Selbst die sparsamen Atoms brauchen noch mehr Energie als ein RasPi oder Arduino. Aber die Firma EAC aus Potsdam stellt z.B. einen kleinen USB-Controller her, der für gerade mal 25€ verkauft wird und zum einen ein 1-Wire-Adapter ist aber noch zwei S0-Eingänge bereit stellt. passend dazu gibt es natürlich eine Library für den Raspberry aber da es auch "nur" ein Serial-Adapter ist, habe ich mir die API angeschaut und nutzen diesen Adapter per PowerShell. Der 1-Wire-Bus ist auch in einem Serverraum durch sehr günstige Temperatursensoren universell einsetzbar und die beiden "Impulsmesser" können wunderbar den Strom müssen.

Hardware

Was da im Briefumschlag kommt, ist bezogen auf die Abmessungen keine große Sache. Da der Hersteller den Adapter primär im RaspberryPI-Umfeld sieht, ist das Fehlen eines Gehäuse auch nicht weiter schlimm. Die meisten Selbstbauer integrieren so ein Gerät in der Regel irgendwo.

Optional auch mit Gehäuse:

Daran müssen sich Windows Administratoren vielleicht erst noch gewöhnen. So sollten Sie den Adapter natürlich nicht am PC einsetzen. Eine Hülle in Form eines kleinen Gehäuse, z.B. einfach eine Aufputz-Verteilerdose aus dem Baumarkt und ein USB-Verlängerungskabel kann dabei schon ausreichen. Die Anschlüsse sind in der PDF-Anleitung sauber beschriftet. Wer also schnell mit einem DS18B20 (Temperatur) müssen möchte, kann die einfach anschließen. Der blaue DHT11 ist leider kein "echtes" 1-Wire-Device und stört den Bus.

 

Schaut man sich die Belegung Sensoren an, dann ist "Data" immer in der Mitte während am USB-Sensor die Datenleitung außen ist. 1:1 einstecken ist daher nicht möglich, sondern sie müssen einmal kreuzen. Aber auch das ist für einen halbwegs versierten Bastler kein Problem.

API

Nach dem Einstecken in einen Windows PC dauert es nur ein paar Sekunden, bis Windows die Treiber installiert. In dem Bild habe ich beide Phasen kombiniert. Zuerst wird ein FT2323R-Baustein erkannt.

Sobald der Treiber aber herunter geladen wird, wird dann nur noch "USB Serial Converter" angezeigt und der COM-Port dazu. Bei mir ist das nun COM11 geworden, also eine fast "normale" serielle Schnittstelle. Zu der wollte ich natürlich wissen, wie sie funktioniert, um sie unter Windows anzusteuern. Vom Hersteller habe ich folgende Information zur "API" erhalten:

... Vom Prinzip her ist das eine serielle Kommunikation mit 115.2kBaud ohne Handshake nach dem ping-pong-Prinzip, d.h. der PC fragt den Adapter mit $? und der schickt alle IDs laufend nummeriert von 0-63 und die beiden S0-Zählstände zurück. Dann fragt der PC diese einzeln ab mit $0..$63 und bekommt die Datenbytes aus den 1wire-Slaves übermittelt, danach geht es wieder von vorne los mit $? und das war es dann auch schon im wesentlichen (abgesehen die Namenszuordnung und die Parametrierung des EEPORM in den Slaves).

Das ist ja einfach und mit einem einfachen "Terminal" habe ich dann COM1 mit 115200Baud ohne RTS/CTS-Handshake geöffnet.

Hinweis: Seit idem 25. Aug 2015 (Firmware u1-01c) beträgt die Baudrate beträgt 38400 anstelle 115200. Die Baudrate lässt sich aber per Lötbrücke auf 115200 gemäß Bild dauerhaft setzen.

Alternativ können Sie ihre Skripte natürlich auf 38400Baud umstellen.

Um die erfolgreiche Kommunikation zu testen, sende ich ein "$?", was zugleich auch eine "Device Suche" initialisiert. Danach sollten Sie ca. 1 Sekunde warten, das die Abfrage abgeschlossen werden kann. Zurück kamen bei mir die Zeilen 2 und 3

Mit dem $? kommen Zeilenweise die 1-Wire Devices und dann noch die beiden S0-Zähler. Mit dem "$0" hole ich dann die Informationen über den ersten Sensor. Bis zu 64 Sensoren ($0-$63) sind möglich. Natürlich habe ich auch mal $1 abgefragt. Wenn kein Sensor dahinter ist, ergibt dies lauter "FF"-Werte.

Der hier gefundene Sensor ist ein Temperatursensor (DS18B20). Allerdings sollte die FamilyID, der rot umrandete Teil, eine 28h anzeigen. Vielleicht ist mein Gerät ja ein "Nachbau" einer anderen Quelle aus China. Die anderen Daten stimmen nämlich schon, wenn der Sensor mir $0 im nächsten Schritt abgefragt wird. Die Daten dieses Sensors bedeuten:

Byte  Bedeutung Wert Auswertung

$0;o 

 

 

Ausgabe des USB-Moduls  Sensor=0 und o="output"

0

Temperatur: Niederwertiges Byte (8 bit)

3F

Die Errechnung der Temperatur ist im Datenblatt schön beschrieben. Achten Sie aber genau auf den Sensortyp. Meiner ist ein DS18S20

Es gibt auch DS1822, DS1820 (ohne S dazwischen), die einen anderen FamilyCode haben und Daten mit anderer Genauigkeit und Auflösung ausgeben. Im Datenblatt findet mann dann auch diese Tabelle:

 

Für positive Werte reicht eine einfache Formel.

Temp = LowByte *0.5

Aus dem 3Fh= 63Dez kommt man auf 19,5 Grad. Wenn das höherwertige Bit aber ungleich 0 ist, dann erhält man die Temperatur, indem man von 256 die Zahl abzieht und mit "-0,5" multipliziert. In PowerShell wäre das dann:

if ($HighByte -eq 00) {
   $Temp = LowByte *0.5
}
else {
   $Temp = LowByte * - 0.5
}

Das gilt natürlich nur für die Sensoren mit der ID 10h.

Temperatur: Höherwertiges Byte (nur untere 3 Bit)

00

2

User1

4B

Nicht relevant

3

User2 

46 

Nicht relevant

4

Configuration Register 

FF 

Nicht relevant

5

Reserved (0xFF) 

FF 

Kann man zur Sicherheit prüfen 

6

Reserved

07 

Nicht relevant 

7

Reserved (0x10)

10 

Kann man zur Sicherheit prüfen 

8

CRC 

38 

Könnte man prüfen 

?

1F

 

PowerShell

Dank .NET ist es sogar in PowerShell ganz einfach möglich, serielle Ports anzusprechen und darauf Daten zu schreiben und zu lesen. Sie müssen nur den passenden Port angeben und schon kann das Skript die Daten auslesen. Ich habe mich hier erst einmal auf die S0-Zähler beschränkt und überspringe alle Zeilen, die auf einen 1-Wire-Sensor hinweisen. Damit spare ich mir noch das Parsen der 1-Write Werte. Technisch ist dies aber sehr einfach.

Wichtig:
Zur Steuerung müssen Sie ein "Dollarzeichen" senden, welches in PowerShell normal einer Variablen voransteht. Stellen Sie mit einfachen Anführungszeichen sicher, dass auch wirklich ein '$' gesendet wird.

Hier ein Beispielcode, der beim Aufruf die beiden S0-Werte zurück gibt und vom 1wire-Bus die Geräte, deren Daten und ggfls. die Temperatur ausgibt.

param (
   [string]$comport = "COM11"
)

$1wirelist=@{}

$port= new-Object System.IO.Ports.SerialPort $comport,115200,None,8,one
$port.ReadTimeout=5000
$port.WriteTimeout=5000
$port.open()

$port.WriteLine('$?')
write-host "Scanning 1-Wire"
start-sleep -milliseconds 1000
while ($port.BytesToRead -ne 0) {
	$line = $port.ReadLine()
	if ($line.startswith('$S0')) {
		Write-host "Found S0-Line $line"
		$s0array = $line -split(';')
		write-host "  S0-Counter1 = " $s0array[1]
		write-host "  S0-Counter2 = " $s0array[2]
	}
	else {
		Write-host "Found 1Wire-Device: $line"
		$1wirearray = $line -split(';')
		$1wirelist.add($1wirearray[0],$1wirearray[2])
	}
}

if ($1wirelist.count -ne 0) {
	foreach ($key in $1wirelist.keys) {
		$port.WriteLine($key)
		start-sleep -milliseconds 100
		$1wiredata = $port.ReadLine()
		write-host ("  1wireData: Device:" + $1wirelist.item($key))
		write-host ("  1wireData:   Data:" + $1wiredata)
		$1wiredataarray = $1wiredata.split(";")
		if ( ($1wirelist.item($key)).startswith("10") ) {
			$highbyte = [Convert]::ToInt32($1wiredataarray[3],16)
			$lowbyte = [Convert]::ToInt32($1wiredataarray[2],16)
			if ($HighByte -eq 00) {
			   $Temp = $LowByte * 0.5
			}
			else {
			   $Temp = (256- $LowByte) * - 0.5
			}
			write-host "Temperatur $temp"
		}
	}
}

$port.Close()

Das gleiche Script als Download
eac1wire.ps1.txt
Hinweis: Das Script ist NICHT für PRTG geeignet. das steht weiter unten

Natürlich kann die Ausgabe auch in jeder Form verändert werden. Dies ist nur ein ganz einfaches Beispiel.

Weiterentwicklung PRTG

Aktuell gibt das PowerShell Script nur die beiden S0-Zähler und die Daten der gefundenen 1-Wire-Geräte aus, aber interpretiert noch nicht die Daten. Aktuell könnte ich das sowieso erst für Thermometer (DC18S20), aber es gibt noch eine ganze Menge weiterer Sensoren. für meine nächsten Experimente zum Erfassen von Stromzählerimpulsen und Temperaturen ist das erst einmal ausreichend.

Als nächste Stufe steht nun natürlich die Entwicklung eines PRTG:Custom Sensor für meine Monitoring Software PRTG an. Hier eine Beispielausgabe:

<?xml version="1.0" encoding="Windows-1252" ?>
<prtg>
   <result>
      <channel>S0-A</channel>
      <value>423</value>
      <float>1</float>
   </result>
   <result>
      <channel>S0-B</channel>
      <value>223</value>
      <float>1</float>
   </result>
   <result>
      <channel>1W-aabbccdd</channel>
      <value>20,5</value>
      <float>1</float>
   </result>
</prtg>

Mittlerweile habe ich eine erste Version, die per Default auf COM4  (per Parameter oder im Skript änderbar) die beiden S0-Zähler und alle 1Wire-Sensoren mit der FamilyID 10h ausliest und als XML-Struktur auf STDOuT ausgibt.

eac1wire-prtg.1.3.ps1.txt
Nach dem Download die Erweiterung ändern, ggfls. den COM-Port anpassen und dann ins EXEXML-Verzeichnis der PRTG-Probe kopieren und als neuer Sensor einrichten.

Das ganze sieht in PRTG dann etwa so aus: 

 

Ich habe nicht vor, das Skript automatisch nach dem COM-Port suchen zu lassen, da dies durchaus andere ähnliche Anbindungen stören könnte (z.B. USV) und lange dauert. Ich könnte mit aber vorstellen, dass man vielleicht den Sensorname editierbar machen kann. Ebenso könnte man die Zählerstände entsprechend der Einheiten der Quelle anpassen. Wenn ein Zähler hier für jede Wh einen Impuls liefert, sind die Werte als kWh vielleicht sinnvoller.

Da es sich aber um ein PowerShell-Script handelt, können Sie dies auch sehr leicht selbst auf ihre Anforderungen anpassen

Was sie sonst noch interessieren könnte

Klein einfache pfiffig und fast autark. Solange der Stick Strom hat, zählt er brav die Impulse, die natürlich schon "sauber" sein sollten. Wer zu Testzwecken mit einer Büroklammer die Kontakte Ersatzweise überbrückt, zählt ganz schnell ganz viele Impulse. Einige Dinge möchte ich aber noch klären:

  • Verzögern
    Aktuell schreibt das PowerShell Script "schnell" die Daten raus. Es kann natürlich sein, dass der Stick etwas braucht, um die Daten zu verarbeiten. Eventuell müssen noch ein paar "Start-Sleep" mehr eingebaut werden. 100ms sollte reichen, aber wenn doch mal bis zu 64 1-Wire-Sensoren dran hängen, dann dauert die Abfrage dann fast 7 Sekunden.
  • Entprellen
    S0-Impulse haben eine Mindestlänge von 30ms. Wenn die Abtastung deutlich schneller erfolgt, dann könnte man per Software abwarten, bis der Pegel lange genug "High" ist oder man schaltet einen Kondensator parallel, um das Signal zu "entprellen". Aktuell können Sie sich mit einem RC-Glied (<4k7) behelfen.
  • Permanentspeicher
    Auf dem Stick ist der USB2RS232-Adapter und natürlich ein Prozessor von Atmel. Von den größeren Atmels (Arduino) weiß ist, dass sie auch ein EEProm enthalten. Da könnte man ab und an den "Zählerstand" speichern und so auch bei Stromunterbrechung einfach dort weiter zählen, wo man stehen gebliebene ist. Kritisch ist das nicht da MRTG, NAGIOS, PRTG und andere problemlos auch "Differenzen" müssen und so einen Ausfall dann einfach auslassen. Ohne Host-CPU ist der Stick auch nur bedingt einsetzbar. Daher ist das eher kein Problem.
  • 1-Wire Schreiben
    Der Stick dann 1-Wire Sensoren sehr einfach auslesen. Einige könne aber auch Befehle annehmen. Man muss sie auch gezielt ansprechen, um bestimmte Werte zu bekommen. Wer sendet beim DS1820 z.B. den 44hex-Befehl um die Temperatur zu bekommen?
  • Programmierbarkeit/update
    Auf dem Stick ist keine kleine CPU mit Software. Laut Hersteller kann der Stick aber nicht über USB aktualisiert werden.

Alles in allem ein kleiner günstiger USB-Stick zum müssen von zwei S0-Eingängen und 1-Wire, mit dem Bastler starten können. Wem das nicht reicht, kann ja immer noch ein "größeres" Produkt oder einen Arduino (Siehe Arduino und S0) einsetzen.

Weitere Links