Pergunta

Estou tentando controlar meu Raspberry Pi carro via celular e webiopi.A função básica funciona bem, tem o interface onde eu clique em avançar e o carro vai para frente e quando eu soltar o botão, ele irá parar.

Eu agora gostaria de integrar o medidor de distância Ultra-sensor, de modo que, quando vou de carro para a frente, o carro deve parar quando algo está em frente a ela.Eu tenho que ir, onde, quando eu clico para botão fwd, o carro vai de carro e parar quando algo está dentro de alcance, mas ele só irá parar quando algo está no intervalo e não quando eu soltar o botão.Meu while é, de alguma forma, loop (preso) e não lendo o botão de liberação da função de webiopi.

Alguém pode por favor ajudar - feito isso para os dias agora e não sabe onde eu estou indo mal :-(

Aqui é o loop do meu 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()

E aqui está o código do meu webiopi chamada de função:

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

Isto é como eu tenho agora, mas ainda não está funcionando (eu sou um noob 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()

Talvez um ligeiro passo em frente.Veja que webipi utiliza o seu próprio 'loop' e eu adicionei o código do loop para verificar qual o estado do motor GPIO somos e a distância e se o motor estiver em execução e se a distância é muito curta, em seguida, parar.Carro se move agora quando eu pressionar o botão de avanço e pára quando eu liberá-lo e quando o movimento para a frente e distância mínima de 30cm ele vai parar.O único problema é que quando a distância é muito curta e eu pressione o botão avançar muito rapidamente várias vezes, agora eu recebo um "GPIO.saída(Eco,1) _webiopi.GPIO.InvalidDirectionException:O GPIO canal não é uma SAÍDA de erro": - ( .

O Código parece agora como esta:

 def go_forward(direction):
   motor_forward()

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

Solução

Eu vou responder a sua principal problema em um minuto, mas, primeiro, quero mencionar algo que você está fazendo como um iniciante em Python, que é o de tornar a sua vida mais complicada do que ele precisa ser.

Não há nenhuma necessidade para o global declaração de que você tem no início da sua função.Em Python, você só precisa usar o global declaração de se pretender escrever para uma variável global.Se tudo o que você precisa fazer é leia a variável, ou chamar a função, não há necessidade de o global instrução.Todos os nomes utilizados na sua função, se eles são nomes de variáveis ou de nomes de funções, serão pesquisados na seguinte ordem:local, anexando, global, builtin."Local" significa os nomes definidos dentro da sua função, assim como seu direction variável."Delimitador" é uma regra usada quando você definir uma função dentro de outra função.Isso é útil em muitas situações, mas é um pouco mais avançada tópico e você não precisa se preocupar com isso agora."Global" significa (nomes de variáveis ou funções, classes ou) definidos no nível superior do programa, tais como o seu motor_stop função entre outras.E, finalmente, "builtin" significa Python embutido nos nomes, como str ou int ou file.

Então, se você deixou de fora o global declaração, em seguida, Python iria procurar o nome motor_stop (e os outros nomes de função) da seguinte maneira:

  1. Local: Há um motor_stop definidos nesta função?Não.Mover-se sobre.
  2. Encerrando: É esta função definida dentro de uma outra função?Não, de modo que o "delimitador" regra não se aplica.Mover-se sobre.
  3. Global: Há um motor_stop definido no nível superior do programa?Sim.Encontrou-a.
  4. (Builtin):Esta regra nunca é verificado em tudo, porque o nome foi encontrado pela "global" regra.

Todas as suas funções são definidas no nível superior do programa, de modo que o "global" regra vai encontrá-los sem a necessidade de o global instrução.Isso deve tornar a sua vida um pouco mais simples.

Agora para a sua questão principal:por que o seu código é um loop para sempre.Isso porque a condição de teste a sua while ciclo nunca vai se tornar falsa.Você está em loop while direction == "fwd", e o código dentro do while ciclo nunca altera o direction variável.Assim cada vez que chega o final do ciclo, ele volta a testar a condição novamente.O direction variável ainda contém a seqüência de caracteres "fwd", e , assim, o loop while é executado uma segunda vez.Em seguida, o direction variável ainda contém a seqüência de caracteres "fwd", e assim ele executa uma terceira vez.E assim por diante, e assim por diante.

Uma forma de sair da while loop quando você quiser sair seria definir o direction variável para outra coisa, como "stop", quando você quer parar.(E. g., depois que você chamar motor_stop()).Outra maneira seria usar o return instrução para sair da função naquele ponto.Mas minha sugestão seria usar o break instrução em vez disso, o que significa que "neste momento, imediatamente o ciclo de sair eu estou." Ele funciona tanto em while loops e for loops, e é uma forma muito útil de instrução para saber sobre.Parece que você quer que seu while loop para sair a qualquer hora que você chamar motor_stop(), então, existem dois lugares que você gostaria de colocar um break instrução:

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

Existem algumas outras mudanças que eu sugiro fazer.Em primeiro lugar, chamar get_range() três vezes, em seu ciclo, mas você realmente só precisa chamá-lo de uma vez.Você já atribuído o resultado para um dist variável, então porque não usar essa variável?

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

E segundo, não há nenhuma maneira no interior do while loop para direction não para ser "fwd", para o final else é desnecessário, e sua função pode ser:

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, você tem um parâmetro de função chamado arg, o que é um nome que não lhe diz nada sobre o que ele serve.Você imediatamente atribuir ele a uma variável chamada direction, o que é muito melhor nome.Então, por que não usar isso como o nome do parâmetro em primeiro lugar?Não há nenhuma regra que diz que uma função de parâmetros de deve ser chamado de "arg";eles podem ser chamados de qualquer coisa que você quiser (exceto uma do Python palavras reservadas como break ou if).Então, vamos dar a sua função mais significativa nome do parâmetro, e que irá simplificar ainda mais:

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

Não.É muito mais fácil de ler e entender, e deve resolver o problema que você estava vendo o seu while loop não sair quando o carro fica muito perto de um objeto.

(Há ainda um possível problema eu posso ver, o que é que o loop while pode não sair enquanto o carro está em marcha para a frente, apesar de lançado o "forward" botão -- mas eu teria que ver o seu motor_forward() código de saber como resolver isso.Pode ser tão simples como colocar um break após a instrução motor_forward(), caso em que não há realmente nenhuma necessidade para uma while loop -- mas eu teria que saber como o seu motor_forward() código interage com webiopi e como webiopi do código de manipulação de eventos funciona.Nenhum que eu conheça, agora, então, eu vou responder que problemas posso responder agora, mesmo se a minha resposta é incompleta, ao invés de deixar você sem responder a todos.)

Editado pela Marca: Aqui é o motor_forward código:

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

Outras dicas

Tente isso, você sempre parar no intervalo, mas pode querer parar de direção

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

btw, você não precisa de o (arg) apenas arg quando você faz referência a ele

imprimir arg

o parens na chamada assinatura estão lá para mostrar sua parm para uma função

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top