Getting IOError: [Errno 121] Remote I/O error with smbus on python (raspberry) while trying to get data over I2C from Arduino

19,405

I solved it!!

I got a hint from this post: https://www.raspberrypi.org/forums/viewtopic.php?t=203286

By adding a delay after bus = smbus.SMBus(1) solved this issue. It seems that a short delay is somehow needed so that the I2C can settle.

Working Code tested by calling script 100times without issues.

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)
Share:
19,405
d s
Author by

d s

Updated on June 21, 2022

Comments

  • d s
    d s almost 2 years

    I am facing problems, that pyhton throws me on my raspberry pi 3 sometimes this IOError during starting a script which is requesting data from an Arduino over I2C.

    Electrical connection is perfect so this is not the issues. Furthermore I also dont get any errors while using i2cget -y 1 0x04

    Only the python scripts sucks sometime and I dont know why.

    This is my Arduino Code:

    I register an onReceive and an onRequestEvent. onReceive Callback will define what kind of data should be send back to the raspberry. onRequest Callback does the response.

        #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();
        }
    }
    

    Here is my python Code. Pretty straight forward but it causes some headache.

    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)
    

    After executing my python script I am getting sometime this error:

    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
    

    Can anyone help me to fix this issue?

    Cheers Dieter