/* El Logger Reads blinking LED:s on meter to get active and reactive power. Tuned for 1000 impulses per kwh and kwhr, each pulse should be about 10 ms in length. To read the leds, a photodiode is placed over each led and then the signal is buffered before transfered to arduino board. Power-meter active power led is mirrored to led on pin #13. Pin 12 is high during 1 khz interrupt execution (to be able to meas int time w osc) Pin 2 is set to 1 khz 50% duty to generate interrupt AD0 is analog value from active power photodiode. AD1 is analog value from reactive power photodiode. TODO: Add a checksum on the message for error checking. */ // constants won't change. Used here to // set pin numbers: const int ledPin = 13; // the number of the LED pin const int dbgPin = 12; const int intPin = 2; // the interrupt gen pin const int adactive = 0; // AD channels for active & reactive power const int adreactive = 1; const int TRIGLEVEL = 35; // triglevel on analog signal 1023 = 5.0V const int UNTRIGLEVEL = 30; #define KWHC (3600000L) // pwr at one pulse per ms, i.e. 1000 pulses per kwh. // Variables will change: int foo; struct intdata { /* internal data */ volatile int base; volatile int baserem; volatile int sig; volatile int sigrem; volatile int trig; volatile long prevtime; volatile int pulses; /* external data for background prog */ volatile int ptrig; volatile int ppulses; volatile long powertime; volatile long power; volatile int sigmax; } id1, id2; volatile long adint = 0; void iniid(struct intdata *id) { id->base = 0; id->sig = 0; id->trig = 0; id->prevtime = 0; id->pulses = 0; } void setup() { // set the digital pin as output: pinMode(ledPin, OUTPUT); pinMode(dbgPin, OUTPUT); pinMode(intPin, OUTPUT); Serial.begin(1200); adint = 0; iniid(&id1); iniid(&id2); attachInterrupt(0, adpoll, FALLING); tone(intPin, 1000); Serial.println("El logger ver 1.0 2011-08-23 /TN "); }; void adpoll() { int ad1, ad2; int tmp, stmp; long tmpl; digitalWrite(dbgPin, 1); adint++; ad1 = analogRead(adactive); /* analog in for active power */ ad2 = analogRead(adreactive); /* analog in for reactive power */ // debug code... // /* ad1 = 100; if ((adint & 0xff0) == 0xff0) ad1 = 200; ad2 = 90; if ((adint & 0x7f0) == 0x710) ad2 = 180; */ // do active power // // filter base, tau = 0.256 seconds. tmp = (ad1 - id1.base + id1.baserem) & 0xff; id1.base = id1.base + ((ad1 - id1.base + id1.baserem) >> 8); id1.baserem = tmp; // filter sig, tau = 0.004 seconds. stmp = ad1 - id1.base; tmp = (stmp - id1.sig + id1.sigrem) & 0x03; id1.sig = id1.sig + ((stmp - id1.sig + id1.sigrem) >> 2); id1.sigrem = tmp; if (id1.sig > id1.sigmax) id1.sigmax = id1.sig; if ((id1.trig) && (id1.sig < UNTRIGLEVEL)) { id1.trig = 0; digitalWrite(ledPin, 0); } if ((id1.trig == 0) && (id1.sig >= TRIGLEVEL)) { id1.trig = 1; // we found a pulse digitalWrite(ledPin, 1); // mirror input to output id1.pulses++; if (id1.sig > id1.sigmax) id1.sigmax = id1.sig; tmpl = adint - id1.prevtime; if (tmpl >= 10000) { // more than 10 seconds? id1.power = id1.pulses * KWHC / tmpl; id1.powertime = tmpl; id1.prevtime = adint; id1.ppulses = id1.pulses; id1.pulses = 0; id1.ptrig = 1; // calculated a value... need to print... } } // do reactive power // // filter base, tau = 0.256 seconds. tmp = (ad2 - id2.base + id2.baserem) & 0xff; id2.base = id2.base + ((ad2 - id2.base + id2.baserem) >> 8); id2.baserem = tmp; // filter sig, tau = 0.004 seconds. stmp = ad2 - id2.base; tmp = (stmp - id2.sig + id2.sigrem) & 0x03; id2.sig = id2.sig + ((stmp - id2.sig + id2.sigrem) >> 2); id2.sigrem = tmp; if (id2.sig > id2.sigmax) id2.sigmax = id2.sig; if ((id2.trig) && (id2.sig < UNTRIGLEVEL)) { id2.trig = 0; } if ((id2.trig == 0) && (id2.sig >= TRIGLEVEL)) { id2.trig = 1; // we found a pulse id2.pulses++; if (id2.sig > id2.sigmax) id2.sigmax = id2.sig; tmpl = adint - id2.prevtime; if (tmpl >= 10000) { // more than 10 seconds? id2.power = id2.pulses * KWHC / tmpl; id2.powertime = tmpl; id2.prevtime = adint; id2.ppulses = id2.pulses; id2.pulses = 0; id2.ptrig = 1; // calculated a value... need to print... } } digitalWrite(dbgPin, 0); } void loop() { // here is where you'd put code that needs to be running all the time. delay(1000); // some debug code... /* Serial.print(" diff: "); foo = millis() - adint; Serial.print(foo); Serial.print("ad: "); Serial.print(id1.base); Serial.print(" "); Serial.println(id1.sig); */ // test for trig on active power and print... if (id1.ptrig == 1) { Serial.print("#A "); Serial.print(id1.powertime); Serial.print("; "); Serial.print(id1.ppulses); Serial.print("; "); Serial.print(id1.power); Serial.print("; "); Serial.print(id1.base); Serial.print("; "); Serial.print(id1.sigmax); Serial.println("; "); id1.sigmax = 0; id1.ptrig = 0; } // test for trig on reactive power and print... if (id2.ptrig == 1) { Serial.print("#B "); Serial.print(id2.powertime); Serial.print("; "); Serial.print(id2.ppulses); Serial.print("; "); Serial.print(id2.power); Serial.print("; "); Serial.print(id2.base); Serial.print("; "); Serial.print(id2.sigmax); Serial.println("; "); id2.sigmax = 0; id2.ptrig = 0; } };