Parallel Port Code -
Here's a copy of the code from Sean Adams implementation, along with
//
my comments.
/* http://www.seanadams.com/pge */ /* You must compile this with gcc -O */ /* Set these */ #define LP_BASE 0x378 /* IO address of your parallel port */ #define Kh 7.2 /* "Disc constant" Watt-hours per turn, labeled on your meter */ #define PULSESPERTURN 2 /* Pulses per turn of the disc i.e. mine has two holes */ #define MRTGPATH "/var/pge.mrtg" /* Save watt-seconds to this file, in a format MRTG can read */ #define DEBOUNCE0 3 /* Rising edge counts as 100ms of zeroes followed by 30ms of ones */ #define DEBOUNCE1 10 /* note that the signal is inverted at the parallel port */ #include <sys/types.h> #include <sys/time.h> #include <stdio.h> #include <unistd.h> #include <asm/io.h> #define LP_DATA LP_BASE #define LP_STATUS LP_BASE + 1 #define LP_CONTROL LP_BASE + 2 // I don't know if I have this with Win32 void sleep_us(unsigned int usecs) { struct timeval sleeptime; sleeptime.tv_sec=usecs / 1000000; sleeptime.tv_usec=usecs % 1000000; select(0,NULL,NULL,NULL,&sleeptime); } // Something doesn't quite make sense to me here. In main, we take a measurement, then write // a record, then repeat forever. // So, why don't we set the start time equal to the last stop time? // And, looking at measure, it doesn't seem to sync to the detection of the hole for the start // of the sample... // Maybe I just need to run it to see how it really works... // unsigned long measure () { unsigned char cur,last; struct timeval starttime, stoptime; unsigned long num0=0, num1=0; gettimeofday(&starttime,NULL); while (num0 < DEBOUNCE0) { if ((inb(LP_STATUS) >> 7)==0) { num0++; } else { num0=0; } sleep_us(10000); } while (num1 < DEBOUNCE1) { if ((inb(LP_STATUS) >> 7)==1) { num1++; } else { num1=0; } sleep_us(10000); } gettimeofday(&stoptime,NULL); return (stoptime.tv_sec*1000+stoptime.tv_usec/1000-starttime.tv_sec*1000-starttime.tv_usec/1000); } int main (int argc, char *argv[]) { unsigned long pulses = 0; unsigned long t; float watts, avgwatts, watthours; FILE *MRTG; if (ioperm(LP_BASE, 3, 1) < 0) { printf ("Can't get permission to access IO port 0x%x\n",LP_BASE); exit(-1); } measure(); // You can see here that it runs forever. I think it could take a sample once every 5 minutes. // It would then wait until it detects a hole, then measure the time to the next hole. This // is then 1/2 revolution. while (1) { t=measure(); pulses++; watthours = Kh * pulses / PULSESPERTURN ; /* total watt-hours */ watts = Kh * 60 * 60 * 1000 / t / PULSESPERTURN; /* current watts */ printf ("%.2f W\t%.2f WH\n",watts,watthours); // We're writing the parameter on the first line, and then zero on the 2nd. // It may be that we could do more... If sampled continuously, then we could // write the peak watthours in the last 5 minutes, as well as the average. if (MRTG=fopen(MRTGPATH,"w")) { fprintf(MRTG,"%.0f\n0\n???\nElectic Meter\n",watthours); fclose(MRTG); } } }