Atlas Scientific Sensoren pH Leitwert etc.

Begonnen von danieljo, 14 November 2015, 15:16:08

Vorheriges Thema - Nächstes Thema

danieljo

Ein Dankeschön geht an Icinger der sich die Zeit genommen hat die classdef zu schreiben. Als Anhang stellen wir euch diese zur Verfügung.

danieljo

Leider gibt es ein kleines Problem:

Und zwar hängt sich ECMD nach einer gewissen Zeit bzw. bei einem gewissen Ereignis auf.

Und zwar sieht das ganze im Log-File so aus:

2015.11.21 07:16:18 5: EZO_pH: read "6.919\r"
2015.11.21 07:16:18 5: EZO_pH: Spontaneously received "6.919\r"
2015.11.21 07:16:18 5: EZO_pH dispatch 6.919
2015.11.21 07:16:18 5: EZO_pH: match regex (\d+\.?\d*)\r for reading pH of device EZO_pH_Sensor with class PH
2015.11.21 07:16:18 5: Postprocessing "6.919\r" with perl command {my $ret=$_;$ret=~s/^(.*)\r$/$1/g; return $ret}.
2015.11.21 07:16:18 5: Postprocessed value is "6.919".
2015.11.21 07:16:18 5: Triggering EZO_pH_Sensor (2 changes)
2015.11.21 07:16:18 5: Notify loop for EZO_pH_Sensor pH: 6.919
2015.11.21 07:16:19 5: EZO_pH: read "6.917\r"
2015.11.21 07:16:19 5: EZO_pH: Spontaneously received "6.917\r"
2015.11.21 07:16:19 5: EZO_pH dispatch 6.917
2015.11.21 07:16:19 5: EZO_pH: match regex (\d+\.?\d*)\r for reading pH of device EZO_pH_Sensor with class PH
2015.11.21 07:16:19 5: Postprocessing "6.917\r" with perl command {my $ret=$_;$ret=~s/^(.*)\r$/$1/g; return $ret}.
2015.11.21 07:16:19 5: Postprocessed value is "6.917".
2015.11.21 07:16:19 5: Triggering EZO_pH_Sensor (2 changes)
2015.11.21 07:16:19 5: Notify loop for EZO_pH_Sensor pH: 6.917


Soweit ist das auch alles Richtig. Das ganze erfolgt Sekündlich. Da der pH-Sensor von sich aus jede Sekunden ein Reading absetzt. Das ganze läuft so lange (mal nur 3 Minuten oder fast auch 12 Stunden) ohne Probleme bis zu diesem Punkt:

2015.11.21 07:16:21 5: EZO_pH: read "6.920\r6.923\r"
2015.11.21 07:16:21 5: EZO_pH: Spontaneously received "6.920\r6.923\r"
2015.11.21 07:16:21 5: EZO_pH dispatch 6.920
6.923
2015.11.21 07:16:22 5: EZO_pH: read "6.923\r"
2015.11.21 07:16:22 5: EZO_pH: Spontaneously received "6.923\r"
2015.11.21 07:16:22 5: EZO_pH dispatch 6.923
2015.11.21 07:16:23 5: EZO_pH: read "6.927\r"
2015.11.21 07:16:23 5: EZO_pH: Spontaneously received "6.927\r"
2015.11.21 07:16:23 5: EZO_pH dispatch 6.927
2015.11.21 07:16:24 5: EZO_pH: read "6.928\r"
2015.11.21 07:16:24 5: EZO_pH: Spontaneously received "6.928\r"
2015.11.21 07:16:24 5: EZO_pH dispatch 6.928
2015.11.21 07:16:25 5: EZO_pH: read "6.929\r"
2015.11.21 07:16:25 5: EZO_pH: Spontaneously received "6.929\r"
2015.11.21 07:16:25 5: EZO_pH dispatch 6.929


Aus irgendeinem Grund liest ECMD 2 Werte direkt hintereinander ein. Was auch eigentlich nicht das Problem sein sollte. Aber dann kommt halt das Dispatch welches besagt 6.920 6.923 und genau wenn so in Eintrag kommt hängt ECMD bzw. Es passiert nix mehr. Sprich im Log-File sehe ich zwar das weitere Werte jede Sekunden gelesen werden aber der "match" eintrag felht. Dann hilf nur ein "shutdown restart"

Das ganze läuft auf einem Testsystem Raspberry Pi 2 mit Debian Whezzy Distru. und aktuellem FHEM sonst nix.

Weiß jemand was das sein kann und wie man das Problem behebt?


danieljo

#17
Problem behoben. Danke Icinger.

Hier nun die aktualisierte classdef

Hier noch ein Hinweis im ECMD Device muss das "partial" Attribut auf 1 oder 2 Sekunden gesetzt werden!


danieljo

#18
Es gibt ja nun noch weitere Sensoren von diesem Hersteller unter anderem Leitwert, Sauerstoffsättigung usw. Da diese Sensoren sowohl UART als auch I2C beherschen wird es bei mehr als einem Sensor natürlich schwierig da zum Beispiel der Raspberry Pi nur eine UART Schnittstelle hat. Man könnte jetzt hingehen und sich ein UART-2-USB Adapter kaufen und somit weitere UART Schnittstellen hinzufügen oder aber man benutzt den I2C Bus.

Hat jemand schonmal ein Modul für I2C Programmiert ? Ist das aufwendig bzw. Schwierig?

Es gibt auf der Herstellerseite unteranderem dieses Python Script für den Raspberry Pi der den Sensor mittels I2C anspricht.

#!/usr/bin/python

import io # used to create file streams
import fcntl # used to access I2C parameters like addresses

import time # used for sleep delay and timestamps
import string # helps parse strings


class atlas_i2c:
    long_timeout = 1.5 # the timeout needed to query readings and calibrations
    short_timeout = .5 # timeout for regular commands
    default_bus = 1 # the default bus for I2C on the newer Raspberry Pis, certain older boards use bus 0
    default_address = 99 # the default address for the pH sensor
   
    def __init__(self, address = default_address, bus = default_bus):
        # open two file streams, one for reading and one for writing
        # the specific I2C channel is selected with bus
        # it is usually 1, except for older revisions where its 0
        # wb and rb indicate binary read and write
        self.file_read = io.open("/dev/i2c-"+str(bus), "rb", buffering = 0)
        self.file_write = io.open("/dev/i2c-"+str(bus), "wb", buffering = 0)
       
        # initializes I2C to either a user specified or default address
        self.set_i2c_address(address)
   
    def set_i2c_address(self, addr):
        # set the I2C communications to the slave specified by the address
        # The commands for I2C dev using the ioctl functions are specified in
        # the i2c-dev.h file from i2c-tools
        I2C_SLAVE = 0x703
        fcntl.ioctl(self.file_read, I2C_SLAVE, addr)
        fcntl.ioctl(self.file_write, I2C_SLAVE, addr)
           
    def write(self, string):
        # appends the null character and sends the string over I2C
        string += "\00"
        self.file_write.write(string)
       
    def read(self, num_of_bytes = 31):
        # reads a specified number of bytes from I2C, then parses and displays the result
        res = self.file_read.read(num_of_bytes) # read from the board
        response = filter(lambda x: x != '\x00', res) # remove the null characters to get the response
        if(ord(response[0]) == 1): # if the response isnt an error
            char_list = map(lambda x: chr(ord(x) & ~0x80), list(response[1:])) # change MSB to 0 for all received characters except the first and get a list of characters
            # NOTE: having to change the MSB to 0 is a glitch in the raspberry pi, and you shouldn't have to do this!
            return "Command succeeded " + ''.join(char_list) # convert the char list to a string and returns it
        else:
            return "Error " + str(ord(response[0]))
   
    def query(self, string):
        # write a command to the board, wait the correct timeout, and read the response
        self.write(string)
       
        # the read and calibration commands require a longer timeout
        if((string.upper().startswith("R")) or
           (string.upper().startswith("CAL"))):
            time.sleep(self.long_timeout)
        elif((string.upper().startswith("SLEEP"))):
            return "sleep mode"
        else:
            time.sleep(self.short_timeout)
           
        return self.read()
           
    def close(self):
        self.file_read.close()
        self.file_write.close()

def main():
    device = atlas_i2c() # creates the I2C port object, specify the address or bus if necessary
   
    print(">> Atlas Scientific sample code")
    print(">> Any commands entered are passed to the board via I2C except:")
    print(">> Address,xx changes the I2C address the Raspberry Pi communicates with.")
    print(">> Poll,xx.x command continuously polls the board every xx.x seconds")
    print(" where xx.x is longer than the %0.2f second timeout." %  atlas_i2c.long_timeout)
    print(" Pressing ctrl-c will stop the polling")
   
    # main loop
    while True:
        input = raw_input("Enter command: ")
       
        # address command lets you change which address the Raspberry Pi will poll
        if(input.upper().startswith("ADDRESS")):
            addr = int(string.split(input, ',')[1])
            device.set_i2c_address(addr)
            print("I2C address set to " + str(addr))
       
        # contiuous polling command automatically polls the board
        elif(input.upper().startswith("POLL")):
            delaytime = float(string.split(input, ',')[1])
           
            # check for polling time being too short, change it to the minimum timeout if too short
            if(delaytime < atlas_i2c.long_timeout):
                print("Polling time is shorter than timeout, setting polling time to %0.2f" %  atlas_i2c.long_timeout)
                delaytime =  atlas_i2c.long_timeout

            # get the information of the board you're polling
            info = string.split(device.query("I"), ",")[1]
            print("Polling %s sensor every %0.2f seconds, press ctrl-c to stop polling" % (info, delaytime))
           
            try:
                while True:
                    print(device.query("R"))
                    time.sleep(delaytime - atlas_i2c.long_timeout)
            except KeyboardInterrupt: # catches the ctrl-c command, which breaks the loop above
                print("Continuous polling stopped")
       
        # if not a special keyword, pass commands straight to board
        else:
            try:
                print(device.query(input))
            except IOError:
                print("Query failed")
       
       
if __name__ == '__main__':
    main()

danieljo

Heute habe ich den Sauerstoff-Sensor bekommen auch als Dissolved Oxigen bezeichnet. Damit lässt sich der Sauerstoffgehalt im Wasser messen.

Diesen sensor benutze ich jetzt erstmal um eine I2C anbindung zu bekommen.

Dazu habe ich ein Raspberry Pi 2 mit Debian Wheezy aufgesetzt und den Sensor an den I2C Bus angeklemmt.

Mit den I2c-Tools in der Kommandozeile unter Debian wird der sensor auf der Adresse 0x61 gefunden.

In FHEM habe ich das RPII2C-Modul eingerichtet um somit von FHEM aus Zugriff auf den I2C Bus zu erhalten.

Da konnte ich auch schon erste erfolge verzeichnen.

Mit:

set I2C_RPI writeblock 0x61 0x52

Sage ich dem Sensor er soll eine Messung starten. nach 1 Sekunde kann ich den Messwert mittels:

get I2C_RPI readblock 0x61 82

abrufen das Ergebnis sieht dann so aus:

received : 1 57 46 55 56 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  |  transmission: Ok

Die erste Zahl ist eine Dezimal 1 diese kann ignoriert werden. Danach folgt der Messwert in ASCII. Umgewandelt lässt sich somit ein Messwert von: 9.78 ermitteln. Was dann heißt das der Sauerstoffgehalt im Wasser 9.78mg/l beträgt.

So nun will ich fürs erste das ganze in ein I2C Modul packen. Der klausw hatte mir schon paar Infos gegeben aber als blutiger anfänger ist das doch schon eine sehr große Nummer.

Das ganze soll wie folgt aussehen:

I2C Adresse : 0x61
Befehl Messung starten "R" = hex 0x52
1000ms warten
Befehl Messwert lesen "R" = dec 82
die 1 Am Anfang entfernen den Rest umwandeln.

Hört sich einfach an, wenn es dann auch so wäre :D

danieljo

Ich habe mir das I2C_SHT21 Modul genommen und begonne umzuändern. Ich habe es für Atlas Scientific Dissolved Oxygen Sensor mal I2C_EZODO genannt.

Ich habe es geschafft den Sensor anzusprechen ein Messung zu starten 1 dann mit usleep 1sekunde zu warten und den Rückgabewert zu empfangen der sieht in der Log-File jetzt so aus:

1 50 50 55 46 49 53

Der Rückgabe wert besteht aus 7 bytes der erste davon ist der Response code dieser kann 1, 2, 254 oder 255 betragen und gibt den Status zurück 1 bedeutet in dem Fall Success. Dieser Wert ist für den gemessen Wert unrelevant.

Die 50 50 55 46 49 53 sind der eigentliche Messerwert in Decimaler Schreibweise. Wenn ich diese Bytes in ASCII umwandel kommt 227.22 raus. beträgt der gemessen Wert nur 12.34 so ist das letzte Byte NULL.

Wie bekomme ich nun diesen Decimalen Wert in einen Nummerischen Wert umgewandelt. Weil das Reading ist im moment 306 wo dieser Wert herkommt weiß ich nicht hängt aber damit zusammen das der Rückgabe Wert nicht richtig umgewandelt wird.


Helmi55

Hallo liebe Freunde
da die Poolsaison ja bald starten wird hänge ich mich gleich dran.
Ich muss meine Solarsteuerung umbauen da die alten mechanischen Dinge schön langsam den Geist aufgeben.
Die Polosteuerung (SolardiffRegelung) habe ich auf meinem Test RPi schon fertig.
Nun möchte ich auch noch gerne den pH-Wert angezeigt bekommen. Ich brauche keine automatische pH Steuerung - das pH-Minus erledige ich händisch.
Nun meine Frage habt ihr das bestellt?  http://www.atlas-scientific.com/product_pages/kits/ph-kit.html
Ist es richtig - das muss man selbst zusammen löten? Grrr....
@danieljo  funktioniert es bei dir wie gewünscht. Der Bypass ist nach der Filterpumpe eingebaut richtig?
Gruß
Helmut
System1 fhem 6.1 auf RPi 4B mit 4GB, HMUSBConfig, DS9490R-1Wire, Busware USB 868, Pool-Solarsteuerung mit FHEM. System2 fhem 6.1 auf RPi 4B mit 4GB (Bullseye) mit Busware USB 868 und 433 und HMUARTLGW für Haussteuerung

https://www.flickr.com/photos/canonhelmi/

danieljo

Zitat von: Helmi55 am 27 Januar 2016, 12:35:52
Hallo liebe Freunde
da die Poolsaison ja bald starten wird hänge ich mich gleich dran.
Ich muss meine Solarsteuerung umbauen da die alten mechanischen Dinge schön langsam den Geist aufgeben.
Die Polosteuerung (SolardiffRegelung) habe ich auf meinem Test RPi schon fertig.
Nun möchte ich auch noch gerne den pH-Wert angezeigt bekommen. Ich brauche keine automatische pH Steuerung - das pH-Minus erledige ich händisch.
Nun meine Frage habt ihr das bestellt?  http://www.atlas-scientific.com/product_pages/kits/ph-kit.html
Ist es richtig - das muss man selbst zusammen löten? Grrr....
@danieljo  funktioniert es bei dir wie gewünscht. Der Bypass ist nach der Filterpumpe eingebaut richtig?
Gruß
Helmut

Hallo,

Der Link von dir bezieht sich auf das Komplette Kit zur pH-Wert Messung. Damit hast du alles was du brauchst. In meinem Fall brauchte ich nur die Platine, da ich bereits eine pH-Elektrode besitze genau wie die Flüssigkeiten zur Kalibrierung etc...

Wenn du sparen möchtest, dann kauf dir nur die EZO pH Platine. Du kannst jede Handelsübliche pH-Elektrode mit BNC Anschluss einsetzten.

Ja ein wenig Löten muss man schon da das ganze nicht Plug & Play ist. Du musst eigentlich nur 3 x 3pin Pfostenverbindereinlöten 2 Widerstände und eine BNC-Buchse und fertig den rest kannst du mit Steckkabeln Verbinden. Desweiteren ist es emphelenswert eine Komplette galvanische Trennung mit einzubauen. Nur so ist zu gewähren das der Messwert auch richtig ist und nicht durch Kriechströme verfälscht werden.

Die pH-Elektrode sollte bestenfalls hinter einem Filter im Bypass stecken am Besten Dunkel und vor Sonnenlicht geschützt sonst veralgt diese doch recht schnell. Bei mir funktioniert die ganze Sache absolut zuverlässig und ohne Fehler.

Du kannst bei www.exp-tech.de mal schauen dort werden diese Sensoren auch angeboten direkt aus Deutschland so entfallen dir Zoll Abwicklung usw.

bei Fragen stehe ich dir gerne zur Verfügung.

Helmi55

Guten Morgen
Danke für deine Info. In dem Shop ist es leider ausverkauft. Werde nachfragen ob es wiederbestellt ist.
Na ja hatte vor ca. 30 Jahen das letzte mal einen Lötkolben in der Hand ;D
Was meinst du mit galvanischer Trennung genau? Ein eigenes Netzteil und einen Optokoppler in der Leitung zum Pi? (Hast du da dann evtl. Kaufvorschläge)
Was benötige ich noch um die pH Sonde lauffähig zu bekommen
Wie gesagt bin Anfänger, habe aber meine Poolsteuerung jetzt fertig und mein großer Wunsch wäre noch
Die Anzeige des pH Wertes.
Muss sowieso vor Saisonstart noch einen Filter bei der Solaranlage einbauen, da könnte ich dann gleich nach dem Filter den Bypass setzen
Herzlichen Dank
Liebe Grüße Helmut
System1 fhem 6.1 auf RPi 4B mit 4GB, HMUSBConfig, DS9490R-1Wire, Busware USB 868, Pool-Solarsteuerung mit FHEM. System2 fhem 6.1 auf RPi 4B mit 4GB (Bullseye) mit Busware USB 868 und 433 und HMUARTLGW für Haussteuerung

https://www.flickr.com/photos/canonhelmi/

danieljo

Ich denke die werden die wieder reinbekommen. Leitwert ist im Moment auch ausverkauft.

Was du brauchst ist nichts weiter als die EZOpH Platine sowie die kleine Platine mit der BNC Buchse. Eine pH-Elektrode. Dann benötigst du ein RaspberryPi und Verbindes das ganze über den I2C Bus. Dann brauchst noch FHEM und das Modul welches im ersten Beitrag angepinnt ist. Viel mehr ist fürs erste nicht nötig.

Thema Galvansiche Trennung. Entweder guckst du das der RaspberryPi über WLAN funkt dann solltest du mittels einem Steckernetzteil bereits eine galvanische Trennung haben. (Einfach, Jedoch habe ich dies nicht überprüft) Oder aber der EZOpH Sensor wird über einen DC/DC Wandler und einem Optokoppler getrennt. (Aufwenig, aber funktioniert einwandfrei)

Wichtig ist die pH-Elektrode erst dann anzustecken wenn die Stromversorgung des RaspberryPi getrennt ist. Damals habe ich mir eine Platine zerschossen aus welchem Grund genau weiß ich leider nicht mehr.

Der Hintergrund der galvansichen Trennung ist folgender. Die pH-Elektrode ist eine äußerst empfindlicher Sensor der je nach pH-Wert eine winzige Spannung erzeugt deren Strombelastbarkeit sehr gering ist. Mit einem normalen Multimeter ist da nix zu Messung. Die Messschaltung ist dementsprechend Hochempfindlich. Wenn du in deinem Pool eine Umwälzpumpe hast die mit dem Stromnetz Verbunden ist. So erfolgt ein Potentialausgleich des ErdLeiters. Dies ist bis hierhin nicht weiter schlimm. Da der Pool meistens ja auch in der "Erde" geerdet ist. Die pH-Elektrode mit ihrem empfindlichen Messeingang ist ebenfalls mit dem Stromnetz verbunden und es erfolgt hier ebenfalls ein Potenzialausgleich. Dies verfälscht aber den Messwert so das du statt pH 7, ph 0 oder 14 misst. Um einwandfreie Messergebnisse zu erzielen Versucht man den "Messkreis" vom "Stromkreis" zu trennen.

Mittels wie oben Beschrieben schnelle Optokoppler für die I2C Schnittstelle und einem kleinen 5V DC/DC Wandler da muss aber gelötet werden oder aber über einen sogennanten Trenntrafo.

Für Leute die einfach nur anwenden wollen ist das alles ziehmlich umständlich.

Ich will dich nicht von deinem Vorhaben abbringen dennnoch ist es auf den ersten Blick recht umfangreich und "teuer" Unterstütze dich aber gerne. Vllt. lässt es sich ja regeln das ich dir das ganze zusammenlöte und du es nur noch Anschließen brauchst. Sprich Löten und galvanische Trennung mittels DC/DC Wandler und Optopkoppler. Ein Satz Bauteile müsste ich hier noch liegen haben.

Helmi55

Danke danieljo für deine ausführliche Erklärung
Darf ich mich bei dir mittels PM am Wochenende melden?
Danke
LG
Helmut
System1 fhem 6.1 auf RPi 4B mit 4GB, HMUSBConfig, DS9490R-1Wire, Busware USB 868, Pool-Solarsteuerung mit FHEM. System2 fhem 6.1 auf RPi 4B mit 4GB (Bullseye) mit Busware USB 868 und 433 und HMUARTLGW für Haussteuerung

https://www.flickr.com/photos/canonhelmi/

danieljo

Zitat von: Helmi55 am 30 Januar 2016, 13:53:32
Danke danieljo für deine ausführliche Erklärung
Darf ich mich bei dir mittels PM am Wochenende melden?
Danke
LG
Helmut

Nichts zu Danken, du darfst dich jederzeit bei mir melden.

danieljo

Der 3. Sensor ist geordert und sollte bis Ende der Woche bei mir eintreffen. Es ist der EZO EC Sensor zur Leitwertmessung im Wasser. Der Leitwert im Leitungswasser kann z.B. aussagen ob ein Wasser weich oder hart ist. Oder z.B. bei einem Vollentsalzer oder einer Umkehrosmoseanlage, dass Harz bzw. die Membran erschöpft ist. Im Aquarium kann man auch daran erkennen wann ein Wasserwechsel fällig wird, da ebenfalls durch die Abfallstoffe im Aquarium der Leitwert steigen kann.

Das passende Modul dazu werde ich hier demnächst veröffentlichen. Es wird dann als Dateianhang im ersten Post angefügt.

Des weiteren baue ich ein kleines Kunststoffgehäuse wo bis zu 4 Sensoren rein passen diese somit vor Staub und Nässe geschützt sind. Das ganze ausgebaut mit einer galvanischen Trennung je Sensor.


danieljo

Heute habe ich damit begonnen alles in seperates Staub und Spritzassergeschütztes Gehäuse zu verbauen. In dem Gehäuse mit den Maßen 110x110x70mm passen bis zu 4 Sensoren rein inkl. Galvanischer Trennung des weiteren habe ich es mit 2 Kabelverschraubungen versehen für den I2C Bus, somit lässt sich der I2C Bus durchschleifen zu weiteren Geräten/Sensoren. Bilder sagen mehr wie Worte:

tomster

#29
Coole Sache!

Hab grad gesehen, dass man die einzelnen Module "nur" auf die BNC-Carrier-Boards aufstecken muss. Saubere Lösung!
Da krieg ich glatt Lust mir eine Teichsteuerung zusammenzulöten...

Die Sensoren jetzt noch mit mysensors zusammenbringen, dann könnt ich tatsächlich schwach werden.

--edit--
Ich hab mich zwar mit mysensors bislang noch nicht beschäftigt (vorsichtshalber aber schon Mal ein paar Arduinos und NRF24L01's beim Chinesen bestellt), aber es ist wohl schon was in der Richtung gemacht worden:
http://forum.mysensors.org/topic/845/surface-mount-atmega328p-au-sensor-board