Raspberry Pi Python循环停止工作



i操作一个传感器:HC SR04来捕捉距离。我是Python和RPI的新手。我的代码工作,我捕捉一段时间内的距离,但有一刻脚本停止了。。。

我的代码:

GPIO.setmode(GPIO.BCM)
GPIO_TRIGGER = 23
GPIO_ECHO = 24
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
def main():
    global state
    print("ultrasonic")
    while True:
        print "1s second refresh.."
        time.sleep(1)
        i = 0
        datas = []
        average = 0
        while i< 1:
            GPIO.output(GPIO_TRIGGER, False)
            time.sleep(C.time['count'])
            GPIO.output(GPIO_TRIGGER, True)
            time.sleep(0.00001)
            GPIO.output(GPIO_TRIGGER, False)
            while GPIO.input(GPIO_ECHO) == 0:
                start = time.time()
            while GPIO.input(GPIO_ECHO) == 1:
                stop = time.time()
            distance = (stop-start) * 17000
            print "Distance : %.1f" % distance
        average = F.getAverage(datas)
        print "Average: %.1f" % average
    GPIO.cleanup()

代码在此停止

while GPIO.input(GPIO_ECHO) == 0:
                start = time.time()

解决方案:带样本超时:

now = time()
while GPIO.input(self.gpio_echo) == 0 and time()-now<waitTime:
    pass

我也在摆弄这个传感器。我的代码执行与您的代码类似,不需要超时就可以工作。我能找到的一个区别是:

while i< 1:
        GPIO.output(GPIO_TRIGGER, False)
        time.sleep(C.time['count'])

我不知道这里的睡眠时间有多长,但可能是这个问题的原因。如果它与我的设置类似,那么将触发器设置为false将直接在设置输入/输出引脚之后,然后需要两秒钟的时间来消除噪声。我不知道你的等待时间可能会更短。在发送脉冲之前,不需要再次将触发器设置为false,我不知道,但这可能会导致错误启动。我会把它改成这样,以类似于我的工作方式,然后在while循环中删除设置为false。

GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
GPIO.output(GPIO_TRIGGER, False)
print("Waiting for sensor to settlen")
time.sleep(2)

我不确定这是否能在不需要暂停的情况下解决问题,但我似乎不需要。


我已经编写了一个模块,用于制作传感器对象,然后允许一些更可读的脚本。我对python也很陌生,也不是一个经验丰富的程序员,所以有些地方可能会出现有趣的错误,但如果你想使用它或只是比较代码,它就在下面:

#! /usr/bin/python3
# dist.py this is a module for objectifying an ultrasonic distance sensor.
import RPi.GPIO as GPIO
import time

class Distancer(object):
    #init takes an input of one GPIO for trigger and one for echo and creates the object,
    #it searches for a calibration file in the working directory (name)Const.txt, if none
    #is found it will initiate a calibration
    def __init__(self, trig, cho, name):
        self.trigger = trig
        self.echo = cho
        self.name = name
        self.filename = self.name + 'Const.txt'
        GPIO.setup(self.trigger, GPIO.OUT)
        GPIO.setup(self.echo, GPIO.IN)
        GPIO.output(self.trigger, False)
        print("Waiting for sensor to calm down")
        time.sleep(2)
        try:
            with open(self.filename, "r") as inConst:
                self.theConst = int(inConst.read())
        except (OSError, IOError) as e:
            print("Not calibrated, initializing calibration")
            self.calibrate()
            with open(self.filename, "r") as inConst:
                self.theConst = int(inConst.read())

    #Returns the echo time
    def measureTime(self):
        GPIO.output(self.trigger, True)
        time.sleep(0.00001)
        GPIO.output(self.trigger, False)
        while GPIO.input(self.echo) == 0:
            pulse_start = time.time()
        while GPIO.input(self.echo) == 1:
            pulse_end = time.time()
        pulse_duration = pulse_end - pulse_start
        return pulse_duration

    #Returns a distance in cm        
    def measure(self):  
        return self.measureTime() * self.theConst

    #Makes you set up the sensor at 3 different distances in order to find the
    #relation between pulse time and distance, it creates the file (name)Const.txt
    #in the working directory and stores the constant there.
    def calibrate(self):
        ten = []
        thirty = []
        seventy = []
        print("Make distance 10 cm, enter when ready")
        input()
        for i in range(30):
            ten.append(10/self.measureTime())
            time.sleep(0.2)
        print("Make distance 30 cm, enter when ready")
        input()
        for i in range(30):
            thirty.append(30/self.measureTime())
            time.sleep(0.2)
        print("Make distance 70 cm, enter when ready")
        input()
        for i in range(30):
            seventy.append(70/self.measureTime())
            time.sleep(0.2)
        allTime = ten + thirty + seventy
        theOne = 0.0
        for i in range(90):
            theOne = theOne + allTime[i]
        theOne = theOne / 90
        with open(self.filename, "w") as inConst:
                inConst.write(str(round(theOne)))

    #Will continually check distance with a given interval until something reaches the
    #treshold (cm), takes an argument to set wether it should check for something being
    #nearer(near) or farther(far) than the treashold. Returns True when treshold is reached. 
    def distWarn(self, nearfar, treashold):
        if nearfar.lower() == "near":
            while True:
                if self.measure() < treashold:
                    return True
                    break
                time.sleep(0.2)
        if nearfar.lower() == "far":
            while True:
                if self.measure() > treashold:
                    return True
                    break
                time.sleep(0.2)             

    #Will measure with a second interval and print the distance
    def keepGoing(self):
        while True:
            try:
                print(str(round(self.measure())) + ' cm')
                time.sleep(1)
            except KeyboardInterrupt:
                print("Won't keep going")
                break

我用下面的代码运行了它来测试它,一切似乎都正常。第一次运行时,它会提示您通过将传感器放置在与某个物体不同的距离来校准传感器。

#! /usr/bin/python3
import RPi.GPIO as GPIO
import time
import dist as distancer
GPIO.setmode(GPIO.BOARD)
TRIG = 16
ECHO = 18
dist = distancer.Distancer(TRIG, ECHO, 'dist')
def main():
    global dist
    print(str(round(dist.measureTime(),5)) + ' s')  
    print(str(round(dist.measure())) + ' cm')
    dist.distWarn('near', 10)
    print('Warning, something nearer than 10 cm at ' + time.asctime( time.localtime(time.time()) ))
    dist.distWarn('far', 10)
    print('Warning, something further than 10 cm at ' + time.asctime( time.localtime(time.time()) ))

    dist.keepGoing()
    GPIO.cleanup()
    print('Fin')

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        GPIO.cleanup()
        print("Exiting")
        time.sleep(1)

我很确定你想要

while GPIO.input(GPIO_ECHO)==GPIO.LOW:
    start = time.time()
while GPIO.input(GPIO_ECHO) == GPIO.HIGH:
    stop = time.time()

我不认为GPIO.input自然会返回0或1,不过你可以测试一下。

不是,我想我丢失了信号,我会在中尝试超时

while GPIO.input(GPIO_ECHO)==GPIO.LOW:
    start = time.time()

我认为我的程序无限期地等待一个信号,但他停留在0

我知道这是个老问题。此问题中描述了问题的原因https://raspberrypi.stackexchange.com/questions/41159/...

解决方案是像OP一样,向类似于以下内容的while循环添加超时:

# If a reschedule occurs or the object is very close
# the echo may already have been received in which case
# the following will loop continuously.
count=time.time()
while GPIO.input(GPIO_ECHO)==0 and time.time()-count<0.1:
   start = time.time()

# if an object is not detected some devices do not
# lower the echo line in which case the following will
# loop continuously.
stop = time.time()
count=time.time()
while GPIO.input(GPIO_ECHO)==1 and time.time()-count<0.1:
   stop = time.time()

最新更新