我用自制的I²C电平转换器连接了Raspberry Pi和Rainbowduino,并安装了Python模块SMBus,Raspberry Pi可以与Rainbowduino通信,但在尝试命令时经常收到输入/输出错误消息。bus.write_i2c_block_data(address, signal, data)
它说:
IOError: [Errno 5] 输入/输出错误
为什么会发生,我该如何修复或忽略这些错误?
我用自制的I²C电平转换器连接了Raspberry Pi和Rainbowduino,并安装了Python模块SMBus,Raspberry Pi可以与Rainbowduino通信,但在尝试命令时经常收到输入/输出错误消息。bus.write_i2c_block_data(address, signal, data)
它说:
IOError: [Errno 5] 输入/输出错误
为什么会发生,我该如何修复或忽略这些错误?
长话短说很多人都被这个困扰,我发现一个非常简单的解决方法如下。
它会让你忽略错误并保持 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 都会增加,从而消除了意外重复发送的可能性。但这可能不是真的必要。
我正在使用带有 i2c 的 Raspberry Pi 和 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 相对较慢并导致程序延迟更多,从而增加失败的机会。
我在 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 出现错误,数据将继续通过并可用。希望这可以帮助。
根据您的 RPi,您可能会使用bus = SMBus(0)
或bus = SMBus(1)
初始化 SMBus。
我希望这能解决你的问题。
我最近遇到了同样的问题。当我禁用 teensy 的串行接口时,错误完全消失了。
我正在使用带有 teensy 3.2 的 RPi 2,通过 i2c 以 2.4mhz 进行通信,以大约 38 Kbps 的速率发送 33 字节的有效负载。