Posts: 6
Threads: 3
Joined: Sep 2020
I'm using Python3.8 for my raspberry pi4 project. I have a GUI that initially displays the label within a grid. I also have a button that when clicked, should display the calculated value of CO2 in the label. However, it does not display the CO2 value and there is no error flagged. Below is my code snippet (I removed others as they're not relevant to this question):
frame2 = Frame(root)
lblCo2 = Label(frame2, text="CO2 (ppm)")
lblCo2.grid(row=4, sticky=W)
valCo2 = Label(frame2, bg="white", width=12)
valCo2grid(row=4, column=1, sticky=W)
btnStart = Button(frame2, text="Start", command=btnStart_callback)
btnStart.grid(row=5, column=1, sticky=W)
frame2.pack()
def btnStart_callback():
CycleCO2()
def CycleCO2():
Cmd1 = [0xFE, 0x44, 0x00, 0x08, 0x02, 0x9F, 0x25)
high = Cmd1[3]
low = Cmd1[4]
co2 = (high*256) + low
valCo2 = tk.Label(frame2, text=co2) Appreciate any help.
Posts: 1,838
Threads: 2
Joined: Apr 2017
Since you've not shown all the code, one is having to guess a bit. On line 20, you assign to valCo2 , but then you never do anything with that variable. Do you need to redraw the frame or something?
Also, why do you need btnStart_callback ? Why not just pass CycleCO2 itself on line 7?
Posts: 12,024
Threads: 484
Joined: Sep 2016
In addition, make sure you add a grid statement to valCo2
Posts: 2,168
Threads: 35
Joined: Sep 2016
Post the bare minimum runnable code showing the problem at hand.
Dont use * imports see Namespace flooding with * imports
Create the label once and then change it's text value in the buttons event handler.
Use a class to easily keep a reference to GUI widgets.
See below code
import tkinter as tk
class Main:
def __init__(self, root):
self.frame = tk.Frame(root)
lblCo2 = tk.Label(self.frame, text="CO2 (ppm)")
lblCo2.grid(row=4, sticky=tk.W)
self.valCo2 = tk.Label(self.frame, bg="white", width=12)
self.valCo2.grid(row=4, column=1, sticky=tk.W)
btnStart = tk.Button(self.frame, text="Start",
command=self.on_btn_start)
btnStart.grid(row=5, column=1, sticky=tk.W)
self.frame.pack()
def on_btn_start(self):
Cmd1 = [0xFE, 0x44, 0x00, 0x08, 0x02, 0x9F, 0x25]
high = Cmd1[3]
low = Cmd1[4]
co2 = (high*256) + low
self.valCo2['text'] = co2
root = tk.Tk()
main = Main(root)
root.mainloop()
Posts: 6
Threads: 3
Joined: Sep 2020
Hi y'all,
This is my first post to this Forum, so I'm not sure how to respond individually. Also new to Python.
I've hooked up a CO2 sensor to the raspberry pi4 monitor. The app is supposed to read data from CO2 sensor. Eventually, I need to create a real-time line chart to show the data coming from the CO2 sensor. For now, I'm just trying to get a single CO2 reading and display it on the valCo2 label. I've written a desktop PC equivalent of this app using VB.Net language. I'm slowly trying to convert my codes to Python.
Here's my full code so far:
import serial, sys, glob, select
import time
import matplotlib.pyplot as plt
import tkinter as tk
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from tkinter import *
from tkinter import messagebox
from itertools import count
from matplotlib.animation import FuncAnimation
from pandas import DataFrame
#Create line chart data
co2Data = {"Time": [1920,1930,1940,1950,1960,1970,1980,1990,2000,2010],
"CO2 ppm": [9.8,12,8,7.2,6.9,7,6.5,6.2,5.5,6.3]
}
#Create a DataFrame
df = DataFrame(co2Data, columns=["Time", "CO2 ppm"])
#Create a display window
root = Tk()
root.wm_title("Soil CO2 Logger" )
root.geometry("800x480")
def btnStart_callback():
CycleCO2()
def btnExit_callback():
root.destroy()
#CO2 Sensor Functions
def CycleCO2():
#Connect to a serial port: serial device and baudrate
dev = "/dev/ttyUSB0"
scan = glob.glob(dev)
rate = "9600"
if(len(scan) == 0):
dev = '/dev/ttyUSB*'
scan = glob.glob(dev)
if(len(scan) == 0):
messagebox.showerror("Error","Unable to find any ports. Scanning for /dev/[ttyACM*|ttyUSB*]") + dev
sys.exit()
serport = scan[0]
if(len(sys.argv) > 1):
l = len(sys.argv) - 1
while( l > 0):
if(sys.argv[l][0] == '/'):
serport = sys.argv[l]
else:
l = l - 1
ser = serial.Serial(
port = serport,
baudrate = rate,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1)
Cmd1 = [0xFE, 0x44, 0x00, 0x08, 0x02, 0x9F, 0x25]
while True:
ser.flushInput()
ser.write(Cmd1)
time.sleep(1.9)
high = Cmd1[3]
low = Cmd1[4]
co2 = (high*256) + low
time.sleep(.1)
valCo2 = tk.Label(frame2, text = str(co2) )
#Plot line chart
fig1 = plt.Figure(figsize=(5,4), dpi=100)
ax1 = fig1.add_subplot(111)
line1 = FigureCanvasTkAgg(fig1, root)
line1.get_tk_widget().pack(side=LEFT, fill=Y)
df = df[["Time", "CO2 ppm"]].groupby("Time").sum()
df.plot(kind="line", legend=True, ax = ax1, color = "b", marker = "o", fontsize = 10)
ax1.set_title("CO2 ppm vs. Time")
frame1 = Frame(root)
lblReadings = Label(frame1, text="CO2 Readings")
lblReadings.grid(row=0, column=0, sticky=W)
lboxResult = Listbox(frame1, width=35)
lboxResult.grid(row=1, sticky=W)
frame1.pack()
frame2 = Frame(root)
lblCoffee = Label(frame2, text="Coffee Break:")
lblCoffee.grid(row=0, sticky=W)
entCoffee = Entry(frame2, width= 12)
entCoffee.grid(row=0, column=1, sticky=W)
lblSample = Label(frame2, text="Sample #:")
lblSample.grid(row=1, sticky=W)
entSample = Entry(frame2, width= 12)
entSample.grid(row=1, column=1,sticky=W)
lblTestTime = Label(frame2, text="Test Time (hh:mm:ss)")
lblTestTime.grid(row=2, sticky=W)
entTestTime = Entry(frame2, width= 12)
entTestTime.grid(row=2, column=1, sticky=W)
lblPeakTime = Label(frame2, text="Countdown to Peak Time")
lblPeakTime.grid(row=3, sticky=W)
entPeakTime = Entry(frame2, width= 12)
entPeakTime.grid(row=3, column=1, sticky=W)
lblCo2 = Label(frame2, text="CO2 (ppm)")
lblCo2.grid(row=4, sticky=W)
valCo2 = Label(frame2, bg="white", width=12)
valCo2.grid(row=4, column=1, sticky=W)
lblPeakCaptured = Label(frame2, text="Peak Captured @ 30-second")
lblPeakCaptured.grid(row=5, sticky=W)
entPeakCaptured = Entry(frame2, width= 12)
entPeakCaptured.grid(row=5, column=1, sticky=W)
frame2.pack()
frame3 = Frame(root)
img = PhotoImage(file="off_bulb.png")
canvas = Canvas(frame3, width=70, height=70)
canvas.create_image(10,10, anchor=NW, image=img)
canvas.pack()
canvas.grid(row=0, column=0, sticky=W)
btnStart = Button(frame3, text="Start", command=btnStart_callback)
btnStart.grid(row=0, column=1, sticky=W)
btnStop = Button(frame3, text="Stop")
btnStop.grid(row=0, column=2, sticky=W)
btnExit = Button(frame3, text="Exit", command=btnExit_callback)
btnExit.grid(row=0, column=3, sticky=W)
frame3.pack()
root.mainloop()
Posts: 6
Threads: 3
Joined: Sep 2020
I wanted to check Yoriz' suggestion as having helped me a lot. I wasn't using classes, so that's a step in the right direction. However, there's no button on this site to select the suggestion that helps (unlike in other forum sites, e.g., Microsoft Developers Network).
I added a reputation point to Yoriz, just to show my gratitude.
I haven't fully solved this yet. It's not posting the value to the label but funny, when I add a messagebox just to see if there's a value read from the sensor, the value is then posted to the label when I click the "OK" button on the messagebox. Obviously, I still need to work on this.
But I followed Yoriz's advise to create classes to make it easier and I'm getting there.
Thanks.
Posts: 6,779
Threads: 20
Joined: Feb 2020
You don't like the Rep or Like buttons that appear at the bottom of every post?
Unlike stackoverflow, this forum thinks the participants can make up their own mind about what answers are good and which are bad. It is very Pythonic.
Posts: 6
Threads: 3
Joined: Sep 2020
Okay. I got it to work:
1. I removed the "while true" statement in the CycleCO2 function.
2. I replaced the following statement:
valCo2 = tk.Label(frame2, text = str(co2) )
with
self.valCo2.config(text = co2) Now it displays the value when click the "Start" button.
|