使用超声波传感器检查距离的功能可冻结Tkinter

时间:2019-02-11 12:54:10

标签: python tkinter

我正在尝试使用带有超声波传感器的python来测量距离,然后每秒用距离值更新tkinter标签。但是,我遇到了问题。它会运行一段时间,从几秒钟到几分钟不等,然后冻结。

这是我的代码:

from tkinter import *
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO_TRIGGER_X = 4
GPIO_ECHO_X = 27
GPIO.setup(GPIO_TRIGGER_X, GPIO.OUT)
GPIO.setup(GPIO_ECHO_X, GPIO.IN)

def distanceX():

    GPIO.output(GPIO_TRIGGER_X, True)
    time.sleep(0.0001)
    GPIO.output(GPIO_TRIGGER_X, False)

    StartTime = time.time()
    StopTime = time.time()

    while GPIO.input(GPIO_ECHO_X) == 0:
        StartTime = time.time()

    while GPIO.input(GPIO_ECHO_X) == 1:
        StopTime = time.time()

    TimeElapsed = StopTime - StartTime
    distance = (TimeElapsed * 34300) / 2

    return distance

def updateDistance():
        dX = distanceX()
        print(dX)
        lengthValue.configure(text=dX)
        root.after(1000, updateDistance)

root = Tk()

root.geometry("200x100")
root.tk_setPalette(background="white", foreground="black")

lengthName = Label(root, text = "Length:")
lengthValue = Label(root, text="start")

lengthName.grid(row=1, column=1)
lengthValue.grid(row=1, column=2)

updateDistance() 
root.mainloop()

我尝试在单独的脚本中单独运行distanceX(),仅打印出值,效果很好。我也尝试过在没有distanceX()的情况下运行脚本,如下所示:

dX = 0

def updateDistance():
        global dX
        print(dX)
        lengthValue.configure(text=dX)
        dX += 1
        root.after(1000, updateDistance)

..也可以正常工作。

有什么想法吗? 如果我没有提供任何必要的信息,请提前道歉,这是我第一次尝试使用python和tkinter ...

2 个答案:

答案 0 :(得分:0)

Tkinter是单线程的。您在函数<?php header("Location: http://localhost/Rocket/includes/thankYou.php"); include('connection.php'); if(isset($_POST['addForm'])) { $fullName = $_POST['fullName']; $email = $_POST['email']; $mobile = $_POST['mobile']; $dob = $_POST['dob']; $degree = $_POST['degree']; $expYears = $_POST['expYears']; $position = $_POST['jobPosition']; $whyHire = $_POST['whyHire']; $uploadCV = $_POST['uploadCV']; $dateApplied = $_POST['dateApplied']; $db = new Database(); $db->connect(); $db->insert('users',array('fullName'=>$fullName,'email'=>$email, 'mobile'=>$mobile, 'dob'=>$dob, 'degree'=>$degree, 'expYears'=>$expYears, 'position'=>$position, 'whyHire'=>$whyHire, 'uploadCV'=>$uploadCV, 'dateApplied'=>$dateApplied)); // Table name, column names and respective values $res = $db->getResult(); print_r($res); if($res) { echo "Sent to DB"; die(); } else { echo "query error"; } } 中的while循环将阻塞主线程,直到它接收到True值并继续执行该函数的其余部分为止。这就是为什么您遇到冻结的原因。

尝试运行以下内容:

distanceX

您将看到由于While循环阻塞了主线程,您的Tk窗口甚至没有弹出。

要解决此问题,您需要对from tkinter import * import time root = Tk() flag = True def something(): global flag while flag: print ("Hello World") time.sleep(1) def set_flag(): global flag flag = False something() root.after(2000,set_flag) root.mainloop() 函数进行线程化。像这样:

distanceX()

您可以在here中阅读有关线程的更多信息。

答案 1 :(得分:0)

发现问题实际上是while中的两个distanceX()循环。都添加了超时,一切都很好。工作代码:

from tkinter import *
import RPi.GPIO as GPIO
import threading, time

GPIO.setmode(GPIO.BCM)
GPIO_TRIGGER_X = 4
GPIO_ECHO_X = 27
GPIO.setup(GPIO_TRIGGER_X, GPIO.OUT)
GPIO.setup(GPIO_ECHO_X, GPIO.IN)

def distanceX():

    while True:
         timeout = time.time() + 0.1
         GPIO.output(GPIO_TRIGGER_X, True)
         time.sleep(0.0001)
         GPIO.output(GPIO_TRIGGER_X, False)

         StartTime = time.time()
         StopTime = time.time()

         while GPIO.input(GPIO_ECHO_X) == 0:
            StartTime = time.time()
            if time.time() > timeout:
                break

         while GPIO.input(GPIO_ECHO_X) == 1:
            StopTime = time.time()
            if time.time() > timeout:
                break

         TimeElapsed = StopTime - StartTime
         distance = (TimeElapsed * 34300) / 2

         print(distance)
         lengthValue.configure(text=distance)

         time.sleep(1)

def check():
    print("All good")


root = Tk()

root.geometry("200x100")
root.tk_setPalette(background="white", foreground="black")

lengthName = Label(root, text = "Length:")
lengthValue = Label(root, text="start")
button = Button(root, text="Check", command=check)

lengthName.grid(row=1, column=1)
lengthValue.grid(row=1, column=2)
button.grid(row=2, column=1)

t1 = threading.Thread(target=distanceX)
t1.start()
root.mainloop()