Pages: [1]   Go Down
Author Topic: DUE problem with micros() inside interrupts  (Read 3063 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi internet,

I have a project that is working refectly with an UNO but not so well with the DUE.  The problem seems to be that the interrupt type is changing or not working as expected.  I have an UNO generating a 490hz 50% PWM signal as the test input to pin 2 on the DUE.  I am using a Parallax oscilloscope to monitor the input signal and it is spot on.  Here is a simple piece of code I have loaded on the DUE that highlights the fault:
Code:
void setup() {
  Serial.begin(115200);
  attachInterrupt(2, FallEdge, FALLING);
}

void loop() {
  interrupts();
}

void FallEdge(){
  Serial.println(micros());
}
If I open the serial monitor, copy the output into a spreadsheet, write an equation to get the difference from one cell to the next ("=A2-A1") ... I can see that every 200 to 80 cycles it only reads about 1040 and then 3040 instead of 2040. It is not a consistent number of cycles from one error to the next. 

This seems like it is trigger on the rising edge instead of the falling edge once in a while, then ignoring a falling edge before going back to working off of falling edges.  I have the circuit protected with a 3.0V zener diode and fed in through a 1kohm resistor so that it doesn't get the UNO's 5V peak output.  Again, on the oscilloscope it looks solid, 3.0V.

As a check on the hardware I also used a frequency generator set at about 3.3v and removed my resistance/zener circuit protection entirely.  I am using Arduino IDE 1.5.2, had the same problem with previous release, 1.5.1r2.

Can someone else setup the same test and verify my sanity?  Has anyone else seen any problems with the interrupts on the DUE?
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2066
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Printing within isr is not recommended as it takes time (0.5ms in your case). Try to print outside the isr..
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

At 490Hz the 0.5ms time to print shouldn't matter though.  Plenty of time to do it and move on, right?  I also tried a little less than 400Hz and had the same problem.  And actually, I noticed the problem without the serial commands.  The example code I posted is just the easiest way to demonstrate the problem.  The program I wrote worked fine on the UNO, but not on the DUE.  The only reason I need the DUE is that I need more memory than the UNO has available.
Logged

Austria
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In such cases and for test purposes I prefer to change an output pin to be minimum invasive (compared the used serial command).
Invert an output inside- and each time the interrupt is called and watch the result with an oszilloscope, logic analizer etc. The comparison between the input signal and the output should show you if the interrupt is missing something.
Another solution might be to use two counters. One inside the interrupt and a second one outside (at this frequency the signal will be detected easily also not using an interrupt). If both count up at the same rate - it should be OK.
I hope I could help.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the idea.  That was what the original program was doing in the interrupt along with a little math.  Originally I wasn't using any serial commands.  I started to write this topic before I was totally done debugging and thats why the title doesn't exactly make sense for how I described it (forgot to change it).  At first I thought it was something specific to the micros() command, but when I realized the time stamps were happening only at a rising or falling edge it started making a little more sense... although it still doesn't make much sense to me.  Seems like something is busted.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I think I have the same problem..
I have both Arduino uno and arduino due.
I had used the function micros() inside an interrupt, and sometimes it seem not work fine in arduino due.
I would like to acquire the frequency (or time beetwen rising edge, i.e. Period) of an input signal on pin 28  (in Arduino due). The signal is a square wave 0/3.3V with PWM 50%.
For example I set the frequency to 2000Hz ( period of 500 micro second ) with a function generation.
this is the simple code:

volatile unsigned long time, Time1, Time2, Period =0;
volatile int i=0;
int Signal=28;

void setup() {
  Serial.begin(9600);
  pinMode(Signal,INPUT); 
  attachInterrupt(Signal,InterruptSegnaleGiriT,FALLING);  //Interrupt on Falling Edge
  }

void loop() {
  if(Period<490 || Period >510){
      Serial.println(Period);
      Serial.println(Time1);
      Serial.println(Time2);
      Serial.println("");
  }
void InterruptSegnaleGiriT(){
      time=micros();
          if(i==0){ 
            Time1=time;
            i=1;
            return;
          }
          if(i==1){
            Time2=time;
            Period=(Time2-Time1);
            i=0;
            return; 
      }
}

If the function micros work fine, this code does not print anything.
The problem is that sometimes the Period print is 1500 micro.
While sometimes Period print is a number near to the limit of an unsigned long,
maybe the Time1 is greater than Time2.

I Have try to put the code on arduino uno, the code work fine!!!
Maybe is a bug on Arduino due micros...
sorry for the english..
thank
       

Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 23
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

submitted as a new issue:

https://github.com/arduino/Arduino/issues/1301
Logged

C.

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just tested the code from my first post and noticed the same problem on a brand new DUE, so I don't think that my hardware is damaged.  Here are other things I have tested:

Using different pins - problem persists
Using RISING instead of FALLING - problem persists
Using CHANGE instead of FALLING - similar problem
Using higher and lower input frequencies - problem persists

I changed the code to only have a counter in the interrupt and it worked correctly, but that doesn't help me.  Here is the code:
Code:
volatile int counter = 0;

void setup() {
  Serial.begin(115200);
  attachInterrupt(2, FallEdge, FALLING);
}

void loop() {
  interrupts();
  if (counter >= 1)  {
    Serial.println(micros());
    counter = 0;
  }
}

void FallEdge(){
  counter++;
}

Then I moved the print statement out of the interrupt, but kept the micros() in the interrupt.  It still had the same problem.  Here is the code:
Code:
volatile unsigned long counter = 0;

void setup() {
  Serial.begin(115200);
  attachInterrupt(2, FallEdge, FALLING);
}

void loop() {
  interrupts();
  if (counter >= 1)  {
    Serial.println(counter);
    counter = 0;
  }
}

void FallEdge(){
  counter = micros();
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 44
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi!
Same here...
I am reading the time between two interrupts - and print the measured values. Also figuered out that printing is not the problem here - proved this by changing ports and measuring these with an oszi. I assume that the value of micros() differs exact 1000micS plus or minus the values they are meant to be - perhaps interesting for debugging.
Let us now when sby finds out more!
Thanks!
Logged

Pages: [1]   Go Up
Jump to: