Loop behaves oddly in I2C receiveEvent I am messing around with an ATmega328P hooked on a Raspberry Pi, communicating over I2C. The ATmega is the slave (details at the end). While testing the basics of the concept, I faced an interesting problem.

This is the code on the ATmega:

#include &lt;Wire.h&gt;

#define SLAVE_ADRESS 0x1A
#define LED 6

int count = 10;
void setup()
{
    pinMode(LED, OUTPUT);
    /*for(int i=1; i&lt;=3; i++)
    {
      digitalWrite(LED, HIGH);
      delay(100);
      digitalWrite(LED, LOW);
      delay(100);
    }*/
    Wire.begin(SLAVE_ADRESS);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
}

void loop()
{
  delay(10);
}

void receiveEvent(int received_bytes)
{
  while(Wire.available())
  {
    unsigned char i = Wire.read();
    if(1)
    {
      int j = 5;
      while(j&gt;0)
      {
        digitalWrite(LED, HIGH);
        delay(300);
        digitalWrite(LED, LOW);
        delay(300);
        j-=1;
      }
    }
    delay(1);
  }
}

void requestEvent()
{
  Wire.write(count);
}


What you would expect it to do is blink the LED connected to pin 6 five times when the Pi sends a byte to the ATmega slave. (Things like if(1) are there because the code was much more specific originally.) The strange thing is that this is not the case:

The LED only blinks 1 time.

I honestly have no idea why. This "stdio-fitted" version of the problematic loop ran on the RPi as expected, prints 5*2 times:

#include &lt;stdio.h&gt;

int main()
{
  int j = 5;
  while(j&gt;0)
  {
    printf("LED, HIGH\n");
    printf("LED, LOW\n");
    j-=1;
  }
  return 0;
}


Circumstances:


I compile the code in the Arduino IDE on the Pi, then upload it
using AVRDUDE to the ATmega with the Pi's GPIOs. No error messages
over the process.
The ATmega gets 3.3 V supply voltage from the Pi, and operates on
16.000 MHz. Only the LED and the Pi is connected to it.
The (Python) code I use on the Pi to write and read a byte is the following. Reading works well, and I know by tests that the ATmega actually receives the correct byte:


import pigpio
import time

pi = pigpio.pi()
atmega = pi.i2c_open(1, 0x1A)

for i in range(6):
    a = pi.i2c_read_byte(atmega)
    print a

pi.i2c_write_byte(atmega, 0x05)
time.sleep(1)
void receiveEvent(int received_bytes)
{
  while(Wire.available())
  {
    unsigned char i = Wire.read();
    if(1)
    {
      int j = 5;
      while(j&gt;0)
      {
        digitalWrite(LED, HIGH);
        delay(300);
        digitalWrite(LED, LOW);
        delay(300);
        j-=1;
      }
    }
    delay(1);
  }
}


receiveEvent is an ISR (interrupt service routine). Don't do delay in an ISR. That will hang indefinitely. Thus the LED only blinks once. You could do delayMicroseconds for testing. In general an ISR should be short.




Interrupts
I2C