Pages: [1]   Go Down
Author Topic: Interrupt timing issue  (Read 391 times)
0 Members and 1 Guest are viewing this topic.
Vancouver, Canada
Offline Offline
Newbie
*
Karma: 1
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey all! I'm new to the forum as well as the arduino - but an experienced programmer.

I've built a circuit to measure the frequency of a 120v/60hz AC phase through zero point detection. On the Arduino side I have:

Code:
volatile unsigned long lastInterrupt = 0;
volatile unsigned long previousInterrupt = 0;

void setup() {
  // some setup code ....
  attachInterrupt(0, zero_cross_int, RISING);
  // ... end setup code
}


void zero_cross_int() {
  previousInterrupt = lastInterrupt();
  lastInterrupt = micros();

  // the code below seems to mess up the timing calculation which normally detects 60Hz, but by adding this it detects 68Hz!!
  delayMicroseconds(65 * 128);
  digitalWrite(PIN_AC_LOAD, HIGH);
  delayMicroseconds(8);
  digitalWrite(PIN_AC_LOAD, LOW);
  // end output code
}

void loop(){
  long elapsed = lastInterrupt - previousInterrupt();
  long lastSignalDistance = micros() - lastInterrupt;
  float rate = ((1000.0 * 1000.0) / elapsed) / 2.0;
  Serial.print(rate, 2);
  Serial.println("Hz");
}


In the interrupt method I am keeping track of the time elapsed between two interrupts and using that to calculate the frequency of the interrupts. That works fine and detects the 60Hz AC frequency, but as soon as I add additional code with some delays the rate gets detected as 68Hz or so. I can't quite explain why, it's as if either the interrupts are running over-top of each other, or the lastInterrupt variable isn't being set until the end of the interrupt method. Can anyone explain this behavior or suggest how to better implement it?

(If anyone is wondering why I'm bothering to calculate the phase, since I could just fire off my code in the interrupt at the rate it is triggered - I have my reasons! I would like to detect the actual phase frequency to more accurately adjust the delays needed for triac firing)

Thanks guys!  smiley-cool
Logged

Beginner Enthusiast

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 508
Posts: 31369
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Simply you can not use a delay inside an ISR.
Logged

Vancouver, Canada
Offline Offline
Newbie
*
Karma: 1
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Not being able to delay inside the ISR sounds like a challenging problem. I need to ensure that I'm pulsing my triac at the exact zero point that the ISR is triggered, and if I am doing that in the main message loop so far I haven't been able to reliably sync.
Logged

Beginner Enthusiast

Offline Offline
Newbie
*
Karma: 0
Posts: 42
love arduino
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

check the good BlinkWithOutDelay
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can calculate the time interval, no worries. Just save the start time from the first interrupt, and when you get the second one, subtract one from the other.

You can also kick off another timer if you want to time up to some interval and set that other timer to cause an interrupt when it fires.

http://www.gammon.com.au/interrupts

http://www.gammon.com.au/forum/?id=11504
Logged

Vancouver, Canada
Offline Offline
Newbie
*
Karma: 1
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks guys.. I was able to rewrite the entire app without using delays. Instead of the interrupt doing any manipulation of outputs, I am using a simple boolean to flag when the interrupt is fired and measuring the distance in between each event. Works fantastic smiley

Logged

Beginner Enthusiast

Pages: [1]   Go Up
Jump to: