Pregunta

Estoy intentando controlar mi automóvil Raspberry Pi mediante conexión inalámbrica y webiopi.La función básica funciona bien: tengo la interfaz donde hago clic en avance y el automóvil avanzará y cuando suelte el botón se detendrá.

Ahora quiero integrar el sensor de distancia ultrasónico para que cuando conduzca hacia adelante, el automóvil se detenga cuando haya algo delante.Lo tengo en modo donde cuando hago clic en el botón de avance, el automóvil se moverá y se detendrá cuando algo esté dentro del alcance, pero solo se detendrá cuando algo esté dentro del alcance y no cuando suelte el botón.Mi bucle while de alguna manera está en bucle (atascado) y no lee la función del botón de liberación de webiopi.

¿Puede alguien ayudarme? Llevo días haciéndolo y no estoy seguro de dónde me estoy equivocando :-(

Aquí está el bucle de mi script en Python:

def go_forward(arg):
  global motor_stop, motor_forward, motor_backward, get_range
  print "Testing"
  print mousefwd()
  while (arg) == "fwd":
      print (arg)
      direction = (arg)
      dist = get_range()
      print "Distance %.1f " % get_range()
      if direction == "fwd" and get_range() < 30:
          motor_stop()
          return
      else:
          motor_forward()

Y aquí está el código de mi llamada a la función webiopi:

 function go_forward() {
              var args = "fwd"
              webiopi().callMacro("go_forward", args);
      }
 function stop1() {
              var args = "stop"
              webiopi().callMacro("go_forward", args);
              webiopi().callMacro("stop");
    }

Así es como lo tengo ahora pero todavía no funciona (soy un novato total :-)):

 def go_forward(arg):
  global motor_stop, motor_forward, motor_backward, get_range
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % get_range()
      if get_range() < 30:
         motor_stop()
      elif direction == "fwd":
         motor_forward()
      else:
         motor_stop()

Quizás un pequeño paso adelante.Vea que webipi usa su propio 'bucle' y agregué el código de bucle para verificar cuál es el estado de los GPIO del motor y la distancia, y si el motor está funcionando y si la distancia es demasiado corta, entonces deténgase.El auto se mueve ahora cuando presiono el botón de avance y se detiene cuando lo suelto y cuando avanza y la distancia es inferior a 30 cm, se detendrá.El único problema es que cuando la distancia es demasiado corta y presiono el botón de avance demasiado rápido varias veces, ahora obtengo un "gpio.output (echo, 1) _webiopi.gpio.invaliddirectionException:El canal GPIO no es un error de SALIDA :-( .

El Código ahora se ve así:

 def go_forward(direction):
   motor_forward()

 def loop():
   if get_range() < 30 and GPIO.digitalRead(M1) == GPIO.HIGH:
     stop()
     print "stop"
   sleep(1)
¿Fue útil?

Solución

Responderé a tu problema principal en un minuto, pero primero quiero mencionar algo que estás haciendo como principiante de Python, lo que hace tu vida más complicada de lo necesario.

No hay necesidad de global declaración que tiene al comienzo de su función.En Python, sólo necesitas usar el global declaración si quieres escribir a una variable global.Si todo lo que necesitas hacer es leer la variable o llamar a la función, entonces no hay necesidad de global declaración.Cualquier nombre utilizado en su función, ya sean nombres de variables o nombres de funciones, se buscará en el siguiente orden:local, envolvente, global, incorporado."Local" significa nombres definidos dentro de su función, como su direction variable."Encerrar" es una regla que se utiliza cuando se define una función dentro de otra función.Esto es útil en muchas situaciones, pero es un tema un poco avanzado y no necesita preocuparse por ello por ahora."Global" significa nombres (de variables, funciones o clases) definidos en el nivel superior de su programa, como su motor_stop función entre otros.Y finalmente, "integrado" significa los nombres integrados de Python, como str o int o file.

Así que si omitiste el global declaración, entonces Python buscaría el nombre motor_stop (y los otros nombres de funciones) de la siguiente manera:

  1. Local: Hay una motor_stop definido en esta función?No.Hacia adelante.
  2. Adjunto: ¿Esta función está definida dentro de otra función?No, por lo que la regla de "adjuntar" no se aplica.Hacia adelante.
  3. Global: Hay una motor_stop definido en el nivel superior del programa?Sí.Lo encontré.
  4. (Incorporado):Esta regla nunca se verifica en absoluto porque el nombre fue encontrado mediante la regla "global".

Todas sus funciones están definidas en el nivel superior de su programa, por lo que la regla "global" las encontrará sin necesidad de global declaración.Esto debería hacer tu vida un poco más sencilla.

Ahora para tu pregunta principal:por qué su código se repite para siempre.Esto se debe a que la condición de prueba de su while El bucle nunca se volverá falso.Estas dando vueltas while direction == "fwd", y el código dentro del while El bucle nunca cambia el direction variable.Entonces, cada vez que llega al final del ciclo, vuelve a probar la condición nuevamente.El direction La variable todavía contiene la cadena. "fwd", por lo que el ciclo while se ejecuta por segunda vez.Entonces el direction La variable todavía contiene la cadena. "fwd", y así se ejecuta por tercera vez.Y así sucesivamente y así sucesivamente.

Una manera de salir del while bucle cuando desea que salga sería configurar el direction variable a otra cosa, como "stop", cuando quieras parar.(Por ejemplo, después de llamar motor_stop()).Otra forma sería utilizar el return declaración para salir de la función en ese punto.Pero mi sugerencia sería utilizar el break Declaración en su lugar, lo que significa "en este punto, inmediatamente salga del bucle en el que estoy". Funciona en ambos while bucles y for bucles, y es una declaración muy útil para conocer.Parece que quieres tu while bucle para salir cada vez que llames motor_stop(), entonces hay dos lugares donde colocarías un break declaración:

def go_forward(arg):
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % get_range()
      if get_range() < 30:
         motor_stop()
         break
      elif direction == "fwd":
         motor_forward()
         # No break statement here, so the while loop continues
      else:
         motor_stop()
         break

Hay algunos otros cambios que sugeriría hacer.primero llamas get_range() tres veces en tu bucle, pero en realidad sólo necesitas llamarlo una vez.Ya has asignado su resultado a un dist variable, entonces ¿por qué no usar esa variable?

def go_forward(arg):
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % dist
      if dist < 30:
         motor_stop()
         break
      elif direction == "fwd":
         motor_forward()
         # No break statement here, so the while loop continues
      else:
         motor_stop()
         break

Y segundo, no hay manera de entrar al while bucle para direction no ser "fwd", por lo que el final else es innecesario y su función puede convertirse en:

def go_forward(arg):
  print "Testing"
  direction = arg
  while direction == "fwd":
      print arg
      dist = get_range()
      print "Distance %.1f " % dist
      if dist < 30:
         motor_stop()
         break
      else:
         motor_forward()

Finalmente, tienes un parámetro de función llamado arg, que es un nombre que no dice nada sobre para qué se utiliza.Inmediatamente lo asignas a una variable llamada direction, que es un nombre mucho mejor.Entonces, ¿por qué no utilizarlo como nombre del parámetro en primer lugar?No hay ninguna regla que diga los parámetros de una función. debe llamarse "arg";se les puede llamar como quieras (excepto una de las palabras reservadas de Python como break o if).Así que démosle a tu función un nombre de parámetro más significativo, y eso la simplificará aún más:

def go_forward(direction):
  print "Testing"
  while direction == "fwd":
      print direction
      dist = get_range()
      print "Distance %.1f " % dist
      if dist < 30:
         motor_stop()
         break
      else:
         motor_forward()

Allá.Esto es mucho más fácil de leer y comprender, y debería resolver el problema que estabas viendo en tu while El bucle no sale cuando el automóvil se acerca demasiado a un objeto.

(Todavía hay un posible problema que puedo ver, y es que es posible que el bucle while no salga mientras el auto avanza, incluso si soltaste el botón "adelante", pero tendría que ver tu motor_forward() código para saber cómo resolver ese.Podría ser tan simple como poner un break declaración después motor_forward(), en cuyo caso realmente no habría necesidad de un while bucle en absoluto, pero tendría que saber cómo motor_forward() El código interactúa con webiopi y cómo funciona el código de manejo de eventos de webiopi.Ninguno de los cuales sé ahora, así que voy a responder qué problemas puedo responder ahora incluso si mi respuesta está incompleta, en lugar de dejarlos sin ninguna respuesta).

Editado por Mark: Aquí está el código motor_forward:

 def motor_forward():
     GPIO.output(M1, GPIO.HIGH)
     GPIO.output(M2, GPIO.LOW)
     string = "echo 0=130 > /dev/servoblaster"
     os.system(string)

Otros consejos

Pruebe esto: siempre se detiene en el rango, pero puede dejar de detenerse en la dirección

  if get_range() < 30:
      motor_stop()
  elif direction == "fwd":
      motor_forward()
  else:
      motor_stop()

Por cierto, no necesita el ARG (ARG) solo cuando lo hace referencia

imprimir arg

Los parens en la firma de llamadas están ahí para mostrar que es un parm a una función

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top