0

我正在尝试通过无线和 webiopi 控制我的 Raspberry Pi 汽车。基本功能工作正常 - 有我单击 fwd 的界面,汽车将前进,当我释放按钮时,它会停止。

我现在想集成超声波距离传感器,这样当我向前行驶时,当前面有东西时,汽车应该停下来。我让它去哪里,当我点击前进按钮时,当有东西在范围内时,汽车会行驶并停止,但它只会在有东西在范围内时停止,而不是当我释放按钮时。我的 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.InvalidDirectionException: The GPIO channel is not an OUTPUT”错误: -( .

代码现在看起来像这样:

 def go_forward(direction):
   motor_forward()

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

2 回答 2

1

试试这个——你总是停在范围内,但可能想停在方向上

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

顺便说一句,当您引用它时,您不需要 (arg) only arg

打印参数

调用签名中的括号用于向函数显示其参数

于 2014-07-28T19:50:12.757 回答
1

我会在一分钟内回答你的主要问题,但首先我想提一下你作为 Python 初学者正在做的事情,这让你的生活变得比它需要的更复杂。

不需要global您在函数开始时的语句。global在 Python 中,如果你想写入一个全局变量,你只需要使用该语句。如果您需要做的只是读取变量或调用函数,则不需要该global语句。函数中使用的任何名称,无论是变量名称还是函数名称,都将按以下顺序搜索:本地、封闭、全局、内置。“本地”是指在您的函数中定义的名称,例如您的direction多变的。“封闭”是在另一个函数中定义函数时使用的规则。这在许多情况下都很有用,但它是一个高级主题,您现在不需要担心它。“全局”是指在您的程序顶层定义的(变量、函数或类的)名称——例如您的motor_stop函数等。最后,“builtin”表示 Python 的内置名称,例如strorintfile

因此,如果您省略了该global语句,那么 Python 将搜索名称motor_stop(和其他函数名称),如下所示:

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

您的所有函数都在程序的顶层定义,因此“全局”规则无需global语句即可找到它们。这应该会让你的生活更简单一些。

现在你的主要问题是:为什么你的代码永远循环。那是因为您的while循环的测试条件永远不会变为假。您正在循环while direction == "fwd",循环内的代码while永远不会更改direction变量。所以每次到达循环结束时,它都会返回再次测试条件。该direction变量仍然包含 string "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()在循环中调用了 3 次,但实际上只需要调用一次。您已经将其结果分配给了一个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”,所以 finalelse是不必要的,你的函数可以变成:

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 的保留字之一,如breakor 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 的事件处理方式代码有效。我现在都不知道,所以即使我的答案不完整,我也会回答我现在可以回答的问题,而不是让你根本没有答案。)

由 Mark 编辑:这是 motor_forward 代码:

 def motor_forward():
     GPIO.output(M1, GPIO.HIGH)
     GPIO.output(M2, GPIO.LOW)
     string = "echo 0=130 > /dev/servoblaster"
     os.system(string)
于 2014-07-29T02:41:10.273 回答