Measuring refrigeration power draw.
purple_stars wrote:
purple_stars wrote:
[snip]
maybe the OP could borrow a data logger or multimeter/laptop setup ...
that's what most people do when they need an expensive tool, borrow it,
or rent it
actually i just looked around and radio shack has a multimeter that can
handle 10amps that has a serial interface on it, even comes with pc
software. costs 70$us, i think i'm going to go get one for myself and
try it out haha
i purchased one of these meters (46-range digital multimeter part
number 22-812) from radio shack earlier this evening, it's pretty nice.
it has all the usual things on it and includes a serial port so that
you can hook it up to your computer. there is some software that comes
with it for the PC but i didn't install it so i don't really know what
it does, i think it does have data logger functions in it. i wanted to
use the meter's output under linux so i had to write some code to parse
the weird binary data coming out of the meter into something
understandable. anyway, since it took over and hour to write a parser
for the data i thought i would post the code and maybe save someone
else the trouble. it should be trivial to write a data logger based on
this.
----
#include stdio.h
#include stdlib.h
#include fcntl.h
#include string.h
#include termios.h
/**
simple scrap of code for 22-812 46-range digital multimeter from
radio shack that compiles on fedora .. listens to the serial port
at 4800 baud and converts all the weird bits the meter sends
across the line into something human readable, hopefully gives
some poor ******* (you) the chance to watch television re-runs
instead of having to figure out what the bit pattern was, like i
had to. i could have cleaned the code up a lot and cut down on
the amount of code but i left it fat and ugly so you could figure
it out with ease and use it for whatever you want. hardly any
error checking in it. cheers.
LEGAL: public domain, no warranties expressed or implied. if it
burns your house down that's your own fault, you should
have been out sailing anyway. enjoy.
**/
char *mode_str [] = { /** string descriptions of modes **/
"DC V ", /* 0x00 */
"AC V ", /* 0x01 */
"DC uA ", /* 0x02 */
"DC mA ", /* 0x03 */
"DC A ", /* 0x04 */
"AC uA ", /* 0x05 */
"AC mA ", /* 0x06 */
"AC A ", /* 0x07 */
"OHM ", /* 0x08 */
"CAP ", /* 0x09 */
"HZ ", /* 0x0a */
"NET HZ ", /* 0x0b */
"AMP HZ ", /* 0x0c */
"DUTY ", /* 0x0d */
"NET DUTY ", /* 0x0e */
"AMP DUTY ", /* 0x0f */
"WIDTH ", /* 0x10 */
"NET WIDTH ", /* 0x11 */
"AMP WIDTH ", /* 0x12 */
"DIODE ", /* 0x13 */
"CONT ", /* 0x14 */
"hFE ", /* 0x15 */
"LOGIC ", /* 0x16 */
"dBm ", /* 0x17 */
"UNKNOWN ", /* 0x18 */
"TEMP " /* 0x19 */
};
#define VAL_1 0 /* array ptrs for digit positions on lcd screen */
#define VAL_2 1
#define VAL_3 2
#define VAL_4 3
typedef struct {
unsigned char match; /* bits to match */
unsigned char value; /* value if matched */
} bit_patterns;
#define MAX_PAT 18
#define CHAR_BLANK 0x10
#define CHAR_MINUS 0x20
#define CHAR_C 0x30
#define CHAR_F 0x40
#define CHAR_P 0x50
#define CHAR_E 0x60
#define CHAR_N 0x70
#define CHAR_L 0x80
bit_patterns pats[] = {
{ 0xd7, 0 }, /* 0 */
{ 0x50, 1 }, /* 1 */
{ 0xb5, 2 }, /* 2 */
{ 0xf1, 3 }, /* 3 */
{ 0x72, 4 }, /* 4 */
{ 0xe3, 5 }, /* 5 */
{ 0xe7, 6 }, /* 6 */
{ 0x51, 7 }, /* 7 */
{ 0xf7, 8 }, /* 8 */
{ 0xf3, 9 }, /* 9 */
{ 0x00,CHAR_BLANK }, /* (special, blank character) */
{ 0x87,CHAR_C }, /* C (special) */
{ 0x27,CHAR_F }, /* F (special) */
{ 0x64,CHAR_P }, /* P (special) */
{ 0xa7,CHAR_E }, /* E (special) */
{ 0x37,CHAR_N }, /* N (special) */
{ 0x86,CHAR_L }, /* L (special) */
{ 0x20,CHAR_MINUS } /* - (special, minus sign or dash) */
};
unsigned char vals[4];
int make_value()
/**
ok, basically this is the deal. there are 4 bytes (out of 9) that
come out of the serial line that are stored in vals[] and each bit
in those bytes is one of the lcd elements ... yes, that is to say
that for instance the character "8" is made up of 7 different
lcd segments, four vert ones and 3 horizonal. we have to match
those bits against what we have in pats[] in order to get a
real value back that is useful. then we print that and the
various decimal points out. you would probably want to make and
return a string or something and use it somewhere else
**/
{
int val;
int n;
int i;
for(n = (int)0;n 4;n++)
{
for(val = (int)-1,i = (int)0;i MAX_PAT;i++)
{
if(pats[i].match == (vals[n] & 0xf7))
val = pats[i].value;
}
if((vals[n] & 0x08) == 0x08)
printf(".");
switch(val) {
case((int)-1):
printf("[BAD(%02x)]",vals[n]&0xf7);
break;
case(0): case(1): case(2): case(3): case(4):
case(5): case(6): case(7): case(8): case(9):
printf("%d",val);
break;
case(CHAR_C): printf("C"); break;
case(CHAR_F): printf("F"); break;
case(CHAR_P): printf("P"); break;
case(CHAR_E): printf("E"); break;
case(CHAR_L): printf("L"); break;
case(CHAR_N): printf("N"); break;
case(CHAR_BLANK): printf(" "); break;
case(CHAR_MINUS): printf("-"); break;
default: break;
}
}
return((int)0);
}
int main(int argc, char **argv)
/**
main()
**/
{
int i;
int s;
int bit;
int len;
unsigned char c;
int neg;
struct termios newtio, oldtio;
/** set the serial port up for 4800 baud, 8n1 /dev/ttyS0 **/
if((s = open("/dev/ttyS0",O_RDWR | O_NOCTTY | O_NONBLOCK)) (int)0)
{ fprintf(stderr,"open(): (int)0\n"); exit((int)-1); }
tcgetattr(s,&oldtio);
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = B4800 | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
tcflush(s,TCIFLUSH);
tcsetattr(s,TCSANOW,&newtio);
fcntl(s,F_SETFL,FASYNC);
bit = (int)0;
/** start reading from the serial port and processing whatever bits
we get from the multimeter. we do this strictly by position,
each "packet" that comes out of the meter is has 9 bytes of
data associated with it, and we just process them in order **/
for(neg = (int)0,len = (int)0;
(i = read(s,&c,1)) = (int)0;usleep(200))
if(i (int)0)
{
switch(bit) {
case(0): /* byte 1 from meter says what the mode is */
printf("[MODE] %s ",mode_str[c&0xff]);
bit = (int)1;
break;
case(1): /* byte 2 from meter contains bits that represent
the actual icons on the lcd screen like the
"OHM" or "HZ" symbols */
printf("[LCD] "); /** print the symbols from LCD **/
if(c & 0x80) printf("Hz ");
if(c & 0x40) printf("OHM ");
if(c & 0x20) printf("K ");
if(c & 0x10) printf("M ");
if(c & 0x08) printf("F ");
if(c & 0x04) printf("A ");
if(c & 0x02) printf("V ");
if(c & 0x01) printf("m ");
bit = (int)2;
break;
case(2): /* byte 3 from meter is more lcd symbols */
if(c & 0x80) printf("u ");
if(c & 0x40) printf("n ");
if(c & 0x20) printf("dBm ");
if(c & 0x10) printf("S ");
if(c & 0x08) printf("% ");
if(c & 0x04) printf("hFE ");
if(c & 0x02) printf("REL ");
if(c & 0x01) printf("MIN ");
bit = (int)3;
break;
case(3): /* byte 4 from meter is one of our lcd values. the
lcd has four actual digits on it, these are what
you are going to be most interested in. each
byte of data has seven "segments" which are the
actual lcd segments which make up the digit, and
another bit for decimal on or off */
vals[VAL_4] = c&0xff;
bit = (int)4;
break;
case(4): /* byte 5 from meter, another digit and decimal */
vals[VAL_3] = c&0xff;
bit = (int)5;
break;
case(5): /* byte 6 from meter, another digit and decimal */
vals[VAL_2] = c&0xff;
bit = (int)6;
break;
case(6): /* byte 7 from meter, another digit and decimal */
vals[VAL_1] = c&0xff;
bit = (int)7;
break;
case(7): /* byte 8 from meter, more lcd symbols */
if(c & 0x80) printf("BEEP ");
if(c & 0x40) printf("DIODE ");
if(c & 0x20) printf("BAT ");
if(c & 0x10) printf("HOLD ");
if(c & 0x08)
{
neg = (int)-1;
printf("- ");
}
if(c & 0x04) printf("~ ");
if(c & 0x02) printf("RS232 ");
if(c & 0x01) printf("AUTO ");
bit = (int)8;
break;
case(8): /* byte 9 from meter, checksum, ignored in this
code but you'd probably want to actually use
it for error checking in your own code */
printf("[CHKSUM] %02x ",c&0xff);
printf("[VAL] ");
make_value(); /* process the digits and make something
out of them. they are stored in the
global variable vals[], 4 bytes worth,
so go parse it and print it out in human
readable form */
printf("\n");
bit = (int)0; /* get the first char all over again */
neg = (int)0; /* reset global negative bit */
break;
default: break;
}
fflush(stdout);
}
tcsetattr(s,TCSANOW,&oldtio);
close(s);
exit((int)0);
}
|