External Interrupts too slow? (Solved)

Hi,

I am using an Arduino Mega with 6 possible External Interrupts. My Problem is that PIN D2 and D3 (Interrupt 0 and 1) is a way slower than the other 4.

All of them are hooked up with a ultrasound sensor and trigger on the falling edge.

Does anyone experienceed this Problem already.

Thanks, notoriou5

Can you please post a program showing the problem ?
How are you measuring the "speed" of the interrupts ?

Here is the code. It might help...

long timer;
int n=6; //set number of sensors! (max 6)
int i, count[5];
volatile long time[5];
volatile boolean flag[5];
long distance[5], timediff[5];

void UltraSonicRead_0 ()
{
  time[0] = micros();
  flag[0] = true;
}

void UltraSonicRead_1 ()
{
  time[1] = micros();
  flag[1] = true;
}

void UltraSonicRead_2 ()
{
  time[2] = micros();
  flag[2] = true;
}

void UltraSonicRead_3 ()
{
  time[3] = micros();
  flag[3] = true;
}

void UltraSonicRead_4 ()
{
  time[4] = micros();
  flag[4] = true;
}

void UltraSonicRead_5 ()
{
  time[5] = micros();
  flag[5] = true;
}

//Interrupt PINS (Echo): D2(PE4), D3(PE5), D21(PD0), D20(PD1), D19(PD2), D18(PD3)
//Trigger: PORTC = PIN D30 bis D37

//Sensoren nach folgendem Prinzip anschließen
//Sensor_0: Echo=D2 ; Trigger=D30; -> reagiert sehr langsam
//Sensor_1: Echo=D3; Trigger=D31; -> reagiert sehr langsam
//Sensor_2: Echo=D21; Trigger=D32;
//Sensor_3: Echo=D20; Trigger=D33;
//Sensor_4: Echo=D19; Trigger=D34;
//Sensor_5: Echo=D18; Trigger=D35;

//vgl.: http://www.gammon.com.au/forum/?id=11488
//und http://www.arduino.cc/en/Reference/PortManipulation

void setup ()
{
  Serial.begin(115200);
  DDRD = DDRD | B00000000;   //PINs auf Port D alle Input
  PORTD = B00000000;
  DDRE = DDRE | B00000000;   //PINs auf Port E alle Input
  PORTE= B00000000;
  DDRK = DDRK | B11111111;   //PINS auf Port K alle Output
  attachInterrupt (0, UltraSonicRead_0, FALLING);
  attachInterrupt (1, UltraSonicRead_1, FALLING);
  attachInterrupt (2, UltraSonicRead_2, FALLING);
  attachInterrupt (3, UltraSonicRead_3, FALLING);
  attachInterrupt (4, UltraSonicRead_4, FALLING);
  attachInterrupt (5, UltraSonicRead_5, FALLING);
}

void loop()
{ 
  for (i=0; i<n; i++)
  {
  flag[i] = false;
  }
  
  PORTK = B00000000;         //D30 bis D37 auf LOW
  delay(2);
  PORTK = B11111111;         //D30 bis D37 auf HIGH
  delay(5);
  PORTK = B00000000;         //D30 bis D37 auf LOW
  
  delayMicroseconds(450);    //delay till signal was send
  timer = micros();
  
  delay(20);    //delay till reading is over; Increase if U only get ERRORS although all sensors are wired up correctly
  
  if (flag[5]) //only preced if all sensors are read (attach the ones wich are wired up) //flag[0] && flag[1] && flag[2] && flag[3] && flag[4] && flag[5]
   {
    for (i=0; i<n; i++)
    {
    timediff[i] = time[i] - timer;
    distance[i] = (timediff[i]*34)/2000;
    Serial.print(distance[i]);
    Serial.print(" "); 
    }
    Serial.print("R");
    Serial.print("\n");
    //delay (500); //set time for speed or disable for max speed
  }
  else
   {
    Serial.print("\n");
    Serial.print("ERROR");
    Serial.print("\n");
    delay(250);
   }
}

You are creating arrays that hold 5 indexes (0-4) and then using 6 indexes in your loops (0-5). This is going to clobber other data. Start by changing 'n' to 5 instead of 6.

These lines don't do what the comment says:

  DDRD = DDRD | B00000000;   //PINs auf Port D alle Input
  DDRE = DDRE | B00000000;   //PINs auf Port E alle Input

In fact they do nothing. Change them to:

  DDRD = B00000000;   //PINs auf Port D alle Input
  DDRE = B00000000;   //PINs auf Port E alle Input
  delay(20);    //delay till reading is over; Increase if U only get ERRORS although all sensors are wired up correctly

The nature of interrupts means that you have no idea when or if they will be triggered so how do you know that waiting 20mS will mean that all of them have been triggered ?

if (flag[5]) //only preced if all sensors are read (attach the ones wich are wired up) //flag[0] && flag[1] && flag[2] && flag[3] && flag[4] && flag[5]

flag[5] will only be true if the interrupt happened in the short amount of time since you set all the levels of flag[] to false a few lines before. How often will that happen I wonder ?

Note what John says about the array sizes and note that time[] should be an unsigned long to avoid problems with rollover.

Hi,
Thanks for the quick reply you two :slight_smile:

Main purpose of the sketch is to read 6 ultrasonic sensors sesimultaneously without waiting in the pulseIn function. The sensor needs around 600micros to get the signal back. If he doesnt get one he will wait for 20ms and then gives a 0. So the delay of 20ms is for the max time he needs to read (or all of them because they work simultaneously).
I changed the array problem and made the time unsigned.
But still remains the question why D2 and D3 read a way slower than the other 4?

Thanks, notoriou5

But still remains the question why D2 and D3 read a way slower than the other 4?

Where are you seeing this slow response ?

I see it in the Serial Output.
I only tested with 1 Sensor hooked up for now.

If I test it with D2 or D3 connected it writes every second (approximately). With the other 4 PINs it writes 10 times the second. It is a hard noticable difference between those PINs.

notoriou5:
I only tested with 1 Sensor hooked up for now.

If I test it with D2 or D3 connected it writes every second (approximately).

Where are you getting the pulse on Interrupt 5 that sets flag[5] that tells you to process the input? Could it be that flag[5] is not getting set as often when the sensor is connected to D2 or D3?

If you want to test the speed of interrupts write a special program to do that without relying on the uncertain responses of sensors. Ideally use another Arduino to generate the test signals so you know exactly what should happen. If you don't have a second Arduino you could probably use one pin as an output connected to one of the interrupt pins.

...R

@johnwasser: flag[5] is supposed to get set the same way as the others. They all get there inpulse from the same Ultrasonic sensor. So if i connect to D2 or D21 shouldnt matter at all. Could it possible that D2 or D3 need to set up a different way? The way the Serial.print gives the Data back does not make sense to me.

@Robin2: If i connect to the exact same sensor there shouldnt be a difference in the amount of inpulses from the sensor. But i could also try with a different arduino.

Notoriou5

notoriou5:
@johnwasser: flag[5] is supposed to get set the same way as the others. They all get there inpulse from the same Ultrasonic sensor. So if i connect to D2 or D21 shouldnt matter at all.

Are you saying that the Echo pin of your one sensor is connected to all five interrupt pins?

notoriou5:
@Robin2: If i connect to the exact same sensor there shouldnt be a difference in the amount of inpulses from the sensor. But i could also try with a different arduino.

That may be true, but you probably can't predict WHEN the interrupts will occur. Using an Arduino program to generate test interrupts would be predictable.

...R

@johnwasser: No, I only connect 1 Sesor at a time to one Echo PIN. I am not trying all simultanously. E.g. I connect the Echo to D2 and the Trigger to D30 (if condition is "flag[0]"). I upload and the Serial.print it slow. After that I change the PIN from D2 to D21 and change the if conditon to "flag[2]", upload and the Serial.print is fast... No clue why.

I also tried to slove the problem with using an PinChange Interrupt instead of the External one. I also wrote a code but it does not seem to work yet, any idead why?

Here is the code:

volatile byte portBstate, portBpast, changedbits;
volatile boolean intcalled = false;
volatile int count=0;

ISR (PCINT0_vect)
{
  portBpast = portBstate;
  portBstate = PINB;
  changedbits = portBpast ^ portBstate;
  
  if (changedbits & 0b00000001)
  {
    count++;        //the idea here is to trigger only on the falling edge
    if (count == 2)
    {
    intcalled = true;
    count = 0;
    }
  }
  else ;
  
}

void setup ()
{
  DDRB = B00000000;
  PORTB = B00000000;
  portBstate = PINB;
  Serial.begin(115200);
  PCICR |= (1<<PCIE0);
  PCMSK0 |= (1<<PCINT0); //Echo is connected to D53
}
void loop ()
{ PORTK = B00000000;         //D30 bis D37 auf LOW
  delay(2);
  PORTK = B11111111;         //D30 bis D37 auf HIGH
  delay(5);
  PORTK = B00000000;         //D30 bis D37 auf LOW
  delay(20);
  
  if (intcalled)
  {
    Serial.print ("PinChange worked");
    intcalled=false;
  }
  else
  {
    Serial.print ("ERROR");
  }
}

Where are you seeing this slow response ?

The way the Serial.print gives the Data back does not make sense to me.

If I test it with D2 or D3 connected it writes every second (approximately). With the other 4 PINs it writes 10 times the second. It is a hard noticable difference between those PINs.

I'm confused about whether or not you are experiencing a difference between the input pins in regards to

timediff[i] = time[i] - timer;

Can you please provide some sample output data of the time differences?

If you read each of the pins using the standard pulseIn(pin,HIGH) method for these distance sensors, do you see a difference in pulse lengths between the different pins?

Maybe this helps to understand the situation :smiley:

Here are two codes. First code is from the Sensor connected to D2, second Code is the sensor connected to D21. The string needs to look that way for later work in labview. The number between strings is supposed to be the "timer" value. 14cm is the distance of the object.

Code for D2:

14 -150 -150 -150 -150 -150 R
8836
14 -148 -148 -148 -148 -148 R
8764
14 -147 -147 -147 -147 -147 R
8684
14 -146 -146 -146 -146 -146 R
8608
14 -145 -145 -145 -145 -145 R
8544
14 -143 -143 -143 -143 -143 R
8464
14 -142 -142 -142 -142 -142 R
8380
14 -140 -140 -140 -140 -140 R
8292
14 -139 -139 -139 -139 -139 R

Code for D21

-128 -128 14 -128 -128 985 R
7552
-627 -627 14 -627 -627 486 R
36892
-1126 -1126 14 -1126 -1126 -12 R
66288
-1629 -1629 14 -1629 -1629 -515 R
95844
-2132 -2132 14 -2132 -2132 -1018 R
125460
-2638 -2638 14 -2638 -2638 -1524 R
155184
-3143 -3143 14 -3143 -3143 -2029 R
184908
-3648 -3648 14 -3648 -3648 -2534 R
214636

While connected to PIN D21 the timer seems to continousliy increase (which makes sense), but while connected to D2 it just gives approximately the same number. No clue why.

I also tested with the normal pulseIn function, but I don't see any time difference. Both are really fast. It somehow has to do with my sketch or the external Interrupts.

notoriou5

notoriou5:
Maybe this helps to understand the situation :smiley:

Nope.

Was that output produced by the code in Reply #13 ?

...R

No, sorry for the confusion. This Output was produced from the Code from reply#2.

Reply #13 only Produces Errors. Would be great if u could have a look and maybe tell me your opinion on it? Somehow the Interrupt gets not triggered...

notoriou5

You are using a series of interrupts to save the value of micros() when they are triggered.
You have an array with 5 elements but you are saving 6 values ? ? ? ?
Your array is defined as long when it should be unsigned long.

You are waiting until flag[5] (the 6th element) is true (even though the flag array only has 5 elements) before printing the results. But you have no control over the order of the interrupts. The mythical 6th one might trigger first.

It would be equally silly to wait for all 6 to be true because some of them might be triggered twice within that time.

You are printing the difference between the micros() value saved by an interrupt and some other value of micros() saved at some other time without having any idea when that second value was saved compared to when the interrupts happened.

Interrupts happen when they feel like happening and you have to write code that takes account of that. The question that is implicit in your title is, frankly, nonsense. There is certainly the possibility of bugs in an Atmega chip - but not one that is that significant. If you have data that suggests that some interrupts are slower than other you can be 99.999999% certain that the problem is in your own code.

...R

@Robin: I was pretty much sure it was my own code from the beginning, I was just wondering why this happens. I only wanted to know if anyone experienced that before and maybe knows whats the problem.

Anyway, there are good news, it really was the Array :smiley: I have no clue why but changing it to 6 helped.

Thanks a lot for all of your help, finnaly the project can move on

notoriou5