使用 Python 模块 SMBus、Raspberry Pi 和 Arduino 的输入/输出错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15245235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Input/output error using Python module SMBus, a Raspberry Pi and an Arduino
提问by holmeswatson
I have connected a Raspberry Piand Rainbowduinotogether with a homemade I2Clevel shifter, and installed the Pythonmodule SMBus, the Raspberry Pi can communicate with the Rainbowduino, but every so often I get an input/output error message when trying the command bus.write_i2c_block_data(address, signal, data).
我已经将Raspberry Pi和Rainbowduino与自制的I2C电平转换器连接在一起,并安装了Python模块SMBus,Raspberry Pi可以与Rainbowduino通信,但是在尝试命令时我经常收到输入/输出错误消息bus.write_i2c_block_data(address, signal, data)。
It says:
它说:
IOError: [Errno 5] Input/output error
IOError: [Errno 5] 输入/输出错误
Why does it happen and how do I fix or ignore these errors?
为什么会发生,我该如何修复或忽略这些错误?
回答by otmezger
Depending on your RPi, you might use bus = SMBus(0)or bus = SMBus(1)to initialize the SMBus.
根据您的 RPi,您可以使用bus = SMBus(0)或bus = SMBus(1)来初始化 SMBus。
I hope this solves your problem.
我希望这能解决你的问题。
回答by Jon I
Long story short alot of people are plagued by this, I found a very simple work around is the following.
长话短说很多人都被这个困扰,我发现一个非常简单的解决方法如下。
It will let you ignore the error and keep tx/rx-ing, calling i2cdetect seems to reinitialize the bus somehow instead of the arduino disappearing from it.
它会让你忽略错误并保持 tx/rx-ing,调用 i2cdetect 似乎以某种方式重新初始化总线,而不是 arduino 从中消失。
i posted an explanation of how i found this solution here (waiting mod approval right now) http://www.raspberrypi.org/phpBB3/viewtopic.php?f=41&t=52517
我在这里发布了我如何找到这个解决方案的解释(现在正在等待 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
Even though this allows the Pi to keep transmitting bad data is still being sent to the arduino. The simplest way I found to get around this was to add an extra check-sum byte to the end of my data blocks.
即使这允许 Pi 继续传输不良数据,但仍将其发送到 arduino。我发现解决这个问题的最简单方法是在数据块的末尾添加一个额外的校验和字节。
I added up each byte of the message inside a byte variable allowing the value to rollover, then assign the check-sum byte whatever value necessary to sum the whole message out to zero.
我将消息的每个字节加到一个允许值翻转的字节变量中,然后为校验和字节分配任何必要的值,以使整个消息总和为零。
The arduino can then check each incoming transmission by summing all the bytes. If the message does not sum out to zero, it is ignored as an erroneous transmission.
然后,arduino 可以通过对所有字节求和来检查每个传入的传输。如果消息的总和不为零,则作为错误传输将其忽略。
I also assigned my messages a one byte message id which increments after each successful transmission, eliminating the possibility of accidental double sends. But that may not really be necessary.
我还为我的消息分配了一个一字节的消息 ID,它在每次成功传输后递增,从而消除了意外双重发送的可能性。但这可能真的没有必要。
回答by user3126397
I wrote this 19 hours ago when I thought I had a fix for the IOError problem: .............................................................................
我在 19 小时前写了这篇文章,当时我以为我已经解决了 IOError 问题:...................................... ……………………………………………………………………………………………………………………………………………………………………
I've been plagued with the same Input/Output error when using bus.write_byte talking to an Arduino. I tried Jon's i2cdetect fix but found that by this time in the code the damage had been done, bad numbers had already gotten to the Arduino and somehow disabled it.
在使用 bus.write_byte 与 Arduino 交谈时,我一直受到相同的输入/输出错误的困扰。我尝试了 Jon 的 i2cdetect 修复程序,但发现此时代码中的损坏已经完成,错误的数字已经到达 Arduino 并以某种方式禁用了它。
What did work was resetting the i2c baudrate, using
什么工作是重置 i2c 波特率,使用
sudo modprobe -r i2c_bcm2708
sudo modprobe i2c_bcm2708 baudrate=100010
After this no more I/O errors!! I'd be very interested in theories on what could cause this apparent baudrate mismatch. Hope this helps!
在此之后不再有 I/O 错误!!我对什么可能导致这种明显的波特率不匹配的理论非常感兴趣。希望这可以帮助!
.................................................................................
………………………………………………………………………………………………………………………………………………………… ……………………………………………………………………………………………………………………………………………………………………………………………………
Well after much more testing what I found was that the baudrate fix did make the rate of errors go down but did not eliminate them.
经过更多的测试,我发现波特率修复确实降低了错误率,但并没有消除它们。
It now seems clear that Jon's i2cdetect call applied right after the error will initialize the RPi so that it can continue. But you also have to deal with the fact that bad data was probably sent to the Arduino and you need to detect this and fix it, and also reinitialize Wire (and in my case the servo driver), so that even though Pi got an error, that the data will continue to get through and be usable. Hope this helps.
现在似乎很清楚,在错误发生后立即应用 Jon 的 i2cdetect 调用将初始化 RPi,以便它可以继续。但是您还必须处理错误数据可能已发送到 Arduino 的事实,您需要检测并修复它,并重新初始化 Wire(在我的情况下是伺服驱动器),这样即使 Pi 出现错误,数据将继续通过并可用。希望这可以帮助。
回答by user3288244
I am creating a buzzing server with a Raspberry Pi and Arduino UNO with i2c and has encountered the same problem. My design is that when the Pi receives a connection request from a socket(by some external machines on the network), it writes '1' to the Arduino and Arduino will enable a loop in loop() by changing a global variable. after the write Pi will continuously read byte from Arduino to check for button state. when the Pi wants to stop reading it sends '0' to stop the loop and reset all counters and LED.
我正在创建一个带有 Raspberry Pi 和带有 i2c 的 Arduino UNO 的嗡嗡声服务器,并遇到了同样的问题。我的设计是,当 Pi 从套接字(由网络上的某些外部机器)接收到连接请求时,它会向 Arduino 写入“1”,Arduino 将通过更改全局变量来启用 loop() 中的循环。写入后 Pi 将不断从 Arduino 读取字节以检查按钮状态。当 Pi 想要停止读取时,它会发送“0”以停止循环并重置所有计数器和 LED。
What happens is that Python will through IOError randomly when writing byte. On the Serial monitor with Arduino I noticed that the last byte received is 1 instead of 0, which is what the pi should have sent. Upon looking at i2cdetect -y 1 I noticed the address is wrong and I tried Jon's method, but as user3126397 mentioned, the bad data has been sent and the Arduino has halted. I attempted his modprobe and that only suppressed the error message and the Arduino is still in halt state.
发生的情况是 Python 在写入字节时会随机通过 IOError。在带有 Arduino 的串行监视器上,我注意到收到的最后一个字节是 1 而不是 0,这是 pi 应该发送的。在查看 i2cdetect -y 1 时,我注意到地址错误,我尝试了 Jon 的方法,但正如 user3126397 所提到的,错误数据已发送,Arduino 已停止。我尝试了他的 modprobe 并且只抑制了错误消息并且 Arduino 仍处于停止状态。
I originally suspect that the data gone sour because of incomplete read/write and therefore added a Serial.println() to check the argument byteCount in onReceive(). Without altering any other code I observed that the no. of successful operations before IOError increased a lot. Therefore I tried to add more println() to test the correlation and noticed a dramatic increase in failure. Finally I commented all the Serial statements and I ended up able to use the server without faults for a considerable number of times(I tested something like 30 times and still no IOError).
我最初怀疑数据因为读/写不完整而变坏,因此添加了一个 Serial.println() 来检查 onReceive() 中的参数 byteCount。在不改变任何其他代码的情况下,我观察到没有。IOError 之前成功操作的数量增加了很多。因此,我尝试添加更多 println() 来测试相关性,并注意到失败的急剧增加。最后,我评论了所有 Serial 语句,最终我能够在相当多的时间内无故障地使用服务器(我测试了大约 30 次,但仍然没有出现 IOError)。
I suspect, with regard to user3126397's solution on resetting the baudrate and my observation on the Serial.println() relationship, that error is indeed caused by synchronisation issues between the pi and Arduino(as Serial is relatively slow and causes more delay in the program, thus increases the chance of failure.
我怀疑,关于 user3126397 关于重置波特率的解决方案以及我对 Serial.println() 关系的观察,该错误确实是由 pi 和 Arduino 之间的同步问题引起的(因为 Serial 相对较慢,导致程序延迟更多,从而增加失败的机会。
回答by Alan McCosh
I recently came across this same issue. When I disabled the teensy's serial interface, the errors disappeared entirely.
我最近遇到了同样的问题。当我禁用 teensy 的串行接口时,错误完全消失了。
I'm using an RPi 2 with a teensy 3.2 communicating over i2c at 2.4mhz, sending 33-byte payloads at a rate of about 38 Kbps.
我正在使用带有 teensy 3.2 的 RPi 2,以 2.4mhz 通过 i2c 进行通信,以大约 38 Kbps 的速率发送 33 字节的有效负载。

