ArduinoUno freezes after X seconds when using Interrupts

Hello everybody,

I am building a quadcopter using my ArduinoUno. In my code I use interrupts to detect receiver inputs. Unfortunately the program freezes after a seemingly random amount of time.

I checked my SRAM usage, that doesn't seem to be the problem.

I used watchdog to find the byte-address that is causing troubles, but unfortunately I can not find the given address in the Disassembly.txt file. This leads me to the conclusion, that the error occures on a dynamically allocated address generated for the interrupts.

Changing the baud rate doesn't solve the problem.

This is how I set the Interrupts:

  // >----- Interrupts for Receiver Input -----<
  PCICR |= (1 << PCIE0);                                                    //Set PCIE0 to enable PCMSK0 scan.
  PCMSK0 |= (1 << PCINT0);                                                  //Set PCINT0 (digital input 8) to trigger an interrupt on state change.
  PCMSK0 |= (1 << PCINT1);                                                  //Set PCINT1 (digital input 9)to trigger an interrupt on state change.
  PCMSK0 |= (1 << PCINT2);                                                  //Set PCINT2 (digital input 10)to trigger an interrupt on state change.
  PCMSK0 |= (1 << PCINT3);                                                  //Set PCINT3 (digital input 11)to trigger an interrupt

And this is the ISR:

// Interrupt Service Routine
ISR(PCINT0_vect){
  current_time = micros();
  //Channel 1=========================================
  if(PINB & B00000001){                                                     //Is input 8 high?
    if(downR == 0){                                                //Input 8 changed from 0 to 1.
      downR = 1;                                                   //Remember current input state.
      prev_timeR = current_time;                                   //Set timer_1 to current_time.
    }
  }
  else if(downR == 1){                                             //Input 8 is not high and changed from 1 to 0.
    downR = 0;                                                     //Remember current input state.
    pwm_valueR = current_time - prev_timeR;                             //Channel 1 is current_time - timer_1.
  }
  //Channel 2=========================================
  if(PINB & B00000010 ){                                                    //Is input 9 high?
    if(downP == 0){                                                //Input 9 changed from 0 to 1.
      downP = 1;                                                   //Remember current input state.
      prev_timeP = current_time;                                               //Set timer_2 to current_time.
    }
  }
  else if(downP == 1){                                             //Input 9 is not high and changed from 1 to 0.
    downP = 0;                                                     //Remember current input state.
    pwm_valueP = current_time - prev_timeP;                             //Channel 2 is current_time - timer_2.
  }
  //Channel 3=========================================
  if(PINB & B00000100 ){                                                    //Is input 10 high?
    if(downH == 0){                                                //Input 10 changed from 0 to 1.
      downH = 1;                                                   //Remember current input state.
      prev_timeH = current_time;                                               //Set timer_3 to current_time.
    }
  }
  else if(downH == 1){                                             //Input 10 is not high and changed from 1 to 0.
    downH = 0;                                                     //Remember current input state.
    pwm_valueH = current_time - prev_timeH;                             //Channel 3 is current_time - timer_3.

  }
  //Channel 4=========================================
  if(PINB & B00001000 ){                                                    //Is input 11 high?
    if(downY == 0){                                                //Input 11 changed from 0 to 1.
      downY = 1;                                                   //Remember current input state.
      prev_timeY = current_time;                                               //Set timer_4 to current_time.
    }
  }
  else if(downY == 1){                                             //Input 11 is not high and changed from 1 to 0.
    downY = 0;                                                     //Remember current input state.
    pwm_valueY = current_time - prev_timeY;                             //Channel 4 is current_time - timer_4.
  }
}

I have used the same ISR routine that Joop Brokking uses in his quadcopter tutorial.
Attached you can find the full Code I am using currently.

I would be really happy if you guys could give me some advice on how to avoid the freezing of my board!
Regards Andy

flight_controller_v5_forum.ino (14 KB)

volatile int prev_timeR = 0;
volatile int prev_timeP = 0;
volatile int prev_timeH = 0;
volatile int prev_timeY = 0;

I don't know if it is related to your problem, but these variables are taking on the value of current_time = micros() they should be typed as volatile unsigned long.

Wouldn't it be sufficient to record the value of micros() and the value from PINB in the ISR and then leave the rest of that code to the main part of your program?

And you read PINB a number of times in your ISR - there is no guarantee that you will get the same value each time. I would just read it once and then work from the saved value.

Both of these parts are very doubtful in my mind

 // do something here that takes less then 1000us (ESC Pulse)
  recordIMUSignals();
  processAccelData();
  processGyroData();
 //keep loop at 250 Hz
  time2=micros()-time1;
  if(time2<4000) {
  delayTime = 4000 - time2;
  delayMicroseconds(delayTime);
  }

Have you checked carefully to see that those three functions together take less than 1000µsecs?

Using delayMicroseconds() seems a very crude way of managing timing. As well as which it is wasting CPU cycles that could probably be used for something productive.

I would never try to slow down the repetition of loop(). All of my efforts would be aimed at getting it to repeat as often as possible.

And I assume your PID function is using floating point maths. If so it is likely to be very slow. I suggest you measure the time it takes.

...R