Serial + I2C Problem

Hi,

I am seeing a weird problem. I am using a Photon with the latest Develop branch. I am using an I2C FRAM chip with the Adafruit library. The I2C device in itself works fine. The Serial terminal also works fine. But not the two combined. I searched the forum but did not see anything similar.

I am reading from the Fram using I2C and dumping the content to the serial terminal using the Adafruit example. A lot - if not most - of the characters printed to serial will be lost. Using Serial.flush() does not help. Using a delay(50) after printing each read character helps. Shortening the time to 10ms, will no longer help.

It is as if the I2C and the Serial use the same Fifo and are interfering. Is this a known restriction / problem? Did anyone else see something like that?

AFAIK Serial.flush() does not act as you’d expect or see on Serial1.flush().
I’ve usually written my own substitute like this

void serialFlushInBuffer()
{
  while(Serial.read() >= 0);
}

Are you using Serial.write() or Serial.print()?

Could you post the dump code or a link to the example you are using?

Hi @ScruffR, thanks for the response!

I am using Serial.print(). Serial.flush() should wait for the output stream to be completely written, I am not sure how to write my own version of that.

The code is too long to be included here, but it is basically the example from https://github.com/adafruit/Adafruit_FRAM_I2C. With very small adaptions to make it run on the Photon (I was amazed by how easy it was to port it!).

You shouldn’t need to care to much about the output buffer since it’s a USB serial which usually goes much faster than 9600 baud (even higher than 115200).
But you might want to call Spark.process() within your dump loop.

And for testing the FIFO theory you might want to try this

for (uint16_t a = 0; a < 32768; a++) {
  value = fram.read8(a);

  // not interested in the actual contents for this test
  value = a & 0xFF;  // just to see if all bytes will be printed

  if ((a % 32) == 0) {
    Serial.print("\n 0x"); Serial.print(a, HEX); Serial.print(": ");
    Spark.process(); // every 32 byte should do
  }
  Serial.print("0x"); 
  if (value < 0x10)  // I guess 0x1 was wrong here 
    Serial.print('0');
  Serial.print(value, HEX); Serial.print(" ");

  //Spark.process();
}
1 Like

FYI, at this time, Serial.flush() is an empty function, unlike Serial1.flush() which actually waits for data transmission to be complete.

1 Like

My assumption was as well that the USB should be fast enough. And the test you proposed was exactly what I had done to prove that the Serial alone works fine.

But the Spark.process() actually fixes the issue for me! Interesting. So it seems the USB does not get enough processing time to write the data out and thus the buffer overflows. Spark.process does give it enough time, apparently. I know that delay(…) also nowadays calls the Spark.process() but maybe only above a certain number of milliseconds. And thus the Spark.process() is much faster.

Thanks for your help!

1 Like

Thanks, I see. Maybe that should be changed. Maybe it should just be Spark.process()???

@Stevie, Spark.process() is not related to Serial so it isn’t good form to call it from Serial.flush() IMO. I will be posting an issue regarding Serial.flush() so it gets looked out at some point.

@peekay123, you are of course right. On the other hand, they seem to be related because it seems that the sending of the data over USB actually happens in Spark.process(). At least to a certain degree.

One could also argue that delay() is not really related to Spark.process(). At least in no way which is obvious to me.

But I agree, that raising an issue towards Serial.flush() is the best solution. At least some form of documentation would be helpful, I would not have come up with the solution @ScruffR proposed…

EDIT: And thinking a bit about it, I have come across similar behavior in other circumstances before, just not that obvious. There were just these little glitches about missing characters in the serial output…

2 Likes

Not the same problem, but I also found unexpected (at least for me) interaction between USB Serial and I2C on a Core. Workaround was to delete Serial.print() statements, but I don’t have an explanation for what was happening yet.