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