Crucial timing - Mains frequency

Hey guys, I'm working on a small project that will allow me to measure the exact frequency of the mains supply.

I've got the basic idea working, however I've been considering using an interrupt to detect the pulses, as the amount of code it executes in the loop affects the overall frequency reading.

My thoughts are, since I'm measuring a full-wave rectified pulse (So should be around 100 pulses per second), the LOW state is much longer lasting than the HIGH stage. My theory is, the code is detecting the LOW state at different times in the pulse, and thus, giving me off-readings.

I'm considering using interrupts to let me measure the frequency exactly, then it can send the data over serial while its not doing anything, to avoid incorrect readings. Here is the code at the moment:

int sensePin = 7;      // pin connected to opto, active low
int counter = 0;        // pulse count variable
long time = 0;           // time before counting
double diff = 0;           // time taken to count
double freq = 0;           // freq calculated
int pcount = 0; // has this pulse been counted
char* freqstring;
void setup() {
  pinMode(sensePin, INPUT);
  Serial.begin(115200);
}


void loop() {
  freq = 0;
  counter = 0;
 time = micros();      // get the start time
 while (counter<100){  // do this until we count 100 full pulses
    if (digitalRead(sensePin) == LOW && pcount == 0){
                      // if low signal & we havent counted it yet
     pcount = 1;     // say we've counted the first half of pulse
  //   digitalWrite(13, HIGH); // turn LED on
     //Serial.println(1);
   }
   if (digitalRead(sensePin) == HIGH && pcount == 1){
                      // if high signal & have counted high signal
     pcount = 0;     // reset indicator
     counter++;       // count the pulse
    // digitalWrite(13, LOW); // turn LED off
     //Serial.println(0);
   }
 }           // at this point we should have counted 100 pulses
// Serial.println("counted to 100");
 diff = micros() - time; // get teh time taken in uS to count 100
// Serial.print("Time taken in uS: ");
// Serial.println(diff);
 diff = diff / 1000000; // convert uS to S
 freq = 100 / diff; // calculate freq
          // frequency is 100 pulses over 1 second, i.e. 1000000us
          // except this will give us 100Hz, so
 freq = freq / 2; // halve it!
Serial.print("Freq: ");
Serial.println(freq, 4);
}

The issue is, even simple stuff like changing the number of chars to serial print changes my frequency reading, which is not really desirable.

How would you recommend I go about measuring the mains frequency efficiently? Even something as simple as a digitalWrite in the loop can shift my results up by 0.2Hz!

Cheers,
Dan

By 'data over serial' do you mean data over serial over mains voltage cables?

Anything involving mains voltages is potentially dangerous and detecting mains frequency and zero crossing is the least of your problems in that case.

By the way, are you aware that you can buy serial-over-mains and ethernet-over-mains and so on relatively cheaply? They work well and, more importantly, don't put your life in danger.

 diff = micros() - time; // get teh time taken in uS to count 100

micros() returns an unsigned long. The time variable is a long. Why are you storing the difference in a double?

    if (digitalRead(sensePin) == LOW && pcount == 0){

You are aware that digitalRead() takes time to convert the pin number to a port/pin combination, right? If you need to accurately, quickly read digital pins, digitalRead is not the way to go.

How are you connecting mains to the Arduino? The Arduino can not deal with AC or negative voltages.

There is an awful lot missing from your post.