Hi I've been trying to implement a DHT22 temperature and humidity sensor with Tkinter GUI where it updates regularly while using the GUI. This is done on a Raspberry Pi 4 using Python. However, while the numbers are updating correctly, it would cause the GUI freeze momentarily while updating the numbers. I have already tried multithreading, but it unfortunately didn't help. Is there any solution to this problem? Any help is greatly appreciated.
Here's the code:
# Import the required libraries
import RPi.GPIO as GPIO
import spidev
import time
import tkinter
from tkinter import *
import tkinter.font as tkFont
from PIL import ImageTk, Image
# import time
import smbus
import serial
import os
import argparse
import Adafruit_DHT
from threading import Thread
SENSOR = Adafruit_DHT.DHT22
# GPIO4 on the Raspberry Pi
SENSOR_PIN = 4
address = 0b01
ssPin = 8
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 976000
spi.mode = 0b11
#spi.bit_order = msbfirst
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(ssPin,GPIO.OUT)
GPIO.setup(22,GPIO.OUT)
GPIO.setup(26,GPIO.OUT)
GPIO.output(ssPin,GPIO.LOW)
GPIO.output(22,GPIO.HIGH)
GPIO.output(26,GPIO.HIGH)
class App:
def __init__(self, master):
def SendScaleReading(self):
S = scale.get() #retrieve value from slider
if S>0:
S+=155
print(S)
spi.xfer([address ,S]) #write data to slave address
frame = Frame(master)
frame.pack()
scale = tkinter.Scale(root,from_=0,to=100,length=700,bg='black',fg='#0000FF', highlightthickness = 0, bd = 0, command=SendScaleReading) #set parameters of slider
scale.place(relx=0.75, rely=0.05)
#scale.place(relx = 0, rely = 0) # set position of slider
fontstyle = tkFont.Font(family='Arial', size=50) #initialise font
scale['font'] = fontstyle
def PowerFn():
global powerBool
# print(ledBool)
if powerBool:
#print('went to on button')
powerBtn.config(image=On_BtnImg)
powerBtn.image = On_BtnImg
#print("on button configured")
powerLabel.config(text="POWER: ON", fg='#00FF00')
# communicating with arduino
GPIO.output(26,GPIO.LOW)
else:
#print('went to off button')
powerBtn.config(image=Off_BtnImg)
powerBtn.image = Off_BtnImg
#print("off button configured")
powerLabel.config(text="POWER: OFF", fg='#FF0000')
# communicating with arduino
GPIO.output(26,GPIO.HIGH)
powerBool = not powerBool
def DirectionFn():
global directionBool
# print(cbBool)
if directionBool:
#print('went to CbOn button')
directionBtn.config(image = On_BtnImg)
directionBtn.image = On_BtnImg
#print("CbOn button configured")
directionLabel.config(text="FORWARD", fg='#00FF00')
# communicating with arduino
GPIO.output(22,GPIO.HIGH)
else:
#print('went to CbOff button')
directionBtn.config(image = Off_BtnImg)
directionBtn.image = Off_BtnImg
# print("CbOff button configured")
directionLabel.config(text="REVERSE", fg='#FF0000')
# communicating with arduino
GPIO.output(22,GPIO.LOW)
directionBool = not directionBool
def tempsensor():
while True:
print("bruh moment")
h, t = Adafruit_DHT.read_retry(SENSOR, SENSOR_PIN)
print(t)
print(h)
temp = "%.1F" %t
hum = "%.1f" %h
temperature.set(temp+ " *C")
humidity.set(hum+ " %")
time.sleep(1);
root = Tk()
app = App(root)
root.config(bg='black')
#root.attributes('-zoomed', True)
#root.state('fullscreen')
rootWidth = root.winfo_screenwidth()
rootHeight = root.winfo_screenheight()
root.attributes('-zoomed', True)
# Create mini window
#canvas = Canvas(root, bg='black', highlightbackground='white')
#canvas.place(relx=0.1, rely=0.03, relheight=0.51, relwidth=0.505)
temperature = StringVar()
temperature.set("----"+" *C")
humidity = StringVar()
humidity.set("----"+" %")
#root.after(2000, tempsensor)
h, t = Adafruit_DHT.read_retry(SENSOR, SENSOR_PIN)
On_img = Image.open("/home/pi/Downloads/on.png")
Off_img = Image.open("/home/pi/Downloads/off.png")
# Resize the image using resize() method according to the screen height and width
btnWidth = int(rootWidth / 6.4)
print(btnWidth)
infobtnWidth = int(rootHeight / 10)
print(infobtnWidth)
On_resize_img = On_img.resize((btnWidth, btnWidth))
Off_resize_img = Off_img.resize((btnWidth, btnWidth))
On_BtnImg = ImageTk.PhotoImage(On_resize_img)
Off_BtnImg = ImageTk.PhotoImage(Off_resize_img)
normalWidth = 1920 # Width of monitor screen used to write this code
normalHeight = 1080 # Height of monitor screen used to write this code
percentWidth = rootWidth / (normalWidth / 100)
percentHeight = rootHeight / (normalHeight / 100)
scale = ((percentWidth + percentHeight) / 2) / 100
fontsize = int(14 * scale)
fontsize = 50
fontstyle = tkFont.Font(family='Arial', size=fontsize)
titleFontsize = int(50 * scale)
if titleFontsize < 8:
titleFontsize = 8
TitleFontstyle = tkFont.Font(family="Gothic", size=titleFontsize)
## Labels ##
titleLabel = Label(root, text="MAX5487 DigiPot", font=TitleFontstyle, fg="red", bg="black")
titleLabel.place(relx=0.35, rely=0.05)
powerLabel = Label(root, text="POWER: OFF", font=fontstyle, fg='red', bg='black')
powerLabel.place(relx=0.2, rely=0.65, anchor=N)
directionLabel = Label(root, text="FORWARD", font=fontstyle, fg='#00FF00', bg='black')
directionLabel.place(relx=0.5, rely=0.65 , anchor=N)
powerBool = True
# boolean for led button
powerBtn = Button(root, image=Off_BtnImg, bg='black', bd=0, activebackground='black', highlightthickness = 0, command=PowerFn)
powerBtn.place(relx=0.2, rely=0.35, anchor=N)
directionBool = False
directionBtn = Button(root, image=On_BtnImg, bg='black', bd=0, activebackground='black', highlightthickness = 0, command=DirectionFn)
directionBtn.place(relx=0.5, rely=0.35, anchor=N)
templabel = Label(root, textvariable=temperature, font=fontstyle, fg='white', bg='red', highlightthickness = 0)
templabel.place(relx=0.2, rely=0.8, anchor=N)
humidlabel = Label(root, textvariable=humidity, font=fontstyle, fg='white', bg='red', highlightthickness = 0)
humidlabel.place(relx=0.5, rely=0.8, anchor=N)
# Button for closing
exit_button = Button(root, text="Exit", font=fontstyle, fg='white', bg='red', highlightthickness = 0, command=root.destroy)
exit_button.place(relx=0.5, rely=0.9, anchor=N)
background_thread = Thread(target=tempsensor)
background_thread.start()
root.mainloop()
Related
Im trying to do a selector to run diferent configs on a emulator, and i put a timer to close this app and run the default option.
My problem is when i run the app and close it without a choise the timer continue and dont stop and after the time end run the other app.
import os
import threading
#import shutil
import tkinter as tk
from tkinter import *
def drivers(driver1, driver2):
wait_time.cancel()
ra_config = open("F:\\Games\\RetroArch\\retroarch.cfg", "rt")
temp_data = ra_config.read()
temp_data = temp_data.replace('video_driver = "' + driver1 + '"', 'video_driver = "' + driver2 + '"')
ra_config.close()
ra_config = open("F:\\Games\\RetroArch\\retroarch.cfg", "wt")
ra_config.write(temp_data)
ra_config.close()
os.startfile (r"F:\\Games\\RetroArch\\retroarch.exe")
root.quit()
HEIGHT = 200
WIDTH = 700
root = tk.Tk()
root.title("Choose one")
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x_coordinate = (screen_width/2) - (WIDTH/2)
y_coordinate = (screen_height/2) - (HEIGHT/2)
root.geometry ("%dx%d+%d+%d" % (WIDTH, HEIGHT, x_coordinate, y_coordinate))
canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()
photo_vul = PhotoImage(file = r"img\\vulkan.png")
photo_gl = PhotoImage(file = r"img\\opengl.png")
photo_icon = PhotoImage(file = r"img\\retroarch-icon.png")
root.iconphoto(False, photo_icon)
#frame = tk.Frame(root, highlightbackground='black', highlightthickness=1, bd=10)
frame = tk.Frame(root, bd=10)
frame.place(relx = 0.5, rely=0.5, relwidth=0.95, relheight=0.95, anchor="c")
button = tk.Button(frame, bg='white', activebackground='white', image = photo_vul, font=60, command=lambda: drivers("glcore", "vulkan"))
button.place(relx = 0.05, relwidth=0.4, relheight=1)
button2 = tk.Button(frame, bg='#0277bd', activebackground='#0277bd', image = photo_gl, font=60, command=lambda: drivers("vulkan", "glcore"))
button2.place(relx = 0.55, relwidth=0.4, relheight=1)
#create the vulkan config if the orig
#og = r"F:\\Games\\RetroArch\\retroarch.cfg"
#tg = r"F:\\Games\\RetroArch\\retroarch-vulkan.cfg"
#shutil.copyfile(og, tg)
#pyinstaller --noconsole --onefile RApicker.py
wait_time = threading.Timer(15.0, drivers,["vulkan", "glcore"]).start()
root.mainloop()
On window delete
def delete_window():
# Stop timer here
root.protocol("WM_DELETE_WINDOW", delete_window)
root.mainloop()
On destroy
def destroy():
# Stop timer here
root.bind("<Destroy>", destroy)
root.mainloop()
This is my first post and I have googled extensively for an answer but found nothing that works. I'm new to python but have some experience with C++/arduino programming.
I'm trying to make a weather station and display some garage door states as image icons. My issue is when it works, it flickers the images and eventually bogs down the system and runs very slowly. I've tried every combination I can think of making objects global or only changing certain parameters in the Label objects to work around the garbage collection issue I've read about. I've tried Canvas as well, but the issue I had with that is no matter what location coordinates I entered, it always showed up in the top center of the screen.
Edit: as per requested, heres a truncated version:
root = tk.Tk()
global garageOpenIcon
global garageClosedIcon
global doorUnlockedIcon
global doorLockedIcon
global doorOpenIcon
backgroundImage = PhotoImage(file = "background.gif")
garageOpenIcon = PhotoImage(file = "garageOpen.gif")
garageClosedIcon = PhotoImage(file = "garageClosed.gif")
doorLockedIcon = PhotoImage(file = "doorLocked.gif")
doorUnlockedIcon = PhotoImage(file = "doorUnlocked.gif")
doorOpenIcon = PhotoImage(file = "doorOpen.gif")
background = Label(root, image = backgroundImage)
background.place(x = 0, y = 0, relwidth = 1, relheight = 1)
global mainDoorLabel
global sideDoorLabel
mainDoorLabel = Label(root)
sideDoorLabel = Label(root)
def getDoors():
global garageOpenIcon
global garageClosedIcon
global doorOpenIcon
global doorUnlockedIcon
global doorLockedIcon
global mainDoorLabel
global sideDoorLabel
#side door open and unlocked:
if(GPIO.input(sideDoorPin) == GPIO.HIGH):
sideDoorLabel = Label(image = doorOpenIcon)
#closed and unlocked:
elif(GPIO.input(sideDoorPin) == GPIO.LOW):
if(GPIO.input(sideDoorLockPin) == GPIO.HIGH):
sideDoorLabel = Label(image = doorUnlockedIcon)
elif(GPIO.input(sideDoorPin) == GPIO.LOW):
sideDoorLabel = Label(image = doorLockedIcon)
#main door:
if(GPIO.input(mainDoorPin) == GPIO.HIGH):
mainDoorLabel = Label(image = garageOpenIcon)
else:
mainDoorLabel = Label(image = garageClosedIcon)
mainDoorLabel.place(x = 50, y = 400)
sideDoorLabel.place(x = 150, y = 400)
root.after(1000, getDoors)
Here is my full code, images work but flicker:
# WeatherStation for Raspberry Pi Model B Rev 2
# steve.a.mccluskey#gmail.com
#
# Code adapted from youtube.com/watch?v=MWKAitSX3vg
# Channel educ8s.tv
# Video name "Raspberry Pi Project: Touch Weather Station using a DHT22 and a Raspberry Pi 3 with TKInter GUI
#
# This program uses readings from several Dallas DS18B20 temp sensors and displays on the LCD along with on a website.
# Temps are collected from a background process called updateSensors.py and written to a JSON file called sensorValues.JSON
# which is located in the web folder at /var/www/html/. This program reads the JSON file. The webpage also reads it so there's
# minimal interferance between programs.
# Sensors are zero indexed. The sensors are assigned to their respective labels by their index number.
# Use readSensors.py to print their index number, digital ID and current temp to the console.
#
# Door sensors are read directly from this program and displayed accordingly. updateDoor.py is also run in background to write to doorSensorValues.json
# also in the web folder to be served to the web page.
#
# Hardware Used:
# Raspberry Pi Model B Rev 2
# Adafruit PITFT - Assembled 480x320 3.5" TFT+Touchscreen For Raspberry Pi, adafruit.com/product/2097
# Adafruit Prototyping Pi Plate Kit for Raspberry Pi, adafruit.com/product/801
# Sparkfun RJ45 Breakout sparkfun.com/products/716
# Sparkfun RJ45 8-Pin Connector sparkfun.com/products/643
# Dallas OneWire DS18B20 Digital Temp Sensors
#
#
#
#
# ------------
# GPIO Pins used:
# 1 ) 3.3v -> orange -> 3.3v
# 2 ) 5.0v
# 3 ) SDA -> white/brown -> I2C SDA
# 4 ) 5.0v
# 5 ) SCL -> brown -> I2C SCL
# 6 ) Gnd -> white/orange -> Gnd
# 7 ) GPIO 7 -> GPIO 4 -> white/green -> OneWire Bus
# 8 ) TXD
# 9 ) Gnd
# 10) RXD
# 11) GPIO 0 -> GPIO 17
# 12) GPIO 1 -> GPIO 18
# 13) GPIO 2 -> GPIO 27 -> blue -> Main Door Sensor
#
# 14) Gnd
# 15) GPIO 3 -> GPIO 22 -> white/blue -> Side Door Sensor
# 16) GPIO 4 -> GPIO 23 -> green -> Side Door Lock Sensor
# 17) 3.3v
# 18) GPIO 5 -> GPIO 24 -> LCD Shield
# 19) SPI MOSI -> LCD Shield
# 20) Gnd
# 21) SPI MISO -> LCD Shield
# 22) GPIO 6 -> GPIO 25 -> LCD Shield
# 23) SPI SCLK -> LCD Shield
# 24) SPI CE0 -> LCD Shield
# 25) Gnd
# 26) SPI CE1 -> LCD Shield
# -------
# Cat5e Pinout :
# White/Orange : Gnd
# Orange : 3.3v
# White/Green : OneWire
# Blue : Main Door Sensor
# White/Blue : Side Door Sensor
# Green : Side Door Lock Sensor
# White/Brown : I2C SDA
# Brown : I2C SCL
from Tkinter import *
import Tkinter as tk
from Tkinter import Canvas
from PIL import ImageTk, Image
import threading
import tkFont
import RPi.GPIO as GPIO
import json
import time
import datetime
#temp sensor assignments:
livingRoom = 1
upstairs = 4
basement = 0
outside = 2
garage = 3
sammyDoor = 5
#digital door sensor pins:
mainDoorPin = 27
sideDoorPin = 22
sideDoorLockPin = 23
GPIO.setmode(GPIO.BCM)
GPIO.setup(mainDoorPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(sideDoorPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(sideDoorLockPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
root = tk.Tk()
global garageOpenIcon
global garageClosedIcon
global doorUnlockedIcon
global doorLockedIcon
global doorOpenIcon
backgroundImage = PhotoImage(file = "background.gif")
garageOpenIcon = PhotoImage(file = "garageOpen.gif")
garageClosedIcon = PhotoImage(file = "garageClosed.gif")
doorLockedIcon = PhotoImage(file = "doorLocked.gif")
doorUnlockedIcon = PhotoImage(file = "doorUnlocked.gif")
doorOpenIcon = PhotoImage(file = "doorOpen.gif")
background = Label(root, image = backgroundImage)
background.place(x = 0, y = 0, relwidth = 1, relheight = 1)
global mainDoorLabel
global sideDoorLabel
global mainDoorState
global sideDoorState
mainDoorLabel = Label(root)
sideDoorLabel = Label(root)
#mainDoorLabel.place(x = 50, y = 400)
#sideDoorLabel.place(x = 150, y = 400)
#temp sensor strings:
mainTemp = StringVar()
mainTemp.set("In: ")
mainTempValue = StringVar()
outTemp = StringVar()
outTemp.set("Out:")
LR = StringVar()
LR.set("Living Room: ")
temperatureLR = StringVar()
UP = StringVar()
UP.set("Upstairs: ")
temperatureUp = StringVar()
DN = StringVar()
DN.set("Basement: ")
temperatureDn = StringVar()
Out = StringVar()
Out.set("Outside: ")
temperatureOut = StringVar()
Garage = StringVar()
Garage.set("Garage: ")
temperatureGg = StringVar()
SammyDoor = StringVar()
SammyDoor.set("SammyDoor: ")
temperatureSammyDoor = StringVar()
currentTime = StringVar()
timeStamp = StringVar()
#temp sensor labels:
mainTempLabel = Label(root, fg = "magenta2", background = "#00dbde", textvariable = mainTemp, font = ("Helvetica", 30))
mainTempLabel.place(x = 20, y = 195)
mainTempValueLabel = Label(root, fg = "magenta2", background = "#00dbde", textvariable = mainTempValue, font = ("Helvetica", 62, "bold"))
mainTempValueLabel.place(x = 100, y = 170)
outTempLabel = Label(root, fg = "magenta2", background = "#00dbde", textvariable = outTemp, font = ("Helvetica", 30))
outTempLabel.place(x = 20, y = 300)
outTempValueLabel = Label(root, fg = "magenta2", background = "#00dbde", textvariable = temperatureOut, font = ("Helvetica", 62, "bold"))
outTempValueLabel.place(x = 100, y = 260)
currentTimeLabel = Label(root, fg = "purple", background = "#00dbde", textvariable = currentTime, font = ("Helvetica", 30))
currentTimeLabel.place(x = 270, y = 5)
LRLabel = Label(root, fg = "white", background = "#00dbde", textvariable = LR, font = ("Helvetica", 25))
LRLabel.place(x = 391, y = 160)
temperatureLRLabel = Label(root, fg = "white", background = "#00dbde", textvariable = temperatureLR, font = ("Helvetica", 25, "bold"))
temperatureLRLabel.place(x = 600, y = 160)
UPLabel = Label(root, fg= "white", background = "#00dbde", textvariable = UP, font = ("Helvetica", 25))
UPLabel.place(x = 391, y = 210)
temperatureUpLabel = Label(root, fg = "white", background = "#00dbde", textvariable = temperatureUp, font = ("Helvetica", 25, "bold"))
temperatureUpLabel.place(x = 600, y = 210)
DNLabel = Label(root, fg = "white", background = "#00dbde", textvariable = DN, font = ("Helvetica", 25))
DNLabel.place(x = 391, y = 260)
temperatureDnLabel = Label(root, fg = "white", background = "#00dbde", textvariable = temperatureDn, font = ("Helvetica", 25, "bold"))
temperatureDnLabel.place(x = 600, y = 260)
GarageLabel = Label(root, fg = "white", background = "#00dbde", textvariable = Garage, font = ("Helvetica", 25))
GarageLabel.place(x = 391, y = 310)
temperatureGgLabel = Label(root, fg = "white", background = "#00dbde", textvariable = temperatureGg, font = ("Helvetica", 25, "bold"))
temperatureGgLabel.place(x = 600, y = 310)
SammyDoorLabel = Label(root, fg = "white", background = "#00dbde", textvariable = SammyDoor, font = ("Helvetica", 25))
SammyDoorLabel.place(x = 391, y = 360)
temperatureSammyDoorLabel = Label(root, fg = "white", background = "#00dbde", textvariable = temperatureSammyDoor, font = ("Helvetica", 25, "bold"))
temperatureSammyDoorLabel.place(x = 600, y = 360)
timeStampLabel = Label(root, fg = "white", background = "#00dbde", textvariable = timeStamp, font = ("Helvetica", 15))
timeStampLabel.place(x = 530, y = 440)
root.attributes("-fullscreen", True)
exitButton = tk.Button(root,fg = "white", text = "X", font = ("Helvetica", 20, "bold"), command = exit, bg = "red")
exitButton.place(x = 680, y = 0)
root.update_idletasks()
def exit():
root.quit()
def updateTemps():
index_value = []
id_value = []
temp_value = []
dateTime_value = []
#try reading json file. will not read if it is being written to by background process updateSensors.py
try:
with open('/var/www/html/sensorValues.json', 'r') as f:
data = f.read()
dataString = json.loads(data)
f.close()
for dateTime in dataString['timestamp']:
dateTime_value = (dateTime['dateTime'])
for index in dataString['sensors']:
temp_value.append(index['temp'])
id_value.append(index['id'])
index_value.append(index['index'])
temperatureLR.set(str(temp_value[livingRoom]) + " F")
temperatureOut.set(str(temp_value[outside]) + " F")
temperatureGg.set(str(temp_value[garage]) + " F")
temperatureUp.set(str(temp_value[upstairs]) + " F")
temperatureDn.set(str(temp_value[basement]) + " F")
temperatureSammyDoor.set(str(temp_value[sammyDoor]) + " F")
timeStamp.set(str(dateTime_value))
avg = format(float(((float(temp_value[livingRoom]) + float(temp_value[upstairs])) / 2.0)), '.1f')
mainTempValue.set(str(avg) + " F")
except:
pass
root.after(2000, updateTemps)
def getDoors():
global garageOpenIcon
global garageClosedIcon
global doorOpenIcon
global doorUnlockedIcon
global doorLockedIcon
global mainDoorLabel
global sideDoorLabel
# sideDoorState = 0
# mainDoorState = 0
#side door open and unlocked:
if(GPIO.input(sideDoorPin) == GPIO.HIGH):
# sideDoorState = 2
sideDoorLabel = Label(image = doorOpenIcon)
#closed and unlocked:
elif(GPIO.input(sideDoorPin) == GPIO.LOW):
if(GPIO.input(sideDoorLockPin) == GPIO.HIGH):
# sideDoorState = 1
sideDoorLabel = Label(image = doorUnlockedIcon)
elif(GPIO.input(sideDoorPin) == GPIO.LOW):
# sideDoorState = 0
sideDoorLabel = Label(image = doorLockedIcon)
#main door:
if(GPIO.input(mainDoorPin) == GPIO.HIGH):
# mainDoorState = 1
mainDoorLabel = Label(image = garageOpenIcon)
else:
mainDoorState = 0
mainDoorLabel = Label(image = garageClosedIcon)
mainDoorLabel.place(x = 50, y = 400)
sideDoorLabel.place(x = 150, y = 400)
root.after(1000, getDoors)
def getTime():
currentTime.set(datetime.datetime.now().strftime("%m-%d-%Y %H:%M:%S"))
root.after(500, getTime)
root.after(1000, getTime)
root.after(1001, updateTemps)
root.after(1000, getDoors)
root.mainloop()
maindoorlabel.configure(image = garageopenicon)
maindoorlabel.image = garageopenicon worked.
recently i have been working on Tkinter in Raspberry pi to build a GUI for home automation, and i wanted to design a validation module which says "ACTIVE" when the sensor is working and "INACTIVE" when sensor has malfunctioned.
I am able to get the validation in the GUI but its not dynamic. Every time i have to re-run the program to get the updated status of the sensors
is there a way where in i can update the Active and Inactive status without re-running the entire program?
I am taking input from GPIO pins on the raspberry pi and reading them in the program
here is the code i have worked on so far:
import RPi.GPIO as GPIO
import time
from tkinter import *
from tkinter import ttk
import tkinter.font
GPIO.setwarnings(False)
Sig1 = 7
GPIO.setmode(GPIO.BOARD)
GPIO.setup(Sig1, GPIO.IN)
out1 = 11# pin11
GPIO.setmode(GPIO.BOARD) # We are accessing GPIOs according to their physical location
GPIO.setup(out1, GPIO.OUT) # We have set our LED pin mode to output
GPIO.output(out1, GPIO.LOW)
gui = Tk()
gui.title("tkinter")
gui.config(background = "gray86")
gui.minsize(1050,620)
Font1 = tkinter.font.Font(family = 'Courier 10 Pitch', size = 20, weight = 'bold')
Font2 = tkinter.font.Font(family = 'Courier 10 Pitch', size = 18, weight = 'bold')
Font3 = tkinter.font.Font(family = 'Courier 10 Pitch', size = 9, weight = 'bold')
def func1_on():
GPIO.output(out1, GPIO.HIGH) # led on
Text1 = Label(gui,text=' ON ', font = Font2, bg = 'gray84', fg='green3', padx = 0)
Text1.grid(row=8,column=1)
def func1_off():
GPIO.output(out1, GPIO.LOW) # led off
Text2 = Label(gui,text='OFF', font = Font2, bg = 'gray84', fg='red', padx = 0)
Text2.grid(row=8,column=1)
label_2 = Label(gui,text='Sensor:', font = Font2, fg='gray40', bg = 'gray84', padx = 10, pady = 10)
label_2.grid(row=6,column=0)
if GPIO.input(Sig1) == True:
Text3 = Label(gui,textvariable=' Active ',relief = "raised", font = Font2, bg = 'gray84', fg='green3', padx = 0)
Text3.grid(row=6,column=1)
else:
Text4 = Label(gui,textvariable=' Inactive ',relief = "raised", font = Font2, bg = 'gray84', fg='red', padx = 0)
Text4.grid(row=6,column=1)
Button1 = Button(gui, text='Switch On', font = Font3, command = func1_on, bg='gray74', height = 1, width = 7)
Button1.grid(row=8,column=0)
Button2 = Button(gui, text='Switch Off', font = Font3, command = func1_off, bg='gray74', height = 1, width = 7)
Button2.grid(row=9,column=0)
gui.mainloop()
it would be greatly appreciated if someone could help me with this.
Use root.after(milliseconds, function_name) run some function periodically.
This function should check sensors, update text in labels and use root.after to run again after some time.
BTW: function_name should be without ()
Minimal example. It updates label with current time
import tkinter as tk
import time
# --- functions ---
def check():
# update text in existing labels
label['text'] = time.strftime('%H:%M:%S')
# run again after 1000ms (1s)
root.after(1000, check)
# --- main ---
root = tk.Tk()
label = tk.Label(root)
label.pack()
check() # run first time
root.mainloop()
In my code I see that the Label is not being updated with the 'textvariable', despite I believe I'm doing it right (probably not!).
varmuTemperature = StringVar(value="default value")
self.Label = Label(Frame2, textvariable = varmuTemperature)
self.Label.pack()
This should show a label with "default value" written on it. The problem is that I don't see anything written.
I have my code posted here.
import matplotlib
import matplotlib.artist as artists
import matplotlib.pyplot as plt
#import matplotlib.mlab as mlab
import scipy.stats
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,
NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import numpy as np
import statistics
from tkinter import *
from tkinter import ttk
import serial
import time
import itertools
integer=0
xList = []
humidityList = []
humidityListHistogram = []
temperatureList = []
temperatureListHistogram = []
cnt=0
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
ser = serial.Serial()
style.use("seaborn-whitegrid")
#varmuTemperature = StringVar()
#varmuHumidity = StringVar()
f=plt.figure(0, figsize=(20,10))
humidityGraph = plt.subplot(224)
humidityGraph.set_title("Humidity vs Time")
humidityGraph.set_ylabel("Humidity RAW (Dec)")
humidityGraph.set_xlabel("Sample ()")
temperatureGraph = plt.subplot(223)
temperatureGraph.set_title("Temperature vs Time")
temperatureGraph.set_ylabel("Temperature RAW (Dec)")
temperatureGraph.set_xlabel("Sample ()")
humidityGraphHistogram = plt.subplot(222)
temperatureGraphHistogram = plt.subplot(221)
temperatureGraphHistogramNormal = temperatureGraphHistogram.twinx()
humidityGraphHistogramNormal = humidityGraphHistogram.twinx()
side_text = plt.figtext(0.93, 0.5, 'Text 1'+'\n'+'Text 2', bbox=dict(facecolor='white'))
plt.subplots_adjust(left = 0.05, right = 0.95, bottom = 0.05, top = 0.95, wspace = 0.16, hspace = 0.21)
class make_window():
def __init__(self, *args, **kwargs):
win = Tk()
win.title("Test")
win.state("zoomed")
Frame1 = Frame(win)
Frame1.pack()
self.comboBoxAvailableCOMPort = ttk.Combobox(Frame1, width = 30)
self.comboBoxAvailableCOMPort['values'] = []
self.comboBoxAvailableCOMPort.pack(padx=5, pady=5, side = LEFT)
self.buttonCheckComAvailable = Button(Frame1, text="Check COM Available", command = self.CheckComAvailable)
self.buttonCheckComAvailable.pack(padx=5, pady=10, side = LEFT)
self.buttonOpenCOMPort = Button(Frame1, text="Open COM Port", command = self.OnOpenCom)
self.buttonOpenCOMPort.pack(padx=5, pady=10, side = LEFT)
self.buttonCloseCOMPort = Button(Frame1, text="Close COM Port" , command = self.OnCloseCOM)
self.buttonCloseCOMPort.pack(padx=5, pady=10,side = LEFT)
self.CheckComAvailable()
Frame2 = Frame(win, highlightbackground = "red", highlightcolor = "red", highlightthickness = 1)
Frame2.pack()
varmuTemperature = StringVar(value="default value")
varmuTemperature.set("trerta")
print(varmuTemperature.get())
self.Label = Label(Frame2, textvariable = varmuTemperature)
self.Label.pack()
self.buttonCloseProgram = Button(Frame2, text="Close Program", command = self.OnCloseProgram)
self.buttonCloseProgram.pack(expand=True, fill='x', anchor='s')
Frame3 = Frame(win)
Frame3.pack()
canvas = FigureCanvasTkAgg(f, Frame3)
canvas.get_tk_widget().pack(padx=5, pady=10, side=BOTTOM, expand = True)
toolbar = NavigationToolbar2Tk(canvas, Frame3)
toolbar.update()
canvas._tkcanvas.pack(padx=5, pady=10,side = TOP)
def CheckComAvailable(self):
self.comboBoxAvailableCOMPort['values'] =[]
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
self.comboBoxAvailableCOMPort['values'] += tuple(result)
self.comboBoxAvailableCOMPort.set(result[0])
def OnOpenCom(self):
ser.baudrate = 115200
ser.port = self.comboBoxAvailableCOMPort.get()
try:
ser.open()
ser.readline()
ser.write("#dut,0$\n".encode('utf-8'))
ser.readline()
ser.write("#v,1800,1800$\n".encode('utf-8'))
ser.write("#W,77,08,07$\n".encode('utf-8'))
ser.readline()
except(OSError):
print("COM Port in use")
def OnCloseCOM(self):
global xList
global humidityList
global temperatureList
global humidityListHistogram
global temperatureListHistogram
global integer
integer=0
xList = []
humidityList = []
temperatureList = []
ser.close()
def OnCloseProgram(self):
self.OnCloseCOM()
exit()
## def toggle_geom(self,event):
## geom=self.master.winfo_geometry()
## print(geom,self._geom)
## self.master.geometry(self._geom)
## self._geom=geom
def animate(i):
global integer
global cnt
try:
ser.write(("#R,77,00,03$" + chr(10)).encode('utf-8'))
humidityLine=ser.readline()
inthumidityLine= int(humidityLine,16)
if (inthumidityLine > 8388608):
inthumidityLine = inthumidityLine - 16777216
humidityList.append(inthumidityLine)
humidityListHistogram.append(inthumidityLine)
ser.write(("#R,77,03,03$" + chr(10)).encode('utf-8'))
temperatureLine=ser.readline()
LineHistogram = temperatureLine
inttemperatureLine= int(temperatureLine,16)
if (inttemperatureLine > 8388608):
inttemperatureLine = inttemperatureLine - 16777216
temperatureList.append(inttemperatureLine)
temperatureListHistogram.append(inttemperatureLine)
xList.append(integer)
integer+=1
##################################################################################################################
## Creates the HUMIDITY Graphics
##################################################################################################################
humidityGraph.clear()
humidityGraph.plot(xList,humidityList,'-b*', label = "Humidity RAW")
humidityGraph.legend(loc='upper right', fancybox = True, frameon = True, shadow = True)
humidityGraph.set_title("Humidity vs Time")
humidityGraph.set_ylabel("Humidity RAW (Dec)")
humidityGraph.set_xlabel("Sample ()")
muHumidity = statistics.mean(humidityListHistogram)
#print("Mean = " + str(muHumidity) + " ; N = " + str(len(humidityListHistogram)))
#global varmuHumidity
#varmuHumidity.set("Humidity: ")
if (len(humidityListHistogram) > 1):
sigmaHumidity = statistics.pstdev(humidityListHistogram)
else:
sigmaHumidity = 100
humidityGraphHistogram.clear()
nHumidity, binsHumidity, patchesHumidity = humidityGraphHistogram.hist(humidityListHistogram, 100, density=False, facecolor='blue', alpha=0.75, histtype = 'stepfilled')
normalDistHumidity = scipy.stats.norm.pdf(binsHumidity, muHumidity, sigmaHumidity)
humidityGraphHistogramNormal.clear()
humidityGraphHistogramNormal.plot(binsHumidity, normalDistHumidity, 'r--')
humidityGraphHistogram.set_title("Histogram for Humidity Data")
humidityGraphHistogram.set_ylabel("Humidity RAW Counts (Dec)")
humidityGraphHistogram.set_xlabel("BINS ()")
humidityGraphHistogramNormal.set_ylabel("Normal Distribution")
##################################################################################################################
## Creates the TEMPERATURE Graphics
##################################################################################################################
temperatureGraph.clear()
temperatureGraph.plot(xList,temperatureList,'-r*', label = "Temperature RAW")
temperatureGraph.legend(loc='upper right', fancybox = True, frameon = True, shadow = True)
temperatureGraph.set_title("Temperature vs Time")
temperatureGraph.set_ylabel("Temperature RAW (Dec)")
temperatureGraph.set_xlabel("Sample ()")
muTemperature = statistics.mean(temperatureListHistogram)
#global varmuTemperature
#varmuTemperature.set("Temperature: " )
if (len(temperatureList) > 1):
sigmaTemperature = statistics.pstdev(temperatureListHistogram)
else:
sigmaTemperature = 100
temperatureGraphHistogram.clear()
nTemperature, binsTemperature, patchesTemperature = temperatureGraphHistogram.hist(temperatureListHistogram, 100, density=False, facecolor='red', alpha=0.75, histtype = 'stepfilled')
normalDistTemperature = scipy.stats.norm.pdf(binsTemperature, muTemperature, sigmaTemperature)
temperatureGraphHistogramNormal.clear()
temperatureGraphHistogramNormal.plot(binsTemperature, normalDistTemperature, 'b--')
temperatureGraphHistogram.set_title("Histogram for Temperature Data")
temperatureGraphHistogram.set_ylabel("Temperature RAW Counts (Dec)")
temperatureGraphHistogram.set_xlabel("BINS ()")
temperatureGraphHistogramNormal.set_ylabel("Normal Distribution")
if (cnt > 100):
xList.pop(0)
humidityList.pop(0)
temperatureList.pop(0)
cnt+=1
except(OSError):
bla=0
win = make_window()
ani = animation.FuncAnimation(f, animate, interval = 300)
make_window.mainloop()
Debugging a bit and start commenting lines of code, I see that the problem may come from the
f=plt.figure(0, figsize=(20,10))
Commenting this line (and all dependencies of this) makes the Label to be written.
Can someone help here, please? I don't get why the graphics can interfere in the Label.
Thanks a lot.
The general problem seems to be your management of instance variables and objects. You keep around as self.* variables, things you'll never need to reference again, like buttonCheckComAvailable, but fail to make self.* variables for things, like varmuTemperature, that you will need to reference later.
Object-wise, you do things that don't make sense:
make_window.mainloop()
as make_window is an object class, not an instance, and an instance of the class make_window won't respond to mainloop anyway as it contains a window but isn't one itself.
Here's my MCVE for your example code that makes varmuTemperature an instance variable and, just for demonstration purposes, sets it when the various buttons on the interface are clicked so you can see it's working:
from tkinter import *
from tkinter import ttk
class make_window():
def __init__(self):
self.win = Tk()
self.win.title("Test")
self.win.state("zoomed")
Frame1 = Frame(self.win)
self.comboBoxAvailableCOMPort = ttk.Combobox(Frame1, width=30)
self.comboBoxAvailableCOMPort['values'] = []
self.comboBoxAvailableCOMPort.pack(padx=5, pady=5, side=LEFT)
Button(Frame1, text="Check COM Available", command=self.CheckComAvailable).pack(padx=5, pady=10, side=LEFT)
Button(Frame1, text="Open COM Port", command=self.OnOpenCom).pack(padx=5, pady=10, side=LEFT)
Button(Frame1, text="Close COM Port", command=self.OnCloseCom).pack(padx=5, pady=10, side=LEFT)
Frame1.pack()
Frame2 = Frame(self.win, highlightbackground="red", highlightcolor="red", highlightthickness=1)
self.varmuTemperature = StringVar(value="default value")
Label(Frame2, textvariable=self.varmuTemperature).pack()
Button(Frame2, text="Close Program", command=self.OnCloseProgram).pack(expand=True, fill='x', anchor='s')
Frame2.pack()
def CheckComAvailable(self):
self.varmuTemperature.set("CheckCom")
def OnOpenCom(self):
self.varmuTemperature.set("OpenCom")
def OnCloseCom(self):
self.varmuTemperature.set("CloseCom")
def OnCloseProgram(self):
self.OnCloseCom()
exit()
window = make_window()
window.win.mainloop()
I am trying to make my variable on my label update, however have encountered a problem where the function of the buttons works by changing the temperature set up and down by 0.5 deg C however the labels on the temp and desired temp will not change with it.
I am working in python3.6
Here is my code, I was wondering if anyone may be able to help me please?
import os
import glob
import time
import RPi.GPIO as GPIO
from datetime import datetime
#Set gpio's
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(17,GPIO.OUT)#RED
GPIO.setup(22,GPIO.OUT)#GREEN
GPIO.setup(27,GPIO.OUT)#BLUE
#grab temp probe information
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
# Read temperature from device
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp():
lines=read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.1)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000
#temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c#, temp_f
temp = read_temp()
desiredtemp = 17
deg = u'\xb0'#utf code for degree
def increase():
global desiredtemp
desiredtemp = desiredtemp + 0.5
print(desiredtemp)
def decrease():
global desiredtemp
desiredtemp = desiredtemp - 0.5
print(desiredtemp)
#Tkinter start
from tkinter import *
root = Tk()
#code to add widgets will go here....
topFrame = Frame(root)
topFrame.pack(side=TOP)
middleFrame = Frame(root)
middleFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
#Set buttons
button1 = Button(bottomFrame, text="Increase (0.5"+ deg +"C)", fg="black", command=increase)
button2 = Button(bottomFrame, text="Decrease (0.5"+ deg +"C)", fg="black", command=decrease)
#use to put buttons on screen
button1.pack(side=LEFT)
button2.pack(side=LEFT)
#Set labels
label1 = Label(topFrame, text="Desired Temp = ", fg="black")
label2 = Label(middleFrame, text="Actual Temp = ", fg="black")
label3 = Label(topFrame, text=desiredtemp, fg="black")
label4 = Label(middleFrame, text=temp, fg="black")
#use to put labels on screen
label1.pack(side=LEFT)
label2.pack(side=LEFT)
label3.pack(side=LEFT)
label4.pack(side=LEFT)
root.mainloop()
#Tkinter End
# Open file to be logged
file = open("/home/pi/Desktop/Templog.csv", "a")
if os.stat("/home/pi/Desktop/Templog.csv").st_size == 0:
file.write("Date, Time, TemperatureSensor1\n")
# Continuous print loop
while True:
print(read_temp())
if(read_temp()<desiredtemp):
GPIO.output(17,GPIO.LOW)
GPIO.output(22,GPIO.HIGH)
else:
GPIO.output(17,GPIO.HIGH)
GPIO.output(22,GPIO.LOW)
now = datetime.now()
file.write(str(now.day)+"-"+str(now.month)+"-"+str(now.year)+","+str(now.hour)+":"+str(now.minute)+":"+str(now.second)+","+str(read_temp())+"\n")
file.flush()
time.sleep(1)
You can use StringVar to associate a string variable with a Label widget. You pass the StringVar to the Label as the textvariable keyword argument and in each button callback simply update the value of the temperature and the StringVar using its set method.
Example extending your own code:
import os
import glob
import time
from datetime import datetime
from tkinter import *
temp = 18
desiredtemp = 17
deg = u'\xb0' # utf code for degree
def increase():
global desiredtemp
desiredtemp += 0.5
tmpstr.set("%s" % desiredtemp)
def decrease():
global desiredtemp
desiredtemp -= 0.5
tmpstr.set("%s" % desiredtemp)
root = Tk()
topFrame = Frame(root)
topFrame.pack(side=TOP)
middleFrame = Frame(root)
middleFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
button1 = Button(bottomFrame, text="Increase (0.5"+ deg +"C)", fg="black", command=increase)
button2 = Button(bottomFrame, text="Decrease (0.5"+ deg +"C)", fg="black", command=decrease)
button1.pack(side=LEFT)
button2.pack(side=LEFT)
tmpstr = StringVar(value="%s" % desiredtemp)
label1 = Label(topFrame, text="Desired Temp = ", fg="black")
label2 = Label(middleFrame, text="Actual Temp = ", fg="black")
label3 = Label(topFrame, textvariable=tmpstr, fg="black")
label4 = Label(middleFrame, text=temp, fg="black")
label1.pack(side=LEFT)
label2.pack(side=LEFT)
label3.pack(side=LEFT)
label4.pack(side=LEFT)
root.mainloop()
Note that use of the global keyword is generally considered a code smell, which should make you consider placing all those elements into a class.