1

I'm using this device, that acts as an I2C slave device on the address 0x23, for communicating with an arduino from a RPi model B. This is an nrf24l01 attached to an AT48 that provides an I2C interface to the nrf24l01 (there is one of these devices on each side, so both RPi and arduino behave as master of their own I2C bus). With this device you can send or receive a single byte wirelessly.

When reading a byte, the device will respond to the read data request with a 0x47 value when there is no byte to be read on the device's receive buffer, or with the incoming byte, when there is one (yes, I know, what happens when the incoming byte is a 0x47? and why 0x47?... can't tell you, I did not design the thing)

When writing data, you just send the byte with

i2cset -y 1 0x23 byte
, or within python and
smbus.write_byte(0x23,byte)

I'm able to successfully send a byte from RPi to the device (this byte is wirelessly transmitted to the other end and successfully received by the arduino), so I'm pretty confident that the wiring setup is ok.
However, when reading from the RPi:
  • If there is no byte available, the read data request returns 0x47, which is correct and expected.
  • If there is a byte available, the read data request yields an I/O Error . The exact text depends on what I use for doing the request. With
    i2cget -y 1 0x23

    , I get Error: read failed.

    From within python, using smbus,
    import smbus
    d=smbus.SMBus(1)
    d.read_byte(0x23)
    ,I get IOError: [Errno 5] Input/output error

    In addition, the failed read operation does empty the device read buffer, so the next call to read a byte returns a nice 0x47. So, the error happens clearly only when there is a byte available, but reading it always throws an exception.
    The fact that I can successfully send and "semi-receive" is what most puzzles me.

    I have tried arduino to arduino and both components work, so maybe is something related to smbus implementation on the RPi side. The behaviour is consistent (happens every single time). However, I have no clue about how to troubleshoot this.

    I've already tested to change transfer speeds (something related to time stretching), I've put and removed pull-up resistors on SDA & SCL. i2cdump -y 1 writes XX on every address of the bus.
    Do you have any other hint, other than debugging the bus with an oscilloscope, which I don't have?

    EDIT FOR ADDING CODE

    This is the code whose equivalent I'd like to have on the Pi, that works ok when replacing the pi by another arduino and this code. I removed all decorations, this is just the loop. The other arduino is waiting for a byte, and when it gets it, it sends another byte back:

    void send(char b) { delay(100); Wire.beginTransmission(0x23); Wire.write(b); Wire.endTransmission(); delay(100); return; }

    void loop() { unsigned char c; // command sent from the other side send(0x10); // wait for other end's answer: while (!Wire.available()) { Wire.requestFrom(0x23,1); Serial.println("waiting 5 secs."); delay(5000); } c=Wire.read(); Serial.print("got "); Serial.println(c,HEX); } I think that the lack of an equivalent to requestFrom() on the RPi is where the problem lies. If I put the call to requestFrom() out of the loop, it gets stuck like with the Pi. Any hints?

    • 1
      You say the Arduino code works. What does the Arduino code do that you are not doing on the Pi. I notice that the (poor) documentation suggests that a restart is sent after an I2C start. Perhaps that is implemented by the Arduino. You may need to bit-bang to support restarts on the Pi. – joan Nov 19 '14 at 12:40
    • Good question. In fact the available API looks quite more complete for arduino. When replacing the Pi with an arduino, I do a Wire.requestFrom() + if (Wire.available() + Wire.read(). AFAIK on the Pi API there's only the pure byte read call (i2cget -y 1 address, or python equivalent), and not the requestFrom() or the available() calls). Can you suggest a good bitbanged solution for the Pi? Thanks – Roberto Nov 19 '14 at 13:39
    • This is only surmise. Bit-banging may not be needed. I'll have a look at the Arduino functions and see how they map to the Pi's I2C/SMBus features. May not get a chance before this evening though. – joan Nov 19 '14 at 13:51
    • requestFrom accepts a booean argument which determines whether a stop or restart is done on the I2C bus. What parameters do you use in the requestFrom call? – joan Nov 19 '14 at 14:00
    • If you get a chance could you post the working Arduino script for the receive or transmit side (or both) that you want to implement on the Pi. – joan Nov 19 '14 at 17:54

    Your Answer

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

    Browse other questions tagged or ask your own question.