Question

J'essaie de contrôler ma voiture Raspberry Pi via sans fil et webiopi.La fonction de base fonctionne bien - ayez l'interface où je clique sur FWD et la voiture avancera et lorsque je relâcherai le bouton, elle s'arrêtera.

Je souhaite maintenant intégrer le capteur de distance à ultrasons afin que lorsque j'avance, la voiture s'arrête lorsque quelque chose se trouve devant elle.Je le fais où, lorsque je clique sur le bouton Avancer, la voiture roulera et s'arrêtera lorsque quelque chose sera à portée, mais elle ne s'arrêtera que lorsque quelque chose sera à portée et non lorsque je relâcherai le bouton.Ma boucle while est en quelque sorte en boucle (bloquée) et ne lit pas la fonction du bouton de déverrouillage de webiopi.

Quelqu'un peut-il m'aider s'il vous plaît - j'y travaille depuis des jours maintenant et je ne sais pas où je me trompe :-(

Voici la boucle de mon script 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()

Et voici le code de mon appel de fonction 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");
    }

C'est comme ça que je l'ai maintenant mais ça ne marche toujours pas (je suis un total noob :-)) :

 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()

Peut-être un léger pas en avant.Voyez que webipi utilise sa propre « boucle » et j'ai ajouté le code de boucle pour vérifier quel est l'état des GPIO du moteur et la distance et si le moteur tourne et si la distance est trop courte, arrêtez-vous.La voiture bouge maintenant lorsque j'appuie sur le bouton avant et s'arrête lorsque je le relâche. Lorsque j'avance et que la distance est inférieure à 30 cm, elle s'arrête.Le seul problème est que lorsque la distance est trop courte et que j'appuie sur le bouton avant trop rapidement plusieurs fois, j'obtiens maintenant un "gpio.output (echo, 1) _webiopi.gpio.invaliddirectionException:Le canal GPIO n'est pas une erreur OUTPUT" :-( .

Le Code ressemble maintenant à ceci :

 def go_forward(direction):
   motor_forward()

 def loop():
   if get_range() < 30 and GPIO.digitalRead(M1) == GPIO.HIGH:
     stop()
     print "stop"
   sleep(1)
Était-ce utile?

La solution

Je répondrai à votre problème principal dans une minute, mais je tiens d'abord à mentionner quelque chose que vous faites en tant que débutant en Python, ce qui rend votre vie plus compliquée qu'elle ne devrait l'être.

Il n'y a pas besoin du global déclaration que vous avez au début de votre fonction.En Python, il vous suffit d'utiliser le global déclaration si vous voulez écrire à une variable globale.Si tout ce que vous avez à faire est lire la variable, ou appeler la fonction, alors il n'y a pas besoin du global déclaration.Tous les noms utilisés dans votre fonction, qu'il s'agisse de noms de variables ou de noms de fonctions, seront recherchés dans l'ordre suivant :local, englobant, global, intégré."Local" signifie les noms définis dans votre fonction, comme votre direction variable."Enclosing" est une règle utilisée lorsque vous définissez une fonction à l'intérieur d'une autre fonction.Ceci est utile dans de nombreuses situations, mais il s’agit d’un sujet un peu avancé et vous n’avez pas à vous en préoccuper pour l’instant."Global" signifie les noms (de variables, de fonctions ou de classes) définis au niveau supérieur de votre programme -- comme votre motor_stop fonction entre autres.Et enfin, « builtin » désigne les noms intégrés de Python, comme str ou int ou file.

Donc si vous avez laissé de côté le global instruction, alors Python rechercherait le nom motor_stop (et les autres noms de fonctions) comme suit :

  1. Locale: Y a-t-il un motor_stop défini dans cette fonction ?Non.Passons à autre chose.
  2. Ci-joint : Cette fonction est-elle définie dans une autre fonction ?Non, donc la règle du « englobant » ne s'applique pas.Passons à autre chose.
  3. Mondial: Y a-t-il un motor_stop défini au niveau supérieur du programme ?Oui.Je l'ai trouvé.
  4. (Intégré):Cette règle n'est jamais vérifiée, car le nom a été trouvé par la règle "globale".

Toutes vos fonctions sont définies au niveau supérieur de votre programme, donc la règle "globale" les trouvera sans avoir besoin du global déclaration.Cela devrait vous rendre la vie un peu plus simple.

Maintenant pour votre question principale :pourquoi votre code tourne pour toujours.C'est parce que le test conditionne votre while la boucle ne deviendra jamais fausse.Vous êtes en boucle while direction == "fwd", et le code à l'intérieur du while la boucle ne change jamais le direction variable.Ainsi, chaque fois qu’il atteint la fin de la boucle, il revient pour tester à nouveau la condition.Le direction la variable contient toujours la chaîne "fwd", et donc la boucle while s'exécute une deuxième fois.Puis le direction la variable contient toujours la chaîne "fwd", et donc il s'exécute une troisième fois.Ainsi de suite.

Une façon de sortir du while boucle quand vous voulez qu'elle se termine serait de définir le direction variable à autre chose, comme "stop", quand tu veux arrêter.(Par exemple, après avoir appelé motor_stop()).Une autre façon serait d'utiliser le return instruction pour quitter la fonction à ce stade.Mais ma suggestion serait d'utiliser le break Déclaration à la place, ce qui signifie "à ce stade, quittez immédiatement la boucle dans laquelle je suis." Cela fonctionne sur les deux while boucles et for boucles, et c'est une déclaration très utile à connaître.On dirait que tu veux ton while boucle pour sortir à chaque fois que vous appelez motor_stop(), il y a donc deux endroits où vous mettriez un break déclaration:

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

Il y a quelques autres changements que je suggérerais d'apporter.D'abord, tu appelles get_range() trois fois dans votre boucle, mais vous n'avez vraiment besoin de l'appeler qu'une seule fois.Vous avez déjà attribué son résultat à un dist variable, alors pourquoi ne pas utiliser cette 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

Et deuxièmement, il n'y a aucun moyen d'entrer dans le while boucle pour direction pas être "fwd", donc la finale else n'est pas nécessaire, et votre fonction peut devenir :

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()

Enfin, vous disposez d'un paramètre de fonction nommé arg, qui est un nom qui ne vous dit rien sur son utilisation.Vous l'attribuez immédiatement à une variable appelée direction, qui est un bien meilleur nom.Alors pourquoi ne pas l’utiliser comme nom de paramètre en premier lieu ?Il n'y a aucune règle qui indique les paramètres d'une fonction doit être appelé « argument » ;ils peuvent être appelés comme vous le souhaitez (sauf l'un des mots réservés de Python comme break ou if).Donnons donc à votre fonction un nom de paramètre plus significatif, et cela la simplifiera encore davantage :

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()

Là.C'est beaucoup plus facile à lire et à comprendre, et cela devrait résoudre le problème que vous rencontriez sur votre while la boucle ne sort pas lorsque la voiture s'approche trop près d'un objet.

(Il y a encore un problème possible que je peux voir, c'est que la boucle while pourrait ne pas se terminer pendant que la voiture avance, même si vous avez relâché le bouton "avancer" -- mais je devrais voir votre motor_forward() code pour savoir comment résoudre celui-là.Cela pourrait être aussi simple que de mettre un break déclaration après motor_forward(), auquel cas il n'y aurait vraiment pas besoin d'un while boucle du tout - mais je devrais savoir comment votre motor_forward() le code interagit avec webiopi et comment fonctionne le code de gestion des événements de webiopi.Je ne connais rien pour le moment, je vais donc répondre aux problèmes auxquels je peux répondre maintenant même si ma réponse est incomplète, plutôt que de vous laisser sans réponse du tout.)

Edité par Mark : Voici le code motor_forward :

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

Autres conseils

Essayez ceci - vous arrêtez toujours de la portée mais vous voudrez peut-être vous arrêter sur la direction

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

BTW Vous n'avez pas besoin de (arg) seulement argument lorsque vous y référez-le

Imprimer arg

Les parens dans la signature d'appel sont là pour montrer son param à une fonction

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top