Sorry for the very basic question, but does the loop() function continue while data is being sent by I2C, because I2C is handled by hardware?
What happens if try to enter a sleep mode like ADC Noise Reduction Mode before the I2C has finished sending? Will the transfer be interrupted? If so, if there a way to tell when the transfer is complete before attempting to enter a sleep mode?
I2C communications are handled by a combination of software with interrupts and hardware. If you put the Arduino to sleep before transmission of a data block is complete, transmission will be suspended.
It might continue when the CPU is awakened, but it would be wise to put in a test or delay to allow the transmission to finish, before activating sleep mode.
Depends on the code. All the I2C library code I have seen is blocking, so, no, nothing else happens. That does not mean it has to be like that, I have certainly not seen all I2C library code and there is nothing to stop you writing you own.
Okay, thanks! So the Arduino Wire.h library is blocking and an Arduino in peripheral mode won't do anything else in the loop until a Wire.write transfer is complete?
Yes, but I don't think I really understood it clearly. My comments are based on my own experience of using Wire on an Arduino. Happy to be corrected, I don't want to mislead @amowry or anyone else.
Using this post from Koepel and the associated Wokwi simulation diagram, I modified the code to show the I2C timing as implemented by the Wire library.
// Just a simple test to capture the data for a screendump.
#include <Wire.h>
byte test[] = "Hello World, this is a long string";
void setup()
{
Wire.begin();
delay(100); // wait 100ms, to make a better screendump
Wire.beginTransmission(0x27);
PORTB |= 0b00100000; // Pin 13 goes HIGH at the beginning of the transfer
Wire.write((char *)test);
PORTB &= ~0b00100000; // Pin 13 goes LOW at the return from Wire.write()
Wire.endTransmission();
PORTB |= 0b00100000; // Pin 13 goes HIGH at the return from Wire.endTransmission()
}
void loop() {}
Pin 13 is driven HIGH and LOW to show the (simulated) Arduino activity.
Here is what it looks like. Transfer is not even initiated as the Wire.write() function returns.
No, Wire.write() returns even before any transmission is initiated. Putting the Arduino to Sleep just after Wire.write() instruction would "disturb" the transmission.
(I edited post #11 to add the corresponding listing)
But as DrDiettrich said on post #3, transfer ends before return of Wire.endTransmission() : with other words, Wire.endTransmission() only returns when transmission is finished.
=> The right place to put the Arduino to sleep is right after Wire.endTransmission().