title: ATMega AVR External Interrupt
body: <p>I have an Arduino Mega application in which I read timing of low-frequency pulses (ca. 10Hz) at various duty cycles.<br>
  I use the external interrupt to catch the pulses, add the signal change times information into a 16-bit array[320] that I read back upon completion.<br>
  I normalize the time by setting the time of the first upgoing change as time 0.
  See attached simplified snippet (a working test with Arduino Mega, pin D2).<br>
  <strong>Problem:</strong> The first full cycle after reset reads the timing as expected, while each consequent cycle has only the <strong>first pulse ok, while all next pulses' timing is being randomly shifted</strong>.<br>
  I have tested and tried numerous options, including volatile and interrupt on change only, but always get the same result: First run is OK, next runs are shifted.<br>
  Any idea will be highly appreciated.</p>
  
  <pre><code>    /*Program reads input pulses at D2 and builds timing array of the up and 
      down going signals, using change interrupts on pin D2 of Mega
      To run, send array size in hex.
      by Sam Tal sam@tadin.co.il  Nov 9, 2017
      */
      #define interruptPin 2
      unsigned int dataArraySize;
      unsigned int timeData[320];
      volatile byte state = LOW;
      unsigned int counts = 0 ;      //Changes counter
      unsigned long startTime;       //The first up going interrupt time.
      //==========================================================
      void setup()
      {
        Serial.begin(115200);
        pinMode(interruptPin, INPUT);
      }
      //=========================================================
      void loop()
      {
        if (Serial.available())
        {
          dataArraySize = Serial.read();
          StartCycle();
        }
      }
      //========================================================
      void StartCycle(void)
      {
        Serial.println("Starting cycle...");
        //Reset the time array;
        memset ( timeData, 0, dataArraySize);
        counts = 0 ;
        state = LOW;
        attachInterrupt(digitalPinToInterrupt(interruptPin), Step, RISING);
      }
  
      //========================================================
      void Step()
      {
        detachInterrupt (digitalPinToInterrupt (interruptPin));
        if (counts == 0)
        {
          startTime = millis();    // Start time of the first rising change.
        }
        if (counts &lt; dataArraySize)
        {
          timeData[counts] = millis() - startTime ;
          counts++;
          attachInterrupt(digitalPinToInterrupt(interruptPin), Step, CHANGE);
        }
        else
        {
          detachInterrupt (digitalPinToInterrupt (interruptPin));
          SendData(timeData, dataArraySize);
        }
      }
       //===========================================================
     void SendData(unsigned int data[] , unsigned int arraysize)
      {
        int f;
        for (f = 0; f &lt; arraysize  ; f++)
        {
          Serial.print(f);
          Serial.print(",") ;
          Serial.println(data[f]);
        }
      }
  </code></pre>