Zero crossing detection

hello
I am through an electronic circuit to detect the I zero crossing it enters the pin enables the interruption arduino and to calculate the period of the input signal.

this and the code I'm using ....

int digitalPin=2;
float pulseHigh,stopTime,startTime,pulseLow,perio;


void setup(){

  Serial.begin(9600);
   pinMode(digitalPin, INPUT);
  
    attachInterrupt(0, periodo,FALLING);

}


void loop(){



}
void periodo(){
   detachInterrupt(0);
  if(digitalRead((2)==HIGH)){
  startTime=micros();
    pulseHigh=startTime-stopTime;
  }
  if(digitalRead((2)==LOW)){
      
       
    startTime=micros();
    pulseLow=stopTime-startTime;
  }
  perio=pulseHigh+pulseLow;
  Serial.println('Periodo');
  Serial.println(pulseHigh,BIN);

}

Thanks Gil

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

You can't use serial print from inside an interrupt routine.

But as I do as a void function does not return?

Thanks Gil

A void function is just a function that returns no values, this has nothing to do with your problem which is that you are using print statements inside an interrupt.

yes you are right I have to do seriaprint outside the function.

I am through an electronic circuit to detect the I zero crossing it enters the pin enables the interruption arduino and to calculate the period of the input signal.

I am just curious. What is the schematic ? Can you post it ? And what is the expect frequency going into the interrupt pulse ?

I did a code to measure the time on and off of a AC voltage from the plug of a home. I use pulseIn(). A little calculation there, and I show the frequency, duty cycle, time on and time off. No interrupt. The Ardiuno is fast enough to use pulseIn(). An interrupt will work, but it as to be very short, like for example :

void myinterrupt()
{
  state = HIGH;
}

And in your main code, you simply check that HIGH using a while() loop or if() or do { } while() loop.

You should not call detachInterrupt in the interrupt routine. When you do that it means that subsequent interrupts will not call periodo again.

Pete

    attachInterrupt(0, periodo,FALLING);

...

void periodo(){
   detachInterrupt(0);
  if(digitalRead((2)==HIGH)){    //  <---- well this will never happen

I did a code to measure the time on and off of a AC voltage from the plug of a home. I use pulseIn(). A little calculation there, and I show the frequency, duty cycle, time on and time off. No interrupt. The Ardiuno is fast enough to use pulseIn(). An interrupt will work, but it as to be very short, like for example :

Hello
I tried to do it your way whatever. I have the circuit in proteus I've put it here.

int pin = 7;
int pin1 = 6;
unsigned long duration, pulseHigh, pulseLow,fre;
void setup()
{
Serial.begin(9600);
pinMode(pin, INPUT);
pinMode(pin1, INPUT);
}

void loop()
{
//Serial.println('duration');
pulseHigh = pulseIn(pin, HIGH);
pulseLow = pulseIn(pin1,LOW);
duration= pulseHigh+pulseLow;
fre=1/duration;
Serial.println(fre);
}

thank Gil

attachInterrupt(0, periodo,FALLING);

...

void periodo(){
detachInterrupt(0);
if(digitalRead((2)==HIGH)){ // <---- well this will never happen

I want to calculate a time period then I will release the microcontroller to do other operations, and only when done and recalculates the period.

thank Gil

I have the circuit in proteus I've put it here.

Link??

Please use the # icon when posting code not the quote icon next to it.

ok thanks for the info

Thanks Gil :slight_smile:

@taurian

What is the frequency of the pulse being measured ?

The example code being show by you will work. The trick is, to sample the pulse a few times, average it and than you display and do other things, and come back you take samples again. The interrupt method is OK, but you have to activate the interrupt, sample the pulse, de-activate the interrupt, and calculate, display, whatever you have to do and repeat.

What is the frequency of the pulse being measured ?

The example code being show by you will work. The trick is, to sample the pulse a few times, average it and than you display and do other things, and come back you take samples again. The interrupt method is OK, but you have to activate the interrupt, sample the pulse, de-activate the interrupt, and calculate, display, whatever you have to do and repeat.

The frequency that will work will be 60Hz to 50Hz

with the interruption is in order so that detects a transition by zero I start taking samples, but I have a problem if the frequency changes. always had to read the frequency ..
I do not know how?

Thanks Gil

Is Your zero crossing detection schematic working?
I got my dimmer working.
I'm using Arduino Mega 1280.
Here is my code, hope You understand:

volatile int counterValue;
int requestValue;

void setup() {
  attachInterrupt(0, resetCounter, CHANGE); 
  cli();                      //Disable global interrupts
  TCCR3A = 0;                 //Set register to 0
  TCCR3B = 0;                 //Set register to 0
  OCR3A = 640;                //Compare match register to get desired timer count (50Hz mains)
  TCCR3B |= (1 << WGM12);     //Turn on CTC mode
  TIMSK3 |= (1 << OCIE3A);    //Enable timer compare interrupt
  TCCR3B |= (1 << CS10);      //Start timer
  sei();                      //Enable global interrupts
  pinMode(7, OUTPUT);
}

ISR(TIMER3_COMPA_vect) {
  counterValue++;
  counterValue &= 0xff;
  if (counterValue==requestValue) {
    digitalWrite(7, HIGH);
  } else {
    digitalWrite(7, LOW);
  }
}

void resetCounter()
{
  counterValue=0;
}

void loop(){
  requestValue=map(analogRead(0), 0, 1023, 0, 255);
}

Is Your zero crossing detection schematic working?
I got my dimmer working.
I'm using Arduino Mega 1280.
Here is my code, hope You understand:

Here is my circuit
I could send the complete program to compile.
I wanted to calculate the frequency of a signal and take samples in the same period when the frequency change in the middle of taking the samples have to cancel these samples ..

Thanks Gil

I'm not able to place an image. how can I do?

Thanks Gil

@taurian

Thank for the explaination. Alright, my schematic amd my code will work for that purpose. My zero crossing circuit use the output of a wall wart <-- extract / harvest transformer - reduce the AC secondary voltage , use op-amp as a comparator, when it cross the zero volt line, the state change, and the pulse is convert to TTL level and goes to a transistor - switch on / off and into a digital pin.

Check this tread. http://arduino.cc/forum/index.php/topic,93205.0.html

@Ragnar

I also did a dimmer using the Arduino. I use the same schematic <-- the zero level , but I rectify in full mode to produce positive pulse only, not positive and cut for 1/2 of 60 Hz. It produce two positive pulse from the 60 Hz, a full wave rectifier. I use the comparator to cut close to the zero to produce a 120 Hz very short pulse, and it is going into an digital / interrupt pin. And from it, it produce a PWM pulse, depending of the reading of the potentiometer, and send a turn off into the opto coupler, and the rest a turn on, the other side , opto and traic take care of the AC wave being cut properly and time right.

Here the tread. http://arduino.cc/forum/index.php/topic,91274.15.html

I use this schematic:

Only problem is that dimmer is working, if requestValue is somewhere between 1 and 216.
I checked with oscilloscope and it gave me from full wave to zero between those values.

I have 8 channels of dimmer and I'm going to dim house lights with returning light switches or impulse light switches or however you call it. Holding switch down dims up, after release it dims down. Short click turns full on or full of etc...