Mains Frequency Meter 9600

mains-frequency-meter / Mains_Frequency_Meter / Mains_Frequency_Meter.pde

2.6 KB · raw

// Frequency measurement

uint8_t errorDelta = 25; // readings where F change over ~1 sec are greater than this millihz are discarded
volatile uint8_t skip = 5; // only skip this many consecutive assumed erroneous readings
const boolean debug = 1; // set this to non-zero to enable debug output to serial port
volatile uint8_t count = 0;
long skipped = 0;
long lastTime;
long lastMillihz;

ISR(ANALOG_COMP_vect) {
  ++count; // counts up and down transitions
}

// Moving coil meter control

int meterPin1 =  5;    // meter wire connected to digital pin 5
int meterPin2 =  3;    // meter wire connected to digital pin 3

void meterWrite(int scale) {
  if (scale >= 0) {
    if (scale > 250) 
      scale = 250;
    digitalWrite(meterPin2, LOW);
    analogWrite(meterPin1, scale);
  }
  else {
    if (scale < -250)
      scale = -250;
    digitalWrite(meterPin1, LOW);
    analogWrite(meterPin2, -scale);
  }
}

// Print to serial port 

void printLog(long now, long millihz, long skipped) {  
  Serial.print(now);
  Serial.print(" useconds ");
  Serial.print(millihz/1000);
  Serial.print('.');
  Serial.print((millihz/100) % 10, DEC);
  Serial.print((millihz/10) % 10, DEC);
  Serial.print((millihz) % 10, DEC);
  Serial.print(" Hz ");
  if (millihz >= 50000)
    Serial.print('+');
  Serial.print((millihz - 50000) * 0.002);
  Serial.println(" % ");
  if (skipped !=0) {
    Serial.print(" ****** SKIPPED: ");
    Serial.print(skipped);
    Serial.println(" ****** ");
  }
}

// Setup

void setup() {
  Serial.begin(57600);
  Serial.println("\n[hertz]");

  // compare against 1.1v reference
  ACSR = _BV(ACBG) | _BV(ACI) | _BV(ACIE);

  // use MUX to select AIO port 1
  ADCSRA &= ~ bit(ADEN);
  ADCSRB |= bit(ACME);
  ADMUX = 0;

  // initialize the digital pins as an output:
  pinMode(meterPin1, OUTPUT);
  pinMode(meterPin2, OUTPUT);

}

// Main loop

void loop() {
  cli();
  if (count >= 100) {  
    count -= 100;
    sei();
    long now = micros();

    if (lastTime != 0) {
      long millihz = long(50e9 / (now - lastTime));

      // Skip erroneous readings and print debug if enabled
      if ((lastMillihz != 0) && (skipped < skip) && (lastMillihz - millihz > errorDelta || millihz - lastMillihz > errorDelta)) {
        skipped++;
        if (debug !=0)
          printLog(now, millihz, skipped);
        millihz = lastMillihz;
      }
      else {
        skipped = 0;
        if (debug !=0)
          printLog(now, millihz, skipped);
        lastMillihz = millihz;
      }
      
      // Update the meter
      
      meterWrite(((millihz - 50000) * 2));
    }

    lastTime = now;
  } 
  else
    sei();
}