i2c communication (400 kHz) between teensy and arduino - delay required

Status
Not open for further replies.

cinhcet

Active member
Hi,

I have a teensy 3.2 connected to an arduino mega via i2c, pullups 3.9 k to 5 V. The teensy is the master, the arduino the slave.

The communication is working fine with the standard i2c speed (100 kHz). However, if I change it to 400 kHz, then the onRequest handler of the arduino is never called. After many hours, I found out that if I add a tiny delay between sending data to the arduino and requesting data from the arduino, it works.

Here is a "minimum working example" that reproduces the behavior.
Teensy code:
Code:
#include <i2c_t3.h>

void setup() {
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
  Wire.onReceive(receiveEvent);
}

void receiveEvent(unsigned int howMany) {
  char cmd = Wire.read();
  // toy code ...
}

void loop() {
  Wire.beginTransmission(1); 
  Wire.write('S');
  Wire.endTransmission();
  delayMicroseconds(3); // 3 microseconds seems to be the minimum number, for 2 it stops working
  Wire.requestFrom(1, 1);

  delay(1000);
  Wire.beginTransmission(1); 
  Wire.write('D');
  Wire.endTransmission();
  delayMicroseconds(3); // 3 microseconds seems to be the minimum number, for 2 it stops working
  Wire.requestFrom(1, 1);
  
  delay(1000);
}

Arduino:
Code:
#include <Wire.h>

#define CSPin 2

bool mode;

void setup() {
  pinMode(CSPin, OUTPUT);
  digitalWrite(CSPin, HIGH);
  Wire.begin(1);          
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
  mode = false;
}

void loop() {}

void receiveEvent(int howMany) {
  char cmd = Wire.read();
  if(cmd == 'S') {
    mode = true;
  } else {
    mode = false;
  }
}

void requestEvent() {
  if(mode) {
    digitalWrite(CSPin, LOW);
  } else {
    digitalWrite(CSPin, HIGH);
  }
  Wire.write('K');
}


While I can live with that delay, I want to understand why it does not work without.
Can someone explain that behavior?
 
I don't have an answer. I do find it interesting that at 400khz, one bit time is 2.5 us. So it appears you need to wait longer than one bit time although that could be a coincidence.
 
I'd guess that the Arduino Mega is so horribly slow, compared to the Teensy 3.2, that it is still processing the incoming 'S' or 'D' after reception and will be badly surprised when your requestFrom() arrives already from the Teensy while the Mega is still occupied with the handling of receiveEvent(). You might narrow this down by driving le Mega's Led high while receiveEvent() is running and low when it's ready. Then, you might probably see with a logic analyzer that receiveEvent is still running when you send the request.

Another guess is that the bool mode should be declared volatile to prevent conflicts.
 
thanks for your answers!

In my understanding of i2c (correct me if I am wrong), the arduino should stretch the i2c clock until its "receiveEvent" handler has finished. So in theory the teensy should wait until the receiveEvent() code is finished.

I will try later this day to connect two teensy and also two arduinos to check whether this just affects the specific teensy arduino combination.

Declaring the bool mode as volatile seems to make sense since receiveEvent() is called in an interrupt, however, I guess it should not cause this issue here. I will try anyway, thanks!
 
In my understanding of i2c (correct me if I am wrong), the arduino should stretch the i2c clock until its "receiveEvent" handler has finished. So in theory the teensy should wait until the receiveEvent() code is finished.
I haven't looked closer to the source code of the Wire library for Arduino, but I guess they did everything to make the stuff non blocking on these old, slow, and asthmatic MCUs...
Declaring the bool mode as volatile seems to make sense since receiveEvent() is called in an interrupt, however, I guess it should not cause this issue here. I will try anyway, thanks!.
Don't guess... modern versions of the gcc compiler tend sometimes to exaggerate and to do too much cleaning.
 
Status
Not open for further replies.
Back
Top