'IOError:[Errno 5]输入/输出错误',同时使用SMBus通过RPi进行模拟读取

Sud*_*xit 17 python analog-digital-converter python-2.7 raspberry-pi

我一直在寻找标题中提到的错误的答案,但这是我第一次得到答案.我试图让我的Raspberry pi读取模拟数据,但是当我在终端窗口中运行代码时,它给出了'IOError:[Errno 5]输入/输出错误'.

用于读取模拟数据的代码如下所示.我正在使用PCF8591 ADC转换器.

from smbus import SMBus

bus = SMBus(0)

print "read a/d press ctrl + c to stop"

bus.write_byte(0x48, 0)
lastval = -1

while True:
  reada = bus.read_byte(0x48)
  if(abs(lastval-reada) > 2):
    print(reada)
    lastval=reada
Run Code Online (Sandbox Code Playgroud)

我理解这可能是因为树莓派中的版本发生了变化,我应该将SMBus(0)更改为SMBus(1).为此我检查了我的RPi版本,这不是修改后的版本.但我仍然试图通过更改SMBus号来运行程序,但仍然没有运气.

我得到的错误如下所示:

Traceback (most recent call last):
  File "analogread.py", line 7, in <module>
    bus.write_byte(0x48, 0)
IOError: [Errno 5] Input/output error
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏.这是我试图执行的更大项目中的基本块.因此,我可以更好地工作,我可以构建我的应用程序.谢谢

小智 20

原因可能是您正在远程工作(SSH).断开远程会话后,您的程序仍在工作,可能会尝试打印或与控制台交互,这是不再可用的.这就是发生在我身上的事.

  • 非常感谢你做的这些!我花了几个小时试图找出问题所在,而您的回答却在几秒钟内解释了实际的问题!我有一个日志记录模块,我通过在打印到控制台的日志语句周围添加try / except块来克服了该错误,因为如果没有人看着它,则不会使用print。 (2认同)

小智 6

虽然该主题很陈旧,但我想与大家分享我的希望,因为我遇到的所有帖子都未提及此潜在的解决方法,希望对其他人有所帮助。

我遇到了类似的问题,但硬件不同(MCP23017和LCD)。

追问了一段时间后,我发现问题不是软件,而是硬件。特别是SCL和SDA线上的上拉电阻。

RPI(在我的情况下为3)具有1.8k电阻,我的LCD也安装了一些上拉电阻(〜2.2k)。运行LCD从来没有问题,但是MCP23017会在运行扫描时通过发出命令“ i2cdetect -y 1”随机从总线上消失并重新出现。

删除LCD上多余的上拉电阻可以解决此问题,并且现在一切正常。


vis*_*olf 5

这些错误可能超出程序员的控制范围,由随机但常见的事件引起。

一种方法是在出现错误之前尝试几次:

def try_io(call, tries=10):
    assert tries > 0
    error = None
    result = None

    while tries:
        try:
            result = call()
        except IOError as e:
            error = e
            tries -= 1
        else:
            break

    if not tries:
        raise error

    return result

try_io(lambda: bus.write_byte(0x48, 0))
Run Code Online (Sandbox Code Playgroud)


pla*_*aes 5

造成这种情况的原因可能是您推送read/write调用的速度比硬件可以接受的速度快。因此,在读/写操作之间添加小的延迟:

from time import sleep
from smbus import SMBus

bus = SMBus(0)

bus.write_byte(0x48, 0)
sleep(0.2)  # Wait for device to actually settle down
lastval = -1

while True:
  reada = bus.read_byte(0x48)
  if(abs(lastval-reada) > 2):
    print(reada)
    lastval=reada
  sleep(0.2) # This might be not needed.
Run Code Online (Sandbox Code Playgroud)

另一种可能性是该地址中实际上并不存在该设备。因此,如果超时没有帮助,请尝试使用 i2c-tools(应该可以通过包管理使用,除非您使用的是自定义软件发行版)来检查设备是否实际可用(有时可能是布线问题,例如忘记了地):

i2cdetect -y [bus number]
Run Code Online (Sandbox Code Playgroud)

为什么是i2c?因为 SMBus 基本上是对 i2c 总线的修改,具有更严格定义的电压电平和时序。