I2C Android Things and Arduino 3v3

I try to communicate, read and write, from Arduino - slave - to RPi - master - with Android Things.

If i R/W, with a level converter, from RPi to Arduino 5v (16Mhz), everything works fine.

So i decide to eliminate the level converter, and use a 3v3 Arduino mini pro (8Mhz).

The write works fine, but when i try to read from the Arduino, the signal stops.

5v_16Mhz


After the Setup to 9, 0 address, and reads to 9, the signal still low and received the data. No problem.

3v3_8Mhz


After the Setup to 9, 0 address, and read to 9, the signal goes high and the data stop.

I used the same example for the Slave:

#include <Wire.h>

byte RFID[20] = {9,8,7,6,5,4,3,2,1,1,2,3,4,5,6,7,8,9,1,2};


void setup() {
  Wire.begin(8);          // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(115200);     // start serial for output
  pinMode(13, OUTPUT);
}

void loop() {
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Serial.println("Master ask");
  digitalWrite(13, HIGH);
  delay(250);
  Wire.write(RFID, 20);
  digitalWrite(13, LOW);
}

// function should be executes whenever data is received from master
// this function is registered as an event, but it's called every time the RPi
// call the Device.
void receiveEvent(int howMany) {
  while (0 < Wire.available()) {
    byte RTC_syn = Wire.read(); // receive byte
    Serial.println(RTC_syn);
  }
}

I really don’t know how drives the signal high…
Someone can help me?

After the Setup to 9, 0 address, and read to 9, the signal goes high and the data stop.

The problem is after the sending of the first two bytes. Given the code on the Raspi was identical for the two transmissions, it seems that the Raspi isn't able to accept a clock stretching at any time during a transfer. As the Pro Mini is slower it needs more time to call the corresponding interrupt handler (BTW, your interrupt handler is as wrong as it can be. delay() calls are not allowed as well as any method call of the Serial object!). Because of that clock stretching the following read request isn't recognized because the start condition didn't happen.

Please post the code you run on the Raspberry Pi.

pylon:
The problem is after the sending of the first two bytes. Given the code on the Raspi was identical for the two transmissions, it seems that the Raspi isn’t able to accept a clock stretching at any time during a transfer.

Good to know, but can not i do something?

pylon:
As the Pro Mini is slower it needs more time to call the corresponding interrupt handler (BTW, your interrupt handler is as wrong as it can be. delay() calls are not allowed as well as any method call of the Serial object!). Because of that clock stretching the following read request isn’t recognized because the start condition didn’t happen.

Right, i avoid the delay and the Serial, the code now is:

#include <Wire.h>

byte RFID[20] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2};
volatile byte p = 0;

void setup() {
  Wire.begin(10);          // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(115200);     // start serial for output
  pinMode(13, OUTPUT);
}

void loop() {
  if (p == 1) Serial.println("masterk ask");
  if (p == 2) Serial.println("master read");
  else {}

  p = 0;
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Wire.write(RFID, 20);
  p = 1;
}

// function should be executes whenever data is received from master
// this function is registered as an event, but it's called every time the RPi
// call the Device.
void receiveEvent(int howMany) {
  while (0 < Wire.available()) {
    byte RTC_syn = Wire.read(); // receive byte
  }
  p = 2;
}

Unfortunately doesn’t works…

pylon:
Please post the code you run on the Raspberry Pi.

Android Things code:

@Throws(IOException::class)
    fun readCalibration(device: I2cDevice?, startAddress: Int): ByteArray {
        // Read three consecutive register values
        return ByteArray(20).also { data ->
            try {
                device?.readRegBuffer(startAddress, data, data.size)
            }
            catch (e: IOException) {
                null
            }
        }
    }

The Arduino code sends 5 bytes but the AndroidThings code requests 20 (given my interpretation of that language is correct)?

Do you have control over that readRegBuffer() method? If you add a delay after the I2C write transmission you might work around the limitation.

pylon:
The Arduino code sends 5 bytes but the AndroidThings code requests 20 (given my interpretation of that language is correct)?

Sorry my mistake, is 20. I corrected.

pylon:
Do you have control over that readRegBuffer() method? If you add a delay after the I2C write transmission you might work around the limitation.

I will try tomorrow and i update you!
thx for now