Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: termostaatti

leka-84 [23.07.2017 17:53:32]

#

Hei!
olen aloittelija vasta näissä hommissa.

Mitä koodista pitää muuttaa kun nyt se päivittää lämpötilat vasta kun ikkunan sulkee?

#!/usr/bin/env python


import time
import RPi.GPIO as GPIO
import Adafruit_DHT
from Tkinter import *

maxTemp = 20
webasto = 27
pin = 4
pin2 = 17

GPIO.setmode(GPIO.BCM)
GPIO.setup(27,GPIO.OUT)
GPIO.setwarnings(False)
humidity2, temperature2 = Adafruit_DHT.read_retry( Adafruit_DHT.DHT22, pin2 )
humidity, temperature = Adafruit_DHT.read_retry( Adafruit_DHT.DHT22, pin )



while True:

	master = Tk()

	def callback():
		global maxTemp
		maxTemp += 1
		print maxTemp
	def callback2():
		global maxTemp
		maxTemp -= 1
		print maxTemp



	sisa = Message(master, text="Sisalampo")
	sisa.configure(font='helvetica 10')
	sisa.pack()


	lamposisa = Text(master, height=1, width=4)
	lamposisa.configure(font='helvetica 18')
	lamposisa.pack()
	lamposisa.insert(END, temperature)

	ulko = Message(master, text="Ulkolampo")
	ulko.configure(font='helvetica 10')
	ulko.pack()


	lampoulko = Text(master, height=1, width=4)
	lampoulko.configure(font='helvetica 18')
	lampoulko.pack()
	lampoulko.insert(END, temperature2)

	lisa = Button(master, text = "+", command = callback)
	lisa.config( foreground="red", font='helvetica 18', height = 2, width = 2)
	lisa.pack()

	lamponaytto = Text(master, height=1, width=2)
	lamponaytto.configure(font='helvetica 18')
	lamponaytto.pack()
	lamponaytto.insert(END, maxTemp)

	miinus = Button(master, text = "-", command = callback2)
	miinus.config( foreground="blue", font='helvetica 18', height = 2, width = 2)
	miinus.pack()


	if temperature < maxTemp:
			GPIO.output(webasto,True)
	else:
			GPIO.output(webasto,False)

	print "Sisalampo={0:f}*C  Kosteus={1:f}%".format(temperature, humidity)
	print "Ulkolampo={0:f}*C  Kosteus={1:f}%".format(temperature2, humidity2)





	master.mainloop()
GPIO.cleanup()

Metabolix [23.07.2017 20:01:35]

#

En tarkkaan ymmärrä, mitä tarkoittaa ”se päivittää lämpötilat”. Päivittää minne? Sensorilta muuttujiin? Ruudulle? Lämmityslaitteelle tiedoksi? Koodissa on kuitenkin ihan selviä virheitä, joten eiköhän seuraava teksti auta jonkin verran.

Tk-ikkuna käytännössä näkyy siinä vaiheessa, kun päästään kohtaan master.mainloop(). Ohjelmassa ei ole esimerkiksi ajastettua toimintaa, joten ikkuna vain on ja odottaa painalluksia tai sulkemista. Ikkunassa olevat painikkeet kyllä muuttavat maxTemp-muuttujan arvoa, mutta callback-funktioissa ei tehdä sillä mitään, joten ohjelma ei siinä kohti ainakaan ”päivitä lämpötiloja”.

Kun ikkuna suljetaan, koodin suoritus jatkuu mainloop-rivistä. Silloin siis mennään while-silmukan alkuun ja yritetään luoda uusi ikkuna. Tässä kohti suoritetaan (uudestaan) myös GPIO.output ja sitä seuraava print. Ehkä tämä on se tarkoittamasi vaihe, jossa ohjelma ”päivittää lämpötilat”.

Ilmeisesti ohjelman alussa luetaan lämpötilan sensorilta. Sitä ei lueta missään vaiheessa uudestaan, joten ohjelma ei säädä lämmitintä järkevästi vaan toimii koko ajan sen mukaan, mikä lämpötila oli käynnistysvaiheessa.

Ohjelma olisi varmaan hyödyllisempi, jos lämpötilan lukeminen ja päivitys tapahtuisivat ajastetussa funktiossa. Erillistä while-silmukkaa ei tarvita, koska Tk:n mainloop jo sisältää silmukan.

Siis: Ota while-silmukka pois. Laita sekä lämpötilan lukeminen että ohjaus yhteen funktioon. Samassa funktiossa pitää päivittää ikkunassa näytettävät tiedot. Suorita funktio ajastetusti sekä tarvittaessa esim. käyttäjän painaessa nappia.

Tässä on ohjelmalle uusi rakenne (muutaman TODO-kohdan kera):

# TODO: Tänne muuttujien ja GPIO:n alustukset, kuten ennenkin.

# Callbackeja muutetaan vähän (ja nimetään kuvaavammin):
def callback_increase_temperature_max():
	global temperature_max
	temperature_max += 1
	päivitys() # ks. tämä funktio alempana.

# Sitten luodaan ikkuna:
master = Tk()
# TODO: Tähän väliin muu ikkunan sisältö.
# Harkitse tarkkaan, mitä ikkunaan laitat...
# Tekstejä ei vielä lisätä, vain tyhjät tekstikentät.
# Tekstin tyypiksi helpoin on Label.

# Tämä funktio lukee sensorin ja toimii sen mukaan:
def päivitys():
	global humidity_in, temperature_in
	global humidity_out, temperature_out
	global temperature_max
	humidity_out, temperature_out = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, pin2)
	humidity_in, temperature_in = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, pin)
	if temperature_in < temperature_max:
			GPIO.output(webasto, True)
	else:
			GPIO.output(webasto, False)

	# Tässä pitää myös päivittää ikkunan sisältö.
	# Esim. jos temperature_max_label = Label(), se päivitetään näin:
	temperature_max_label.configure(text = temperature_max)
	# TODO: Vastaavasti näytetään muut arvot.

# Tämä funktio suoritetaan sekunnin välein:
def silmukka():
	global master
	master.after(1000, silmukka)
	päivitys()

# Suoritetaan silmukkafunktio kerran, jotta ikkunan sisältö tulee oikeaksi
# ja silmukan seuraava suorituskerta tulee ajastettua sekunnin päähän.
silmukka(master)

# Aloitetaan Tk:n suoritus. Tämä loppuu, kun ikkuna suljetaan.
master.mainloop()
GPIO.clean()

leka-84 [24.07.2017 08:47:48]

#

Kiitos! Sehän alkoi toimimaan. On vaan tuo lämpötilojen lukeminen antureilta niin hidasta, että päivittäessä jumiutuu koko ohjelma muutamaksi sekunniksi.

Metabolix [24.07.2017 19:54:30]

#

Voisit siinä tapauksessa lukea anturit vaikka 10 sekunnin välein erillisessä säikeessä (thread), jolloin lukeminen ei jumittaisi ohjelmaa.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta