shramik
Posts: 22
Joined: Sat Jan 07, 2017 11:31 am

unboundlocalerror local variable 'start' referenced before assignment

Thu Dec 07, 2017 5:25 pm

i am running a python script on my raspberry pi to detect presence of human using ultrasonic sensor. it works for some time and suddenly i get this error "unboundlocalerror local variable 'start' referenced before assignment"

Code: Select all

#!/usr/bin/python
# -*- coding: utf-8 -*-

import RPi.GPIO as gpio
import time


class Sensor(object):
    def __init__(self, trig = 0, echo = 0, name = "Name"):
        self.trig = trig
        self.echo = echo
        self.name = name

        gpio.setmode(gpio.BCM)
        gpio.setwarnings(False)

        gpio.setup(self.trig, gpio.OUT)
        gpio.setup(self.echo, gpio.IN)

        gpio.output(self.trig, False)

        print ("Waiting For Sensor To Settle")
        time.sleep(1)


    def sense(self):
        gpio.output(self.trig, True)
        time.sleep(0.00001)
        gpio.output(self.trig, False)

        while gpio.input(self.echo) == 0:
            start = time.time()
        while gpio.input(self.echo) == 1:
            end = time.time()

        duration = end - start
        distance = duration * 17150

        return round(distance, 2)

    def end(self):
        gpio.cleanup()
above code is saved as USSensor,py and imported in main program below.

Code: Select all

import USSensor
from time import sleep

sensor_1 = USSensor.Sensor(24, 25, "Front")

while True:
            mm = sensor_1.sense()
            time.sleep(0.2)
            if mm > 1 and mm < 70:
                print("motion detected 2")
                print(mm)

User avatar
thagrol
Posts: 319
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK

Re: unboundlocalerror local variable 'start' referenced before assignment

Thu Dec 07, 2017 5:43 pm

Your "sense" method is probably being called when the GPIO is high and so "start" never gets set.

shramik
Posts: 22
Joined: Sat Jan 07, 2017 11:31 am

Re: unboundlocalerror local variable 'start' referenced before assignment

Thu Dec 07, 2017 6:04 pm

thank you sir,
so how can i avoid this?

User avatar
thagrol
Posts: 319
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK

Re: unboundlocalerror local variable 'start' referenced before assignment

Thu Dec 07, 2017 9:22 pm

shramik wrote:
Thu Dec 07, 2017 6:04 pm
thank you sir,
so how can i avoid this?

Quick and dirty: Change your sense method to

Code: Select all

 def sense(self):
        gpio.output(self.trig, True)
        time.sleep(0.00001)
        gpio.output(self.trig, False)

        start = time.time()
        while gpio.input(self.echo) == 1:
            pass
        end = time.time()

        duration = end - start
        distance = duration * 17150

        return round(distance, 2)
I'm assuming your code sends a pulse, waits for an echo and uses the elapsed time to estimate distance. I'm also assuming that your input pin is pulled low when not recieving an echo.

As originally written it will never give an acurate reading. Your code constantly resets "start" until the echo arrives so duration will always be the time it takes python to execute one pass through each while loop regardless of how long the echo takes.

A better approach might be to use a property to return distance coupled with a worker thread to send pings and a callback to detect the echo and do the calculation.

shramik
Posts: 22
Joined: Sat Jan 07, 2017 11:31 am

Re: unboundlocalerror local variable 'start' referenced before assignment

Fri Dec 08, 2017 8:15 am

is there a way i can use try except to avoid this unnboundlocalerror every time it occurs so that the script keeps on running continuously.

shramik
Posts: 22
Joined: Sat Jan 07, 2017 11:31 am

Re: unboundlocalerror local variable 'start' referenced before assignment

Fri Dec 08, 2017 10:50 am

can someone help me out of this.. in real need to solve this error.

User avatar
elParaguayo
Posts: 1905
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: unboundlocalerror local variable 'start' referenced before assignment

Fri Dec 08, 2017 12:41 pm

I don't think you should be using try...except... here. Thagrol's approach looks more sensible to me. Did you try it?
Last edited by elParaguayo on Fri Dec 08, 2017 7:42 pm, edited 1 time in total.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

User avatar
thagrol
Posts: 319
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK

Re: unboundlocalerror local variable 'start' referenced before assignment

Fri Dec 08, 2017 2:19 pm

shramik wrote:
Fri Dec 08, 2017 8:15 am
is there a way i can use try except to avoid this unnboundlocalerror every time it occurs so that the script keeps on running continuously.
Yes but it's not an approach I'd recommend.

Again this is quick and dirty:

Code: Select all

def sense(self):
        gpio.output(self.trig, True)
        time.sleep(0.00001)
        gpio.output(self.trig, False)

        while gpio.input(self.echo) == 0:
            start = time.time()
        while gpio.input(self.echo) == 1:
            end = time.time()

        try:
            duration = end - start
        except:
            duration = 0 # change '0' as apropriate for your use case
            
        distance = duration * 17150

        return round(distance, 2)

shramik
Posts: 22
Joined: Sat Jan 07, 2017 11:31 am

Re: unboundlocalerror local variable 'start' referenced before assignment

Fri Dec 08, 2017 6:14 pm

thank you so much sir. it is working good so far.

User avatar
thagrol
Posts: 319
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK

Re: unboundlocalerror local variable 'start' referenced before assignment

Fri Dec 08, 2017 6:54 pm

Working yes. Working good not so much.

I can't stress enough that you really should rethink how you're doing this.

As I mentioned above, the value you get for duration is likely to be the same regardless of how long it takes for the echo to be detected as you're constantly resetting the start time until the echo arrives. You need to set "start" once when you trigger the ping rather than keep reseting it until the echo arrives.

Another, perhaps more major, issue is that your entire script will block waiting for the echo, if it never arrives your sense method will never return.

Both my suggestions above are quick and dirty in that they'll work under ideal conditions but will likely fail in unknown and interesting ways outside them.

shramik
Posts: 22
Joined: Sat Jan 07, 2017 11:31 am

Re: unboundlocalerror local variable 'start' referenced before assignment

Sat Dec 09, 2017 4:26 am

sir, now the script goes into a infinite loop and uses entire CPU usage and hangs the system. is there any other code to find the distance using ultrasonic sensor.

User avatar
elParaguayo
Posts: 1905
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: unboundlocalerror local variable 'start' referenced before assignment

Sat Dec 09, 2017 7:11 am

What distance sensor are you using? The gpiozero library has code which could help
http://gpiozero.readthedocs.io/en/stabl ... nce-sensor
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

User avatar
thagrol
Posts: 319
Joined: Fri Jan 13, 2012 4:41 pm
Location: Darkest Somerset, UK

Re: unboundlocalerror local variable 'start' referenced before assignment

Sat Dec 09, 2017 11:50 am

shramik wrote:
Sat Dec 09, 2017 4:26 am
sir, now the script goes into a infinite loop and uses entire CPU usage and hangs the system. is there any other code to find the distance using ultrasonic sensor.
I did try to warn you of problems with your approach, including this one.

As elParaguayo suggested gpiozero might help but the quick and dirty fix would be to add a timeout to your while loops.

Without writing the code for you, this is one way do it:

Code: Select all

store time and start sending ultrasound
wait for echo to be detected or for maximum time to be exceeded
store time
stop sending ultrasound
calculate distance (half the elapsed time multiplied by some constant)
I'd also put this into a seperate thread started during your class' init method with a property that returns the most recent measurement.

As I mentioned above, your original code would never have given the correct distance. It's measuring the length of the pulse rather than the time taken for the echo to arrive. Your first while loop is uneccessary, you only need to store the start time once when you start sending ultrasound.

To reduce CPU load, use a callback function rather than a while loop to detect the incoming echo. See the documentation for your chosen gpio library for how to do this.(Hint: you'll need to use instance variables to store the start time, end time, and distance)

Edit:
The reason you're seeing an infinite loop is that that is what you've written. Your calling function has a "while True" loop which will never exit and which calls your sense method 5 times a second. This is componded by your sense method having two tight loops that may never exit.

You're using a very short pulse length: 0.00001 seconds. It's entirely possible given that linux is a multi-tasking system and that it takes time to execute any line of code that the entire pulse could be received and the gpio state be back to 0 before you even enter the first while loop. That same loop will never exit if the gpio never goes high (i.e. no echo is received).

Return to “Python”

Who is online

Users browsing this forum: No registered users and 19 guests