// GPIBDevice.cpp: CGPIBDevice クラスのインプリメンテーション // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GPIBDevice.h" #include "WinSub.h" #include #include //#include "decl-32.h" #include "sicl.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // 構築/消滅 ////////////////////////////////////////////////////////////////////// int CGPIBDevice::iscanf(INST id, LPSTR format, LPSTR str) { int ret = ::iscanf(id, "%t", str); if(m_DebugConsole && m_pDebugEdit) { m_pDebugEdit->ReplaceSel("<<"); m_pDebugEdit->ReplaceSel(str); char *cp = str + strlen(str); if(cp-2 >= str) cp = cp-2; if(strcmp(cp, "\r\n") != 0) m_pDebugEdit->ReplaceSel("\r\n"); } return ret; } int CGPIBDevice::iprintf(INST id, LPSTR format ...) { va_list ap; va_start(ap, format); char str[256]; vsprintf(str, format, ap); int ret = ::iprintf(id, str); if(m_DebugConsole && m_pDebugEdit) { // strcat(str, "\r\n"); m_pDebugEdit->ReplaceSel(">>"); m_pDebugEdit->ReplaceSel(str); char *cp = str + strlen(str); if(cp-2 >= str) cp = cp-2; if(strcmp(cp, "\r\n") != 0) m_pDebugEdit->ReplaceSel("\r\n"); } return ret; } CGPIBDevice::CGPIBDevice() { m_DoAutoSet = FALSE; m_VoltageToCurrentFactor = 1.0; m_pDebugEdit = NULL; m_DebugConsole = false; m_LastVoltage = 0.0; m_LastCurrent = 0.0; m_SleepDVMAquire = 0; m_SleepDCMAquire = 1; m_LastError = 1; m_hDCM = 0; m_hDVM = 0; m_hSource = 0; m_ZeroCheckDVM = false; m_ZeroCheckDCM = false; m_IsDebugMode = false; m_SourceVoltageLimit = 30.0; m_SourceCurrentLimit = 1.0e-4; m_DVMVoltageLimit = 30.0; m_pMessageWnd1 = NULL; m_pMessageWnd2 = NULL; } CGPIBDevice::~CGPIBDevice() { // StopSource(0.0); CloseAll(); } int CGPIBDevice::CloseAll() { if(m_hSource) { SetSource(0.0); StopSource(); iclose(m_hSource); } m_hSource = 0; if(m_hDVM) iclose(m_hDVM); m_hDVM = 0; if(m_hDCM) iclose(m_hDCM); m_hDCM = 0; m_pMessageWnd1 = NULL; m_pMessageWnd2 = NULL; return 1; } double CGPIBDevice::ReadCurrent() { static double d = 0.0; if(m_hDCM <= 0) return 0.0; if(m_pMessageWnd1) { m_pMessageWnd1->SetWindowText("Reading Current"); CWUtils::PumpMessage(); } /* static int a=0; if(a == 0) { a = 1; char str[150]; sprintf(str, "%d %d %g", m_SleepDCMAquire, m_SleepDVMAquire, m_VoltageToCurrentFactor); MessageBox(NULL, str, "str", MB_OK); } */ if(m_SleepDCMAquire > 0) Sleep(m_SleepDCMAquire); if(m_IsDebugMode) { d += 1.0; return d*d; } double val; char str[256]; char *cp; double limit; switch(m_DCMGPIBType) { case GPIBDEVICE_KEITHLEY220: val = m_AppliedValue; if(val > m_SourceCurrentLimit) m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; return m_LastCurrent = val; break; case GPIBDEVICE_KEITHLEY2001: //2001 // iprintf(m_hDCM, ":conf:curr:dc\n"); iprintf(m_hDCM, ":READ?\n"); iscanf(m_hDCM, "%t", str); val = StrToDouble(str); if(val > m_SourceCurrentLimit) m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; return m_LastCurrent = val; break; case GPIBDEVICE_KEITHLEY182: //182 iprintf(m_hDCM, "F0X\r\n"); break; case GPIBDEVICE_KEITHLEY617: //617 iprintf(m_hDCM, "F1X\r\n"); iscanf(m_hDCM, "%t", str); // ::MessageBox(NULL, str, "str", MB_OK); val = StrToDouble(str); if(val > m_SourceCurrentLimit) m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; return m_LastCurrent = val; break; case GPIBDEVICE_KEITHLEY6517: //6517 // iprintf(m_hDCM, ":conf:curr:dc\n"); /* iprintf(m_hDCM, ":SENS:CURR:RANG:UPP %e \n", fabs(m_SourceCurrentLimit)); iprintf(m_hDCM, ":READ?\n"); iscanf(m_hDCM, "%t", str); val = StrToDouble(str); */ for(limit = 20e-12 ; limit <= m_SourceCurrentLimit*10 ; limit *= 10.0) { iprintf(m_hDCM, ":SENS:CURR:RANG:UPP %e \n", limit); iprintf(m_hDCM, ":READ?\n"); iscanf(m_hDCM, "%t", str); val = StrToDouble(str); if(val < 1.0) break; } if(val > m_SourceCurrentLimit) m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; return m_LastCurrent = val; break; case GPIBDEVICE_HP4140B: iprintf(m_hDCM, "E\n"); // Sleep(20); ReadFromDevice(m_hDCM, str, 22); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(CString("Current: ") + CString(str)); // MessageBox(str, "str", MB_OK); val = StrToDouble(str); if(val > m_SourceCurrentLimit) m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; cp = strchr(str, ','); if(cp) m_LastVoltage = StrToDouble(cp+1); else m_LastVoltage = 0.0; return m_LastCurrent = val; break; case GPIBDEVICE_NF5610B: iprintf(m_hDCM, "?ODT\r\n"); iscanf(m_hDCM, "%t", str); // ReadFromDevice(m_hDCM, str, 22); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(CString("Current: ") + CString(str)); val = StrToDouble(str+1) * m_VoltageToCurrentFactor; // strcpy(str2, str); // sprintf(str, "cur: %g(%s)", val, str2); // MessageBox(NULL, str, "curr", MB_OK); if(val > m_SourceCurrentLimit) m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; return m_LastCurrent = val; break; default: if(m_LastError > 0) MessageBox("Invalid DCM Device", "Error in CGPIB:ReadCurrent", MB_OK); m_LastError = GPIBERR_INVALIDDCMDEVICE; break; } *str = 0; iscanf(m_hDCM, "%t", str); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(CString("Current: ") + CString(str)); val = StrToDouble(str); if(val > m_SourceCurrentLimit) m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; return m_LastCurrent = val; } double CGPIBDevice::ReadVoltage() { if(m_hDVM <= 0) return 0.0; if(m_pMessageWnd1) { m_pMessageWnd1->SetWindowText("Reading Voltage"); CWUtils::PumpMessage(); } static double d = 0.0; if(m_SleepDVMAquire > 0) Sleep(m_SleepDVMAquire); if(m_IsDebugMode) { d += 1.0; return d; } char str[256]; *str = 0; double val; switch(m_DVMGPIBType) { case GPIBDEVICE_KEITHLEY2001: //2001 // iprintf(m_hDVM, ":conf:volt:dc\n"); iprintf(m_hDVM, ":READ?\n"); iscanf(m_hDVM, "%t", str); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(str); m_LastGPIBString = str; val = StrToDouble(str); if(val > m_DVMVoltageLimit) m_LastError = GPIBERR_EXCEEDDVMVOLTAGELIMIT; return m_LastVoltage = val; break; case GPIBDEVICE_KEITHLEY182: //182 iprintf(m_hDVM, "F0X\r\n"); iscanf(m_hDVM, "%t", str); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(str); m_LastGPIBString = str; val = StrToDouble(str); if(val > m_DVMVoltageLimit) m_LastError = GPIBERR_EXCEEDDVMVOLTAGELIMIT; return m_LastVoltage = val; break; case GPIBDEVICE_KEITHLEY6517: //6517 if(m_DCMGPIBType == GPIBDEVICE_KEITHLEY6517 || m_SourceGPIBType == GPIBDEVICE_KEITHLEY6517) { return m_AppliedValue; } else { // iprintf(m_hDVM, ":conf:volt:dc\n"); iprintf(m_hDVM, ":READ?\n"); } break; case GPIBDEVICE_KEITHLEY617: if(m_DCMGPIBType == GPIBDEVICE_KEITHLEY617 || m_SourceGPIBType == GPIBDEVICE_KEITHLEY617) { return m_AppliedValue; } else { iprintf(m_hDVM, "F0X\n"); iprintf(m_hDVM, "B0X"); iscanf(m_hDVM, "%t", str); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(str); m_LastGPIBString = str; val = StrToDouble(str); if(val > m_DVMVoltageLimit) m_LastError = GPIBERR_EXCEEDDVMVOLTAGELIMIT; return m_LastVoltage = val; } break; case GPIBDEVICE_KEITHLEY230: return m_AppliedValue; break; case GPIBDEVICE_HP4140B: if(m_DCMGPIBType == GPIBDEVICE_HP4140B) { return m_LastVoltage; } else { return m_AppliedValue; } break; case GPIBDEVICE_AM271: iprintf(m_hDVM, "RAT0M0"); break; case GPIBDEVICE_NF5610B: iprintf(m_hDVM, "?ODT\r\n"); ReadFromDevice(m_hDVM, str, 22); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(CString("Voltage: ") + CString(str)); val = StrToDouble(str+1); if(val > m_SourceVoltageLimit) m_LastError = GPIBERR_EXCEEDSOURCEVOLTAGELIMIT; return m_LastVoltage = val; break; default: if(m_LastError > 0) MessageBox("Invalid DVM Device", "Error in CGPIB:ReadVoltage", MB_OK); m_LastError = GPIBERR_INVALIDDVMDEVICE; break; } iscanf(m_hDVM, "%t", str); if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText(CString("Voltage: ") + CString(str)); m_LastGPIBString = str; val = StrToDouble(str); if(val > m_DVMVoltageLimit) m_LastError = GPIBERR_EXCEEDDVMVOLTAGELIMIT; return m_LastVoltage = val; } double CGPIBDevice::ApplySource(double val) { if(m_hSource <= 0) return 0.0; if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Apply Source"); if(m_IsDebugMode) return val; switch(m_SourceGPIBType) { case GPIBDEVICE_KEITHLEY220: iprintf(m_hSource, "F1X\n"); break; case GPIBDEVICE_KEITHLEY230: iprintf(m_hSource, "F1X\n"); break; case GPIBDEVICE_KEITHLEY6517: iprintf(m_hSource, ":OUTP:STAT ON\n"); break; case GPIBDEVICE_KEITHLEY617: iprintf(m_hSource, "O1X\n"); // ::MessageBox(NULL,"aaa","aaa",MB_OK); break; case GPIBDEVICE_KEITHLEY182: iprintf(m_hSource, "F1X\n"); break; case GPIBDEVICE_HP4140B: iprintf(m_hSource, "W1\r\n"); break; default: MessageBox("Invalid Source Device", "Error in CGPIBDevice::ApplySource", MB_OK); return 0.0; } return val; } double CGPIBDevice::SetSource(double val) { char str[256]; if(fabs(val) < 1e-20) val = 0.0; if(m_hSource <= 0) return 0.0; if(m_pMessageWnd1) { sprintf(str, "Set source to %g", val); m_pMessageWnd1->SetWindowText(str); } if(m_IsDebugMode) return 0.0; switch(m_SourceGPIBType) { case GPIBDEVICE_KEITHLEY220: if(fabs(val) > m_SourceCurrentLimit) { m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; iprintf(m_hSource, "I%8.4fX\n", 0.0); return 0.0; } iprintf(m_hSource, "I%8.4lgX\n", val); break; case GPIBDEVICE_KEITHLEY230: if(fabs(val) > m_SourceVoltageLimit) { m_LastError = GPIBERR_EXCEEDSOURCEVOLTAGELIMIT; iprintf(m_hSource, "V%8.4gX\n", 0.0); return 0.0; } iprintf(m_hSource, "V%8.4gX\n", val); break; case GPIBDEVICE_KEITHLEY6517: if(fabs(val) > m_SourceVoltageLimit) { m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; iprintf(m_hSource, ":SOUR:VOLT %6.3f\n", 0.0); return 0.0; } iprintf(m_hSource, ":SOUR:VOLT %6.3f\n", val); break; case GPIBDEVICE_KEITHLEY617: if(fabs(val) > m_SourceVoltageLimit) { m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; iprintf(m_hSource, "V+%6.3fX", 0.0); iprintf(m_hSource, "O0X"); return 0.0; } iprintf(m_hSource, "D1X\n"); iprintf(m_hSource, "V%+6.3fX\n", val); iprintf(m_hSource, "D1X\n"); // sprintf(str, "D1V%+6.3fO1X", val); // ::MessageBox(NULL,str,"V val",MB_OK); break; case GPIBDEVICE_HP4140B: iprintf(m_hSource, "W7\r\n"); Sleep(10); if(fabs(val) > m_SourceVoltageLimit) { m_LastError = GPIBERR_EXCEEDSOURCECURRENTLIMIT; iprintf(m_hSource, "PA%6.3f\r\n", 0.0); Sleep(10); iprintf(m_hSource, "W1\r\n"); return 0.0; } iprintf(m_hSource, "PA%6.3f\r\n", val); Sleep(10); iprintf(m_hSource, "W1\r\n"); break; default: if(m_LastError > 0) MessageBox("Invalid Source Device", "Error in CGPIBDevice::SetSource", MB_OK); m_LastError = GPIBERR_INVALIDSOURCEDEVICE; return 0.0; } m_AppliedValue = val; return 0.0; } double CGPIBDevice::StopSource(double val) { if(m_hSource <= 0) return 0.0; if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Stop Source"); if(m_IsDebugMode) return 0.0; SetSource(0.0); switch(m_SourceGPIBType) { case GPIBDEVICE_KEITHLEY220: iprintf(m_hSource, "F0X\n"); break; case GPIBDEVICE_KEITHLEY230: iprintf(m_hSource, "F0X\n"); break; case GPIBDEVICE_KEITHLEY6517: iprintf(m_hSource, ":OUTP:STAT OFF\n"); break; case GPIBDEVICE_KEITHLEY617: iprintf(m_hSource, "O0X\n"); break; case GPIBDEVICE_KEITHLEY182: iprintf(m_hSource, "F1X\n"); break; case GPIBDEVICE_HP4140B: iprintf(m_hSource, "W7\r\n"); break; default: if(m_LastError > 0) MessageBox("Invalid Source Device", "Error in CGPIBDevice::StopSource", MB_OK); m_LastError = GPIBERR_INVALIDSOURCEDEVICE; return 0.0; } return 0.0; } int CGPIBDevice::OpenGPIBDevice(CString string, int & devicetype, int & deviceaddr) { ClearLastError(); m_SourceVoltageLimit = 30.0; m_SourceCurrentLimit = 1.0e-4; m_DVMVoltageLimit = 30.0; SetGPIBDevice(string, devicetype, deviceaddr); m_LastGPIBString.Format("hpib7,%d", deviceaddr); if(m_IsDebugMode) return deviceaddr; int ret = iopen(m_LastGPIBString.GetBuffer(256)); if(ret <= 0) { m_LastError = GPIBERR_CANTOPENGPIBDEVICE; return ret; } itimeout(ret, 3000); return ret; } int CGPIBDevice::SetGPIBDevice(CString string, int & devicetype, int & deviceaddr) { char str[256]; strcpy(str, string.GetBuffer(256)); char *cp = strrchr(str, ','); if(cp) { *cp = 0; cp++; } else return -1; if(_strnicmp(str, "HP4140B", 7) == 0) { devicetype = GPIBDEVICE_HP4140B; } else if(_strnicmp(str, "KEITHLEY6517", 12) == 0) { devicetype = GPIBDEVICE_KEITHLEY6517; } else if(_strnicmp(str, "KEITHLEY617", 11) == 0) { devicetype = GPIBDEVICE_KEITHLEY617; } else if(_strnicmp(str, "KEITHLEY2001", 12) == 0) { devicetype = GPIBDEVICE_KEITHLEY2001; } else if(_strnicmp(str, "KEITHLEY230", 11) == 0) { devicetype = GPIBDEVICE_KEITHLEY230; } else if(_strnicmp(str, "KEITHLEY182", 11) == 0) { devicetype = GPIBDEVICE_KEITHLEY182; } else if(_strnicmp(str, "KEITHLEY220", 11) == 0) { devicetype = GPIBDEVICE_KEITHLEY220; } else if(_strnicmp(str, "KEITHLEY236", 11) == 0) { devicetype = GPIBDEVICE_KEITHLEY236; } else if(_strnicmp(str, "AM271", 5) == 0) { devicetype = GPIBDEVICE_AM271; } else if(_strnicmp(str, "NF5610B", 7) == 0) { devicetype = GPIBDEVICE_NF5610B; } else { CString err; err.Format("Invalid device [%s]", str); ::MessageBox(NULL, err, "Error in SetGPIBDevice", MB_OK); return -1; } deviceaddr = atoi(cp); return deviceaddr; } int CGPIBDevice::InitInterface() { if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Init Interface"); if(m_IsDebugMode) return 1; return 1; } int CGPIBDevice::InitSource() { if(m_hSource <= 0) { ::MessageBox(NULL, "Invalid Source", "Error", MB_OK); return -1; } if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Init Source"); if(m_IsDebugMode) return 1; switch(m_SourceGPIBType) { case GPIBDEVICE_KEITHLEY220: iprintf(m_hSource, "I%gX\n", 0.0); iprintf(m_hSource, "F0X\n"); break; case GPIBDEVICE_KEITHLEY230: iprintf(m_hSource, "D0R0X\n"); iprintf(m_hSource, "V%gX\n", 0.0); iprintf(m_hSource, "F0X\n"); break; case GPIBDEVICE_KEITHLEY6517: iprintf(m_hSource, ":SOUR:VOLT:MCON ON \n"); break; case GPIBDEVICE_KEITHLEY617: iprintf(m_hSource, "O0X\n"); iprintf(m_hSource, "V%gX\n", 0.0); iprintf(m_hSource, "F1X\n"); break; case GPIBDEVICE_HP4140B: // iprintf(m_hSource, "F1RA1I3J1A5T1"); iprintf(m_hSource, "F1RA1I1J0A5T2"); Sleep(10); iprintf(m_hSource, "PA%g\r\n", 0.0); Sleep(10); iprintf(m_hSource, "W7\r\n"); break; default: if(m_LastError > 0) MessageBox("Invalid Source Device", "Error in CGPIB:InitSource", MB_OK); m_LastError = GPIBERR_INVALIDSOURCEDEVICE; } return 1; } int CGPIBDevice::InitDVM() { if(m_hDVM <= 0) return -1; if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Init DVM"); if(m_IsDebugMode) return 1; switch(m_DVMGPIBType) { case GPIBDEVICE_KEITHLEY2001: //2001 iprintf(m_hDVM, "*RST\n"); iprintf(m_hDVM, "*CLS\n"); iprintf(m_hDVM, ":conf:volt:dc\n"); iprintf(m_hDVM, ":voltage:dc:average:count 100\n"); iprintf(m_hDVM, ":SYSTEM:ZCHECK 0\n"); break; case GPIBDEVICE_KEITHLEY182: //182 iprintf(m_hDVM, "N1XR0XS2XT0XB1XG0X\r\n"); break; case GPIBDEVICE_KEITHLEY6517: //6517 if(m_DCMGPIBType == GPIBDEVICE_KEITHLEY6517) { } else { iprintf(m_hDVM, "*RST\r\n"); iprintf(m_hDVM, "*CLS\r\n"); iprintf(m_hDVM, ":conf:volt:dc\r\n"); iprintf(m_hDVM, ":sens:volt:dc:dig 7\r\n"); iprintf(m_hDVM, ":sens:volt:dc:aper 0.1\r\n"); iprintf(m_hDVM, ":voltage:dc:average:count 100\r\n"); iprintf(m_hDVM, ":SYSTEM:ZCHECK 0\r\n"); } break; case GPIBDEVICE_KEITHLEY617: iprintf(m_hDCM, "F0R0D0G1C0X"); // C1: ZeroCheck on, F0:Volt, R0 Auto Range // D0: electrometer (Display mode), G1:Reading without prefix // X: execute break; case GPIBDEVICE_HP4140B: // iprintf(m_hDVM, "F1RA1I3J1T1"); // iprintf(m_hDVM, "F1RA1I1J0T1"); break; case GPIBDEVICE_KEITHLEY230: break; case GPIBDEVICE_AM271: break; case GPIBDEVICE_NF5610B: iprintf(m_hDVM, "BFR1\r\n"); // Frequency range 10-120Hz iprintf(m_hDVM, "BTC5\r\n"); // Time constant 300ms iprintf(m_hDVM, "ODS2345,2367\r\n"); // Output datum A and phi if(m_DoAutoSet) { iprintf(m_hDVM, "AUS600\r\n"); // Auto Set (Timeout 600s) ::MessageBox(NULL, "Press OK when AutoSet completes", "Wait for a while", MB_OK); } break; default: if(m_LastError > 0) MessageBox("Invalid DVM Device", "Error in CGPIB:InitDVM", MB_OK); m_LastError = GPIBERR_INVALIDDVMDEVICE; return -1; } return 1; } int CGPIBDevice::InitDCM() { if(m_hDCM <= 0) return -1; if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Init DCM"); if(m_IsDebugMode) return 1; switch(m_DCMGPIBType) { case GPIBDEVICE_KEITHLEY2001: //2001 iprintf(m_hDCM, "*RST\n"); iprintf(m_hDCM, "*CLS\n"); iprintf(m_hDCM, ":conf:curr:dc\n"); // iprintf(m_hDCM, ":curr:dc:average:count 100\n"); break; case GPIBDEVICE_KEITHLEY182: //182 // iprintf(m_hDCM, "N1XR0XS2XT0XB1XG0X\r\n"); break; case GPIBDEVICE_KEITHLEY6517: //6517 // iprintf(m_hDCM, "*RST\n"); iprintf(m_hDCM, "*CLS\n"); // Sleep(1000); iprintf(m_hDCM, ":conf:curr:dc\n"); iprintf(m_hDCM, ":sens:curr:dc:rang:auto on\n"); iprintf(m_hDCM, ":sens:curr:dc:dig:auto on\n"); iprintf(m_hDCM, ":SENS:CURR:RANG:AUTO:LLIM 0 \n"); iprintf(m_hDCM, ":SENS:CURR:RANG:AUTO:ULIM 10e%d \n", (int)log10(fabs(m_SourceCurrentLimit))); // iprintf(m_hDCM, ":sens:curr:dc:dig 7\n"); // iprintf(m_hDCM, ":sens:curr:dc:aper 0.1\n"); // iprintf(m_hDCM, ":SENS:CURR:AVER:COUN 100 \n"); // iprintf(m_hDCM, ":SENS:CURR:NPLC 10 \n"); iprintf(m_hDCM, ":SYSTEM:ZCHECK 0\n"); break; case GPIBDEVICE_KEITHLEY617: iprintf(m_hDCM, "F1R0D0G1C0X"); // C1: ZeroCheck on, F1:Amps, R0 Auto Range // D0: electrometer (Display mode), G1:Reading without prefix // X: execute break; case GPIBDEVICE_HP4140B: // iprintf(m_hDCM, "F1RA1I3J1T1"); iprintf(m_hDCM, "F1RA1I1J0T2"); break; case GPIBDEVICE_NF5610B: iprintf(m_hDCM, "BFR1\r\n"); // Frequency range 10-120Hz iprintf(m_hDCM, "BTC5\r\n"); // Time constant 300ms iprintf(m_hDCM, "ODS2345,2367\r\n"); // Output datum A and phi if(m_DoAutoSet) { iprintf(m_hDCM, "AUS600\r\n"); // Auto Set (Timeout 600s) ::MessageBox(NULL, "Press OK when AutoSet completes", "Wait for a while", MB_OK); } break; case GPIBDEVICE_KEITHLEY220: break; default: if(m_LastError > 0) MessageBox("Invalid DCM Device", "Error in CGPIB:InitDCM", MB_OK); m_LastError = GPIBERR_INVALIDDCMDEVICE; return -1; } return 1; } double CGPIBDevice::SetSourceVoltageLimit(double volt) { if(m_hSource <= 0) return 0.0; if(m_pMessageWnd1) { char str[256]; sprintf(str, "Set Source voltage limit to %g", volt); m_pMessageWnd1->SetWindowText(str); } m_SourceVoltageLimit = volt; if(m_IsDebugMode) return volt; // iprintf(m_CSRC, "V%gX\n", m_VoltageLimit); return volt; } double CGPIBDevice::SetDVMVoltageLimit(double volt) { if(m_hDVM <= 0) return 0.0; if(m_pMessageWnd1) { char str[256]; sprintf(str, "Set DVM voltage limit to %g", volt); m_pMessageWnd1->SetWindowText(str); } m_DVMVoltageLimit = volt; if(m_IsDebugMode) return volt; switch(m_SourceGPIBType) { case GPIBDEVICE_KEITHLEY220: iprintf(m_hSource, "V%gX\n", m_SourceVoltageLimit); break; case GPIBDEVICE_KEITHLEY230: if(m_SourceVoltageLimit > 100) m_SourceVoltageLimit = 100.0; break; case GPIBDEVICE_KEITHLEY6517: iprintf(m_hSource, ":SOUR:VOLT:LIM %6.3g\n", m_SourceVoltageLimit); iprintf(m_hSource, ":SOUR:VOLT:LIMIT:STAT ON\n"); break; } return volt; } double CGPIBDevice::SetSourceCurrentLimit(double current) { if(m_hSource <= 0) return 0.0; if(m_pMessageWnd1) { char str[256]; sprintf(str, "Set Source current limit to %g", current); m_pMessageWnd1->SetWindowText(str); } m_SourceCurrentLimit = current; if(m_IsDebugMode) return current; switch(m_SourceGPIBType) { case GPIBDEVICE_HP4140B: if(m_SourceCurrentLimit <= 1.0001e-4) iprintf(m_hSource, "L1M1"); else if(m_SourceCurrentLimit <= 1.0001e-3) iprintf(m_hSource, "L2M2"); else { m_SourceCurrentLimit = 1e-2; iprintf(m_hSource, "L3M3"); } break; case GPIBDEVICE_KEITHLEY220: // iprintf(m_hSource, "V%gX\n", m_SourceVoltageLimit); break; case GPIBDEVICE_KEITHLEY230: if(current >= 100e-3) { iprintf(m_hSource, "I2X\n"); m_SourceCurrentLimit = 100e-3; } else if(current >= 20e-3) iprintf(m_hSource, "I1X\n"); else iprintf(m_hSource, "I0X\n"); break; case GPIBDEVICE_KEITHLEY6517: break; } return current; } bool CGPIBDevice::SetZeroCheckDVM(bool b) { if(m_hDVM <= 0) return 0.0; if(m_pMessageWnd1) { if(b) m_pMessageWnd1->SetWindowText("Set Zero Check for DVM"); else m_pMessageWnd1->SetWindowText("Unset Zero Check for DVM"); } m_ZeroCheckDVM = b; if(m_IsDebugMode) return b; switch(m_DVMGPIBType) { case GPIBDEVICE_KEITHLEY2001: //2001 if(m_ZeroCheckDVM) iprintf(m_hDVM, ":SYSTEM:ZCHECK 1\r\n"); else iprintf(m_hDVM, ":SYSTEM:ZCHECK 0\r\n"); break; case GPIBDEVICE_KEITHLEY182: //182 //iprintf(m_hDVM, "N1XR0XS2XT0XB1XG0X\r\n"); break; case GPIBDEVICE_KEITHLEY6517: //6517 if(m_DCMGPIBType == GPIBDEVICE_KEITHLEY6517) { } else { if(m_ZeroCheckDVM) iprintf(m_hDVM, ":SYSTEM:ZCHECK 1\r\n"); else iprintf(m_hDVM, ":SYSTEM:ZCHECK 0\r\n"); } break; case GPIBDEVICE_KEITHLEY617: if(m_ZeroCheckDVM) iprintf(m_hDVM, "C1X"); else iprintf(m_hDVM, "C0X"); break; case GPIBDEVICE_HP4140B: break; } return b; } bool CGPIBDevice::SetZeroCheckDCM(bool b) { if(m_hDCM <= 0) return 0.0; if(m_pMessageWnd1) { if(b) m_pMessageWnd1->SetWindowText("Set Zero Check for DCM"); else m_pMessageWnd1->SetWindowText("Unset Zero Check for DCM"); } m_ZeroCheckDCM = b; if(m_IsDebugMode) return b; switch(m_DVMGPIBType) { case GPIBDEVICE_KEITHLEY2001: //2001 if(m_ZeroCheckDCM) iprintf(m_hDCM, ":SYSTEM:ZCHECK 1\r\n"); else iprintf(m_hDCM, ":SYSTEM:ZCHECK 0\r\n"); break; case GPIBDEVICE_KEITHLEY182: //182 //iprintf(m_hDVM, "N1XR0XS2XT0XB1XG0X\r\n"); break; case GPIBDEVICE_KEITHLEY6517: //6517 if(m_ZeroCheckDCM) iprintf(m_hDCM, ":SYSTEM:ZCHECK 1\r\n"); else iprintf(m_hDCM, ":SYSTEM:ZCHECK 0\r\n"); break; case GPIBDEVICE_KEITHLEY617: if(m_ZeroCheckDCM) iprintf(m_hDCM, "C1X"); else iprintf(m_hDCM, "C0X"); break; case GPIBDEVICE_HP4140B: case GPIBDEVICE_KEITHLEY220: break; } return b; } double CGPIBDevice::ReadAveragedVoltage(int naverage) { if(m_hDVM <= 0) return 0.0; double v = 0.0; if(naverage < 1) naverage = 1; if(m_DVMGPIBType == GPIBDEVICE_HP4140B) { if(m_DCMGPIBType == GPIBDEVICE_HP4140B) { return m_LastVoltage; } else { return m_AppliedValue; } } if(m_DCMGPIBType == GPIBDEVICE_KEITHLEY230) return m_AppliedValue; if(m_DCMGPIBType == GPIBDEVICE_KEITHLEY6517 || m_SourceGPIBType == GPIBDEVICE_KEITHLEY6517) return m_AppliedValue; for(int i = 0 ; i < naverage ; i++) { if(m_LastError <= 0) return 0.0; CWUtils::PumpMessage(); v += ReadVoltage(); } double ret = v/naverage; if(m_pMessageWnd1) { char str[256]; sprintf(str, "Averaged V=%g", ret); m_pMessageWnd1->SetWindowText(str); } return m_LastVoltage = ret; } double CGPIBDevice::ReadAveragedCurrent(int naverage) { if(m_hDCM <= 0) return 0.0; double v = 0.0; double volt = 0.0; if(naverage < 1) naverage = 1; for(int i = 0 ; i < naverage ; i++) { if(m_LastError <= 0) return 0.0; CWUtils::PumpMessage(); v += ReadCurrent(); if(m_DCMGPIBType == GPIBDEVICE_HP4140B) volt += m_LastVoltage; } double ret = v/naverage; if(m_DCMGPIBType == GPIBDEVICE_HP4140B) m_LastVoltage = volt/naverage; if(m_pMessageWnd1) { char str[256]; sprintf(str, "Averaged I=%g", ret); m_pMessageWnd1->SetWindowText(str); } return m_LastCurrent = ret; } double CGPIBDevice::ReadStableVoltage(double MaxSec, double Accuracy, int nAccuracy, int naverage) { if(m_hDVM <= 0) return 0.0; if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Wait for stablizing voltage"); if(nAccuracy < 2) return m_LastVoltage = ReadAveragedVoltage(naverage); if(nAccuracy > 50) nAccuracy = 50; if(naverage < 1) naverage = 1; double stack[50]; int pointer = 0, count = 0; Accuracy /= 100.0; DWORD start, now; int maxsec = int((MaxSec+999)/1000); start = GetTickCount(); double avg; double acc = -1.0; while(1) { stack[pointer] = ReadAveragedVoltage(naverage); if(m_LastError <= 0) return 0.0; count++; if(count >= 5) { double vmin = 1e30, vmax = -1e30; avg = 0.0; for(int j = pointer ; j > pointer-nAccuracy ; j--) { int p = j; if(p < 0) p = 50+p; avg += stack[p]; if(vmin > stack[p]) vmin = stack[p]; if(vmax < stack[p]) vmax = stack[p]; } avg /= nAccuracy; if(fabs(avg) > 1.0e-20) acc = fabs((vmax-vmin)/avg); else acc = 0.0; now = GetTickCount(); if(acc < Accuracy || fabs(vmax-vmin) < 1.0e-9) { if(m_pMessageWnd2) { char str[256]; sprintf(str, "[%g]Stable %dms(%d) V=%g (%2.0f%%)", m_AppliedValue, now-start, count, avg, acc*100.0); m_pMessageWnd2->SetWindowText(str); } return m_LastVoltage = avg; } if(now-start >= MaxSec) { if(m_pMessageWnd2) { char str[256]; sprintf(str, "[%g]Not stabld. %dms(%d) V=%g (%2.0f%%)", m_AppliedValue, now-start, count, avg, acc*100.0); m_pMessageWnd2->SetWindowText(str); } return m_LastVoltage = avg; } } pointer++; if(pointer >= 50) pointer = 0; } return 0.0; } double CGPIBDevice::ReadStableCurrent(double MaxSec, double Accuracy, int nAccuracy, int naverage) { // char str[256]; // sprintf(str, "%d, %d, %s", m_hDCM, m_DCMGPIBAddr, (LPCSTR)m_LastGPIBString); // MessageBox(str, "StableCurrent", MB_OK); if(m_hDCM <= 0) return 0.0; if(m_pMessageWnd1) m_pMessageWnd1->SetWindowText("Wait for stablizing current"); if(nAccuracy < 2) return m_LastCurrent = ReadAveragedCurrent(naverage); if(nAccuracy > 50) nAccuracy = 50; if(naverage < 1) naverage = 1; double stack[50]; int pointer = 0, count = 0; Accuracy /= 100.0; DWORD start, now; start = GetTickCount(); double avg; double acc = -1.0; // bool f = true; while(1) { stack[pointer] = ReadAveragedCurrent(naverage); if(m_LastError <= 0) return 0.0; /* if(f) { char str[256]; sprintf(str, "%g (%d/%d)", stack[pointer], pointer, naverage); if(MessageBox(str, "stack, pointer/navg", MB_YESNO) == IDNO) f = false; } */ count++; if(count >= nAccuracy) { double vmin = 1e30, vmax = -1e30; avg = 0.0; for(int j = pointer ; j > pointer-nAccuracy ; j--) { int p = j; if(p < 0) p = 50+p; avg += stack[p]; // char str[256]; // sprintf(str, "%d(%d) %g %g", j, p, stack[p], avg); // MessageBox(str, str, MB_OK); if(vmin > stack[p]) vmin = stack[p]; if(vmax < stack[p]) vmax = stack[p]; } avg /= nAccuracy; if(fabs(avg) > 1.0e-20) acc = fabs((vmax-vmin)/avg); else acc = 0.0; now = GetTickCount(); if(acc < Accuracy || fabs(vmax-vmin) < 1.0e-13) { if(m_pMessageWnd2) { char str[256]; sprintf(str, "[%g]Stable %dms(%d) I=%g (%2.0f%%)", m_AppliedValue, now-start, count, avg, acc*100.0); m_pMessageWnd2->SetWindowText(str); } // else // MessageBox("null Message2", "mess", MB_OK); return m_LastCurrent = avg; } if(now-start >= MaxSec) { if(m_pMessageWnd2) { char str[256]; sprintf(str, "[%g]Not stabld. %dms(%d) I=%g (%2.0f%%)", m_AppliedValue, now-start, count, avg, acc*100.0); m_pMessageWnd2->SetWindowText(str); } // else // MessageBox("null Message2", "mess", MB_OK); return m_LastCurrent = avg; } } pointer++; if(pointer >= 50) pointer = 0; } return 0.0; } CWnd * CGPIBDevice::SetMessageWnd1(CWnd * pwnd) { return m_pMessageWnd1 = pwnd; } CWnd * CGPIBDevice::SetMessageWnd2(CWnd * pwnd) { return m_pMessageWnd2 = pwnd; } double CGPIBDevice::StrToDouble(char * str) { char *cp; for(cp = str ; *cp != 0 ; cp++) { if(strchr("\t+-0123456789.E", *cp) != NULL) break; } if(*cp == 0) return 0.0; return atof(cp); } int CGPIBDevice::ReadFromDevice(int hDev, char * str, int len) { int ret,i1; unsigned long i2; int count = 0; while(1) { Sleep(1); ret = iread(m_hDCM, str+count, 1, &i1, &i2); if(i2 == 0) break; count++; if(count > len) break; } *(str+count) = 0; if(m_DebugConsole && m_pDebugEdit) { m_pDebugEdit->ReplaceSel("<<"); m_pDebugEdit->ReplaceSel(str); char *cp = str + strlen(str); if(cp-2 >= str) cp = cp-2; if(strcmp(cp, "\r\n") != 0) m_pDebugEdit->ReplaceSel("\r\n"); } return 1; /* while(1) { ret= iread(m_hDCM, str, len, &i1, &i2); str[i2] = 0; CWUtils::PumpMessage(); if(i2 == 0) { m_LastError = -4; CWUtils::PumpMessage(); *str = 0; return -1; } else if(i2 > 5) { return 1; } // Sleep(50); } return -1; */ } CString& CGPIBDevice::GetLastErrorString(int err) { int Err; static CString s; if(err <= -99999) Err = m_LastError; else Err = err; switch(Err) { case GPIBERR_CANTOPENGPIBDEVICE: s = CString("CGPIBDevice: Can't open GPIB Deiece"); return s; break; case GPIBERR_EXCEEDDVMVOLTAGELIMIT: s = CString("CGPIBDevice: Exceeds DVM Voltage Limit"); return s; break; case GPIBERR_EXCEEDSOURCECURRENTLIMIT: s.Format("CGPIBDevice: Exceeds Source Current Limit[%g/%g]", m_LastCurrent, m_SourceCurrentLimit); return s; break; case GPIBERR_EXCEEDSOURCEVOLTAGELIMIT: s = CString("CGPIBDevice: Exceeds Source Voltage Limit"); return s; break; case GPIBERR_INVALIDDVMDEVICE: s = CString("CGPIBDevice: Invlid DVM Device"); return s; break; case GPIBERR_INVALIDDCMDEVICE: s = CString("CGPIBDevice: Invlid DCM Device"); return s; break; case GPIBERR_INVALIDSOURCEDEVICE: s = CString("CGPIBDevice: Invlid Source Device"); return s; break; case GPIBERR_TERMINATEDBYUSER: s = CString("CGPIBDevice: Terminated By User"); return s; break; default: if(Err > 0) { s = CString("CGPIBDevice: No Error"); return s; } else { s = CString("CGPIBDevice: Invalid Error"); return s; } } s = CString("CGPIBDevice: No Error"); return s; } bool CGPIBDevice::SetDebugConsole(bool b, CEdit *pEdit) { m_pDebugEdit = pEdit; return m_DebugConsole = b; } double CGPIBDevice::SetVoltageToCurrentFactor(double val) { return m_VoltageToCurrentFactor = val; } BOOL CGPIBDevice::SetDoAutoSet(BOOL b) { return m_DoAutoSet = b; }