//
// name Victor86B_usbDMM.cpp
// author david moloney, movidius ltd.
// purpose decodes and displays output from Victor 86B USB DMM
// date 03 Jan 2012
// note based on HIDAPI http://www.signal11.us/oss/hidapi/
//
#pragma warning(disable : 4996) // disable MSVC++ printf warning
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include "hidapi.h"
#include "time.h"
/* Victor 86B DMM on my machine returns following descriptor
Device Found
type: 1244 d237
path: \\?\hid#vid_1244&pid_d237#9&29fd82b3&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
serial_number:
Manufacturer:
Product:
Release: 100
Interface: -1
*/
void report_HIDs() {
struct hid_device_info *devs, *cur_dev;
devs = hid_enumerate(0x0, 0x0);
cur_dev = devs;
while (cur_dev) {
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
printf("\n");
if (cur_dev->vendor_id==0x1244) printf(" Manufacturer: Victor\n");
else printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
if (cur_dev->product_id==0xd237) printf(" Product: 86B DMM\n");
else printf(" Product: %ls\n", cur_dev->product_string);
printf(" Release: %hx\n", cur_dev->release_number);
printf(" Interface: %d\n", cur_dev->interface_number);
printf("\n");
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
} // report_HIDs()
struct Victor86B_display { // Victor 86B LCD Display descriptor
/*
AUTO RS232 REL HOLD BATT
DC - - - -
AC | | | | | | | | % C
- - - - - < >
| | | | | | | | n m F V A
- . - . - . - μ
M k Ω Hz
*/
int digit[4], decimal[4], minus;
int AUTO, RS232, REL, HOLD, BATT;
int AC, DC;
int Percent, degC;
int Spkr, Diode;
int nano, milli, Farads, V, A;
int micro;
int Mega, Kilo, Ohms, Hertz;
int Overload;
}; // struct Victor86B_display
struct DMM_reading { // DMM_reading
double value; // value of reading
int units; // Volts, Amps, oC etc.
int info; // Overload, REL, HOLD etc.
}; // struct DMM_reading
struct DMM_reading decode_Victor86B(unsigned char* buf) {
// Victor86B multimeter LCD control bits passed back as a string of 14 hex characters
// details derived experimentally using the Victor86B DMM and a Bench PSU
struct DMM_reading DMM;
int LCD_minus=0;
int LCD_digit[4];
int LCD_decimal[4];
int LCD_DC = 0; // DC
int LCD_AC = 0; // AC
int LCD_V = 0; // Volts
int LCD_A = 0; // Amps
int LCD_m = 0; // m - milliamps
int LCD_u = 0; // u - microamps
int LCD_REL = 0; // REL
int LCD_HOLD = 0; // HOLD
int LCD_Hz = 0; // Hz
int LCD_oC = 0; // degrees C
int LCD_M = 0; // Mega - ohms
int LCD_OL = 0; // Overload
if (strlen((char*)buf)!=23) { // display error message if USB HID packet (buf) incomplete!
//
printf("no string read from DMM ... %d\n",strlen((char*)buf));
printf(" 1. make sure DMM is switched on\n");
printf(" 2. try plugging out USB and replacing\n");
DMM.info = -1;
return DMM;
}
else { // decode and display digits from USB HID packet (buf)
// LCD digits annunciators
// - - - -
// | | | | | | | |
// - - - - - M Hz
// | | | | | | | | DC REL V
// - - - - AC HOLD m oC u A
//
// buf 3,10 6,9 5,7 0,2 1 4 8 11 12 13
// reset display variables
LCD_minus=0;
LCD_digit[0]=LCD_digit[1]=LCD_digit[2]=LCD_digit[3]=0;
LCD_decimal[0]=LCD_decimal[1]=LCD_decimal[2]=LCD_decimal[3]=0;
// LCD_digit[3] - most significant digit
/*
digit 4 of Victor86B LCD display ... values are decimal!
.
LCD b3 b10 b10
0 33 79 95
1 17 111 127
2 65 15 31
3 97 239 255
4 81 175 191
*/
// +X
if ((unsigned)buf[3]== 33 && (unsigned)buf[10]== 79) LCD_digit[3]=0;
if ((unsigned)buf[3]== 17 && (unsigned)buf[10]==111) LCD_digit[3]=1;
if ((unsigned)buf[3]== 65 && (unsigned)buf[10]== 15) LCD_digit[3]=2;
if ((unsigned)buf[3]== 97 && (unsigned)buf[10]==239) LCD_digit[3]=3;
if ((unsigned)buf[3]== 81 && (unsigned)buf[10]==175) LCD_digit[3]=4;
// -X
if ((unsigned)buf[3]== 33 && (unsigned)buf[10]== 95) { LCD_digit[3]=0; LCD_minus=1; }
if ((unsigned)buf[3]== 17 && (unsigned)buf[10]==127) { LCD_digit[3]=1; LCD_minus=1; }
if ((unsigned)buf[3]== 65 && (unsigned)buf[10]== 31) { LCD_digit[3]=2; LCD_minus=1; }
if ((unsigned)buf[3]== 97 && (unsigned)buf[10]==255) { LCD_digit[3]=3; LCD_minus=1; }
if ((unsigned)buf[3]== 81 && (unsigned)buf[10]==191) { LCD_digit[3]=4; LCD_minus=1; }
// LCD_digit[2]
/*
digit 3 of Victor86B LCD display
.
LCD b6 b9 b9
0 47 69 85
1 31 101 117
2 79 5 21
3 111 229 245
4 95 165 181
5 239 37 53
6 239 69 85
7 31 229 245
8 111 69 85
9 111 37 53
[.] bit 5 of buf[9] controls the decimal-point which preceeds digit 3 of the LCD
*/
// X
if ((unsigned)buf[6]== 47 && (unsigned)buf[9]== 69) LCD_digit[2]=0;
if ((unsigned)buf[6]== 31 && (unsigned)buf[9]==101) LCD_digit[2]=1;
if ((unsigned)buf[6]== 79 && (unsigned)buf[9]== 5) LCD_digit[2]=2;
if ((unsigned)buf[6]==111 && (unsigned)buf[9]==229) LCD_digit[2]=3;
if ((unsigned)buf[6]== 95 && (unsigned)buf[9]==165) LCD_digit[2]=4;
if ((unsigned)buf[6]==239 && (unsigned)buf[9]== 37) LCD_digit[2]=5;
if ((unsigned)buf[6]==239 && (unsigned)buf[9]== 69) LCD_digit[2]=6;
if ((unsigned)buf[6]== 31 && (unsigned)buf[9]==229) LCD_digit[2]=7;
if ((unsigned)buf[6]==111 && (unsigned)buf[9]== 69) LCD_digit[2]=8;
if ((unsigned)buf[6]==111 && (unsigned)buf[9]== 37) LCD_digit[2]=9;
// .X
if ((unsigned)buf[6]== 47 && (unsigned)buf[9]== 85) { LCD_digit[2]=0; LCD_decimal[2]=1; }
if ((unsigned)buf[6]== 31 && (unsigned)buf[9]==117) { LCD_digit[2]=1; LCD_decimal[2]=1; }
if ((unsigned)buf[6]== 79 && (unsigned)buf[9]== 21) { LCD_digit[2]=2; LCD_decimal[2]=1; }
if ((unsigned)buf[6]==111 && (unsigned)buf[9]==245) { LCD_digit[2]=3; LCD_decimal[2]=1; }
if ((unsigned)buf[6]== 95 && (unsigned)buf[9]==181) { LCD_digit[2]=4; LCD_decimal[2]=1; }
if ((unsigned)buf[6]==239 && (unsigned)buf[9]== 53) { LCD_digit[2]=5; LCD_decimal[2]=1; }
if ((unsigned)buf[6]==239 && (unsigned)buf[9]== 85) { LCD_digit[2]=6; LCD_decimal[2]=1; }
if ((unsigned)buf[6]== 31 && (unsigned)buf[9]==245) { LCD_digit[2]=7; LCD_decimal[2]=1; }
if ((unsigned)buf[6]==111 && (unsigned)buf[9]== 85) { LCD_digit[2]=8; LCD_decimal[2]=1; }
if ((unsigned)buf[6]==111 && (unsigned)buf[9]== 53) { LCD_digit[2]=9; LCD_decimal[2]=1; }
// LCD_digit[1]
/* .
LCD b5 b7 b7
0 54 84 100
1 38 116 132
2 86 20 36
3 118 244 4
4 102 180 196
5 246 52 68
6 246 84 100
7 38 244 4
8 118 84 100
9 118 52 68
*/
// X
if ((unsigned)buf[5]== 54 && (unsigned)buf[7]== 84) LCD_digit[1] =0;
if ((unsigned)buf[5]== 38 && (unsigned)buf[7]==116) LCD_digit[1] =1;
if ((unsigned)buf[5]== 86 && (unsigned)buf[7]== 20) LCD_digit[1] =2;
if ((unsigned)buf[5]==118 && (unsigned)buf[7]==244) LCD_digit[1] =3;
if ((unsigned)buf[5]==102 && (unsigned)buf[7]==180) LCD_digit[1] =4;
if ((unsigned)buf[5]==246 && (unsigned)buf[7]== 52) LCD_digit[1] =5;
if ((unsigned)buf[5]==246 && (unsigned)buf[7]== 84) LCD_digit[1] =6;
if ((unsigned)buf[5]== 38 && (unsigned)buf[7]==244) LCD_digit[1] =7;
if ((unsigned)buf[5]==118 && (unsigned)buf[7]== 84) LCD_digit[1] =8;
if ((unsigned)buf[5]==118 && (unsigned)buf[7]== 52) LCD_digit[1] =9;
// .X
if ((unsigned)buf[5]== 54 && (unsigned)buf[7]==100) { LCD_digit[1] =0; LCD_decimal[1]=1; }
if ((unsigned)buf[5]== 38 && (unsigned)buf[7]==132) { LCD_digit[1] =1; LCD_decimal[1]=1; }
if ((unsigned)buf[5]== 86 && (unsigned)buf[7]== 36) { LCD_digit[1] =2; LCD_decimal[1]=1; }
if ((unsigned)buf[5]==118 && (unsigned)buf[7]== 4) { LCD_digit[1] =3; LCD_decimal[1]=1; }
if ((unsigned)buf[5]==102 && (unsigned)buf[7]==196) { LCD_digit[1] =4; LCD_decimal[1]=1; }
if ((unsigned)buf[5]==246 && (unsigned)buf[7]== 68) { LCD_digit[1] =5; LCD_decimal[1]=1; }
if ((unsigned)buf[5]==246 && (unsigned)buf[7]==100) { LCD_digit[1] =6; LCD_decimal[1]=1; }
if ((unsigned)buf[5]== 38 && (unsigned)buf[7]== 4) { LCD_digit[1] =7; LCD_decimal[1]=1; }
if ((unsigned)buf[5]==118 && (unsigned)buf[7]==100) { LCD_digit[1] =8; LCD_decimal[1]=1; }
if ((unsigned)buf[5]==118 && (unsigned)buf[7]== 68) { LCD_digit[1] =9; LCD_decimal[1]=1; }
//
if ((unsigned)buf[5]==150 && (unsigned)buf[7]==228) LCD_OL = 1; // O.L Overload
if ((unsigned)buf[5]==150 && (unsigned)buf[7]==212) LCD_OL = 1; // O.L Overload
// LCD_digit[0] least significant digit
/* .
LCD b0 b2 b0
0 75 29 91
1 107 13 123
2 11 61 27
3 235 93 251
4 171 77 187
5 43 221 59
6 75 221 91
7 235 13 251
8 75 93 91
9 43 93 59
*/
// X
if ((unsigned)buf[0]== 75 && (unsigned)buf[2]== 29) LCD_digit[0]=0;
if ((unsigned)buf[0]==107 && (unsigned)buf[2]== 13) LCD_digit[0]=1;
if ((unsigned)buf[0]== 11 && (unsigned)buf[2]== 61) LCD_digit[0]=2;
if ((unsigned)buf[0]==235 && (unsigned)buf[2]== 93) LCD_digit[0]=3;
if ((unsigned)buf[0]==171 && (unsigned)buf[2]== 77) LCD_digit[0]=4;
if ((unsigned)buf[0]== 43 && (unsigned)buf[2]==221) LCD_digit[0]=5;
if ((unsigned)buf[0]== 75 && (unsigned)buf[2]==221) LCD_digit[0]=6;
if ((unsigned)buf[0]==235 && (unsigned)buf[2]== 13) LCD_digit[0]=7;
if ((unsigned)buf[0]== 75 && (unsigned)buf[2]== 93) LCD_digit[0]=8;
if ((unsigned)buf[0]== 43 && (unsigned)buf[2]== 93) LCD_digit[0]=9;
// .X
if ((unsigned)buf[0]== 91 && (unsigned)buf[2]== 29) { LCD_digit[0]=0; LCD_decimal[0]=1; }
if ((unsigned)buf[0]==123 && (unsigned)buf[2]== 13) { LCD_digit[0]=1; LCD_decimal[0]=1; }
if ((unsigned)buf[0]== 27 && (unsigned)buf[2]== 61) { LCD_digit[0]=2; LCD_decimal[0]=1; }
if ((unsigned)buf[0]==251 && (unsigned)buf[2]== 93) { LCD_digit[0]=3; LCD_decimal[0]=1; }
if ((unsigned)buf[0]==187 && (unsigned)buf[2]== 77) { LCD_digit[0]=4; LCD_decimal[0]=1; }
if ((unsigned)buf[0]== 59 && (unsigned)buf[2]==221) { LCD_digit[0]=5; LCD_decimal[0]=1; }
if ((unsigned)buf[0]== 91 && (unsigned)buf[2]==221) { LCD_digit[0]=6; LCD_decimal[0]=1; }
if ((unsigned)buf[0]==251 && (unsigned)buf[2]== 13) { LCD_digit[0]=7; LCD_decimal[0]=1; }
if ((unsigned)buf[0]== 91 && (unsigned)buf[2]== 93) { LCD_digit[0]=8; LCD_decimal[0]=1; }
if ((unsigned)buf[0]== 59 && (unsigned)buf[2]== 93) { LCD_digit[0]=9; LCD_decimal[0]=1; }
// LCD annunciators
// M Hz
// DC REL V
// AC HOLD m oC u A
// buf 1 4 8 11 12 13
if ((unsigned)(buf[ 1]& 16)) LCD_DC = 1; // DC
if ((unsigned)buf[13]== 140) LCD_V = 1; // Volts
if ((unsigned)buf[13]== 124) LCD_A = 1; // Amps
if ((unsigned)buf[ 8]== 134) LCD_m = 1; // m - milliamps
if ((unsigned)buf[12]== 126) LCD_u = 1; // u - microamps
if ((unsigned)buf[ 4]== 177) LCD_REL = 1; // REL
if ((unsigned)buf[ 4]== 241) LCD_HOLD = 1; // HOLD
if ((unsigned)buf[13]== 172) LCD_Hz = 1; // Hz
if ((unsigned)buf[11]== 191) LCD_oC = 1; // degrees C
if ((unsigned)buf[ 4]== 145) LCD_M = 1; // Mega - ohms
// printf DMM output to display .. only print leading decimal-point!
if (LCD_OL==1) { // overload
printf(" 0L - DMM Overloaded, change range setting");
}
else { // normal operation
(LCD_minus==1) ? printf("-"):printf(" ");
printf("%d",LCD_digit[3]);
//printf(" [%d,%d] ",buf[3],buf[10]); // digit 3
(LCD_decimal[2]==1) ? printf("."):printf("");
printf("%d",LCD_digit[2]);
//printf(" [%d,%d] ",buf[6],buf[ 9]); // digit 2
(LCD_decimal[1]==1) ? printf("."):printf("");
printf("%d",LCD_digit[1]);
//printf(" [%d,%d] ",buf[5],buf[ 7]); // digit 1
(LCD_decimal[0]==1) ? printf("."):printf("");
printf("%d",LCD_digit[0]);
//printf(" [%d,%d] ",buf[0],buf[ 2]); // digit 0
}
printf(" ");
if (LCD_m) printf("m"); // m - milliamps
if (LCD_u) printf("u"); // u - microamps
if (LCD_V) printf("V"); // Volts
if (LCD_A) printf("A"); // Amps
if (LCD_oC) printf("oC"); // degrees C
if (LCD_M) printf("Mohms"); // Mega - ohms
if (LCD_Hz) printf("Hz"); // Hz
printf(" ");
if ((LCD_V || LCD_A)) (LCD_DC==1) ? printf("DC") : printf("AC"); // AC/DC
printf(" ");
if (LCD_REL) printf("REL"); // REL
if (LCD_HOLD) printf("HOLD"); // HOLD
//printf(" buf[%d,%d,%d,%d,%d,%d,%d,%d] ",buf[1],buf[4],buf[8],buf[11],buf[12],buf[13],buf[14],buf[15]); // ?
return DMM;
}
} // decode_Victor86B()
void display_buffer(unsigned char* buf) {
printf("\n");
printf("%d,%d, ",buf[3],buf[10]); // digit 3
printf("%d,%d, ",buf[6],buf[ 9]); // digit 2
printf("%d,%d, ",buf[5],buf[ 7]); // digit 1
printf("%d,%d, ",buf[0],buf[ 2]); // digit 0
printf("%d,%d, ",buf[1],buf[ 4]); // ?
printf("\n");
} // display_buffer()
int main(int argc, char* argv[]) {
int res;
unsigned char buf[256];
hid_device *handle;
int read=0;
clock_t ticks1, ticks2;
//report_HIDs(); // report attached USB HIDs to screen
handle = hid_open(0x1244, 0xd237, NULL);
if (!handle) {
printf("Victor86B DMM not found - \n PLUG in USB cable and ensure yellow RS232 button on DMM is set\n");
//return 1;
}
else {
printf("found Victor86B DMM\n");
}
// while (read<10) {
while (1) { // read out data from DMM over USB
ticks1=clock(); // start-time
res = 0;
while (res == 0) {
res = hid_read(handle, buf, sizeof(buf));
if (res == 0) printf("waiting...\n");
if (res < 0) printf("Unable to read()\n");
}
// measure time take to read data from DMM
ticks2=clock()-ticks1; // elapsed time
//printf("%ld,",ticks2);
//printf("%2.2fsec,",(double)CLOCKS_PER_SEC/(double)ticks2);
decode_Victor86B(buf);
printf("\n");
read++;
} // while()
while (1); //
hid_close(handle);
hid_exit();
return 0;
} // main()
// Victor86B_usbDMM.cpp