【问题标题】:Python, Webiopi and Raspberry PiPython、Webiopi 和树莓派
【发布时间】:2014-09-20 02:20:06
【问题描述】:

我正在尝试通过无线和 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" error :-( .

代码现在看起来像这样:

 def go_forward(direction):
   motor_forward()

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

【问题讨论】:

    标签: python raspberry-pi robot webiopi


    【解决方案1】:

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

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

    因此,如果您省略了 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
    

    其次,direction notwhile 循环中没有办法是“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 的保留字之一,如 breakif)。所以让我们给你的函数一个更有意义的参数名称,这将进一步简化它:

    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 循环可能不会退出,即使您释放了“前进”按钮 - 但我必须看到您的 @987654367 @代码知道如何解决那个问题。它可能就像在motor_forward()之后放置一个break语句一样简单,在这种情况下,根本不需要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)
    

    【讨论】:

    • 非常感谢您花时间和精力详细解释和指出我的问题所在!另外,感谢您如此详细地解释 python 代码!我真的很感激这一点。我今晚将测试脚本,因为我现在要上班了——但我迫不及待地想试一试。谢谢。
    • @Mark - 不客气。顺便说一句,请注意我在复制和粘贴代码并对其进行编辑时犯了一个编辑错误,并且有几行以else direction == "fwd": 结尾。这些行应该只是else:。我已经编辑了我的答案以修复这些错误,但如果您在看到此评论之前已经复制并粘贴了我的答案,您将需要获取新编辑的更正版本。
    • 谢谢,我现在就试一试。
    • 好的,代码现在看起来好多了,运行起来也更流畅了,但仍然存在 while 循环没有注册我释放前进按钮的问题。我将继续使用代码。这是 motor_forward() 代码:def motor_forward(): GPIO.output(M1, GPIO.HIGH) GPIO.output(M2, GPIO.LOW) string = "echo 0=130 &gt; /dev/servoblaster" os.system(string)
    • 我想再次感谢你教我很多关于 python 以及 def 和循环如何工作的知识。我会将您的答案标记为正确,尽管我仍然需要弄清楚如何让我的树莓汽车在没有新错误的情况下正常工作 - 可能不得不放弃 webiopi 并尝试通过网络界面控制我的汽车的一些不同方式,但我仍然会,但需要更多的时间。非常感谢。
    【解决方案2】:

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

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

    顺便说一句,当你引用它时,你不需要 (arg) 唯一的 arg

    打印参数

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

    【讨论】:

    • 感谢您的帮助,非常感谢。我对 python 很陌生,但我可以看到你的代码在做什么,并且 100% 有意义。不幸的是,它仍然不想工作 :-( 在某个地方它仍然卡在一个循环中。
    • 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()
    猜你喜欢
    • 2017-05-17
    • 2018-03-15
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2023-03-30
    • 1970-01-01
    • 2014-12-09
    相关资源
    最近更新 更多