【问题标题】:Input/output error using Python module SMBus, a Raspberry Pi and an Arduino使用 Python 模块 SMBus、Raspberry Pi 和 Arduino 的输入/输出错误
【发布时间】:2013-03-06 10:49:09
【问题描述】:

我已经连接了Raspberry PiRainbowduino以及自制的I²C电平转换器,并安装了Python模块SMBus,树莓派可以与Rainbowduino通信,但我经常得到尝试命令 bus.write_i2c_block_data(address, signal, data) 时出现输入/输出错误消息。

上面写着:

IOError: [Errno 5] 输入/输出错误

为什么会发生,我该如何修复或忽略这些错误?

【问题讨论】:

  • 此错误仍在继续。它发生时似乎是随机的。有时它会发生并且仍然会发送命令,有时则不会。这可能是由于干扰吗?我在想 smbus 必须从从设备接收确认,否则在成功接收命令时它不会出错(因此确认会受到干扰,从而导致错误)。否则传输会受到干扰,因此从站不会发送适当的确认
  • 我也遇到了同样的问题......
  • 我还没有找到解决这个问题的方法,虽然我认为它是由时钟偏差引起的,所以降低 RaspberryPi 上的 I2C 速度可能会有所帮助,尽管所有实现看起来都有些混乱。有时命令通过,但模块仍然出错,有时命令不通过并出错。因此,我设置了一段时间尝试捕获系统,如果出现错误,它会尝试再次发送命令。使用这些数据包,我发送一个两字节的数据包编号。如果 Rainbowduino 已经执行了这个数据包/命令,那么它会忽略它,如果需要代码,请告诉我
  • 我得到了一个使用bus = SMBus(1) 而不是bus = SMBus(0) 的解决方案(我使用的是512 MB RPi)。我不知道这是否可以解决您的问题。

标签: python arduino raspberry-pi


【解决方案1】:

长话短说很多人都被这个困扰,我发现一个非常简单的解决方法如下。

它会让你忽略错误并保持 tx/rx-ing,调用 i2cdetect 似乎会以某种方式重新初始化总线,而不是 arduino 从总线上消失。

我在此处发布了有关我如何找到此解决方案的说明(现在正在等待 mod 批准) http://www.raspberrypi.org/phpBB3/viewtopic.php?f=41&t=52517

try:
    bus.write_i2c_block_data(address, signal, data)
except IOError:
    subprocess.call(['i2cdetect', '-y', '1'])
    flag = 1     #optional flag to signal your code to resend or something

尽管这允许 Pi 继续传输不良数据,但仍将其发送到 arduino。我发现解决这个问题的最简单方法是在数据块的末尾添加一个额外的校验和字节。

我将消息的每个字节加到一个允许值翻转的字节变量中,然后为校验和字节分配任何必要的值,以将整个消息求和为零。

然后,arduino 可以通过对所有字节求和来检查每个传入的传输。如果消息的总和不为零,则将其作为错误传输而忽略。

我还为我的消息分配了一个单字节的消息 ID,每次成功传输后该 ID 都会递增,从而消除了意外重复发送的可能性。但这可能没有必要。

【讨论】:

    【解决方案2】:

    我正在使用 Raspberry Pi 和带有 i2c 的 Arduino UNO 创建一个嗡嗡声服务器,并且遇到了同样的问题。我的设计是,当 Pi 收到来自套接字的连接请求(通过网络上的一些外部机器)时,它会向 Arduino 写入“1”,并且 Arduino 将通过更改全局变量来启用 loop() 中的循环。写入后 Pi 将不断从 Arduino 读取字节以检查按钮状态。当 Pi 想要停止读取时,它会发送“0”来停止循环并重置所有计数器和 LED。

    Python 在写入字节时会随机通过 IOError。在带有 Arduino 的串行监视器上,我注意到收到的最后一个字节是 1 而不是 0,这是 pi 应该发送的。在查看 i2cdetect -y 1 后,我注意到地址错误,我尝试了 Jon 的方法,但正如 user3126397 提到的,错误数据已发送,Arduino 已停止。我尝试了他的 modprobe 并且只抑制了错误消息并且 Arduino 仍处于停止状态。

    我最初怀疑数据变坏是因为读/写不完整,因此添加了一个 Serial.println() 来检查 onReceive() 中的参数 byteCount。在不更改任何其他代码的情况下,我观​​察到没有。 IOError 之前成功操作的数量增加了很多。因此,我尝试添加更多 println() 来测试相关性,并注意到失败率急剧增加。最后,我评论了所有的 Serial 语句,我最终能够在相当多的时间内无故障地使用服务器(我测试了大约 30 次,仍然没有 IOError)。

    我怀疑,关于 user3126397 关于重置波特率的解决方案和我对 Serial.println() 关系的观察,该错误确实是由 pi 和 Arduino 之间的同步问题引起的(因为 Serial 相对较慢并导致更多延迟在程序中,从而增加了失败的机会。

    【讨论】:

      【解决方案3】:

      根据您的 RPi,您可以使用 bus = SMBus(0)bus = SMBus(1) 来初始化 SMBus。

      我希望这能解决你的问题。

      【讨论】:

      • 不,我可以得到一些 I2C 通信,只是经常有丢包。
      【解决方案4】:

      我在 19 小时前写了这篇文章,当时我认为我已经解决了 IOError 问题: ..................................................... ....................

      在使用 bus.write_byte 与 Arduino 对话时,我遇到了同样的输入/输出错误。我尝试了 Jon 的 i2cdetect 修复程序,但发现此时代码中的损坏已经造成,错误的数字已经到达 Arduino 并以某种方式禁用了它。

      起作用的是重置 i2c 波特率,使用

          sudo modprobe -r i2c_bcm2708
          sudo modprobe i2c_bcm2708 baudrate=100010
      

      在此之后不再出现 I/O 错误!!我会对可能导致这种明显波特率不匹配的理论非常感兴趣。希望这会有所帮助!

      .................................................. ....................................

      经过更多测试后,我发现波特率修复确实降低了错误率,但并没有消除它们。

      现在看来,Jon 的 i2cdetect 调用在错误后立即应用将初始化 RPi 以便它可以继续运行,这似乎很清楚。但是您还必须处理错误数据可能已发送到 Arduino 的事实,您需要检测并修复它,并重新初始化 Wire(在我的情况下是伺服驱动器),这样即使 Pi 出现错误,数据将继续通过并可用。希望这会有所帮助。

      【讨论】:

        【解决方案5】:

        我最近遇到了同样的问题。当我禁用 teensy 的串行接口时,错误完全消失了。

        我正在使用带有 teensy 3.2 的 RPi 2,通过 i2c 以 2.4mhz 进行通信,以大约 38 Kbps 的速率发送 33 字节的有效负载。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-17
          相关资源
          最近更新 更多