1

Im trying to build a temperature monitor using pyqt5 on a raspberry pi 3 with ds18b20 sensors attached. I am pretty new to python and pyqt5.

The Gui file (frameless.py) was developed with QT 4 designer. The Gui should serve as a basic example for a more enviromental sensors (e.g pH EC etc.) to be implemented. The actual code (runframeless.py) is shown below.

I am well aware that is is best to use threads (or Multithreading) if more senosor data are to be read at the same time, but currently I am stuck in a pretty simple problem.

Problem: The temperature is shown in the textlabel, but the temperature value in def read_temp(self) is not updated.

Question: Can anyone explain why it is not updated and help me getting the code right so that the temperature value shown in the gui is changed when the temperature acually changes?

runframeless.py

# -*- coding: utf-8 -*-
# file: runframeless.py)
#-create a skeleton class(es) for Raspberry Pi GUI-

# need this
import sys
import time
import datetime
import os
import glob
#----This gets the Qt stuff------------------------
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5 import QtWidgets

from PyQt5.QtCore import Qt

from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLabel


# Import QtCreator/qtdesigner file
import frameless

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '10*')[0]
device_file = device_folder + '/w1_slave'

#-------------------------------------------------
#----class(es) for our Raspberry Pi GUI-----------
#-------------------------------------------------

class MainWindow(QMainWindow, frameless.Ui_MainWindow): 
    def __init__(self):
        super(self.__class__, self).__init__()
        self.setupUi(self) # gets defined in the UI file

        self.label.setText(str(self.read_temp()))


        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.read_temp)
        self.timer.start()    

    def read_temp(self):
        f = open(device_file, 'r')
        lines = f.readlines()
        f.close()
        time.sleep(.1)
        while lines[0].strip()[-3:] != 'YES':
            time.sleep(.1)
            #lines = self.read_temp()
        equals_pos = lines[1].find('t=')
        if equals_pos != -1:
            temp_string = lines[1][equals_pos+2:]
            temp_c = float(temp_string) / 1000.0
            return temp_c


if __name__ == "__main__": 
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()

    sys.exit(app.exec_())

file: frameless.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'frameless.ui'
#
# Created: Tue Feb 27 17:31:49 2018
#      by: PyQt5 UI code generator 5.3.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        self.setWindowFlags(Qt.FramelessWindowHint) # frameless
        MainWindow.resize(800, 480)
        MainWindow.setStyleSheet("background:rgb(0, 0, 0);")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setStyleSheet("")
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(660, 430, 101, 31))
        self.pushButton.setStyleSheet("background: rgb(255, 255, 255) ")
        self.pushButton.setObjectName("pushButton")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(10, 170, 751, 41))
        self.widget.setObjectName("widget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label_2 = QtWidgets.QLabel(self.widget)
        self.label_2.setStyleSheet("background: rgb(255, 255, 255) ")
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setStyleSheet("background: rgb(255, 255, 255) ")
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        self.pushButton.clicked.connect(MainWindow.close)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "exit"))
        self.label_2.setText(_translate("MainWindow", "Ds18B20-sensor"))
        self.label.setText(_translate("MainWindow", "TextLabel"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
drk
  • 13
  • 3
  • It's not merely "best" to use threads. You *must* use either multi-threading or multi-processing (or equivalent) to avoid blocking the gui thread. There are [dozens of examples on SO](https://www.google.com/search?q=pyqt+thread+site:stackoverflow.com) that will show you how to do this. – ekhumoro Feb 27 '18 at 19:20
  • Actually the gui is not blocked at all , it is simply not updating the temperature value. that is why I am looking for a solution how to update the label before I start writing code that includes a thread or multithreading – drk Feb 27 '18 at 22:27

2 Answers2

1

When debugging code, it pays to logically step through how the program works.

Firstly, this line self.label.setText(str(self.read_temp())) runs once as it is in the __init__ method. This calls the self.read_temp() method which returns the temperature and places it in the text box.

Next, you create a QTimer in the __init__ method, which calls self.read_temp() every second. So when the timer triggers every second, self.read_temp is run, the temperature is read out, and returned to whatever internal code the QTimer uses to call your method.

At this point the QTimer throws away the return value because it doesn't want it, can't use it, etc.

As you can probably now see, the reason why it doesn't update is because you have never told it to update.

I would suggest adding the line self.label.setText(str(temp_c)) prior to the return temp_c line in order to update the label from the code that runs every second.

three_pineapples
  • 11,579
  • 5
  • 38
  • 75
  • Sorry for the late response - and thank you so much for explaining the program logic - which helps far more than throwing in a solution- your explanation makes perfect sense - and your suggestion works- I was just not smart enough to walk through the steps by myself. – drk Mar 01 '18 at 22:59
  • @drk You're welcome! It takes time to get used to thinking in the right way to understand how GUI programs work, but I'm sure you'll get there with practice! If this answer has solved your issue, please consider marking it as "accepted" by clicking the tick on the left hand side of my answer. Thanks and good luck with the rest of your program! – three_pineapples Mar 01 '18 at 23:36
0

I made a repository in github that contain a code in python and PyQt5 for temperature control (monitoring) whith raspberry Pi and ds18b20 sensor You can use that by following link https://github.com/salarshekari/ds18b20-raspberry-pyqt5 please do not forget star if you like that

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 11 '22 at 21:14
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/30794841) – Achxy_ Jan 15 '22 at 07:41