Home |
Search |
Today's Posts |
#5
![]()
posted to rec.boats.cruising
|
|||
|
|||
![]()
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); } |
Thread Tools | Search this Thread |
Display Modes | |
|
|
![]() |
||||
Thread | Forum | |||
Delay on timer relay for AC power supplies | Electronics | |||
Sunball...5X more power | Cruising | |||
Build Your own refrigeration - cheap parts for engine drive and 110VAC dual system | Boat Building |