Python、Webiopi 和树莓派
-
20-12-2019 - |
题
我正在尝试通过无线和 webiopi 控制我的 Raspberry Pi 汽车。基本功能运行良好 - 在界面中单击“前进”,汽车将前进,当我释放按钮时,汽车将停止。
我现在想集成超声波距离传感器,这样当我向前行驶时,当前面有东西时,汽车应该停下来。当我点击前进按钮时,汽车会行驶并在有东西在范围内时停止,但只有在有东西在范围内时才会停止,而不是在我释放按钮时停止。我的 while 循环不知何故循环(卡住)并且没有从 webiopi 读取释放按钮功能。
有人可以帮忙吗 - 已经做了好几天了,不确定我哪里出了问题:-(
这是我的 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()
这是我的 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");
}
这就是我现在的情况,但仍然无法正常工作(我完全是个菜鸟:-)):
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()
也许向前迈出了一小步。看到 webipi 使用它自己的“循环”,我添加了循环代码来检查电机 GPIO 的状态和距离,以及电机是否正在运行,如果距离太短则停止。现在,当我按下前进按钮时,汽车会移动,当我松开按钮时,汽车会停止,当向前移动且距离小于 30 厘米时,汽车会停止。唯一的问题是,当距离太短,并且我按过多快的速度按“ gpio.output(echo,1)_webiopi.gpio.gpio.invaliddireclectionexception:GPIO 通道不是输出”错误:-( 。
代码现在看起来像这样:
def go_forward(direction):
motor_forward()
def loop():
if get_range() < 30 and GPIO.digitalRead(M1) == GPIO.HIGH:
stop()
print "stop"
sleep(1)
解决方案
我将在一分钟内回答您的主要问题,但首先我想提一下您作为 Python 初学者正在做的事情,这使您的生活变得比实际需要的更加复杂。
没有必要 global
您在函数开始处的声明。在Python中,你只需要使用 global
如果你愿意的话声明 写 到一个全局变量。如果您需要做的就是 读 变量,或者调用函数,那么就不需要 global
陈述。函数中使用的任何名称,无论是变量名称还是函数名称,都将按以下顺序搜索:本地的、封闭的、全局的、内置的。“本地”是指在函数内部定义的名称,例如 direction
多变的。“封闭”是在另一个函数中定义一个函数时使用的规则。这在许多情况下都很有用,但这是一个有点高级的主题,您现在不需要担心它。“全局”是指在程序顶层定义的名称(变量、函数或类的名称)——例如您的 motor_stop
功能等。最后,“builtin”表示 Python 的内置名称,例如 str
或者 int
或者 file
.
所以如果你遗漏了 global
语句,然后Python将搜索名称 motor_stop
(以及其他函数名称)如下:
- 当地的: 有没有
motor_stop
在这个函数中定义?不。继续。 - 附: 这个函数是在另一个函数中定义的吗?不,所以“封闭”规则不适用。继续。
- 全球的: 有没有
motor_stop
在程序的顶层定义?是的。找到了。 - (内置):该规则根本不会被检查,因为该名称是由“全局”规则找到的。
所有函数都在程序的顶层定义,因此“全局”规则将找到它们,而不需要 global
陈述。这应该会让你的生活变得更简单一些。
现在回答你的主要问题:为什么你的代码永远循环。那是因为你的测试条件 while
循环永远不会变成假。你正在循环播放 while direction == "fwd"
, ,以及里面的代码 while
循环永远不会改变 direction
多变的。因此,每次到达循环末尾时,它都会返回再次测试条件。这 direction
变量仍然包含字符串 "fwd"
, ,因此 while 循环第二次运行。然后 direction
变量仍然包含字符串 "fwd"
, ,所以它运行第三次。等等等等。
退出的一种方法 while
当你希望它退出时循环是设置 direction
变量为其他内容,例如 "stop"
, ,当你想停下来的时候。(例如,在您拨打电话后 motor_stop()
)。另一种方法是使用 return
语句在此时退出该函数。但我的建议是使用 break
相反,语句是“在这一点上,立即退出我所处的循环”。它两者都可以 while
循环和 for
循环,这是一个非常有用的语句。看起来你想要你的 while
每次调用时循环退出 motor_stop()
, ,所以有两个地方你可以放 break
陈述:
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
我建议进行一些其他更改。首先,你打电话 get_range()
在循环中调用三次,但实际上只需要调用一次。您已经将其结果分配给 dist
变量,那么为什么不使用该变量呢?
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
其次,里面没有路 while
循环 direction
不是 成为“fwd”,所以最后 else
是不必要的,你的函数可以变成:
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()
最后,你有一个名为的函数参数 arg
, ,这个名称并没有告诉你它的用途。您立即将其分配给一个名为的变量 direction
, ,这是一个更好的名字。那么为什么不首先使用它作为参数名称呢?没有规定函数的参数 必须 被称为“arg”;它们可以被称为任何你喜欢的名字(除了 Python 的保留字之一,例如 break
或者 if
)。因此,让我们为您的函数指定一个更有意义的参数名称,这将进一步简化它:
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()
那里。这更容易阅读和理解,并且应该可以解决您所看到的问题 while
当汽车离物体太近时循环不会退出。
(我仍然可以看到一个可能的问题,即汽车向前行驶时 while 循环可能不会退出,即使您释放了“前进”按钮 - 但我必须看到您的 motor_forward()
代码以了解如何解决该问题。这可能就像放一个简单的 break
之后的声明 motor_forward()
, ,在这种情况下确实不需要 while
根本循环——但我必须知道你的 motor_forward()
代码与 webiopi 交互以及 webiopi 的事件处理代码如何工作。我现在都不知道,所以即使我的答案不完整,我也会回答我现在可以回答的问题,而不是让你完全没有答案。)
马克编辑: 这是 motor_forward 代码:
def motor_forward():
GPIO.output(M1, GPIO.HIGH)
GPIO.output(M2, GPIO.LOW)
string = "echo 0=130 > /dev/servoblaster"
os.system(string)
其他提示
试试吧 - 你总是停下来,但可能想要停止方向
if get_range() < 30:
motor_stop()
elif direction == "fwd":
motor_forward()
else:
motor_stop()
.
btw您不需要(arg)仅在您引用它时才arg(arg)
打印arg
呼叫签名中的窥视是在那里向一个函数显示一个parm