获取 IOError:[Errno 121] 尝试通过 I2C 从 Arduino 获取数据时,Python(树莓)上的 smbus 发生远程 I/O 错误

问题描述 投票:0回答:3

我遇到了问题,pyhton 在启动通过 I2C 从 Arduino 请求数据的脚本时有时会在我的树莓派 3 上抛出这个 IOError。

电气连接非常完美,所以这不是问题。 此外,我在使用 i2cget -y 1 0x04

时也没有收到任何错误

只有 python 脚本有时很糟糕,我不知道为什么。

这是我的 Arduino 代码:

我注册了一个 onReceive 和一个 onRequestEvent。 onReceive 回调将定义应该发送回树莓派的数据类型。 onRequest 回调执行响应。

    #include <CommonFunction.h>
#include <Wire.h>

#define I2C_ADDRESS 0x4

commonFunc GetCountsEverySecond;
int g_iOnRequestActionCode = 0;
unsigned long g_lSecondsSinceStart = 0;

void setup() 
{
    Wire.begin(I2C_ADDRESS);
    Wire.onRequest(sendDataOverI2CGateway);
    Wire.onReceive(defineOnRequestAction);
}


void loop() 
{
    tickSeconds();
}

void tickSeconds()
{
    if (GetCountsEverySecond.TimeTriggerAt(1000))
    {
        g_lSecondsSinceStart++;
    }
}

void sendOperationTimeDataOverI2C()
{
    unsigned long longInt = g_lSecondsSinceStart;
    byte size = sizeof(longInt);

    byte arr[size];
    for (int i = 0; i < size; i++)
    {
        int iBitShift = 8 * (size - i - 1);
        if (iBitShift >= 8)
            arr[i] = ((longInt >> iBitShift) & 0xFF);
        else
            arr[i] = (longInt & 0xFF);
    }
    Wire.write(arr, size);
    g_bI2CSending = true;
}

void sendDataOverI2CGateway()
{
    switch(g_iOnRequestActionCode)
    {
        case 0:
            sendRainDataOverI2C();
            break;
        case 1: // send firmware version
            sendVersionDataOverI2C();
            break;
        case 2: // send operation time of arduino in seconds from start
            sendOperationTimeDataOverI2C();
            break;
        default: break;
    }
}

void defineOnRequestAction(int iBuffer) 
{
    while (Wire.available())
    {
        g_iOnRequestActionCode = Wire.read();
    }
}

这是我的Python代码。 很简单,但它会引起一些头痛。

import smbus
import time
bus = smbus.SMBus(1)
while True:
        data = bus.read_i2c_block_data(0x04,0x02,4)
        result = 0
        for b in data:
                result = result * 256 + int(b)
        print(result)
        time.sleep(1)

执行我的 python 脚本后,有时会出现此错误:

pi@WeatherStation:~/workspace $ sudo python readTimeOperationData.py
Traceback (most recent call last):
  File "readTimeOperationData.py", line 5, in <module>
    data = bus.read_i2c_block_data(0x04,0x02,4)
IOError: [Errno 121] Remote I/O error

谁能帮我解决这个问题?

干杯迪特

python arduino raspberry-pi i2c smbus
3个回答
13
投票

我解决了!!

我从这篇文章中得到了提示: https://www.raspberrypi.org/forums/viewtopic.php?t=203286

通过在

bus = smbus.SMBus(1)
之后添加延迟解决了这个问题。 似乎需要一段短暂的延迟,以便 I2C 能够稳定下来。

通过调用脚本 100 次测试工作代码没有问题。

import smbus
import time
bus = smbus.SMBus(1)
time.sleep(1) #wait here to avoid 121 IO Error
while True:
    data = bus.read_i2c_block_data(0x04,0x02,4)
    result = 0
    for b in data:
        result = result * 256 + int(b)
    print(result)
    time.sleep(1)

3
投票

这对我有用

import smbus
import time
bus = smbus.SMBus(1)
time.sleep(1)

如果您使用 RPLCD 库,请在初始化对象之前添加此代码

bus = smbus.SMBus(1)
time.sleep(1) #wait here to avoid 121 IO Error      
lcd = CharLCD('PCF8574', 0x27)
lcd.cursor_pos = (0,0)

谢谢你


0
投票

我想通过 I2C 信息发送到 Arduino Nano,我尝试了你所说的一切,但没有任何效果。 这是我在 RaspberryPi5 上的 Python 代码:

from smbus import SMBus
from time import sleep

addr = 0x8
bus = SMBus(1)
sleep(1)

while 1:
    bus.write_byte(addr, 0x1)
    print("on")
    input()
    bus.write_byte(addr, 0x0)
    input()
    print("off")

有人可以帮我解决这个问题吗? 欢呼塔拉洪

© www.soinside.com 2019 - 2024. All rights reserved.