UnboundLocalError: local variable 'signaloff' referenced before assignment - python

I'm trying to read ultrasonic range when a button is pressed on a raspberry pi.
I'm getting a random error that happens about 1 in three times. Have also tried running 'print reading(0)' three times with a wait of 2 seconds in between each attempt and sometimes it works and sometimes it fails on the first try.
The error is:
Traceback (most recent call last):
File "test.py", line 37, in <module>
print reading(0)
File "test.py", line 30, in reading
timepassed = signalon - signaloff
UnboundLocalError: local variable 'signaloff' referenced before assignment
The code is:
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
# btn on pin 18
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# LED on pin 24
GPIO.setup(24, GPIO.OUT)
# GPIO output = the pin that's connected to "Trig" on the sensor
# GPIO input = the pin that's connected to "Echo" on the sensor
GPIO.setup(17,GPIO.OUT)
GPIO.setup(27,GPIO.IN)
def reading(sensor):
if sensor == 0:
GPIO.output(17, GPIO.LOW)
time.sleep(0.3)
GPIO.output(17, True)
time.sleep(0.00001)
GPIO.output(17, False)
while GPIO.input(27) == 0:
signaloff = time.time()
while GPIO.input(27) == 1:
signalon = time.time()
timepassed = signalon - signaloff
distance = timepassed * 17000
return distance
else:
print "Incorrect usonic() function varible."
while True:
input_state = GPIO.input(18)
if input_state == False:
print('Button Pressed')
GPIO.output(24, True)
print reading(0)
time.sleep(2)
GPIO.output(24, False)

If GPIO.input(27) returns 0 the first time you call it, the while loop will never be entered, and signaloff will never be set. The same is actually true for the loop that set signalon, although that issue might be rarer.

Related

Python Threading: Using 2 Light Dependant Resistors (LDR)

I am using a simple code from PiMyLife tutorial to read from a Light Dependant Resistor using a capacitor. This works great..
I then added a 2nd LDR and capacitor, added it to pin 31 and then duplicated the code (the rc_time function and the fuction call) to add an additional Light Dependant Resistor but for some reason the second function call never happens.
#!/usr/local/bin/python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
#define the pin that goes to the circuit
pin_ldr_one = 29
pin_ldr_two = 31
def rc_time_one (pin_ldr_one):
count_one = 0
#Output on the pin for
GPIO.setup(pin_ldr_one, GPIO.OUT)
GPIO.output(pin_ldr_one, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_ldr_one, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_ldr_one) == GPIO.LOW):
count_one += 1
return count_one
def rc_time_two (pin_ldr_two):
count_two = 0
#Output on the pin for
GPIO.setup(pin_ldr_two, GPIO.OUT)
GPIO.output(pin_ldr_two, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_ldr_two, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_ldr_two) == GPIO.LOW):
count_two += 1
return count_two
#Catch when script is interrupted, cleanup correctly
try:
# Main loop
while True:
print("LDR 1: ",rc_time_one(pin_ldr_one))
print("LDR 2: ",rc_time_two(pin_ldr_two))
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
So I thought I would try threading instead thinking that the 2 function calls were having issues.
So this is the threading code I came up with however this too fails to run the second (in this cask 2nd thread). Any ideas where I am going wrong. Thanks for all your help
#!/usr/local/bin/python
import RPi.GPIO as GPIO
import time
from time import sleep, perf_counter
from threading import Thread
GPIO.setmode(GPIO.BOARD)
#define the pin that goes to the circuit
pin_ldr_one = 29
pin_ldr_two = 31
def rc_time_one (pin_ldr_one = 29):
count_one = 0
#Output on the pin for
GPIO.setup(pin_ldr_one, GPIO.OUT)
GPIO.output(pin_ldr_one, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_ldr_one, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_ldr_one) == GPIO.LOW):
count_one += 1
print("LDR 1: ",count_one)
return count_one
def rc_time_two (pin_ldr_two = 31):
count_two = 0
#Output on the pin for
GPIO.setup(pin_ldr_two, GPIO.OUT)
GPIO.output(pin_ldr_two, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_ldr_two, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_ldr_two) == GPIO.LOW):
count_two += 1
print("LDR 2: ",count_two)
return count_two
#Catch when script is interrupted, cleanup correctly
try:
# Main loop
while True:
# create two new threads
t1 = Thread(target=rc_time_one)
t2 = Thread(target=rc_time_two)
# start the threads
t1.start()
t2.start()
t1.join()
t2.join()
#print("LDR 1: ",rc_time_one(pin_ldr_one))
#print("LDR 2: ",rc_time_two(pin_ldr_two))
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
Peter

Combining two python codes for raspberry pi with a servo and ldr sensor

I have Python code running on my raspberry pi 2b and a light sensor, which measures the amount of time it takes for the capacitor of the light sensor to charge and send the pin high:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
pin_to_circuit = 7
def rc_time (pin_to_circuit):
count = 0
#Output on the pin for
GPIO.setup(pin_to_circuit, GPIO.OUT)
GPIO.output(pin_to_circuit, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_to_circuit, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_to_circuit) == GPIO.LOW):
count += 1
if count > 1000000:
return True
else:
return count
#Catch when script is interrupted, cleanup correctly
try:
# Main loop
while True:
print rc_time(pin_to_circuit)
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
I want when the count goes higher than 1000000, a MG90S, that I have also connected to the pi and a 4AA battery pack, moves about 90 degrees.
The code I was trying to integrate to move the servo:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p.ChangeDutyCycle(7.5) # turn towards 90 degree
time.sleep(1) # sleep 1 second
p.stop()
GPIO.cleanup()
I want to combine these two Python codes. I tried for a bit, but I have almost no Python experience.
The code is now:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
pin_to_circuit = 7
def move_90_degrees():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p = GPIO.PWM(12, 50)
p.start(7.5)
p.ChangeDutyCycle(7.5) # turn towards 90 degree
time.sleep(1) # sleep 1 second
p.stop()
def rc_time (pin_to_circuit):
count = 0
#Output on the pin for
GPIO.setup(pin_to_circuit, GPIO.OUT)
GPIO.output(pin_to_circuit, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_to_circuit, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_to_circuit) == GPIO.LOW):
count += 1
if count > 1000000:
return True
move_90_degrees()
else:
return count
#Catch when script is interrupted, cleanup correctly
try:
# Main loop
while True:
print rc_time(pin_to_circuit)
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
The code does print True when the count exceeds 1000000, but the servo still doesn't move. The servo code on its own does however work correctly. (I forgot a bit of the servo code, that's why p wasn't defined, sorry.)
You could just integrate the code block you are using to move the MG90S into a function, insert it before or below your def rc_time (pin_to_circuit): (but first you have to define p inside, its not really clear what p refers to):
New Function from second code block:
def move_90_degrees():
p = '???'
GPIO.setup(12, GPIO.OUT)
p.ChangeDutyCycle(7.5) # turn towards 90 degree
time.sleep(1) # sleep 1 second
p.stop()
After defining this function, call it inside your first block like:
if count > 1000000:
move_90_degrees()
return True
else:
return count
That should work.
I've made a mistake in the code. I changed the order of the function call inside of the
if count > 1000000:
return True
move_90_degrees()
else:
return count
block to :
if count > 1000000:
move_90_degrees()
return True
else:
return count
otherwise, the code returns before the function call is executed. Is it working now?

QTR-8RC Reflectance Sensor Array not returning data

I purchased a QTR-8RC Reflectance Sensor Array and now trying to configure it with Python. I am trying to determine the rate of decay of the voltage that is being read by my receivers (phototransistors) so that I know when a line is being detected. I don't know why my Python code isn't returning anything. Not even a warning statement. Additional information includes that by default the GPIO is an output and the LEDs are ON. Any help is appreciated!
import RPi.GPIO as GPIO
from time import sleep
def Read():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(5, GPIO.OUT)
sleep(0.01)
count = 0
GPIO.setup(5, GPIO.IN)
while GPIO.input(5) == True:
count = count + 1
return count
while True:
Read()
print(Read())
sleep(1)
I don't have any knowledge about QTR-8RC Reflectance Sensor Array.
But looking at your python code, the problem might be with
while GPIO.input(5) == True
If the value is always true then the line with the return statement is never reached.
You could use print statement after while block to check that. Something like
while GPIO.input(5) == True:
count = count + 1
print "while loop has ended"
return count
Instead of running the program continuously run it for some time and check the outputs.
And may be you need to increase the sleep time to see the output practically.
import RPi.GPIO as GPIO
from time import sleep
def Read():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(5, GPIO.OUT)
sleep(0.01)
count = 0
GPIO.setup(5, GPIO.IN)
while GPIO.input(5) == True:
count = count + 1
print "count :", count
return count
for _ in range(100):
print(Read())
sleep(2)

How to control LEDs via a LDR and a button as well?

I'm currently working on a Node-RED webapplication to control several leds with switch buttons. Next, using a Python script to read the LDR value. This value will be used to determine if it's light or dark outside. When it's dark, one led has to be enabled and the others disabled, the opposite when it's light.
#!/usr/bin/env python
import cgitb ; cgitb.enable()
import spidev
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
spi = spidev.SpiDev() # create spi object
spi.open(0,0) # open spi port 0, device CS0 pin 24
# read SPI data 8 possible adc's (0 thru 7)
def readadc(adcnum):
if ((adcnum > 7) or (adcnum < 0)):
return -1
r = spi.xfer2([1,(8+adcnum)<<4,0])
adcout = ((r[1]&3) << 8) + r[2]
return adcout
As you can see, the rest of this script keeps going because of the while loop.
while True:
tmp0 = readadc(0) # read channel 0
if(tmp0 > 500):
msg = "LIGHT"
GPIO.output(17, False)
else:
msg = "DARK"
GPIO.output(17, True)
GPIO.output(18, False)
GPIO.output(22, False)
GPIO.output(27, False)
time.sleep(0.3)
print msg
Finnally, I can't use both. Once I click one a switch the led will go on for 1 second. I need to find a manner to combine both methods. Any tips?
IF what you want, is for the light conditions to dictate the initial led state, as well as updating the state when the light conditions change; but the switches to over-ride these until the light conditions change, then this should help:
light_set = None
while True:
tmp0 = readadc(0) # read channel 0
if(tmp0 > 500) and light_set != "LIGHT":
msg = "LIGHT"
light_set = msg
GPIO.output(17, False)
else if light_set != "DARK":
msg = "DARK"
light_set = msg
GPIO.output(17, True)
GPIO.output(18, False)
GPIO.output(22, False)
GPIO.output(27, False)
time.sleep(0.3)
print msg
This should "remember" what this code section last set the led to, so it won't keep setting it if it's changed with a switch. It will still change it, when the current light conditions aren't what it last set it to though.

RaspberryPi webiopi script error doesn't work

I want to experiment with the RaspberryPi, but the .py code doesn't work. It gives me a lot of errors.
a space error
indentation error: expected an indented block " global VELUX_STATE, AUTO_mode "
I only copied the code from the official forum, that works for other people.
Link:
http://egrasland.blogspot.fr/2014/01/control-your-velux-roller-shutter-with.html
I copy the code and paste in "sudo nano script.py"
What do I do wrong ?
Furthermore, the code from the official webiopi from RaspberryPi doesn't work either for me. Debug gives error, and the program doesn't start.
Link: https://code.google.com/p/webiopi/wiki/Tutorial_Basis
Thanks for the answers.
The code I used is:
Python server script :
import webiopi import datetime
GPIO = webiopi.GPIO
VELUX_UP = 17 # GPIO pin using BCM numbering VELUX_DOWN = 18 # GPIO pin using BCM numbering VELUX_STOP = 27 # GPIO pin using BCM numbering
VELUX_STATE = 0 # DOWN AUTO_MODE = 1
HOUR_UP = 9 # Turn Velux UP at HOUR_DOWN = 19 # Turn Velux Down at
# setup function is automatically called at WebIOPi startup
def setup(): global VELUX_STATE, AUTO_MODE
# set the GPIO used for VELUX command to output
GPIO.setFunction(VELUX_UP, GPIO.OUT)
GPIO.setFunction(VELUX_DOWN,GPIO.OUT)
# STOP function not used at this time
GPIO.setFunction(VELUX_STOP,GPIO.OUT)
GPIO.digitalWrite(VELUX_STOP, GPIO.LOW)
# retrieve current datetime now = datetime.datetime.now()
if (AUTO_MODE==1):
# test time
if ((now.hour >= HOUR_UP) and (now.hour < HOUR_DOWN)):
GPIO.digitalWrite(VELUX_UP, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_UP, GPIO.LOW)
VELUX_STATE = 1
else:
GPIO.digitalWrite(VELUX_DOWN, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_DOWN, GPIO.LOW)
VELUX_STATE = 0
# loop function is repeatedly called by WebIOPi
def loop(): global VELUX_STATE, AUTO_MODE
# retrieve current datetime now = datetime.datetime.now()
if (AUTO_MODE==1):
# toggle VELUX UP all days at the correct time
if ((now.hour == HOUR_UP) and (now.minute == 0) and (VELUX_STATE == 0)):
GPIO.digitalWrite(VELUX_UP, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_UP, GPIO.LOW)
VELUX_STATE = 1 #UP
# toggle VELUX DOWN all days at the correct time
if ((now.hour == HOUR_DOWN) and (now.minute == 0) and (VELUX_STATE == 1)):
GPIO.digitalWrite(VELUX_DOWN, GPIO.HIGH)
webiopi.sleep(0.2)
GPIO.digitalWrite(VELUX_DOWN, GPIO.LOW)
VELUX_STATE = 0 #DOWN
# gives CPU some time before looping again webiopi.sleep(1)
# destroy function is called at WebIOPi shutdown
def destroy():
GPIO.digitalWrite(VELUX_UP, GPIO.LOW)
GPIO.digitalWrite(VELUX_DOWN, GPIO.LOW)
GPIO.digitalWrite(VELUX_STOP, GPIO.LOW)
#webiopi.macro def getHours():
return "%d;%d" % (HOUR_UP, HOUR_DOWN)
#webiopi.macro def setHours(on, off):
global HOUR_UP, HOUR_DOWN
HOUR_UP = int(on)
HOUR_DOWN = int(off)
return getHours()
#webiopi.macro def getAutoMode():
return "%d" % (AUTO_MODE)
#webiopi.macro def setAutoMode():
global AUTO_MODE
if AUTO_MODE:
AUTO_MODE=0
else:
AUTO_MODE=1
return getAutoMode()
The debug can't I post here because its on my RaspberryPi and the browser is to slow :)
But the first error he give is the dubble spaces by the comment VELUX UP
"HOUR_UP = 9 # Turn Velux UP at"
I solved this but then is it the error
"def setup():
global VELUX_STATE, AUTO_MODE"
Why?
Thanks!

Categories