TerraControl - Terrariensteuerung mit dem Computer

Welches Terrarium & Einrichtung für die Landeinsiedlerkrebse?
Antworten
Benutzeravatar
Grischnach
LEK-Larve Z2
Beiträge: 24
Registriert: Dienstag 19. November 2013, 17:54

TerraControl - Terrariensteuerung mit dem Computer

Beitrag von Grischnach »

In unserem alten Terrarium kamen zur Steuerung bis jetzt immer herkömliche Zeitschaltuhren und ein TC2-pro zum Einsatz.
Das Problem daran war jedoch, dass die Zeitschaltuhren nicht synchron liefen. Irgendwann ging das Taglicht aus und erst einige Minuten später das Nachtlicht an. Wenn man nicht wollte, dass die Krebse im dunkeln sitzen, musste man einmal im Monat die Uhren neu stellen.
Auf die Dauer war mit das zu anstrengend und da wir gerade ein neues Terrarium planten, musste dafür eine neue Steuerung her.
Die Kompaktlösung dafür hieß Raspberry-Pi. Das ist ein ca. Check-Karten großer Minikomputer mit dem sich dank frei programmierbarer Ein- und Ausgänge alles mögliche realisieren lässt. Außerdem kostet er nicht die Welt, so dass man alles in allem genauso viel bezahlt, wie für das TC2-pro und divere Zeitschaltuhren.
Aber der Pi bietet noch mehr Vorteile. Mit ihm kann man taggenaue Zeitschaltpunkte programmieren. Und davon auch noch beliebig viele. Außerdem kann man auch eine vielzahl an Temeperatur und Feuchtigkeistssenoren anschließen. Dadurch sieht man ganz genau wo es wie warm ist.

In unserem Terrarium sind 3 DHT22 Sensoren verbaut. Die lesen Temperatur und Feuchtigkeit parallel aus und sind ziemlich kompakt. Kostenpunkt: 3,50€/Stck.
Das Programm im Raspberry, dass alles kontrolliert - TerraControl - habe ich selbst programmiert. Es ist so konzipiert, dass es alle paar Sekunden die Temperatur prüft und die Heizung entsprechend über eine Relaisplatine an- und abschaltet. Dabei achtet das Programm auch auf Tag und Nacht.


Parallel dazu dient das Prgramm auch als Zeitschaltuhr. Abends wird das Licht abhängig vom Sonnenuntergang eingeschaltet. Dazu habe ich im Programm eine Tabelle hintelegt in der jeweils die Zeiten am 1. und 15. des Monatgs verändert wird. Engere Taktungen gehen natürlich auch.
Abends wird dann das Nachtlicht ein- und 2 Sekunden später das Taglicht ausgeschaltet.

Zudem kann bei Bedarf jederzeit über ein Touchscreen das Licht manuell an und aus gemacht werden.

Um das ganze nachzubauen benötigt man neben etwas handwerklichem Geschick (es muss ein bisschen gelötet werden) folgendes:

- Raspberry Pi mit SD-Karte, Netzteil und ggf. W-LAN-Stick (alles zusammen ca. 50€)
- Display nach Gusto (bei mir ist es ein 7" Touch-Display) (ca. 70€, ohne Touch wesentlich billiger)
- Steckverbindungen für den Strom (ich habe Kaltromstecker benutzt) (Stck. ca. 2 €)
- Relaisplatine (ca. 5 €)
- Kabel (gibt es fertig für den GPIO-Port des Raspberry, für den Strom ansonsten 3 x 1,5 mm2)
- DHT22 Temperatur-Sensor (zur Verbindung mit dem Pi muss man da einen Widerstand einlöten) (3,50€) + 3-litziges Kabel
- Fassungen, Night-Light, Heizung, etc.

TerraControl läuft im Moment in der Version 1.00 auf meinem Terrarium. Es ist seit etwas über 2 Wochen im Dauerbetrieb. Dabei gab es keinen Absturz und auch sonst keine Probleme. Allerdings habe ich einen kleinen (Denk-)Fehler in der Zuweisung der Licht-Einschaltzeiten bemerkt. Deswegen habe ich schon die Version 1.01 in der Hinterhand für diejenigen, die Interesse daran haben.
Das Programm ist in Python3 programmiert. Da es speziell für unser Terrarium und unsere Ansprüche programmiert wurde, ist es ziemlich starr. Das bedeutet, alle Zeiten, Soll-Temperaturen und die dazu passende Hardware sind im Quellcode einprogrammiert. Um sie zu ändern, benötigt man deswegen ein bisschen Erfahrung im programmieren mit Python. Gott sei dank aber nicht viel, denn alle meine Kenntnisse die zum programmieren von TerraControl nötig waren, habe ich aus einem Buch.

Deswegen möchte ich auch diejenigen, die nicht programmieren können ermutigen, beim nächsten Terrarium über die Möglichkeit einen Computer einzusetzten nachzudenken.

Falls jemand Interesse an TerraControl hat, kann er sich gerne melden.

PS.: Das Bild ist noch von einer frühren Version, die nur einen Temperatur/Feuchtigkeitsensor programmiert hatte.
Dateianhänge
DSC_0072 (800x530).jpg
Benutzeravatar
Lordkroaq
LEK-Larve Z2
Beiträge: 11
Registriert: Samstag 2. April 2016, 23:50

Beitrag von Lordkroaq »

Hallo, ich bin grade dabei mein allererstes Terrarium zu bauen und will zur Steuerung ebenfalls einen Raspberry Pi nutzen. Als Vorlage habe ich die Ressourcen von Raspivivgenommen - hier ist es in PHP geschrieben und beinhaltet einen Webserver, den ich mir zudem noch übers Internet zugänglich mache, damit ich auch unterwegs nachschauen kann ob alles in Ordnung ist. Die Steuerung der Elektronik mache ich jedoch über Funksteckdosen und habe dazu noch einen Funksender an den Pi angeschlossen. Hier bin ich noch dabei den Code von Raspiviv anzupassen und die entsprechenden Befehle zur Steuerung der Funksteckdosen in die ganzen Automatismen einzubauen.
Benutzeravatar
Beetz
M-LEK
Beiträge: 3011
Registriert: Dienstag 25. November 2008, 15:15

Beitrag von Beetz »

Ich finde diese Idee total cool. Hab mir sowas schon mehrmals gedacht, aber dabei ist es geblieben und mit meinem raspi hab ich leider nur wenig eingespielt.

Weiter so kreativ sein :) finde ich super.

Gesendet von meinem XT1092 mit Tapatalk
Benutzeravatar
Lordkroaq
LEK-Larve Z2
Beiträge: 11
Registriert: Samstag 2. April 2016, 23:50

Beitrag von Lordkroaq »

So, mittlerweile hab ich es hinbekommen, war am Ende einfacher als gedacht. Anfang der Woche kommen die Pflanzen rein, dann wird das Terrarium eingelaufen und ich kann noch an den Parametern für die automatische Beheizung und den Vernebler drehen. Diese werten werden jetzt alle 5 Minuten aus der Datenbank gelesen und mit den eingestellten Schwellwerten verglichen. Ist es zu kalt, geht die Heizung an, ist es zu warm aus - mit der Luftfeuchte analog.

So sieht die Übersicht auf der Seite aus. Die Werte sind natürlich noch nicht im Normalbereich - das Einlaufen geht diese Woche los, sobald die Pflanzen drin sind ;)
http://imgur.com/2NR3ZC7
Benutzeravatar
Grischnach
LEK-Larve Z2
Beiträge: 24
Registriert: Dienstag 19. November 2013, 17:54

Beitrag von Grischnach »

Vorbereitungen auf dem Pi um Terra Control nutzen zu können:
1. Ich Empfehel Tight VNC oder ähnliches auf dem Pi zu installieren um alle bequem vom Desktop-PC oder Laptop zu programmieren:
Hier gibts eine gute Anleitung dazu: Tight VNC Server auf Raspberry Pi
2. Wenn man ebenfalls den DHT-22 Temperatursensor benutz, muss man die entsprechende Bibliothek auf Python installiert haben, damit der Pi mit dem Sensor kommunizieren kann. Hier die Anleitung: DHT-22
(Sonst findet man auch viele weitere Anleitungen und Schaltbilder, wenn man nach 'DHT-22 Raspberry sucht'

---------- Automatische Beitragszusammenführung ----------
---------- Beitrag hinzugefügt: 10:10 ----------


Hier auch noch der Quellcode für alle die das Programm nutzen und/oder verbesser wollen ;-)

(PS.: Da im Forum nur 10.000 Zeichen gehen, muss ich es auf zwei mal posten)

TerraControl Version 1.01
#!/usr/bin/python3.2

from time import *
from tkinter import *
import _thread
from RPi import GPIO
import Adafruit_DHT

#Tk().wm_title("Terra Control")

TCVersion = "1.01" # Hier Versionsummer eintragen

GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN) #Thermometer rechts 1
GPIO.setup(22, GPIO.IN) #Thermometer mitte 2
GPIO.setup(23, GPIO.IN) #Thermometer links 3
GPIO.setup(27, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(17, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)

month=["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]
day=["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"]

Monat=1
Tag=1
Flextime1 = "21:30"

DLightStatus = 0
NLightStatus = 0
HeaterStatus = 0
HeaterFuse = 1
IstTemp1 = 0
IstHumid1 = 0
IstTemp2 = 0
IstHumid2 = 0
IstTemp3 = 0
IstHumid3 = 0
DLightStatusText = "Aus"
NLightStatusText = "Aus"
HeaterStatusText = "Aus"
SysTime = 0
CntrTime = 0
CntrSec = 0
DayTime = 0
DayTimeText = "Nacht"


#Uhr
def checkTime():
global SysTime
global CntrTime
global CntrSec
global Tag
global Monat
while True:
t=localtime()
dateText = day[t.tm_wday] + ", der "+ str(t.tm_mday) + "." + month[t.tm_mon-1] + " " + str(t.tm_year)
timeText = "%02i:%02i " %(t.tm_hour, t.tm_min)
secText = "%02i" %(t.tm_sec)
UhrText = " Uhr"
SysTime = "%02i:%02i:%02i" %(t.tm_hour, t.tm_min, t.tm_sec)
CntrTime = "%02i:%02i" %(t.tm_hour, t.tm_min)
CntrSec = t.tm_sec

Monat=t.tm_mon
Tag=t.tm_mday

DateLabel.config(text=dateText)
TimeLabel.config(text=timeText)
SecLabel.config(text=secText)
UhrLabel.config(text=UhrText)
sleep(1)

#Tagessteuerung
def daycheck():
global Flextime1
global Monat
global Tag
DLightLabel.config(fg="black")
while True:
if Monat == 1 and Tag >= 1 and Tag <15:
Flextime1 = "16:00"
elif Monat == 1 and Tag >= 15:
Flextime1 = "16:15"
elif Monat == 2 and Tag >= 1 and Tag <15:
Flextime1 = "16:35"
elif Monat == 2 and Tag >= 15:
Flextime1 = "17:00"
elif Monat == 3 and Tag >= 1 and Tag <15:
Flextime1 = "17:25"
elif Monat == 3 and Tag >= 15:
Flextime1 = "17:45"
elif Monat == 4 and Tag >= 1 and Tag <15:
Flextime1 = "19:15"
elif Monat == 4 and Tag >= 15:
Flextime1 = "19:30"
elif Monat == 5 and Tag >= 1 and Tag <15:
Flextime1 = "20:00"
elif Monat == 5 and Tag >= 15:
Flextime1 = "20:15"
elif Monat == 6 and Tag >= 1 and Tag <15:
Flextime1 = "20:35"
elif Monat == 6 and Tag >= 15:
Flextime1 = "20:45"
elif Monat == 7 and Tag >= 1 and Tag <15:
Flextime1 = "20:50"
elif Monat == 7 and Tag >= 15:
Flextime1 = "20:50"
elif Monat == 8 and Tag >= 1 and Tag <15:
Flextime1 = "20:20"
elif Monat == 8 and Tag >= 15:
Flextime1 = "20:00"
elif Monat == 9 and Tag >= 1 and Tag <15:
Flextime1 = "19:20"
elif Monat == 9 and Tag >= 15:
Flextime1 = "18:55"
elif Monat == 10 and Tag >= 1 and Tag <15:
Flextime1 = "18:20"
elif Monat == 10 and Tag >= 15:
Flextime1 = "17:50"
elif Monat == 11 and Tag >= 1 and Tag <15:
Flextime1 = "16:20"
elif Monat == 11 and Tag >= 15:
Flextime1 = "16:00"
elif Monat == 12 and Tag >= 1 and Tag <15:
Flextime1 = "15:45"
elif Monat == 12 and Tag >= 15:
Flextime1 = "15:45"
else:
sleep(0.1)
sleep(1200)

#Zeitschaltuhr
def timer():
global DLightStatus
global NLightStatus
global SysTime
global CntrTime
global CntrSec
global DayTime
global Flextime1
NLightLabel.config(fg="black")
# Parameter and (CntrSec == 0 or CntrSec == 1 or CntrSec == 2)
#t=localtime()
TimerTime1 = "16:00" #Tageslicht an
TimerTime2 = "21:00" #Lichtwechsel abends
TimerTime3 = "21:00" #ohne Funktion
TimerTime4 = "02:00" #Nachtlicht aus
Morning = "09:00" #Nachtabsenkungszeit
Evening = "19:00" #Nachtabsenkungszeit 19.00
while True:
if CntrTime == Flextime1 and (CntrSec == 0 or CntrSec == 1 or CntrSec == 2):
DLightStatus = 1
if CntrTime == TimerTime2 and (CntrSec == 0 or CntrSec == 1 or CntrSec == 2):
NLightStatus = 1
sleep (2)
DLightStatus = 0
if CntrTime == TimerTime4 and (CntrSec == 0 or CntrSec == 1 or CntrSec == 2):
NLightStatus = 0
if CntrTime == Morning and (CntrSec == 0 or CntrSec == 1 or CntrSec == 2):
DayTime = 1
if CntrTime == Evening and (CntrSec == 0 or CntrSec == 1 or CntrSec == 2):
DayTime = 0
sleep(0.5)

#Thermometer
def TempCheck():
global IstTemp1
global IstHumid1
global IstTemp2
global IstHumid2
global IstTemp3
global IstHumid3
global HeaterFuse
counter1=0
counter2=0
counter3=0
while True:
#Thermometer1
Humid1, Temp1 = Adafruit_DHT.read(Adafruit_DHT.DHT22,4)
if type(Temp1) == float and type(Humid1) == float:
IstTemp1 = round(Temp1,1)
IstHumid1 = round(Humid1)
counter1 = 0
TempLabel1.config(fg="black")
if IstHumid1 >= 70:
HumidLabel1.config(fg="black")
elif IstHumid1 < 70 and IstHumid1 > 55:
HumidLabel1.config(fg="yellow")
elif IstHumid1 <= 55:
HumidLabel1.config(fg="red")
else:
counter1 += 1
if counter1 >= 10:
TempLabel1.config(fg="grey")
HumidLabel1.config(fg="grey")
if counter1 >= 60:
HeaterFuse = 0
#Thermometer2
Humid2, Temp2 = Adafruit_DHT.read(Adafruit_DHT.DHT22,22)
if type(Temp2) == float and type(Humid2) == float:
IstTemp2 = round(Temp2,1)
IstHumid2 = round(Humid2)
counter2 = 0
TempLabel2.config(fg="black")
if IstHumid2 >= 70:
HumidLabel2.config(fg="black")
elif IstHumid2 < 70 and IstHumid2 > 55:
HumidLabel2.config(fg="yellow")
elif IstHumid2 <= 55:
HumidLabel2.config(fg="red")
else:
counter2 += 1
if counter2 >= 10:
TempLabel2.config(fg="grey")
HumidLabel2.config(fg="grey")
#Thermometer3
Humid3, Temp3 = Adafruit_DHT.read(Adafruit_DHT.DHT22,23)
if type(Temp3) == float and type(Humid3) == float:
IstTemp3 = round(Temp3,1)
IstHumid3 = round(Humid3)
counter3 = 0
TempLabel3.config(fg="black")
if IstHumid3 >= 70:
HumidLabel3.config(fg="black")
elif IstHumid3 < 70 and IstHumid3 > 55:
HumidLabel3.config(fg="yellow")
elif IstHumid3 <= 55:
HumidLabel3.config(fg="red")
else:
counter3 += 1
if counter3 >= 10:
TempLabel3.config(fg="grey")
HumidLabel3.config(fg="grey")
sleep(2)

Benutzeravatar
Grischnach
LEK-Larve Z2
Beiträge: 24
Registriert: Dienstag 19. November 2013, 17:54

Beitrag von Grischnach »

Teil 2 von TerraControl 1.01:
#Thermostat
def TempControl():
global IstTemp1
global IstHumid1
global HeaterFuse
global HeaterStatus
global HeaterStatusText
global DayTime
#SollTemp = 20.0
#SollHumid = 70.0
while True:
if DayTime == 0:
SollTemp = 21.0 # Soll-Temperatur NACHT
elif DayTime == 1:
SollTemp = 27.0 # Soll-Temperatur TAG
if HeaterFuse == 1:
if IstTemp1 < SollTemp:
HeaterStatus = 1
elif IstTemp1 > SollTemp + 1:
HeaterStatus = 0
if HeaterStatus == 0:
HeaterStatusText = "Stand-by"
elif HeaterStatus == 1:
HeaterStatusText = "An"
elif HeaterFuse == 0:
HeaterStatusText = "Aus"
HeaterStatus = 0
sleep(0.5)

#Eventhandler/Steuerelektronik
def eventHandler():
global DLightStatusText
global NLightStatusText
global HeaterStausText
global DLightStatus
global NLightStatus
global DayTimeText
global DayTime
GPIO.output(18, True) #GPIO für die Pumpe wird hier deaktiviert
while True:
if DLightStatus == 0:
GPIO.output(27, True)
DLightStatusText = "Aus"
elif DLightStatus == 1:
GPIO.output(27, False)
DLightStatusText = "An"
if NLightStatus == 0:
GPIO.output(15, True)
NLightStatusText= "Aus"
elif NLightStatus == 1:
GPIO.output(15, False)
NLightStatusText = "An"
if HeaterStatus == 0:
GPIO.output(17, True)
elif HeaterStatus == 1:
GPIO.output(17, False)
if DayTime == 0:
DayTimeText = "Nacht"
elif DayTime == 1:
DayTimeText = "Tag"
DayTimeButton.config(text=DayTimeText)
DLightButton.config(text=DLightStatusText)
NLightButton.config(text=NLightStatusText)
HeaterButton.config(text=HeaterStatusText)
TempLabel1.config(text = str(IstTemp1) + " °C")
HumidLabel1.config(text = str(IstHumid1) + " %")
TempLabel2.config(text = str(IstTemp2) + " °C")
HumidLabel2.config(text = str(IstHumid2) + " %")
TempLabel3.config(text = str(IstTemp3) + " °C")
HumidLabel3.config(text = str(IstHumid3) + " %")
sleep(0.1)

#Schalter Tageslicht
def toggleDLight():
global DLightStatus
if DLightStatus == 0:
DLightStatus = 1
elif DLightStatus == 1:
DLightStatus = 0

#Schalter Nachtlicht
def toggleNLight():
global NLightStatus
if NLightStatus == 0:
NLightStatus = 1
elif NLightStatus == 1:
NLightStatus = 0

#Schalter Heizung
def toggleHeater():
global HeaterFuse
if HeaterFuse == 0:
HeaterFuse = 1
elif HeaterFuse == 1:
HeaterFuse = 0

#Schalter Tag/Nachtabsenkung
def toggleDayTime():
global DayTime
if DayTime == 0:
DayTime = 1
elif DayTime == 1:
DayTime = 0


window = Tk()
window.wm_title("Terra Control V"+TCVersion)

w = window.winfo_screenwidth()
h = window.winfo_screenheight()
window.geometry(str(w)+ "x" + str(h) + "+0+0")

dateframe=Frame(master=window)
timeframe=Frame(master=window)
tempframe=Frame(master=window)
#humidframe=Frame(master=window)
buttonframe=Frame(master=window)
DateLabel=Label(master=dateframe, font=("Arial", 35))
TimeLabel=Label(master=timeframe, font=("Arial", 50))
SecLabel=Label(master=timeframe, font=("Arial", 35))
UhrLabel=Label(master=timeframe, font=("Arial", 50))
TempNameLabel=Label(master=tempframe, text="Temperatur:", font=("Arial", 35))
HumidNameLabel=Label(master=tempframe, text="Luftfeuchtigkeit:", font=("Arial", 35))
TempLabel1=Label(master=tempframe, font=("Arial", 40))
HumidLabel1=Label(master=tempframe, font=("Arial",40))
TempLabel2=Label(master=tempframe, font=("Arial", 20))
HumidLabel2=Label(master=tempframe, font=("Arial",20))
TempLabel3=Label(master=tempframe, font=("Arial", 20))
HumidLabel3=Label(master=tempframe, font=("Arial",20))
DLightLabel=Label(master=buttonframe, text="Beleuchtung", font=("Arial", 15), fg="yellow")
NLightLabel=Label(master=buttonframe, text="Nachtlicht", font=("Arial",15), fg="yellow")
HeaterLabel=Label(master=buttonframe, text="Heizung", font=("Arial", 15))
DayTimeLabel=Label (master=buttonframe, text="Tag-/Nacht-Zyklus", font=("Arial", 15))
DLightButton=Button(master=buttonframe, text=DLightStatus, command=toggleDLight, font=("Arial", 15), width=20, height=4)
NLightButton=Button(master=buttonframe, text=NLightStatus, command=toggleNLight, font=("Arial", 15), width=20, height=4)
HeaterButton=Button(master=buttonframe, text=HeaterStatusText, command=toggleHeater, font=("Arial",15),width=20, height=4)
DayTimeButton=Button(master=buttonframe, text=DayTimeText, command=toggleDayTime, font=("Arial",15),width=20, height=4)


dateframe.grid(row=0, column=0, sticky=W) #)
timeframe.grid(row=1,column=0,padx = 380, sticky=W)
tempframe.grid(row=2,column=0)
#humidframe.grid(row=2, column=1, sticky=W)
buttonframe.grid(row=3, column=0, pady=20, sticky=W + E, padx = 60)
DateLabel.grid(row=0,column=0, ipadx=250)
TimeLabel.grid(row=0,column=0)
SecLabel.grid(row=0,column=1)
UhrLabel.grid(row=0,column=2)
TempNameLabel.grid(row=0,column=0, ipadx=100)
HumidNameLabel.grid(row=0,column=1, ipadx=250)
TempLabel1.grid(row=1,column=0, ipadx=100)
HumidLabel1.grid(row=1,column=1, ipadx=250)
TempLabel2.grid(row=2,column=0, ipadx=100)
HumidLabel2.grid(row=2,column=1, ipadx=250)
TempLabel3.grid(row=3,column=0, ipadx=100)
HumidLabel3.grid(row=3,column=1, ipadx=250)
DLightLabel.grid(row=0, column=0)
NLightLabel.grid(row=0,column=1)
HeaterLabel.grid(row=0, column=2)
DayTimeLabel.grid(row=0, column=3)
DLightButton.grid(row=1, column=0)
NLightButton.grid(row=1, column=1)
HeaterButton.grid(row=1, column=2)
DayTimeButton.grid(row=1, column=3)

_thread.start_new_thread(checkTime,())
_thread.start_new_thread(timer,())
_thread.start_new_thread(TempCheck,())
_thread.start_new_thread(TempControl,())
_thread.start_new_thread(eventHandler,())
_thread.start_new_thread(daycheck,())

window.mainloop()
Benutzeravatar
Curlz
L-LEK
Beiträge: 7289
Registriert: Freitag 17. April 2009, 19:43
Landeinsiedler in Pflege: 40
Kontaktdaten:

Beitrag von Curlz »

ps. eine Text-Datei als Anhang wäre einfacher gewesen ;)

Edit: ok, .txt geht nicht. Aber das ganze als .pdf geht.
Viele Grüße,

Curlz
und ihre Zwickis


Curlz Crabs Blog
Antworten