我正在尝试通过无线和 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 (以及其他函数名称)如下:

  1. 当地的: 有没有 motor_stop 在这个函数中定义?不。继续。
  2. 附: 这个函数是在另一个函数中定义的吗?不,所以“封闭”规则不适用。继续。
  3. 全球的: 有没有 motor_stop 在程序的顶层定义?是的。找到了。
  4. (内置):该规则根本不会被检查,因为该名称是由“全局”规则找到的。

所有函数都在程序的顶层定义,因此“全局”规则将找到它们,而不需要 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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top