I currently have a piece of code designed to communicate with two motors via a TCP Device Server which sends ASCII commands to them in order to trace sinusoidal paths. I wish to have the movement continue indefinitely and then immediately stop when KeyboardInterrupt is triggered, then have the motors move back to their defined home positions before the program ends.
This code can currently replicate sinusodial motion, but it currently does not stop immediately when KeyboardInterrupt is triggered, nor do the motors move back to their home positions. The sinusodial loop is designed such that when KeyboardInterrupt occurs, a global variable called move changes from True to False and this breaks the loop. The simplified code is given below:
import socket
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.connect(("192.168.177.200", 4001)) # Y motor
s2.connect(("192.168.177.200", 4002)) # X motor
# Disengage the motor to allow manual movement by wheel
s1.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
homeposition = input("Are the motors centred? Press 'y' to confirm: ")
if homeposition == 'y':
s1.send("EN\n".encode("ASCII"))
s2.send("EN\n".encode("ASCII")) # energise the motors so they cannot be moved
print("Motors Engaged")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
else:
print("Set home position and restart program")
exit()
#----ADD DATA FOR SAMPLING SINUSODIAL FUNCTIONS----
radius = input("Desired radius of movement (mm):")
radius = float(radius)
print("radius of circular path (mm): ", radius)
# need slightly different ratios for each motor due to different thread sizes
gearpositionlim_x = 20000 #one rotation equals 2.5mm (+ bearing ration on manipulator of 2:1)
gearpositionlim_y = 10000 #one rotation equals 2mm
# sample sine and cosine
step = 2*pi / 1000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim_x*np.cos(time_range)
y_motorrange = gearpositionlim_y*np.sin(time_range)
x_motorrange = ['la'+str(int(i)) for i in x_motorrange]
y_motorrange = ['la'+str(int(i)) for i in y_motorrange]
#print(x_motorrange)
x_motorrange_wcom = []
y_motorrange_wcom = []
{x_motorrange_wcom.extend([e, 'm', 'np']) for e in x_motorrange} # add movement prompts and wait for movement to complete
{y_motorrange_wcom.extend([e, 'm', 'np']) for e in y_motorrange} # add movement prompts and wait for movement to complete
# Set Acceleration and Deceleration of Motors
s1.send("AC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("AC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Acceleration set to 10 ")
s1.send("DEC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DEC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Deceleration set to 10")
def setup(): #move to initial position before starting movement
s2.send(str(str(x_motorrange_wcom[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
move = False
print(move)
end()
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
I believe my issue is with my function motormove(), but I am unsure of what I should do in order to achieve my desired operation. Does anyone know how this can be achieved?
Thanks in advance
Using library signal should be sufficient for your usecase. See code bellow.
import socket
import signal
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
gearpositionlim = int(10000)
# sample sine and cosine
step = 2*pi / 2000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim*np.sin(time_range)
y_motorrange = gearpositionlim*np.cos(time_range)
def handler(signum, frame):
res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
if res == 'y':
exit(1)
else:
#Do STH
def setup():
s2.send(y_motorrange[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
signal.signal(signal.SIGINT, handler)
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
This should be working just fine, note the signal function being called on KeyboardInterrupt, this redirects to signal function where, you can either exit or do something else.
Related
This question already has answers here:
Why does sys.exit() not exit when called inside a thread in Python?
(6 answers)
Closed 1 year ago.
I wrote a script that can draw polylines (it over on github) from ScalableVectorGraphics(.svg) by moving the Mouse accordingly.
When you are handing the control over your mouse to a script, a killswitch is certainly necessary, so I found an example for a Keyboard listener somwhere on the Internet:
def on_press(key):
try:
sys.exit()
print('alphanumeric key {0} pressed'.format(key.char))
print('adsfadfsa')
except AttributeError:
print('special key {0} pressed'.format(
key))
def main():
listener = keyboard.Listener( #TODO fix sys.exit()
on_press=on_press)
listener.start()
if __name__ == '__main__':
main()
It seems to be working: If i add a a print statement before the sys.exit() it is instantly executed properly.
But with sys.exit() it keeps moving my mouse and the python interpreter is still on Taskmanager. I don't know why it keeps executing.
Thank you in advance for your suggestions.
MrSmoer
Solution was: os._exit(1)
Full Sourcecode:
from pynput import mouse as ms
from pynput import keyboard
from pynput.mouse import Button, Controller
import threading
import time
from xml.dom import minidom
import re
sys.path.append('/Users/MrSmoer/Desktop/linedraw-master')
mouse = ms.Controller()
tlc = None
brc = None
brc_available = threading.Event()
biggestY = 0
biggestX = 0
drwblCnvsX = 0
drwblCnvsY = 0
def on_click(x, y, button, pressed):
if not pressed:
# Stop listener
return False
def on_press(key):
try:
sys.exit()
print('alphanumeric key {0} pressed'.format(key.char))
print('adsfadfsa')
except AttributeError:
print('special key {0} pressed'.format(
key))
def initialize():
print("Please select your programm and then click at the two corners of the canvas. Press any key to cancel.")
with ms.Listener(
on_click=on_click) as listener:
listener.join()
print('please middleclick, when you are on top left corner of canvas')
with ms.Listener(
on_click=on_click) as listener:
listener.join()
global tlc
tlc = mouse.position
print('please middleclick, when you are on bottom left corner of canvas')
with ms.Listener(
on_click=on_click) as listener:
listener.join()
global brc
brc = mouse.position
mouse.position = tlc
print('thread finished')
brc_available.set()
def getDrawabableCanvasSize(polylines):
global biggestX
global biggestY
for i in range(len(polylines)): # goes throug all polylines
points = hyphen_split(polylines[i]) # Splits polylines to individual points
for c in range(len(points)): # goes throug all points on polyline
cord = points[c].split(',') # splits points in x and y axis
if float(cord[0]) > (biggestX - 5):
biggestX = float(cord[0]) + 5
if float(cord[1]) > (biggestY - 5):
biggestY = float(cord[1]) + 5
print('TLC: ', tlc)
print('bigX: ', biggestX)
print('bigY: ', biggestY)
cnvswidth = tuple(map(lambda i, j: i - j, brc, tlc))[0]
cnvsheight = tuple(map(lambda i, j: i - j, brc, tlc))[1]
cnvsapr = cnvswidth / cnvsheight
print('Canvasaspr: ', cnvsapr)
drwblcnvaspr = biggestX / biggestY
print('drwnble aspr: ', drwblcnvaspr)
if drwblcnvaspr < cnvsapr: # es mus h vertikal saugend
print('es mus h vertikal saugend')
finalheight = cnvsheight
finalwidth = finalheight * drwblcnvaspr
else: # es muss horizontal saugend, oder aspect ratio ist eh gleich
print('es muss horizontal saugend, oder aspect ratio ist eh gleich')
finalwidth = cnvswidth
scalefactor = finalwidth / biggestX
print(scalefactor)
return scalefactor
def drawPolyline(polyline, scalefactor):
points = hyphen_split(polyline)
#print(points)
beginpoint = tlc
for c in range(len(points)): # goes throug all points on polyline
beginpoint = formatPoint(points[c], scalefactor)
if len(points) > c + 1:
destpoint = formatPoint(points[c + 1], scalefactor)
mouse.position = beginpoint
time.sleep(0.001)
mouse.press(Button.left)
# time.sleep(0.01)
mouse.position = destpoint
# time.sleep(0.01)
mouse.release(Button.left)
else:
destpoint = tlc
#print("finished line")
mouse.release(Button.left)
def formatPoint(p, scale):
strcord = p.split(',')
#print(scale)
#print(tlc)
x = float(strcord[0]) * scale + tlc[0] # + drwblCnvsX/2
y = float(strcord[1]) * scale + tlc[1] # + drwblCnvsY/2
#print('x: ', x)
#print('y: ', y)
thistuple = (int(x), int(y))
return thistuple
def hyphen_split(a):
return re.findall("[^,]+\,[^,]+", a)
# ['id|tag1', 'id|tag2', 'id|tag3', 'id|tag4']
def main():
listener = keyboard.Listener( #TODO fix sys.exit()
on_press=on_press)
listener.start()
thread = threading.Thread(target=initialize()) #waits for initializing function (two dots)
thread.start()
brc_available.wait()
# print(sys.argv[1])
doc = minidom.parse('/Users/MrSmoer/Desktop/linedraw-master/output/out.svg') # parseString also exists
try:
if sys.argv[1] == '-ip':
doc = minidom.parse(sys.argv[2])
except IndexError:
print('Somethings incorrect1')
polylines = NotImplemented
try:
doc = minidom.parse('/Users/MrSmoer/Desktop/linedraw-master/output/out.svg') # parseString also exists
# /Users/MrSmoer/Desktop/linedraw-master/output/output2.svg
#doc = minidom.parse('/Users/MrSmoer/Desktop/Test.svg')
polylines = [path.getAttribute('points') for path
in doc.getElementsByTagName('polyline')]
doc.unlink()
except:
print('Somethings incorrect3')
# print(polylines)
scalefactor = getDrawabableCanvasSize(polylines)
for i in range(len(polylines)):
drawPolyline(polylines[i], scalefactor)
if __name__ == '__main__':
main()
Sometimes, when writing a multithreadded app, raise SystemExit and sys.exit() both kills only the running thread. On the other hand, os._exit() exits the whole process.
While you should generally prefer sys.exit because it is more "friendly" to other code, all it actually does is raise an exception.
If you are sure that you need to exit a process immediately, and you might be inside of some exception handler which would catch SystemExit, there is another function - os._exit - which terminates immediately at the C level and does not perform any of the normal tear-down of the interpreter
A simple way to terminate a Python script early is to use the built-in quit() function. There is no need to import any library, and it is efficient and simple.
Example:
#do stuff
if this == that:
quit()
You may try these options!!
Hope it works fine!! If not tell us, we will try more solutions!
That sys.exit() ends up killing the thread that it's executing it, but you program seems to take advantage of multiple threads.
You will need to kill all the threads of the program including the main one if you want to exit.
So, I am programming in python on my pi. Through a cwiid library I am connecting my wii controller. This works fine.
But, after my wii controller connects trough bluetooth, suddenly the leds won't work.
The same line of code works before connecting, but doesn't work anymore after connecting. How is this possible?
My complete code:
if __name__ == '__main__':
from sys import path
path.append("..")
import RPi.GPIO as GPIO
from time import sleep
import os
import cwiid
from MotorPwm2 import MotorPwm
from GPIOFuckUp import GPIOFuckUp
from Basis import Basis
GPIOFuckUp()
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
motor = MotorPwm([10, 9, 8, 7])
basis = Basis()
startbool = False
running = True
left_light = 21
right_light = 20
left_siren = 16
right_siren = 26
GPIO.setup(left_light, GPIO.OUT)
GPIO.setup(right_light, GPIO.OUT)
GPIO.setup(left_siren, GPIO.OUT)
GPIO.setup(right_siren, GPIO.OUT)
left_pin = GPIO.PWM(left_light, 1000)
right_pin = GPIO.PWM(right_light, 1000)
left_pin_s = GPIO.PWM(left_siren, 1000)
right_pin_s = GPIO.PWM(right_siren, 1000)
left_pin.start(100)
right_pin.start(100)
left_pin_s.start(0)
right_pin_s.start(0)
# Code above works. Leds turn on, with no problems.
def turn_on_left():
dim_left(100)
def turn_on_right():
dim_right(100)
def turn_on_lefts():
dim_lefts(100)
def turn_on_rights():
dim_rights(100)
def turn_on():
print 'aan'
dim_left(100)
dim_right(100)
def turn_off_lefts():
dim_lefts(0)
def turn_off_rights():
dim_rights(0)
def turn_off_left():
dim_left(0)
def turn_off_right():
dim_right(0)
def turn_off():
dim_left(0)
dim_right(0)
def dim(percentage):
dim_left(percentage)
dim_right(percentage)
def dim_left(percentage):
left_pin.ChangeDutyCycle(percentage)
print 'left'
def dim_right(percentage):
right_pin.ChangeDutyCycle(percentage)
print 'right'
def dim_lefts(percentage):
left_pin_s.ChangeDutyCycle(percentage)
def dim_rights(percentage):
right_pin_s.ChangeDutyCycle(percentage)
def siren_loop():
while running:
dim_lefts(100)
dim_rights(100)
sleep(0.05)
turn_off_lefts()
turn_off_rights()
sleep(0.05)
dim_rights(100)
sleep(0.05)
turn_on_rights()
sleep(0.05)
dim_lefts(100)
sleep(0.05)
dim_lefts(0)
sleep(0.05)
# Def things above also work. Copied the code in another file just to try
the leds, and that also worked.
button_delay = 0.1
print 'Press 1 + 2 on your Wii Remote now ...'
# Here the controller is connecting. After it is connected the leds turn of
# Before the following print lines are printed.
# Connect to the Wii Remote. If it times out
# then quit.
try:
wii = cwiid.Wiimote()
#GPIO.output(PIN_LED, 0)
except RuntimeError:
print "Error opening wiimote connection"
#GPIO.output(PIN_LED, 0)
# Uncomment this line to shutdown the Pi if pairing fails
os.system("sudo reboot")
quit()
print 'Wii Remote connected...\n'
print 'Press some buttons!\n'
print 'Press PLUS and MINUS together to disconnect and quit.\n'
wii.rpt_mode = cwiid.RPT_BTN
while True:
buttons = wii.state['buttons']
# If Plus and Minus buttons pressed
# together then rumble and quit.
if (buttons - cwiid.BTN_PLUS - cwiid.BTN_MINUS == 0):
print '\nClosing connection ...'
wii.rumble = 1
#GPIO.output(PIN_LED, 1)
sleep(1)
wii.rumble = 0
#GPIO.output(PIN_LED, 0)
os.system("sudo reboot")
exit(wii)
# Button presses below work and print the correct lines. Just no leds :(
if (buttons & cwiid.BTN_LEFT):
print 'Left pressed'
motor.left_forward(50)
sleep(button_delay)
elif (buttons & cwiid.BTN_RIGHT):
print 'Right pressed'
motor.right_forward(50)
sleep(button_delay)
elif (buttons & cwiid.BTN_UP):
print 'Up pressed'
motor.forward(100)
sleep(button_delay)
elif (buttons & cwiid.BTN_DOWN):
print 'Down pressed'
motor.backward(100)
sleep(button_delay)
elif (buttons & cwiid.BTN_A):
print 'A'
if startbool == False:
print 'start aan'
startbool = True
sleep(0.5)
else:
print 'start uit'
startbool = False
sleep(0.5)
elif (buttons & cwiid.BTN_1):
if running:
turn_on()
sleep(5)
print '1'
print 'Licht 5 sec aan'
elif (buttons & cwiid.BTN_2):
print '2'
print 'sirene 5 sec aan'
siren_loop()
sleep(5)
else:
GPIO.cleanup()
So, for example, the start values turn the leds on when I run the program. This happens, the leds light up. But then, after the wii remote connects, they turn off and are impossible to turn on again.
After trying for another few hours, I finally found the problem.
The last line said:
else:
GPIO.cleanup()
Which resetted all the pins, hence they were not working. Deleting the else made everything work again.
Now I know the problem it seems so simple xD
i manipulate a sensor : HC SR04 to capture a distance.
I'm a newbie in Python and RPI. My code work, I capture distance during a time but one moment the script stop...
My code :
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()
The code stop here
while GPIO.input(GPIO_ECHO) == 0:
start = time.time()
THE SOLUTION : with a sample timeout :
now = time()
while GPIO.input(self.gpio_echo) == 0 and time()-now<waitTime:
pass
I am also mucking about with this sensor. My code executes similar to yours and I need no timeout for it to work.
The one difference I can find is this:
while i< 1:
GPIO.output(GPIO_TRIGGER, False)
time.sleep(C.time['count'])
I don't know how long the sleep time is here, but it might be that that's causing the problem. If it would be similar to mine setting the Trigger to false would be directly after the setup of the in/out pins instead, and then there's a two second wait to eliminate noise. Your wait time might be lower, I can't tell. There should be no need to set the trigger to false again just before you send the pulse and, I don't know, but it might be causing a false start. I would change it to this to work similarly to mine and then remove the setting to false in the while loop.
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
GPIO.output(GPIO_TRIGGER, False)
print("Waiting for sensor to settle\n")
time.sleep(2)
I'm not sure if this will solve the issue without the need for a timeout, but I don't seem to need one.
I've written a module for making an object of the sensor which then allows for some more readable scripting. I'm also quite new to python and not at all an experienced programmer so fun errors might be there somewhere, but it's here below if you want to use it or just compare code:
#! /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
I've run it with the code below to test it and everything seems to work. First time it's run it will prompt you to calibrate the sensor by putting it at different distances from something.
#! /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)
I am pretty sure you want
while GPIO.input(GPIO_ECHO)==GPIO.LOW:
start = time.time()
while GPIO.input(GPIO_ECHO) == GPIO.HIGH:
stop = time.time()
I don't think GPIO.input naturally returns zeros or ones, you can test that though.
Not really, I think that i lost the signal, i'll try a timeout in
while GPIO.input(GPIO_ECHO)==GPIO.LOW:
start = time.time()
I think that my program wait indefinitely a signal but he stay to 0
I know this is an old question. The cause of the problem was described in this question https://raspberrypi.stackexchange.com/questions/41159/...
The solution is to add a timeout, like the OP did, to the while loops similar to this:
# 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()
First off, I'm very new to python. I have a raspberry pi connected via lan to a few nodes. I want the pi to be the power interface for the nodes. When a button is pressed, magic packets get sent to the nodes to wake them up. Once the nodes have been powered up, the same momentary switch will be able to power off the nodes, by ssh-ing into each and executing the "poweroff" command. While the machines are coming up, and while the machines are powering off, an LED should be blinking.
My attempt so far has most of the functionality I described, but the LED blinking is spotty, and I'm noticing that some of my threads are being redundantly executed.
My Question is, how do I get the led blinking to more accurately represent the state change of the machines.
Here is the script:
#!/usr/bin/python
import RPi.GPIO as GPIO
import threading
import time
import os
from subprocess import call
nodes = [
{
"name": "node-1",
"mac": "80:EE:73:AE:AA:7C",
"ip": "10.15.1.254",
},
#more nodes...
]
#function to blink the leds
def blink(pin,number):
try:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
count =0
while count < number:
GPIO.output(pin,GPIO.HIGH)
time.sleep(.5)
GPIO.output(pin,GPIO.LOW)
time.sleep(.5)
count +=1
return
except Exception as inst:
print "error: could not blink"
#function to turn LED on or off based on power state
def led(pin, state):
try:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)
if state ==1:
GPIO.output(pin, GPIO.HIGH)
else:
GPIO.output(pin, GPIO.LOW)
except:
print "error: could not turn on LED"
#function to wake up a node
def wake(node, mac):
try:
print "waking" +node
call(["wakeonlan", mac])
except Exception as inst:
print "error: could not wake " + node
#function to power off nodes
def shutdown(node, ip):
try:
print "shutting down " +node
call(["ssh", "-o", "StrictHostKeyChecking=no", "root#"+ip, "poweroff"])
except Exception as inst:
print "error: could not shutdown " + node
#function to check the state of the nodes (if node can be pinged, it is up)
def checkstate(node,ip):
try:
response = os.system("ping -i 0.1 -c 1 -w2 " + ip + " > /dev/null 2>&1")
if response == 0:
state =1
else:
state =0
return state
except:
print "error could not ping"
#function checks if all node states are the same
def checksame(list):
try:
list = iter(list)
first = next(list)
return all(first == rest for rest in list)
except StopIteration:
return list[0]
def main():
while True:
state = []
for node in nodes:
node_name = node.get('name', '')
node_ip = node.get('ip', '')
state.append(checkstate(node_name,node_ip)) #write each node state to an array
power_state = state[1]
if power_state ==1:
led(40,1) #turn LED on because all the nodes are on
if not checksame(state): #checks that all values in state array are the same. If not, led should blink because there is a state change or an error in a node
t = threading.Thread(target=blink, args=(40,8) )
t.start()
else:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(05, GPIO.IN, pull_up_down=GPIO.PUD_UP)
button_state = GPIO.input(05)
if button_state == False: #this is the button press detection
if power_state ==1:
#button has been pressed, and machines are on, need to be off
for node in nodes:
node_name = node.get('name', '')
node_ip = node.get('ip', '')
shutdown(node_name, node_ip)
print "Nodes have been shut down"
else:
#button has been pressed, machines are off, need to be on
for node in nodes:
node_name = node.get('name', '')
node_mac = node.get('mac', '')
wake(node_name,node_mac)
print "Nodes have been powered on"
t = threading.Thread(target=blink, args=(40, 180) )#this is a hack to show the LED blinking until the nodes can be pinged, otherwise, the LED would be off until the nodes were ping-able
t.start()
time.sleep(0.2)
if __name__ == "__main__":
main()
i need to combine my python codes which when the door is closed the PIR sensor will start to sense movement. when i combine these two files, it will run only the first while loop. it did not run to the next loop. can someone figure it out?
the first while loop:
#function for door closing
def door_open():
print("Door Open")
# function for the door closing
def door_close():
print("Door Close")
while True:
if GPIO.input(door_sensor): # if door is opened
if (sensorTrigger):
door_open() # fire GA code
sensorTrigger = False # make sure it doesn't fire again
if not io.input(door_sensor): # if door is closed
if not (sensorTrigger):
door_close() # fire GA code
sensorTrigger = True # make sure it doesn't fire again
second while loop:
Current_State = 0
Previous_State = 0
# Loop until PIR output is 0
while GPIO.input(GPIO_PIR)==1:
Current_State = 0
print " Ready"
while True :
# Read PIR state
Current_State = GPIO.input(GPIO_PIR)
if Current_State==1 and Previous_State==0:
# PIR is triggered
print " Motion detected!"
# Record previous state
Previous_State=1
elif Current_State==0 and Previous_State==1:
# PIR has returned to ready state
print " Ready"
Previous_State=0
# Wait for 10 milliseconds
time.sleep(0.01)
except KeyboardInterrupt:
print " Quit"
# Reset GPIO settings
GPIO.cleanup()
i try to combine these two loops, but the result only the first loop is run
#function for door closing
def door_open():
print("Door Open")
# function for the door closing
def door_close():
print("Door Close")
while True:
if GPIO.input(door_sensor): # if door is opened
if (sensorTrigger):
door_open() # fire GA code
sensorTrigger = False # make sure it doesn't fire again
if not io.input(door_sensor): # if door is closed
if not (sensorTrigger):
door_close() # fire GA code
sensorTrigger = True # make sure it doesn't fire again
door_close_thread = threading.Thread(target=door_close)
door_close_thread.daemon = True
door_close_thread.start()
Current_State = 0
Previous_State = 0
try:
print "Waiting for PIR to settle..."
# Loop until PIR output is 0
while GPIO.input(GPIO_PIR)==1:
Current_State = 0
print " Ready"
while True :
# Read PIR state
Current_State = GPIO.input(GPIO_PIR)
if Current_State==1 and Previous_State==0:
# PIR is triggered
print " Motion detected!"
# Record previous state
Previous_State=1
if not Current_State==0 and Previous_State==1:
# PIR has returned to ready state
print " Ready"
Previous_State=0
# Wait for 10 milliseconds
time.sleep(0.01)
except KeyboardInterrupt:
print " Quit"
# Reset GPIO settings
GPIO.cleanup()
Don't use two while loops.
The only way you'll break out of while True: is by calling break.
Use a single while loop and split it with if conditionals.