Interrupt Routine Stops Arduino

I've got a sketch to read the signal coming from an rc-receiver (call it PPM or PWM,..).
I basically need the lenght of the pulses coming.
So I did this:

attachInterrupt(INPUT_INTERRUPT,calcInput,CHANGE);

and then:

void calcInput()
{
  // if the pin is high, its the start of an interrupt
  if(digitalRead(INPUT_PIN) == HIGH)
  {
    startPeriod = micros();
  }
  else if(startPeriod && (inputSignal == 0))
  {
    inputSignal = (int)(micros() - startPeriod);
    startPeriod = 0;
  }
}

The else if statement I found to be of no use. The condition was met allways. So I changed it to else{ .. }.
For 4 channels this methods works quite elegant and is understood very fast. But the drawback is Interrupt-clashing. I now try to get the ISR faster -> so move it register-scale, like:

//#define DEBUG

#define FLAG_INT0 1

volatile uint32_t signal;
uint8_t flag;


void setup(void)
{
  Serial.begin(9600);

  pinMode(2, INPUT);

  sei();                    // Enable global interrupts
  EIMSK |= (1 << INT0);//|(1 << INT1);     //12.2.2 Enable external interrupt INT0 and INT1

  // PCICR |= (1<<PCIE0); // up to 2 for pinChangeInterrupts
  // PCMSK2 |= (1<<PCINT20); // digital pin 4
  // PCMSK1 |= (1<<PCINT8); // analog pin 0
  // PCMSK0 |= (1<< PCINT0); // digital pin 8

  //External Interrupt Control Register A
  EICRA |= (1<<ISC00);//|(1<<ISC10); //trigger any logical change INT0 and INT1

}


void loop(void){
  if(flag & FLAG_INT0)
  {
    Serial.print("The Signal was: ");

    uint8_t sreg = SREG;
    cli();
    Serial.println(signal);
    SREG = sreg;

    flag ^= FLAG_INT0;
  }
}//loop



ISR(INT0_vect)
{
  static uint16_t startTime;

  if(PIND & (1<<PIND2)) // if digital pin 2 is high
  {
    startTime = micros();
  }
  else
  {
    signal = (int)(micros() - startTime);
    flag |= FLAG_INT0;
  }
}

This works perfect at first. But after a few values > 1000 the arduino stops printing values. If I keep it <1000 everything works. 800 and 890 no deal.. but as soon as the value is 1000 for more than say 20-30 times, it just hangs.

I can even go above 1000 and then below again without crash, but staying above 1000 crashes after some times.

Am I doing something wrong? Is it,because micros() does something forbidden or overflows at 1000? Any help appreciated!

Try "static uint32_t startTime;". Guess, why.

The Signal was: 996
The Signal was: 1008
The Signal was: 1016
The Signal was: 1024
The Signal was: 1020
The Signal was: 1024
The Signal was: 1020
The Signal was: 1024
The Signal was: 1020
The Signal was: 1020
The Signal was: 1024
...
The Signal was: 1024
The Signal was: 1024
Th

with ISR:

ISR(INT0_vect)
{
  static uint32_t startTime;

  if(PIND & (1<<PIND2)) // if digital pin 2 is high
  {
    startTime = micros();
  }
  else
  {
    signal = (int)(micros() - startTime);
    flag |= FLAG_INT0;
  }
}

micros() returns an unsigned long -> 32bit, I read it up. Thanks for the hint!
Still doesn't resolve the "hang".

Don't call Serial.print with interrupts disabled. If the output buffer is full, then the call blocks waiting for free space in the transmit buffer, which will never happen because it depends on getting a transmit buffer empty interrupt.

dc42:
Don't call Serial.print with interrupts disabled. If the output buffer is full, then the call blocks waiting for free space in the transmit buffer, which will never happen because it depends on getting a transmit buffer empty interrupt.

Short, precise and working. Nothing to wish for more! :wink:

Thank you! I allready tried debug output within the ISR - which didn't work either,.. now it's obvious.