1

I am using a Raspberry Pi B+ model with an Adafruit Capacitive Touch Sensor. I have installed the dependencies:

sudo apt-get update
sudo apt-get install build-essential python-dev python-smbus python-pip git

I have installed the software for the Python MPR121 Library:

cd ~
git clone https://github.com/adafruit/Adafruit_Python_MPR121.git

and I have installed the library:

cd Adafruit_Python_MPR121
sudo python setup.py install

But when I try to run:

cd examples
sudo python simpletest.py

I continue to get the error code:

IOError: [Errno 5] Input/output error

I have been reading different questions on here that are similar to my issue, but I have not been able to find an answer that fixes my specific problem.

Here are two pictures of my current setup:

enter image description here

enter image description here

  • You shouldn't expect people to follow links to find out what you are doing. The error is clear. Presumably you have not connected your device to the I2C bus properly. What steps have you taken to verify the bus is working? – joan Jul 12 '16 at 13:47
  • :/ "IOError" can seem a bit ambiguous. It would be good if you included a photograph of the sensor connected to the pi -- I know this seems simple, but it is common for people to have problems with this kind of thing because of a simple mistake with the connection, such as a backward ribbon cable (which, beware, can cause permanent physical damage to the pi). – goldilocks Jul 12 '16 at 13:54
  • @goldilocks Thank you for the advice! Here are 2 pictures of my current setup. – Elyse Zurawski Jul 12 '16 at 14:34
  • @joan I have updated my post with the steps I have taken so far. If you have any advice on what my next approach should be, that would be very helpful. – Elyse Zurawski Jul 12 '16 at 14:36
  • 1
    Hmm -- well that looks pretty straight forward. You might want to contact Adafruit and ask them how this could go wrong (I think they have a forum and should provide decent support); you could include a link to this question. – goldilocks Jul 12 '16 at 14:38
1

After digging through Adafruit's customer service forum, I have found that this error is related to a poor soldering job.

https://forums.adafruit.com/viewtopic.php?f=50&t=97271&p=491149&hilit=IOError%3A+%5BErrno+5%5D+Input%2Foutput+error#p491149

Thank you @goldilocks for pointing me in the right direction.

  • I hate soldering ;) Yours actually looks pretty decent where the 40 pin break out is. – goldilocks Jul 12 '16 at 14:50
0

Although I think Pi hats are supposed to include an EEPROM which should set this up for you, if this is I2C or SPI based (which it probably is, although I can't tell from the product page which) you may have to enable the buses. Look in /boot/config.txt and find this section:

# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
#dtparam=i2s=on
dtparam=spi=on

Note that I've changed this slightly by uncommenting two lines; that's what you want to do. If for some reason you can't find this section in config.txt, just cut n' paste those lines in. You'll then need to reboot.

0

This is a common problem with the Raspberry Pi I2C interface. It is caused by the I2C driver in Raspbian not implementing Clock Stretching, even though the hardware is perfectly capable of doing it! I hit this brick wall myself when interfacing a PIC24 microcontroller to the Pi using I2C.

The solution I came up with was to do the absolute minimal processing in the Slave interrupt routine at the PIC. I mean MINIMAL. Virtually no processing otherwise the slave fails to respond to consecutive bytes and the required ACK/NACK signals, due to NO clock stretching. I used flags in the interrupt handler to signal an update to a procedure called by the main loop for received data and Send Data is buffered in advance by the main loop so it can be sent instantly without lots of pre-processing.

Here is my Interrupt handler 'C' code that I ended up with, that works perfectly. Some variables are not defined here as they are stored elsewhere. I hope this info helps everyone. My PIC's internal clock is 16MHz as that affects my instruction cycle. The clock of your I2C slave system should be considered if you want to use my code as a template to modify for your own needs.

/*-------------------------------------------------------*/
// Date:        25th Feb 2018
// Author:      Pete
// Description  I2C Interrupt Handler
/*-------------------------------------------------------*/

int Address;
int command = 0;
int I2Cstate = 0;

void __attribute__((interrupt, no_auto_psv)) _SI2C1Interrupt(void)
{
    if (I2C1STATbits.D_A == 0)     // Check for address byte received
    {
        I2Cstate = 0;              // Idicate Address phase

        i2cRXindex = 0;            // Zero RX array pointer
    Address = I2C1RCV;             // Read the Address byte shifted 1 bit left

    if (I2C1STATbits.R_W)          // Check for read from Slave
        {         
            i2cTXindex = 0;        // Zero TX array pointert
                                   // Send to master and Increment pointer
            switch (command)       // Use 'Command' to Select Data            {
                case 10:           // Get Battery RAW value Command
                {
                    I2C1TRN = batteryTXbuffer[i2cTXindex++];
                    break;
                }
                case 20:           // Get Front Distance value Command
                {
                    I2C1TRN = UfrontTXbuffer[i2cTXindex++];
                    break;
                }
                case 30:           // Get Left Distance value Command
                {
                    I2C1TRN = UleftTXbuffer[i2cTXindex++];
                    break;
                }
                case 40:           // Get Right Distance value Command
                {
                    I2C1TRN = UrightTXbuffer[i2cTXindex++];
                    break;
                }
                case 50:           // Get Differential Distance value Command
                {
                    I2C1TRN = UdiffTXbuffer[i2cTXindex++];
                    break;
                }
            }
        }
    }
    else                           // If not Address then must be Data
    {
        if (I2C1STATbits.R_W)      // If Write then Send Byte to Master
        {
            switch (command)       // Use 'Command' to Select the Data 
            {
                case 10:           // Get Battery RAW value Command
                {
                    I2C1TRN = batteryTXbuffer[i2cTXindex++];
                    break;
                }
                case 20:           // Get Front Distance value Command
                {
                    I2C1TRN = UfrontTXbuffer[i2cTXindex++];
                    break;
                }
                case 30:           // Get Left Distance value Command
                {
                    I2C1TRN = UleftTXbuffer[i2cTXindex++];
                    break;
                }
                case 40:           // Get Right Distance value Command
                {
                    I2C1TRN = UrightTXbuffer[i2cTXindex++];
                    break;
                }
                case 50:           // Get Differential Distance value Command
                {
                    I2C1TRN = UdiffTXbuffer[i2cTXindex++];
                    break;
                }
            }
        }
        else                       // otherwise Read incoming Byte
        {
            // Receive from Master and Increment pointer
            // If previous Byte was Address then this byte must be the Command
            if (I2Cstate == 0)
            {
                command = I2C1RCV; // Store the Command byte
                I2Cstate = 1;
            }
            else                   // otherwise it is Data so process according to Command
            {
                switch (command)
                {
                    case 1:        // Left Motor speed value
                    {
                        leftMotor = I2C1RCV;
                        leftMotorSet = 1;   // Flag update required
                        break;
                    }
                    case 2:                 // right Motor speed value
                    {
                        rightMotor = I2C1RCV;
                        rightMotorSet = 1;  // Flag update required
                        break;
                    }
                    case 42:                // Left & Right Motor speed values (2 bytes)
                    {
                        i2cRXbuffer[i2cRXindex++] = I2C1RCV;

                        // Check for Command received (2 bytes)
                        if (i2cRXindex == 2)
                        {
                            motorSet = 1;   // Flag update required
                        }
                        break;
                    }
                    case 43:                // Servo Angle value (1 byte)
                    {
                        kicker = I2C1RCV;
                        kickerSet = 1;      // Flag update required
                        break;
                    }
                }
            }
        }
    }

    IFS1bits.SI2C1IF = 0;                  // Clear the Slave Interrupt Flag
}

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.