I've got a tornado web server running on my Raspberry and a ultrasonic sensor connected to it. I've got a html page with a start and stop button, when I click start the script is sending a message "start" to the serwer and it runs a function that prints the distance.
Now i'm trying to stop the function when clicking stop button. But when te function is printing the distances and I click the stop button on my website the server doesnt recive the "stop" message.
The code is here: http://pastebin.com/SVRZNXgH
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
# Ta funkcja dokonuje pomiaru odleglosci
def pomiar():
# Ustawienie pinow czujnika odleglosci
GPIO_TRIGGER = 16
GPIO_ECHO = 18
# Ustawienie pinu buzzera
GPIO_BUZZER = 22
# Ustawienie pinu serwomechanizmu
GPIO_SERVO = 13
# Ustawienie pinow
GPIO.setup(GPIO_TRIGGER,GPIO.OUT)
GPIO.setup(GPIO_ECHO,GPIO.IN)
GPIO.setup(GPIO_SERVO,GPIO.OUT)
# Ustawienie Trigget jako false (stan niski)
GPIO.output(GPIO_TRIGGER, False)
GPIO.setup(GPIO_TRIGGER,GPIO.OUT)
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
start = time.time()
while GPIO.input(GPIO_ECHO)==0:
start = time.time()
while GPIO.input(GPIO_ECHO)==1:
stop = time.time()
elapsed = stop-start
distance = (elapsed * 34300)/2
print "odleglosc : %.1f" % distance
time.sleep(2)
return distance
# Funkcja dokonujaca sprawdzenia kata
def sprawdz_kat():
GPIO_SERVO = 13
GPIO.setup(GPIO_SERVO,GPIO.OUT)
p = GPIO.PWM(GPIO_SERVO,50)
katy = [10,12.5,5,2.5];
start = 20.0;
for x in katy:
p.ChangeDutyCycle(x)
time.sleep(0.5)
odleglosc = pomiar()
print "odleglosc : %.1f" % odleglosc
if(odleglosc>start):
start=odleglosc
kat = x
if(kat==10):
return float(-45)
if(kat==12.5):
return float(-90)
if(kat==5):
return float(45)
if(kat==2.5):
return float(90)
# Funkcja do obrotu robota o zadany kat
def obrot(kat):
obrot=abs(kat/100)
print(obrot)
if(kat<0):
GPIO.output(M1_EN, True) # True - do przodu, False - do tylu
GPIO.output(M2_EN, True) # False - do przodu, True - do tylu
else:
GPIO.output(M1_EN, False) # True - do przodu, False - do tylu
GPIO.output(M2_EN, False) # False - do przodu, True - do tylu
LEWA_PWM.ChangeDutyCycle(25)
PRAWA_PWM.ChangeDutyCycle(25)
time.sleep(obrot)
LEWA_PWM.ChangeDutyCycle(0)
PRAWA_PWM.ChangeDutyCycle(0)
GPIO.output(M1_EN, True)
GPIO.output(M2_EN, False)
# Program labiryntu
def labirynt():
distance = pomiar()
p.start(7.5)
while True:
distance = pomiar()
GPIO.setup(GPIO_BUZZER,GPIO.OUT)
GPIO.output(GPIO_BUZZER, False)
time.sleep(0.08)
GPIO.setup(GPIO_BUZZER,GPIO.IN)
time.sleep(distance/500)
LEWA_PWM.ChangeDutyCycle(10)
PRAWA_PWM.ChangeDutyCycle(10)
if(distance<50):
LEWA_PWM.ChangeDutyCycle(0)
PRAWA_PWM.ChangeDutyCycle(0)
kat = sprawdz_kat()
print kat
obrot(kat)
p.ChangeDutyCycle(7.5)
time.sleep(0.5)
GPIO.setup(GPIO_SERVO,GPIO.IN)
GPIO.cleanup
def stop_all():
GPIO.output(GPIO_TRIGGER, False)
GPIO.output(GPIO_ECHO, False)
GPIO.cleanup()
# Ustawienie pinow czujnika odleglosci
GPIO_TRIGGER = 16
GPIO_ECHO = 18
# Ustawienie pinu buzzera
GPIO_BUZZER = 22
# Ustawienie pinu serwomechanizmu
GPIO_SERVO = 13
# Ustawienie pinow
GPIO.setup(GPIO_TRIGGER,GPIO.OUT)
GPIO.setup(GPIO_ECHO,GPIO.IN)
GPIO.setup(GPIO_SERVO,GPIO.OUT)
# Ustawienie Trigget jako false (stan niski)
GPIO.output(GPIO_TRIGGER, False)
# Ustawienia dla serwa
p = GPIO.PWM(GPIO_SERVO,50) #Ustawienie czestotliwosci na 50Hz
#poczatkowy kat serwa 90 stopni (neutralny)
# Ustawienia buzzera
GPIO.setup(GPIO_BUZZER,GPIO.IN)
# -----------------------
# Ustawienia silnikow
# -----------------------
# Prawa strona
M1_PWM = 26
M1_EN = 24
# Lewa strona
M2_PWM = 23
M2_EN = 21
# Prawa strona ustawienia jako output
GPIO.setup(M1_PWM,GPIO.OUT)
GPIO.setup(M1_EN,GPIO.OUT)
# Lewa strona ustawienia jako output
GPIO.setup(M2_PWM,GPIO.OUT)
GPIO.setup(M2_EN,GPIO.OUT)
# Prawa strona ustawienie stanow niskich
GPIO.output(M1_PWM, False)
GPIO.output(M1_EN, True) # True - do przodu, False - do tylu
# Lewa strona ustawienie stanow niskich
GPIO.output(M2_PWM, False)
GPIO.output(M2_EN, False) # False - do przodu, True - do tylu
# Ustawienie PWM dla prawej strony
PRAWA_PWM = GPIO.PWM(26,50)
# Ustawienie PWM dla lewej strony
LEWA_PWM = GPIO.PWM(23,50)
# Poczatkowe ustawienia PWM silnikow
PRAWA_PWM.start(0)
LEWA_PWM.start(0)
from tornado.options import define, options
define("port", default=8080, help="run on the given port", type=int)
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html')
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print 'new connection'
self.write_message("connected")
def on_message(self, message):
print 'message received %s' % message
self.write_message('message received %s' % message)
aaa = message
if message == "gora":
GPIO.output(M1_EN, True)
GPIO.output(M2_EN, False)
LEWA_PWM.ChangeDutyCycle(8)
PRAWA_PWM.ChangeDutyCycle(8)
if message == "dol":
GPIO.output(M1_EN, False)
GPIO.output(M2_EN, True)
LEWA_PWM.ChangeDutyCycle(8)
PRAWA_PWM.ChangeDutyCycle(8)
if message == "stop":
LEWA_PWM.ChangeDutyCycle(0)
PRAWA_PWM.ChangeDutyCycle(0)
if message == "lewo":
GPIO.output(M1_EN, True)
GPIO.output(M2_EN, True)
LEWA_PWM.ChangeDutyCycle(20)
PRAWA_PWM.ChangeDutyCycle(20)
if message == "prawo":
GPIO.output(M1_EN, False)
GPIO.output(M2_EN, False)
LEWA_PWM.ChangeDutyCycle(20)
PRAWA_PWM.ChangeDutyCycle(20)
while (aaa == "start_maze"):
pomiar()
def on_close(self):
print 'connection closed'
if __name__ == "__main__":
tornado.options.parse_command_line()
app = tornado.web.Application(
handlers=[
(r"/", IndexHandler),
(r"/ws", WebSocketHandler),
(r'/js/(.*)', tornado.web.StaticFileHandler, {'path': "/home/pi/js"}),
(r'/css/(.*)', tornado.web.StaticFileHandler, {'path': "/home/pi/css"}),
(r'/fonts/(.*)', tornado.web.StaticFileHandler, {'path': "/home/pi/fonts"}),
]
)
httpServer = tornado.httpserver.HTTPServer(app)
httpServer.listen(options.port)
print "Listening on port:", options.port
tornado.ioloop.IOLoop.instance().start()
The reason is that you got an endless loop in line 227.
One possible solution:
pomiar
function a method of the websocket handlerself.running
and on start set it to true. And call self.pomiar()
self.running
to false
pomiar
remove the time.sleep
it does block the complete tornado server. Instead:...
if self.running:
tornado.ioloop.IOLoop.instance().add_timeout(time.time() + 2, self.pomiar)
The add_timeout makes tornado call your pomiar function again in two seconds. Checking first if self.running
is still true
makes sure your pomiar
function is only called as long as stop is not called.
There are a lot of other ways to solve this. You might want to read more about tornado and the asynchronous functions it provides, for example: http://tornado.readthedocs.org/en/latest/gen.html