Lightswitch sin touchs con Raspberry Pi -- python campo con beginner campo con timer campo con raspberry-pi camp codereview Relacionados El problema

Touchless lightswitch with Raspberry Pi


10
vote

problema

Español

Actualmente estoy desarrollando un interruptor de luz sin contacto a través de una PI de frambuesa, un módulo ultrasónico y un bonito módulo de radio.

Sin embargo, soy bastante principiante en Python y fue difícil (al menos para mí) lograr mi objetivo. Cada vez que la distancia medida se cae por debajo del límite, el interruptor se dispara "ON" (1) y, después de eso, si la distancia se está reduciendo nuevamente, el interruptor se activa "OFF" (0).

  #!/usr/bin/env python  import os import sys import time import RPi.GPIO as GPIO  GPIOTrigger = 23 GPIOEcho    = 24  def wait(sec):   while sec > 0:     sys.stdout.write(str(sec) + '      ')     sec -= 1     time.sleep(1)  def MeasureDistance():   GPIO.output(GPIOTrigger, True)   time.sleep(0.00001)   GPIO.output(GPIOTrigger, False)   StartTime = time.time()   while GPIO.input(GPIOEcho) == 0:     StartTime = time.time()   while GPIO.input(GPIOEcho) == 1:     StopTime = time.time()   TimeElapsed = StopTime - StartTime   Distance = (TimeElapsed * 34300) / 2   return Distance def main():   STATUS = 0   try:     while True:       Distance = MeasureDistance()       if Distance > 10.0:         time.sleep(0.01)       else:         if STATUS != 1:       print("Passing by (%.1f cm)" % Distance)           import subprocess           subprocess.call(["/root/rcswitch-pi/send", "10000", "1", "1"])           wait(5)           STATUS = 1         else:           subprocess.call(["/root/rcswitch-pi/send", "10000", "1", "0"])           wait(5)           STATUS = 0    except KeyboardInterrupt:     print("Stopped by user")     GPIO.cleanup() if __name__ == '__main__':   # use GPIO pin numbering convention   GPIO.setmode(GPIO.BCM)   GPIO.setup(GPIOTrigger, GPIO.OUT)   GPIO.setup(GPIOEcho, GPIO.IN)   GPIO.output(GPIOTrigger, False)   main()   

Esto funciona pero no estoy seguro de si hay una mejor manera de determinar el último estado de STATUS o si hay algunas trampas que podría no ver.

Original en ingles

I am currently developing a touchless lightswitch via a Raspberry Pi, an ultrasonic module and a nice radio module.

However, I am quite a beginner in Python and it was a hard time (at least for me) to accomplish my goal. Whenever the measured distance is falling below the limit the switch is triggered "on" (1) and after that if the distance is falling short again the switch is triggered "off" (0).

#!/usr/bin/env python  import os import sys import time import RPi.GPIO as GPIO  GPIOTrigger = 23 GPIOEcho    = 24  def wait(sec):   while sec > 0:     sys.stdout.write(str(sec) + '     \r')     sec -= 1     time.sleep(1)  def MeasureDistance():   GPIO.output(GPIOTrigger, True)   time.sleep(0.00001)   GPIO.output(GPIOTrigger, False)   StartTime = time.time()   while GPIO.input(GPIOEcho) == 0:     StartTime = time.time()   while GPIO.input(GPIOEcho) == 1:     StopTime = time.time()   TimeElapsed = StopTime - StartTime   Distance = (TimeElapsed * 34300) / 2   return Distance def main():   STATUS = 0   try:     while True:       Distance = MeasureDistance()       if Distance > 10.0:         time.sleep(0.01)       else:         if STATUS != 1:       print("Passing by (%.1f cm)" % Distance)           import subprocess           subprocess.call(["/root/rcswitch-pi/send", "10000", "1", "1"])           wait(5)           STATUS = 1         else:           subprocess.call(["/root/rcswitch-pi/send", "10000", "1", "0"])           wait(5)           STATUS = 0    except KeyboardInterrupt:     print("Stopped by user")     GPIO.cleanup() if __name__ == '__main__':   # use GPIO pin numbering convention   GPIO.setmode(GPIO.BCM)   GPIO.setup(GPIOTrigger, GPIO.OUT)   GPIO.setup(GPIOEcho, GPIO.IN)   GPIO.output(GPIOTrigger, False)   main() 

This works but I am unsure whether there is a nicer way of determining the last status of STATUS or if there are some pitfalls I might not see.

           

Lista de respuestas

2
 
vote
vote
La mejor respuesta
 

MeasureDistance . La forma en que está escrita, a veces mide la duración de la señal, a veces el tiempo (deseado) para que llegue el ECHO (considere lo que sucede si ingresa el primer 9988777665544332 Loop). Sugerencia:

  def MeasureDistance():     StartTime = time.time()     GPIO.output(GPIOTrigger, True)     while GPIO.input(GPIOEcho) == 0:         pass     # Found the raising front     StopTime = time.time()     GPIO.output(GPIOTrigger, False)   

Por supuesto, si el eco llega más rápido de lo que se ejecuta el código (y Python es lento), obtendrías el tiempo transcurrido 0. Supongo que no hay nada que pueda hacer al respecto, aparte de recurrir a las interrupciones. Además, es posible que desee poner algunas salvaguardas (tal vez un temporizador) en caso de que el frente de elevación nunca llegue.

main . No veo la necesidad de import subprocess en el medio del código. Además, las variables estatales tienden a crear un código no matriz. Sugerencia:

      try:         Distance = MeasureDistance()         while True:             while Distance > 10.0:                 Distance = MeasureDistance()                 wait(5)             switch_on()             while Distance < 10.0:                 Distance = MeasureDistance()                 wait(5)             switch_off()     except KeyboardInterrupt:   

PS: A MAGIC 34300 Constante debe ir. Dale un buen nombre simbólico (sí, todos sabemos que tiene algo que ver con la velocidad del sonido).

actualización. Por lo general, en las situaciones como la tuya, puede tener un comportamiento divertido a la distancia de ruptura. Debido a factores aleatorios (como el tiempo de ejecución del código, y muchos más) la distancia se mide con un cierto error, y el interruptor continuará y se apagará de manera impredecible. Para lidiar con él, permitir una histéresis:

              while Distance > breaking_distance - tolerance:                 Distance = MeasureDistance()                 wait(5)             switch_on()             while Distance < breaking_distance + tolerance:                 Distance = MeasureDistance()                 wait(5)             switch_off()   
 

MeasureDistance. The way it is written, sometimes it measures the duration of the signal, sometimes the (desired) time for the echo to arrive (consider what happens if you enter the first while loop). Suggestion:

def MeasureDistance():     StartTime = time.time()     GPIO.output(GPIOTrigger, True)     while GPIO.input(GPIOEcho) == 0:         pass     # Found the raising front     StopTime = time.time()     GPIO.output(GPIOTrigger, False) 

Of course, if the echo arrives faster than the code executes (and Python is slow), you'd get the elapsed time 0. I suppose there's nothing you can do about that, other than resorting to interrupts. Also, you may want to put some safeguards (a timer maybe) in case the raising front never arrives.

main. I don't see the need to import subprocess in the middle of the code. Also, state variables tend to create an unmaintainable code. Suggestion:

    try:         Distance = MeasureDistance()         while True:             while Distance > 10.0:                 Distance = MeasureDistance()                 wait(5)             switch_on()             while Distance < 10.0:                 Distance = MeasureDistance()                 wait(5)             switch_off()     except KeyboardInterrupt: 

PS: a magic 34300 constant must go. Give it a nice symbolic name (yes we all know it has something to do with the speed of sound).

Update. Usually in the situations like yours you may have a funny behaviour at the breaking distance. Due to random factors (like the code execution time, and many more others) the distance is measured with a certain error, and the switch will go on and off unpredictably. To deal with it, allow for a hysteresis:

            while Distance > breaking_distance - tolerance:                 Distance = MeasureDistance()                 wait(5)             switch_on()             while Distance < breaking_distance + tolerance:                 Distance = MeasureDistance()                 wait(5)             switch_off() 
 
 

Relacionados problema

7  Control de sirena de Python  ( Python siren control ) 
A continuación se muestra algún código que he reunido para contolar una sirena para un servicio de incendio. Funciona por WebScraping un feed de paginación ...

4  Presentación de diapositivas de Pygame  ( Pygame slideshow ) 
He escrito un programa básico de presentación de diapositivas que utiliza Pygame para administrar la pantalla de visualización. Cicliza a través de todos los ...

1  MultiPhReed MJPG Network Stream Server  ( Multithreaded mjpg network stream server ) 
Soy un poco de neófito cuando se trata de C ++, y así me gustaría algún comentario sobre un proyecto reciente. El código se sienta en un PI de frambuesa y t...

11  Tablero de botón Python RPI  ( Python rpi button board ) 
Mi proyecto consiste en un PI 2B v1.1 de Raspberry conectado a una serie de botones Push-Botones a través de Pins GPIO. El objetivo es crear un panel de boton...

4  Reconociendo una secuencia de lectura a través del software OCR  ( Recognizing a sequence read through ocr software ) 
Estoy tratando de reconocer una oración que he leído a través del software de reconocimiento de caracteres ópticos. Este código finalmente se ejecutará en una...

1  Programa de manejador de eventos basado en el microcontrolador Arduino, envíe las lecturas del sensor sobre el bus en serie  ( Arduino microcontroller based event handler program send sensor readings over s ) 
Estoy trabajando en un proyecto con un microcontrolador Arduino y un PI de frambuesa. El código tendrá que hacer lo siguiente: Si la varianza calculada de...

19  Encienda automáticamente la computadora de Raspberry Pi (según la presencia del usuario en el hogar)  ( Automatically turn on computer from raspberry pi based on user presence in home ) 
Sé que el código está lleno de datos inútiles y errores de estilismo y análisis, y realmente me encantaría y apreciaría tener una idea de un profesional para ...

4  Respondiendo a la entrada en serie  ( Responding to serial input ) 
Este código para la placa PI de Raspberry espera para la entrada en serie, luego reproduce una flecha con un sonido y un mensaje. Quisiera algún comentario o ...

2  D20PFSRD DISCORD BOT SCRAPER ABSTRACCIÓN Y DESMISAMIENTO  ( D20pfsrd discord bot scraper abstraction and deployment ) 
Escribí un bot de la discordia que escucha los enlaces al reglamento D20PFSRD en el chat de la discordia, verifica si son hazañales o magia, y luego raspa la ...

7  Controlador de calefacción de la frambuesa PI  ( Raspberry pi heating controller ) 
En "la mayoría" (mi experiencia) casas antiguas del Reino Unido, calefacción central y agua caliente vienen en una caldera de gas. Están controlados por un pr...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos