Python, Webiopi e Raspberry Pi
-
20-12-2019 - |
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)
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:
- Local: Há um
motor_stop
definidos nesta função?Não.Mover-se sobre. - 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.
- Global: Há um
motor_stop
definido no nível superior do programa?Sim.Encontrou-a. - (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