1

I have been trying to create a retropie unit, and I'm in the midst of writing a script to inject uinput events for the analog axis values. This is the code I've written so far, but the issue is that I get IOERROR: (Errno 121) Remote I/O error.

When I use the command i2cdetect -y 1, the module shows up at address 0x48.

from evdev import UInput, ecodes as e;
import smbus;
from time import sleep;

def analogRead(pin):
    global bus;
    return bus.read_byte(0x48+pin);


bus = smbus.SMBus(1);
ui = UInput();

bus.write_byte_data(0x48,0x40 | (0 & 0x03) | (1 & 0x03) | (2 & 0x03), 0 | 1 | 2);

sleep(0.2);

bus.read_byte(0x48);

sleep(0.2);

bus.read_byte(0x49);

sleep(0.2);

bus.read_byte(0x50);

sleep(0.2);

while True:
    if analogRead(0)  <= 10:
        ui.write(e.EV_KEY, e.KEY_S, 0);
        ui.write(e.EV_KEY, e.KEY_W, 1);
    elif analogRead(0) >= 245:
        ui.write(e.EV_KEY, e.KEY_S, 1);
        ui.write(e.EV_KEY, e.KEY_W, 0);
    else:
        ui.write(e.EV_KEY, e.KEY_S, 0);
        ui.write(e.EV_KEY, e.KEY_W, 0);

    if analogRead(1)  <= 10:
        ui.write(e.EV_KEY, e.KEY_D, 0);
        ui.write(e.EV_KEY, e.KEY_A, 1);
    elif analogRead(1) >= 245:
        ui.write(e.EV_KEY, e.KEY_D, 1);
        ui.write(e.EV_KEY, e.KEY_A, 0);
    else:
        ui.write(e.EV_KEY, e.KEY_D, 0);
        ui.write(e.EV_KEY, e.KEY_A, 0);

EDIT: This issue occurs every time I attempt to run the python script.

The goal is to use a single pcf8591, and read three separate inputs: y-axis, x-axis, and the button press.

REVISED CODE:

from evdev import UInput, ecodes as e;
import smbus;
from time import sleep;

bus = smbus.SMBus(1);
ui = UInput();

bus.read_byte(0x48);

The revised, smaller sample, allows me to get a value of 128, which I assume references the first analog output, the y-axis. How can I access the other two analog inputs( button and x-axis )? I tried to increment the address by one to 0x49, but that is what produces my IOERROR.

  • Hi @Ian Rosenberg, Welcome. Ah, let me see. The error "IOERROR: (Errno 121) Remote I/O error" is a common error of I2C transmission. The "i2cdetect -y 1" detects you I2C device OK usually means the i2cdetect utility reads the device at address 0x48 OK. But there a couple of reasons that there are transmission error afterwards, including: (1) Wiring too long, (2) I2C speed too high, ... Usually get arounds include: (1) Reboot Rpi, (2) Shorten connecting wires, ... – tlfong01 Nov 14 '19 at 3:49
  • You can find more get arounds in my answer to the following question: raspberrypi.stackexchange.com/questions/98116/…. – tlfong01 Nov 14 '19 at 3:58
  • When do you get the error? Always? Occasionally? Please edit your question to include this information. – joan Nov 14 '19 at 8:25
  • I found your program a bit confusing. Please confirm if you are doing 3 ADCs at the same time. I would suggest to start with only one ADC, to make troubleshooting easier. If you simplify your program to do just one channel, I am more encouraged to read you a bit long program. :) – tlfong01 Nov 14 '19 at 9:43
  • Just now I have quickly read my pcf8591 programming cheat sheet to refresh my memory. Now I am ready to read your program, IF simplified. imgur.com/gallery/j4OKFt3 – tlfong01 Nov 14 '19 at 9:46
2

SMBus's write_byte_data is the function I needed. I had to specify which register I was using per analog input.

The I/O error I had was the result of only having a single pcf8591 located at 0x48.

| improve this answer | |
  • (1) Yes, need to write to address 0x48 and only address 0x48, not 0x49. (2) Yes and no, you need to use two write-byte data commands, and one read-Byte command. (3) You don't need to specify any register, because THERE IS NO REGISTER to specify (only channels which are NOT registers). (4) Perhaps you can simplify your code, removing "evdev", and just play with one axis, instead of all three axis. You might like to update question with a simple code, then I can see any causes of error. I am checking out if or too I2C low speed cause sample and hold cap leaks charge and cause error, ... – tlfong01 Nov 18 '19 at 7:27
  • I am not sure if you are confused. To clarify: (1) If you have only one PCF8591 module, then you only use address 0x48. It is only when you have more than one module in the same bus, then you can modify the address decode pins, to use, say 0x49. I have successfully placed one PCF859 at Bus 1, two PCF8591s in Bus 2, and one more in Bus 3. For your case of only one module in I2C Bus 1, you always address defualt of 0x48. (2) As I said earlier, there is no registers in PCF8591. You only send 3 bytes, and read the first results at the same time you send the third byte. / to continue, ... – tlfong01 Nov 19 '19 at 14:54
  • I old read register command to cheat the PCF8591, using control byte as reg addr. There are a couple of methods, so you might use other I2C commands. I know I2C block read command does not work, so I did not try it. I tried write I2C adress, write control byte, then read results, but no luck, then I tried read twice (first read seems not accurate results). I am still trying some other tricks. This is a summary: imgur.com/gallery/W2La5UX. This is a very long program, but you only need get the two values I2C buss address and control word: penzu.com/public/d0b57ae8. Cheers. – tlfong01 Nov 19 '19 at 15:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.