Функция проверки расстояния с помощью ультразвукового датчика замерзает tkinter - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь использовать 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 голосов
/ 12 февраля 2019

Оказывается, проблема в том, что на самом деле были две петли 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()
0 голосов
/ 11 февраля 2019

Tkinter однопоточный.Ваш цикл while в функции distanceX блокирует основной поток до тех пор, пока он не получит значение True и продолжит работу с остальной частью функции.Вот почему вы испытываете зависания.

Попробуйте выполнить следующее:

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()

И вы увидите, что ваше окно Tk даже не всплывает из-за цикла, блокирующего основной поток.

Чтобы решить эту проблему, вам нужно выполнить функцию distanceX().Примерно так:

from tkinter import *
import threading, time

root = Tk()
flag = True

def something():
    global flag
    while flag:
        print ("Hello world")
        time.sleep(1)

def set_flag():
    global flag
    flag = False

t = threading.Thread(target=something)
t.start()
root.after(2000,set_flag)
root.mainloop()

Подробнее о потоках вы можете прочитать в здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...