Selbstbau I2C Füllstandssensor mit ECMD in FHEM

Begonnen von BrainHunter, 05 Januar 2016, 21:56:34

Vorheriges Thema - Nächstes Thema

BrainHunter

Hallo an alle Bastler,

Ich habe schon vor längerem einen kapazitiven Füllstandssensor für eine Regentonne/Zisterne entwickelt und letztes Jahr auch in FHEM eingebunden. Das Ganze läuft nun auch sehr zuverlässig, deshalb hier nun eine kurze Vorstellung des Ganzen:
Beim Sensor selbst handelt es sich um ein Rohr mit innen gespanntem isoliertem Draht. Gemessen wird die Ladezeit dieses Kondensators. Die dazugehörige Elektronik besteht aus einer kleinen Platine mit einem Mikrocontroller, der die Messung durchführt die Kommunikationsschnittstellen bedient. Eine detailierte Beschreibung des Sensors mit Schaltplan, PCB und Sourcecode habe ich HIER veröffentlicht.

Der Sensor bietet sowohl eine RS232 (nur 5V!) als auch eine I2C Schnittstelle, wobei in meinem Aufbau Letztere über einen Ethersex (Pollin NetIO) verwendet wird.
Die Einbindung in FHEM habe ich so realisiert:

Definieren des Netio, wichtig dabei das attr classdefs:
Code (NetIO attr) Auswählen

define NETIO_Garten ECMD telnet 192.168.0.15:2701
attr NETIO_Garten classdefs FUELLSTAND=/opt/fhem/fuellstand.classdef
attr NETIO_Garten requestSeparator �
attr Wassertonne_Fuellstand room Garten


Code (Füllstands define) Auswählen

define Wassertonne_Fuellstand ECMDDevice FUELLSTAND 8
attr Wassertonne_Fuellstand IODev NETIO_Garten
attr Wassertonne_Fuellstand room Garten

Die "8" im define bestimmt die i2c Device Addresse.

Zyklisch den Füllstand abrufen mit einem at:
Code (at def) Auswählen

define at_Wassertonne_Fuellstand at +*00:05 get Wassertonne_Fuellstand fuellstand
attr at_Wassertonne_Fuellstand room Garten


Die classdef die im fhem ordner liegt sieht so aus:
Code (fuellstand.classdef) Auswählen

# Übergabeparameter I2C ID
params i2cID
# Umsetzung in ECMD Befehle
# Fuellstand 0-100%:
get fuellstand cmd {"i2c rbd %i2cID 0\n"}
get fuellstand expect "0x[\da-fA-F]+\n"
get fuellstand postproc {hex(trim("$_"));}
#
# raw Value - Register 2+3:
get raw cmd {"i2c rwd %i2cID 2\n"}
get raw expect "0x[\da-fA-F]+\n"
get raw postproc {unpack("S", pack("n",hex(trim("$_"))));}
#
# max value - Register 4+5:
get max_value cmd {"i2c rwd %i2cID 4\n"}
get max_value expect "0x[\da-fA-F]+\n"
get max_value postproc {unpack("S", pack("n",hex(trim("$_"))));}
set max_value params Value
set max_value cmd {sprintf("i2c wwd %i2cID 4 %04x\n", unpack("n", pack("S", %Value)));}
set max_value expect "0x[\da-fA-F]+\n"
set max_value postproc {unpack("S", pack("n",hex(trim("$_"))));}
#
# min_value - Register 6+7:
get min_value cmd {"i2c rwd %i2cID 6\n"}
get min_value expect "0x[\da-fA-F]+\n"
get min_value postproc {unpack("S", pack("n",hex(trim("$_"))));}
set min_value params Value
set min_value cmd {sprintf("i2c wwd %i2cID 6 %04x\n", unpack("n", pack("S", %Value)));}
set min_value expect "0x[\da-fA-F]+\n"
set min_value postproc {unpack("S", pack("n",hex(trim("$_"))));}
#
# Measure - Register 1 = 1!
set Measure cmd {"i2c wbd %i2cID 1 01\n"}
set Measure expect "0x01\n"
set Measure postproc {s/([0x01\n|;]*)/success/; "$_" eq "success" ? "ok" : "error"; }
#
# write eeprom - Register 1 = 2!
set write_eeprom cmd {"i2c wbd %i2cID 1 02\n"}
set write_eeprom expect "0x02\n"
set write_eeprom postproc {s/([0x02\n|;]*)/success/; "$_" eq "success" ? "ok" : "error"; }
#
# read eeprom - Register 1 = 3!
set read_eeprom cmd {"i2c wbd %i2cID 1 03\n"}
set read_eeprom expect "0x03\n"
set read_eeprom postproc {s/([0x03\n|;]*)/success/; "$_" eq "success" ? "ok" : "error"; }


Schließlich kann man mit dem Füllstand auch noch etwas anfangen, z.b. bei niederem Füllstand der Wassertonne die angeschlossene Pumpe abschalten:

define Garten_Pump_Threshold THRESHOLD Wassertonne_Fuellstand:fuellstand:1:10 Garten_Pump|set @ on|set @ off|0


Ich hoffe das ist für den Einen oder Anderen einmal nützlich.
grüße Nico

Edit:
Ein Füllstandsverlauf einer Wassertonne kann dann aussehen wie im angehängten Bild ;-)


jnewton957

Hallo,

das finde ich usgesprochen interessant und ich würde das gerne nachbauen.

Ich habe aktuell den KEMO Füllstandsanzeige für Wassertanks [M167N]. D.h. Ich habe aktuell eben ein Rohr in der Zisterne mit 8 Kontakten. Daher auch 8 Kabel im/"unter" dem Rasen verlegt in die Garage wo die Anzeige angebracht ist.

Also würde ich mit deiner Idee schon mal bis in die Garage bekommen. Leider habe ich keinen Anschluss/Kabelkanal von der Garage zu meinem Server/Raspi.
Wie bekomme ich die "Daten" nun übertragen ?
Kann man da eine Funklösung dransetzen ?

Ich habe selbstbau CUL 433 und 868 am Laufen. Die würde ich gerne als EMpfänger verwenden wollen. Wie mache ich das aber mit dem Sender ??

Danke für Infos


Jörg
FHEM6.2 auf Pi5
V 1.66 nanoCUL 433 (IT)
V 1.66 nanoCUL868 (HM)
sqlite3 LogDb
ELRO AB440, DECT200,  TFA30.3125, esp8266, HM, TabletUI, IR-Schreiblesekopf (Udo),tibber Pulse, Kostal Pico, cfos Wallbox, Modbus TCP

BrainHunter

Hallo Jörg,

Eine  Möglichkeit wäre ein Funkmodul direkt an den Sensor Microcontroller anzuschließen und diesen entsprechend zu Programmieren. Die Platine, die ich damals entwofen habe, hat die SPI Schnittstelle schon auf Kontakten herrausgeführt -> Man kann ein RFMxx, NRF24L01 oder CC1101 Modul anzuschließen.
Es ist auch kein Hexenwerk die Funktionalität in einen "Arduino" zu portieren. Die verwendeten Register vom ATMega8 sollten sich nicht oder nur wenig vom ATMega32 unterscheiden. Dann kannst du die diversen Arduino Libraries für die Funkmodule verwenden.
Es bleibt eben der Programmieraufwand.

Alternativ gehst du per I2C Bus bis in die Garage und stellst dir dort einen RPi oder ein Pollin NetIO als I2c <-> Ethernet Gateway auf. Diesen kannst du dann wiederum per Wlan oder PowerLan an deinen Server anbinden. Ich habe meinen Füllstandssensor per Ethersex (NetIO) angebunden. Dieser steht im Wintergarten und ein I2C Kabel geht raus an die Tonne. Zum Server geht es per Lankabel.

Hoffe das bringt dich etwas weiter.
Wenn du noch mehr Fragen hast immer raus damit!
grüße Nico