surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Ultrasonic sensor script hang up random

Thu Feb 20, 2014 6:40 pm

Hi all,
I have set up a little script that, after checking the distance with a ultrasonic sensor (HC-SR04), do the led blink if the distance is less of 8 cm.
My setup is made by 4 MCP23S17 chips with a 5v external power supply, connected to the raspberry with mosfets (SPI), and the ultrasonic sensor connected to one chip (with a resistor to pull down the echo pin).

Everything works really well exept 2 things.

1- If I don't insert this: 'stop = time.time()' as first line of 'def measure()' I have this error (but not always....just random.... :shock: ):

python UnboundLocalError: local variable 'stop' referenced before assignment

I have copy/paste this script from http://www.raspberrypi-spy.co.uk/2013/0 ... n-part-2/' .... so I think that it must works well... and the error is random.... really strange.....

2- The script after run for a while (5 minutes....10 minutes) hang up....2/3 /10 minutes (no error messages), and after, start again to works.... really, really extrange.....
When the process hang up, the cpu use go at 50%.... Normally is it at 1% level
.

Could be these problems related to the SPI buffer or the frequency of the MCP23S17 that it is not enough?

edit: I have change this value in the mcp23s17.c file:

from
#define MCP_SPEED 4000000
to
#define MCP_SPEED 10000000

Now my chips speed is 10Mhz? Correct? ...or I need to do something else?

I'm testing it..... I will give you a feedback in 1 hour..


Edit2: Doesn't works.... :x

Please help me, because I don't really know how to fix it :?
Thank you in advance

Code: Select all

import wiringpi2 as wiringpi
from time import sleep
import time


wiringpi.wiringPiSetup()           # initialise wiringpi
wiringpi.mcp23s17Setup(65,0,0)     # set up the pins, spi port, address (mcp23s17-0)
wiringpi.mcp23s17Setup(81,0,1)     # set up the pins, spi port, address (mcp23s17-1)
wiringpi.mcp23s17Setup(97,1,0)
wiringpi.mcp23s17Setup(113,1,1)


wiringpi.pinMode(104,0)    
wiringpi.digitalWrite(104,0)
wiringpi.pinMode(119,0)
wiringpi.digitalWrite(119,0)


wiringpi.pinMode(72,1)   
wiringpi.digitalWrite(72,0) 
wiringpi.pinMode(121,1)    
wiringpi.digitalWrite(121,0)
wiringpi.pinMode(88,1)  
wiringpi.digitalWrite(88,0)
wiringpi.pinMode(128,0)
wiringpi.pinMode(127,1)
wiringpi.digitalWrite(127,0)
GPIO_TRIGGER = 127
GPIO_ECHO    = 128


def blinking_led1_button1_er1():
      wiringpi.digitalWrite(88,1)
      wiringpi.digitalWrite(72,1)
      sleep(0.5)
      wiringpi.digitalWrite(88,0)
      wiringpi.digitalWrite(72,0)
      sleep(0.5)
      wiringpi.digitalWrite(88,1)
      wiringpi.digitalWrite(72,1)
      sleep(0.5)
      wiringpi.digitalWrite(88,0)
      wiringpi.digitalWrite(72,0)
      sleep(0.5)
      wiringpi.digitalWrite(88,1)
      wiringpi.digitalWrite(72,1)
      sleep(0.5)
      wiringpi.digitalWrite(88,0)
      wiringpi.digitalWrite(72,0)
      sleep(0.5)


def measure():
  # This function measures a distance
  stop = time.time()
  wiringpi.digitalWrite(GPIO_TRIGGER, 1)
  time.sleep(0.00001)
  wiringpi.digitalWrite(GPIO_TRIGGER, 0)
  start = time.time()

  while wiringpi.digitalRead(GPIO_ECHO)==0:
    start = time.time()

  while wiringpi.digitalRead(GPIO_ECHO)==1:
    stop = time.time()

  elapsed = stop-start
  distance = (elapsed * 34300)/2

  return distance

def measure_average():
  # This function takes 5 measurements and
  # returns the average.
   distance1=measure()
   time.sleep(0.1)
   distance2=measure()
   time.sleep(0.1)
   distance3=measure()
   time.sleep(0.1)
   distance4=measure()
   time.sleep(0.1)
   distance5=measure()
   time.sleep(0.1)
   distance = distance1 + distance2 + distance3 + distance4 + distance5
   distance = distance / 5
   return distance

while True:
    distance = measure_average()
    if distance > 8:
        if  wiringpi.digitalRead(104) == 1 or wiringpi.digitalRead(119) == 1:
            blinking_led1_button1_er1()
    else:
        wiringpi.digitalWrite(121,1)
        time.sleep(0.5)
        wiringpi.digitalWrite(121,0)
        time.sleep(0.5)
    time.sleep(0.1)

# Wrap main content in a try block so we can
# catch the user pressing CTRL-C and run the
# GPIO cleanup function. This will also prevent
# the user seeing lots of unnecessary error
# messages.
#  distance = measure_average()
   #  print "Ultrasonic Measurement"
   #  print "Distance : %.1f" % distance
   #  if distance < 8:
   #      wiringpi.digitalWrite(121,1)
   #  else:
    #     wiringpi.digitalWrite(121,0)
    # time.sleep(2)

User avatar
joan
Posts: 14995
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 8:02 pm

If there is a reschedule between

Code: Select all

  while wiringpi.digitalRead(GPIO_ECHO)==0:
    start = time.time()
and

Code: Select all

  while wiringpi.digitalRead(GPIO_ECHO)==1:
    stop = time.time()
the stop = time.time() statement may not be executed because the echo line has gone low before the while statement was reached.

That explains why you get the stop not defined error.

Possibly something similar causes the other error.

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 8:17 pm

Hi Joan, thank you for your answer.

How can I fix this problem? What do you sugest?
I have to change 'while' to 'if'?

Thanks

User avatar
joan
Posts: 14995
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 8:32 pm

Simplest change is to initialise the stop time after the first loop.

Code: Select all

   while wiringpi.digitalRead(GPIO_ECHO)==0:
      start = time.time()

   stop = time.time()

   while wiringpi.digitalRead(GPIO_ECHO)==1:
      stop = time.time()

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 8:43 pm

I'm testing it... Crossing fingers...

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 8:58 pm

No way.... Doesn't works.

I have notice that when hang, another process has high CPU use (40%)

kworker/u2:1

?????????

User avatar
joan
Posts: 14995
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 9:01 pm

The change I suggested only covers the first error (variable read before assignment). The random hang is down to something else in the code.

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 9:04 pm

Have you got any idea for the hang problem?

User avatar
joan
Posts: 14995
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 9:22 pm

If there is a reschedule between

Code: Select all

   wiringpi.digitalWrite(GPIO_TRIGGER, 0)
and

Code: Select all

   while wiringpi.digitalRead(GPIO_ECHO)==0:
      start = time.time()
The echo might have come and gone before the while loop is reached. The code would then hang on that while loop.

That doesn't explain why it later restarts (unless the echo line is noisy).

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 9:36 pm

I'm testing it....

It seems that if I increase hz in mcp23s17.c the problem of hang occur after few minute (1/2). So i change it again...

Are you sure that this problem is related to software? ....and not to the hrw? Because kworker/u2:1 seems to be IRQ stuff....

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 9:42 pm

.... I think that the problem could be related to CS channels.
Look the processes in hang:
Python
kworker/u2:1
kworker/u2:0

But i don't have any idea how to fix it.... :-(

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Thu Feb 20, 2014 10:33 pm

I'm looking on internet.... It seems that kworker process is not only related to hrw... So you have reason.... Better to focus the troubleshooting on sw.

Any idea how to modify it?

surfparadise
Posts: 102
Joined: Fri May 10, 2013 9:01 am

Re: Ultrasonic sensor script hang up random

Fri Feb 21, 2014 12:01 am

Fix it!!!

after the WiringpiDigitalWrite(GPIO_TRIGGER, 0) command just add:

time.sleep(0.00006)
and all works fine.

Thank you Joan! You has reason....as usual...

nizam
Posts: 15
Joined: Wed Jul 30, 2014 1:52 am

Re: Ultrasonic sensor script hang up random

Thu Jul 31, 2014 3:39 am

i`m sorry for interrupt ..
actually i have just the same problem as you..
still about the "hang up result" is not solved.
but the 3rd one is, my sensor doesnt give me a stable reading...for example if we measure a 3cm sometimes it become 10 or 15 cm or maybe worse.

and I have copy/paste this script from http://www.raspberrypi-spy.co.uk/2013/0 ... on-part-2/' ....
i want to use it faster maybe the delay time around 25ms, so i erase the average calculation. this is the code :

Code: Select all

#!/usr/bin/python

import time
import RPi.GPIO as GPIO

def measure():
  GPIO.output(GPIO_TRIGGER, True)
  time.sleep(0.00001)
  GPIO.output(GPIO_TRIGGER, False)
  time.sleep(0.00006)
  start = time.time()

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

  while GPIO.input(GPIO_ECHO)==1:
    stop = time.time()

  elapsed = stop-start
  distance = (elapsed * 34300)/2

  return distance
GPIO.setmode(GPIO.BCM)


GPIO_TRIGGER = 23
GPIO_ECHO    = 24

print "Ultrasonic Measurement"


GPIO.setup(GPIO_TRIGGER,GPIO.OUT)  # Trigger
GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo

GPIO.output(GPIO_TRIGGER, False)

try:

  while True:

    distance = measure()
    print "Distance : %.1f" % distance
    time.sleep(0.0025)

except KeyboardInterrupt:
  GPIO.cleanup()
thanks for helping..

Nafees-ul-hasan
Posts: 1
Joined: Tue Nov 01, 2016 7:53 pm

Re: Ultrasonic sensor script hang up random

Tue Nov 01, 2016 8:15 pm

I solved the 1st problem as follows:

Code: Select all

def measure():
	try:
	  GPIO.output(GPIO_TRIGGER, True)
	  time.sleep(0.00001)
	  GPIO.output(GPIO_TRIGGER, False)
	  time.sleep(0.00006)
	  start = time.time()

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

	  while GPIO.input(GPIO_ECHO)==1:
	    stop = time.time()

	  elapsed = stop-start
	  distance = (elapsed * 34300)/2
	  return distance
	except:
	  print("error encountered, retrying") 
	  measure()

still can't find the solution for hanging at a random value.

theashwanisingla
Posts: 1
Joined: Tue Nov 28, 2017 10:25 am

Re: Ultrasonic sensor script hang up random

Tue Nov 28, 2017 11:09 am

surfparadise wrote:
Thu Feb 20, 2014 6:40 pm
Hi all,
I have set up a little script that, after checking the distance with a ultrasonic sensor (HC-SR04), do the led blink if the distance is less of 8 cm.
My setup is made by 4 MCP23S17 chips with a 5v external power supply, connected to the raspberry with mosfets (SPI), and the ultrasonic sensor connected to one chip (with a resistor to pull down the echo pin).

Everything works really well exept 2 things.

1- If I don't insert this: 'stop = time.time()' as first line of 'def measure()' I have this error (but not always....just random.... :shock: ):

python UnboundLocalError: local variable 'stop' referenced before assignment

I have copy/paste this script from http://www.raspberrypi-spy.co.uk/2013/0 ... n-part-2/' .... so I think that it must works well... and the error is random.... really strange.....

2- The script after run for a while (5 minutes....10 minutes) hang up....2/3 /10 minutes (no error messages), and after, start again to works.... really, really extrange.....
When the process hang up, the cpu use go at 50%.... Normally is it at 1% level
.

Could be these problems related to the SPI buffer or the frequency of the MCP23S17 that it is not enough?

edit: I have change this value in the mcp23s17.c file:

from
#define MCP_SPEED 4000000
to
#define MCP_SPEED 10000000

Now my chips speed is 10Mhz? Correct? ...or I need to do something else?

I'm testing it..... I will give you a feedback in 1 hour..


Edit2: Doesn't works.... :x

Please help me, because I don't really know how to fix it :?
Thank you in advance

Code: Select all

import wiringpi2 as wiringpi
from time import sleep
import time


wiringpi.wiringPiSetup()           # initialise wiringpi
wiringpi.mcp23s17Setup(65,0,0)     # set up the pins, spi port, address (mcp23s17-0)
wiringpi.mcp23s17Setup(81,0,1)     # set up the pins, spi port, address (mcp23s17-1)
wiringpi.mcp23s17Setup(97,1,0)
wiringpi.mcp23s17Setup(113,1,1)


wiringpi.pinMode(104,0)    
wiringpi.digitalWrite(104,0)
wiringpi.pinMode(119,0)
wiringpi.digitalWrite(119,0)


wiringpi.pinMode(72,1)   
wiringpi.digitalWrite(72,0) 
wiringpi.pinMode(121,1)    
wiringpi.digitalWrite(121,0)
wiringpi.pinMode(88,1)  
wiringpi.digitalWrite(88,0)
wiringpi.pinMode(128,0)
wiringpi.pinMode(127,1)
wiringpi.digitalWrite(127,0)
GPIO_TRIGGER = 127
GPIO_ECHO    = 128


def blinking_led1_button1_er1():
      wiringpi.digitalWrite(88,1)
      wiringpi.digitalWrite(72,1)
      sleep(0.5)
      wiringpi.digitalWrite(88,0)
      wiringpi.digitalWrite(72,0)
      sleep(0.5)
      wiringpi.digitalWrite(88,1)
      wiringpi.digitalWrite(72,1)
      sleep(0.5)
      wiringpi.digitalWrite(88,0)
      wiringpi.digitalWrite(72,0)
      sleep(0.5)
      wiringpi.digitalWrite(88,1)
      wiringpi.digitalWrite(72,1)
      sleep(0.5)
      wiringpi.digitalWrite(88,0)
      wiringpi.digitalWrite(72,0)
      sleep(0.5)


def measure():
  # This function measures a distance
  stop = time.time()
  wiringpi.digitalWrite(GPIO_TRIGGER, 1)
  time.sleep(0.00001)
  wiringpi.digitalWrite(GPIO_TRIGGER, 0)
  start = time.time()

  while wiringpi.digitalRead(GPIO_ECHO)==0:
    start = time.time()

  while wiringpi.digitalRead(GPIO_ECHO)==1:
    stop = time.time()

  elapsed = stop-start
  distance = (elapsed * 34300)/2

  return distance

def measure_average():
  # This function takes 5 measurements and
  # returns the average.
   distance1=measure()
   time.sleep(0.1)
   distance2=measure()
   time.sleep(0.1)
   distance3=measure()
   time.sleep(0.1)
   distance4=measure()
   time.sleep(0.1)
   distance5=measure()
   time.sleep(0.1)
   distance = distance1 + distance2 + distance3 + distance4 + distance5
   distance = distance / 5
   return distance

while True:
    distance = measure_average()
    if distance > 8:
        if  wiringpi.digitalRead(104) == 1 or wiringpi.digitalRead(119) == 1:
            blinking_led1_button1_er1()
    else:
        wiringpi.digitalWrite(121,1)
        time.sleep(0.5)
        wiringpi.digitalWrite(121,0)
        time.sleep(0.5)
    time.sleep(0.1)

# Wrap main content in a try block so we can
# catch the user pressing CTRL-C and run the
# GPIO cleanup function. This will also prevent
# the user seeing lots of unnecessary error
# messages.
#  distance = measure_average()
   #  print "Ultrasonic Measurement"
   #  print "Distance : %.1f" % distance
   #  if distance < 8:
   #      wiringpi.digitalWrite(121,1)
   #  else:
    #     wiringpi.digitalWrite(121,0)
    # time.sleep(2)
Hi, I also faced same problem when i used ultrasonic for the very first time. Then I found the problem in while loop. Actually we use two while loops to detect echo. It is so fast that sometimes echo goes High while time.time() command is being executed and it become low before time.time() command completes. It happens in case when CPU usage increases and speed becomes a bit slower.
so I suggest to use following commands:

def measure():
# This function measures a distance
stop = time.time()
wiringpi.digitalWrite(GPIO_TRIGGER, 1)
time.sleep(0.00001)
wiringpi.digitalWrite(GPIO_TRIGGER, 0)
start = time.time()

while wiringpi.digitalRead(GPIO_ECHO)==0:
pass
start = time.time()

while wiringpi.digitalRead(GPIO_ECHO)==1:
pass
stop = time.time()

elapsed = stop-start
distance = (elapsed * 34300)/2

return distance

It worked in my case. reply me if it works in your script.
thanks.

Return to “Python”