From 8d48934b6018eb33af5c49e9dbf9f1e6807e2154 Mon Sep 17 00:00:00 2001 From: HYEONGWON SON <83201492+Soku3D@users.noreply.github.com> Date: Fri, 31 May 2024 19:59:51 +0900 Subject: [PATCH] - --- App/keithleyApp_1_1.py | 10 +- Samples/2420Test.ipynb | 99 ++++++++--- Samples/2420Test2.ipynb | 157 +++++++++++++++++ Samples/2600bTest.ipynb | 15 +- Samples/PyVisa-Keityley-2018-06-22.ipynb | 205 +++++++++++++++++++++++ Samples/dataTest.py | 36 ++++ Samples/qthread.py | 75 +++++++++ Samples/qthread2.py | 76 +++++++++ Samples/sweepModeTest.py | 29 ++++ Samples/sweepModeTest3.py | 66 ++++++++ Samples/test | 2 + Samples/testSweep2.py | 110 ++++++++++++ 12 files changed, 844 insertions(+), 36 deletions(-) create mode 100644 Samples/2420Test2.ipynb create mode 100644 Samples/PyVisa-Keityley-2018-06-22.ipynb create mode 100644 Samples/dataTest.py create mode 100644 Samples/qthread.py create mode 100644 Samples/qthread2.py create mode 100644 Samples/sweepModeTest.py create mode 100644 Samples/sweepModeTest3.py create mode 100644 Samples/test create mode 100644 Samples/testSweep2.py diff --git a/App/keithleyApp_1_1.py b/App/keithleyApp_1_1.py index 9cbc699..dd0a36c 100644 --- a/App/keithleyApp_1_1.py +++ b/App/keithleyApp_1_1.py @@ -8,7 +8,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6.QtWidgets import QApplication, QMainWindow -from PyQt6.QtCore import QTimer, Qt +from PyQt6.QtCore import QTimer, Qt, QThread, pyqtSignal from PyQt6.QtGui import QPalette, QIcon, QPixmap, QPainter, QColor from ctypes.wintypes import HANDLE, HICON from ctypes import windll @@ -362,8 +362,10 @@ def keithleyConnect(self,deviceName, address): try: self.device2635b = rm.open_resource(f'GPIB::{address}::INSTR') - self.IsConnected_2635b.setStyleSheet('color: black;') + self.IsConnected_2635b.setStyleSheet('color: green;') self.IsConnected_2635b.setText(f"Connected to {address}") + time.sleep(1) + self.IsConnected_2635b.setText("") self.device2420.write('smua.source.func = smua.OUTPUT_DCV')# 전압 source mode self.device2420.write('smua.measure.func = smua.FUNC_DCI') # 전류 measure mode self.device2635b.write(f'smua.source.limiti = {self.CurrentLimit_2635b.value()}') # 전류 한계 설정 @@ -378,8 +380,8 @@ def keithleyConnect(self,deviceName, address): try: self.device2420 = rm.open_resource(f'GPIB::{address}::INSTR') - self.IsConnected_2420.setStyleSheet('color: black;') - self.IsConnected_2420.setText(f"Connected to {address}") + self.IsConnected_2420.setStyleSheet('color: green;') + self.IsConnected_2420.setText(f"Connected to {address}") print(self.device2420.query('*IDN?')) self.device2420.write(':SOUR:FUNC VOLT')# 전압 source mode diff --git a/Samples/2420Test.ipynb b/Samples/2420Test.ipynb index 4263613..1e3f685 100644 --- a/Samples/2420Test.ipynb +++ b/Samples/2420Test.ipynb @@ -14,20 +14,29 @@ "execution_count": 1, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "KEITHLEY INSTRUMENTS INC.,MODEL 2420,4051227,C32 Oct 4 2010 14:20:11/A02 /J/L\n", + "\n" + ] + }, { "ename": "VisaIOError", - "evalue": "VI_ERROR_LIBRARY_NFOUND (-1073807202): A code library required by VISA could not be located or loaded.", + "evalue": "VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mVisaIOError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[1], line 5\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtime\u001b[39;00m\n\u001b[0;32m 4\u001b[0m rm \u001b[38;5;241m=\u001b[39m pyvisa\u001b[38;5;241m.\u001b[39mResourceManager()\n\u001b[1;32m----> 5\u001b[0m device24 \u001b[38;5;241m=\u001b[39m rm\u001b[38;5;241m.\u001b[39mopen_resource(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mGPIB::24::INSTR\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m 7\u001b[0m \u001b[38;5;66;03m# DeviceID\u001b[39;00m\n\u001b[0;32m 8\u001b[0m \u001b[38;5;28mprint\u001b[39m(device24\u001b[38;5;241m.\u001b[39mquery(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m*IDN?\u001b[39m\u001b[38;5;124m'\u001b[39m))\n", - "File \u001b[1;32mc:\\Users\\son\\anaconda3\\Lib\\site-packages\\pyvisa\\highlevel.py:3255\u001b[0m, in \u001b[0;36mResourceManager.open_resource\u001b[1;34m(self, resource_name, access_mode, open_timeout, resource_pyclass, **kwargs)\u001b[0m\n\u001b[0;32m 3227\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Return an instrument for the resource name.\u001b[39;00m\n\u001b[0;32m 3228\u001b[0m \n\u001b[0;32m 3229\u001b[0m \u001b[38;5;124;03mParameters\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 3252\u001b[0m \n\u001b[0;32m 3253\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 3254\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m resource_pyclass \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m-> 3255\u001b[0m info \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mresource_info(resource_name, extended\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[0;32m 3257\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 3258\u001b[0m \u001b[38;5;66;03m# When using querying extended resource info the resource_class is not\u001b[39;00m\n\u001b[0;32m 3259\u001b[0m \u001b[38;5;66;03m# None\u001b[39;00m\n\u001b[0;32m 3260\u001b[0m resource_pyclass \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_resource_classes[\n\u001b[0;32m 3261\u001b[0m (info\u001b[38;5;241m.\u001b[39minterface_type, info\u001b[38;5;241m.\u001b[39mresource_class) \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[0;32m 3262\u001b[0m ]\n", - "File \u001b[1;32mc:\\Users\\son\\anaconda3\\Lib\\site-packages\\pyvisa\\highlevel.py:3182\u001b[0m, in \u001b[0;36mResourceManager.resource_info\u001b[1;34m(self, resource_name, extended)\u001b[0m\n\u001b[0;32m 3170\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Get the (extended) information of a particular resource.\u001b[39;00m\n\u001b[0;32m 3171\u001b[0m \n\u001b[0;32m 3172\u001b[0m \u001b[38;5;124;03mParameters\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 3178\u001b[0m \n\u001b[0;32m 3179\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 3181\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m extended:\n\u001b[1;32m-> 3182\u001b[0m ret, err \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvisalib\u001b[38;5;241m.\u001b[39mparse_resource_extended(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msession, resource_name)\n\u001b[0;32m 3183\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 3184\u001b[0m ret, err \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvisalib\u001b[38;5;241m.\u001b[39mparse_resource(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msession, resource_name)\n", - "File \u001b[1;32mc:\\Users\\son\\anaconda3\\Lib\\site-packages\\pyvisa\\ctwrapper\\functions.py:2076\u001b[0m, in \u001b[0;36mparse_resource_extended\u001b[1;34m(library, session, resource_name)\u001b[0m\n\u001b[0;32m 2072\u001b[0m alias_if_exists \u001b[38;5;241m=\u001b[39m create_string_buffer(constants\u001b[38;5;241m.\u001b[39mVI_FIND_BUFLEN)\n\u001b[0;32m 2074\u001b[0m \u001b[38;5;66;03m# [ViSession, ViRsrc, ViPUInt16, ViPUInt16, ViAChar, ViAChar, ViAChar]\u001b[39;00m\n\u001b[0;32m 2075\u001b[0m \u001b[38;5;66;03m# ViRsrc converts from (str, unicode, bytes) to bytes\u001b[39;00m\n\u001b[1;32m-> 2076\u001b[0m ret \u001b[38;5;241m=\u001b[39m library\u001b[38;5;241m.\u001b[39mviParseRsrcEx(\n\u001b[0;32m 2077\u001b[0m session,\n\u001b[0;32m 2078\u001b[0m resource_name,\n\u001b[0;32m 2079\u001b[0m byref(interface_type),\n\u001b[0;32m 2080\u001b[0m byref(interface_board_number),\n\u001b[0;32m 2081\u001b[0m resource_class,\n\u001b[0;32m 2082\u001b[0m unaliased_expanded_resource_name,\n\u001b[0;32m 2083\u001b[0m alias_if_exists,\n\u001b[0;32m 2084\u001b[0m )\n\u001b[0;32m 2086\u001b[0m res \u001b[38;5;241m=\u001b[39m [\n\u001b[0;32m 2087\u001b[0m buffer_to_text(val)\n\u001b[0;32m 2088\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m val \u001b[38;5;129;01min\u001b[39;00m (resource_class, unaliased_expanded_resource_name, alias_if_exists)\n\u001b[0;32m 2089\u001b[0m ]\n\u001b[0;32m 2091\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m res[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m] \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n", - "File \u001b[1;32mc:\\Users\\son\\anaconda3\\Lib\\site-packages\\pyvisa\\ctwrapper\\highlevel.py:226\u001b[0m, in \u001b[0;36mIVIVisaLibrary._return_handler\u001b[1;34m(self, ret_value, func, arguments)\u001b[0m\n\u001b[0;32m 223\u001b[0m \u001b[38;5;66;03m# Set session back to a safe value\u001b[39;00m\n\u001b[0;32m 224\u001b[0m session \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m--> 226\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_return_value(session, ret_value)\n", - "File \u001b[1;32mc:\\Users\\son\\anaconda3\\Lib\\site-packages\\pyvisa\\highlevel.py:251\u001b[0m, in \u001b[0;36mVisaLibraryBase.handle_return_value\u001b[1;34m(self, session, status_code)\u001b[0m\n\u001b[0;32m 248\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_last_status_in_session[session] \u001b[38;5;241m=\u001b[39m rv\n\u001b[0;32m 250\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m rv \u001b[38;5;241m<\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m--> 251\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m errors\u001b[38;5;241m.\u001b[39mVisaIOError(rv)\n\u001b[0;32m 253\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m rv \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39missue_warning_on:\n\u001b[0;32m 254\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m session \u001b[38;5;129;01mand\u001b[39;00m rv \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_ignore_warning_in_session[session]:\n", - "\u001b[1;31mVisaIOError\u001b[0m: VI_ERROR_LIBRARY_NFOUND (-1073807202): A code library required by VISA could not be located or loaded." + "\u001b[1;32mc:\\Users\\son97\\Documents\\GitHub\\KeithleyApp\\Samples\\2420Test.ipynb Cell 2\u001b[0m line \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 44\u001b[0m result \u001b[39m=\u001b[39m Keithley\u001b[39m.\u001b[39mquery(\u001b[39m\"\u001b[39m\u001b[39m:READ?\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m 45\u001b[0m yvalues \u001b[39m=\u001b[39m Keithley\u001b[39m.\u001b[39mquery_ascii_values(\u001b[39m\"\u001b[39m\u001b[39m:FETC?\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[1;32m---> 46\u001b[0m data \u001b[39m=\u001b[39m Keithley\u001b[39m.\u001b[39;49mquery(\u001b[39m'\u001b[39;49m\u001b[39mTRAC:DATA? 1,1\u001b[39;49m\u001b[39m'\u001b[39;49m) \n\u001b[0;32m 48\u001b[0m \u001b[39mprint\u001b[39m(yvalues)\n\u001b[0;32m 49\u001b[0m \u001b[39mprint\u001b[39m(result)\n", + "File \u001b[1;32mc:\\Users\\son97\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyvisa\\resources\\messagebased.py:647\u001b[0m, in \u001b[0;36mMessageBasedResource.query\u001b[1;34m(self, message, delay)\u001b[0m\n\u001b[0;32m 644\u001b[0m \u001b[39mif\u001b[39;00m delay \u001b[39m>\u001b[39m \u001b[39m0.0\u001b[39m:\n\u001b[0;32m 645\u001b[0m time\u001b[39m.\u001b[39msleep(delay)\n\u001b[1;32m--> 647\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mread()\n", + "File \u001b[1;32mc:\\Users\\son97\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyvisa\\resources\\messagebased.py:485\u001b[0m, in \u001b[0;36mMessageBasedResource.read\u001b[1;34m(self, termination, encoding)\u001b[0m\n\u001b[0;32m 483\u001b[0m \u001b[39mif\u001b[39;00m termination \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m 484\u001b[0m termination \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_read_termination\n\u001b[1;32m--> 485\u001b[0m message \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_read_raw()\u001b[39m.\u001b[39mdecode(enco)\n\u001b[0;32m 486\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[0;32m 487\u001b[0m \u001b[39mwith\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mread_termination_context(termination):\n", + "File \u001b[1;32mc:\\Users\\son97\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyvisa\\resources\\messagebased.py:441\u001b[0m, in \u001b[0;36mMessageBasedResource._read_raw\u001b[1;34m(self, size)\u001b[0m\n\u001b[0;32m 434\u001b[0m \u001b[39mwhile\u001b[39;00m status \u001b[39m==\u001b[39m loop_status:\n\u001b[0;32m 435\u001b[0m logger\u001b[39m.\u001b[39mdebug(\n\u001b[0;32m 436\u001b[0m \u001b[39m\"\u001b[39m\u001b[39m%s\u001b[39;00m\u001b[39m - reading \u001b[39m\u001b[39m%d\u001b[39;00m\u001b[39m bytes (last status \u001b[39m\u001b[39m%r\u001b[39;00m\u001b[39m)\u001b[39m\u001b[39m\"\u001b[39m,\n\u001b[0;32m 437\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_resource_name,\n\u001b[0;32m 438\u001b[0m size,\n\u001b[0;32m 439\u001b[0m status,\n\u001b[0;32m 440\u001b[0m )\n\u001b[1;32m--> 441\u001b[0m chunk, status \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mvisalib\u001b[39m.\u001b[39;49mread(\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49msession, size)\n\u001b[0;32m 442\u001b[0m ret\u001b[39m.\u001b[39mextend(chunk)\n\u001b[0;32m 443\u001b[0m \u001b[39mexcept\u001b[39;00m errors\u001b[39m.\u001b[39mVisaIOError \u001b[39mas\u001b[39;00m e:\n", + "File \u001b[1;32mc:\\Users\\son97\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyvisa\\ctwrapper\\functions.py:2336\u001b[0m, in \u001b[0;36mread\u001b[1;34m(library, session, count)\u001b[0m\n\u001b[0;32m 2334\u001b[0m buffer \u001b[39m=\u001b[39m create_string_buffer(count)\n\u001b[0;32m 2335\u001b[0m return_count \u001b[39m=\u001b[39m ViUInt32()\n\u001b[1;32m-> 2336\u001b[0m ret \u001b[39m=\u001b[39m library\u001b[39m.\u001b[39;49mviRead(session, buffer, count, byref(return_count))\n\u001b[0;32m 2337\u001b[0m \u001b[39mreturn\u001b[39;00m buffer\u001b[39m.\u001b[39mraw[: return_count\u001b[39m.\u001b[39mvalue], ret\n", + "File \u001b[1;32mc:\\Users\\son97\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyvisa\\ctwrapper\\highlevel.py:226\u001b[0m, in \u001b[0;36mIVIVisaLibrary._return_handler\u001b[1;34m(self, ret_value, func, arguments)\u001b[0m\n\u001b[0;32m 223\u001b[0m \u001b[39m# Set session back to a safe value\u001b[39;00m\n\u001b[0;32m 224\u001b[0m session \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[1;32m--> 226\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mhandle_return_value(session, ret_value)\n", + "File \u001b[1;32mc:\\Users\\son97\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\pyvisa\\highlevel.py:251\u001b[0m, in \u001b[0;36mVisaLibraryBase.handle_return_value\u001b[1;34m(self, session, status_code)\u001b[0m\n\u001b[0;32m 248\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_last_status_in_session[session] \u001b[39m=\u001b[39m rv\n\u001b[0;32m 250\u001b[0m \u001b[39mif\u001b[39;00m rv \u001b[39m<\u001b[39m \u001b[39m0\u001b[39m:\n\u001b[1;32m--> 251\u001b[0m \u001b[39mraise\u001b[39;00m errors\u001b[39m.\u001b[39mVisaIOError(rv)\n\u001b[0;32m 253\u001b[0m \u001b[39mif\u001b[39;00m rv \u001b[39min\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39missue_warning_on:\n\u001b[0;32m 254\u001b[0m \u001b[39mif\u001b[39;00m session \u001b[39mand\u001b[39;00m rv \u001b[39mnot\u001b[39;00m \u001b[39min\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_ignore_warning_in_session[session]:\n", + "\u001b[1;31mVisaIOError\u001b[0m: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed." ] } ], @@ -36,33 +45,71 @@ "import time\n", "\n", "rm = pyvisa.ResourceManager()\n", - "device24 = rm.open_resource('GPIB::24::INSTR')\n", + "Keithley = rm.open_resource('GPIB::24::INSTR')\n", "\n", "# DeviceID\n", - "print(device24.query('*IDN?'))\n", + "print(Keithley.query('*IDN?'))\n", + "\n", + "startv = \"0\"\n", + "stopv = \"60\"\n", + "stepv =\"1\"\n", + "steps= \"61\"\n", + "startvprime = float(startv)\n", + "stopvprime = float(stopv)\n", + "stepvprime = float(stepv)\n", + "steps = (stopvprime - startvprime) / stepvprime \n", + "\n", + "# Turn off concurrent functions and set sensor to current with fixed voltage\n", + "Keithley.write(\":SENS:FUNC:CONC OFF\")\n", + "Keithley.write(\":SOUR:FUNC VOLT\")\n", + "Keithley.write(\":SENS:FUNC 'CURR:DC' \")\n", "\n", + "# Voltage starting, ending, and spacing values based on input\n", + "Keithley.write(\":SOUR:VOLT:STAR \", startv)\n", + "Keithley.write(\":SOUR:VOLT:STOP \", stopv)\n", + "Keithley.write(\":SOUR:VOLT:STEP \", stepv)\n", + "Keithley.write(\":SOUR:SWE:RANG AUTO\")\n", "\n", + "# Set compliance current (in A), sweep direction, and data acquisition\n", + "Keithley.write(\":SENS:CURR:PROT 1\")\n", + "Keithley.write(\":SOUR:SWE:SPAC LIN\")\n", + "Keithley.write(\":SOUR:VOLT:DEL 0.5\")\n", + "Keithley.write(\":SOUR:SWE:POIN \", str(int(steps)))\n", + "Keithley.write(\":SOUR:SWE:DIR UP\")\n", + "Keithley.write(\":TRIG:COUN \", str(int(steps)))\n", + "Keithley.write(\":FORM:ELEM CURR\")\n", "\n", - "currentLimit = 0.1\n", - "device24.write(f':SENS:CURR:PROT {currentLimit}') # Set Current Limit\n", + "# Set sweep mode and turn output on\n", + "Keithley.write(\":SOUR:VOLT:MODE SWE\")\n", + "Keithley.write(\":OUTP ON\")\n", "\n", - "minVoltage = -60\n", - "maxVoltage = 60\n", + "# Initiate sweep, collect ACSII current values, and turn output off\n", + "result = Keithley.query(\":READ?\")\n", + "yvalues = Keithley.query_ascii_values(\":FETC?\")\n", + "#data = Keithley.query('TRAC:DATA? 1,1') \n", "\n", + "print(yvalues)\n", + "print(result)\n", + "Keithley.write(\":OUTP OFF\")\n", + "Keithley.write(\":SOUR:VOLT 0\")\n", "\n", - "device24.write(':SOUR:FUNC VOLT')# Set voltage source mode\n", - "device24.write(':SENS:FUNC \"CURR\"') # Set current measure mode\n", - "for volt in range(minVoltage, maxVoltage+1):\n", - " \n", - " #\n", - " device24.write()\n", - " #wait 1 second\n", - " time.sleep(1)\n", - " \n", + "# Import Pyplot, NumPy, and SciPy\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from scipy import stats\n", "\n", + "# Create xvalues array and calculate conductance\n", + "xvalues = np.arange(startvprime,stopvprime,stepvprime)\n", + "slope, intercept, r_value, p_value, std_error = stats.linregress(xvalues, yvalues)\n", "\n", - "device24.write(':OUTP OFF')\n", - "device24.close()" + "# Plot values and output conductance to command line\n", + "print(\"Conductance:\", slope, \"Siemens\")\n", + "plt.plot(xvalues,yvalues)\n", + "plt.xlabel(' Drain-Source Voltage (V)')\n", + "plt.ylabel(' Drain-Source Current (A)')\n", + "plt.title('IV Curve')\n", + "plt.show()\n", + "np.savetxt(\"test\", (xvalues,yvalues)) " ] } ], @@ -82,7 +129,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.7" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/Samples/2420Test2.ipynb b/Samples/2420Test2.ipynb new file mode 100644 index 0000000..dd3ff4a --- /dev/null +++ b/Samples/2420Test2.ipynb @@ -0,0 +1,157 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2400 device\n", + "\n", + "2400 device는 drain/source voltage를 인가하고, 이에 따른 transistor device에 흐르는 전류를 측정한다." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "KEITHLEY INSTRUMENTS INC.,MODEL 2420,4051227,C32 Oct 4 2010 14:20:11/A02 /J/L\n", + "\n", + "Voltage: 0 V, Current: -1.382756E-09\n", + " A\n", + "Voltage: 1 V, Current: -2.017378E-10\n", + " A\n", + "Voltage: 2 V, Current: -1.951761E-10\n", + " A\n", + "Voltage: 3 V, Current: -1.815496E-10\n", + " A\n", + "Voltage: 4 V, Current: -1.860914E-10\n", + " A\n", + "Voltage: 5 V, Current: -1.850819E-10\n", + " A\n", + "Voltage: 6 V, Current: -1.775108E-10\n", + " A\n", + "Voltage: 7 V, Current: -1.840714E-10\n", + " A\n", + "Voltage: 8 V, Current: -1.724632E-10\n", + " A\n", + "Voltage: 9 V, Current: -1.734720E-10\n", + " A\n", + "Voltage: 10 V, Current: -1.765009E-10\n", + " A\n", + "Measurements complete.\n", + "Voltage: 0 V, Current: -1.382756E-09\n", + " A\n", + "Voltage: 1 V, Current: -2.017378E-10\n", + " A\n", + "Voltage: 2 V, Current: -1.951761E-10\n", + " A\n", + "Voltage: 3 V, Current: -1.815496E-10\n", + " A\n", + "Voltage: 4 V, Current: -1.860914E-10\n", + " A\n", + "Voltage: 5 V, Current: -1.850819E-10\n", + " A\n", + "Voltage: 6 V, Current: -1.775108E-10\n", + " A\n", + "Voltage: 7 V, Current: -1.840714E-10\n", + " A\n", + "Voltage: 8 V, Current: -1.724632E-10\n", + " A\n", + "Voltage: 9 V, Current: -1.734720E-10\n", + " A\n", + "Voltage: 10 V, Current: -1.765009E-10\n", + " A\n" + ] + } + ], + "source": [ + "import pyvisa\n", + "import time\n", + "\n", + "# VISA 리소스 매니저 생성\n", + "rm = pyvisa.ResourceManager()\n", + "\n", + "# Keithley 2420 계측기에 연결 (VISA 주소를 적절히 변경)\n", + "keithley = rm.open_resource('GPIB0::24::INSTR')\n", + "\n", + "# 장치 ID 확인 (선택사항)\n", + "print(keithley.query('*IDN?'))\n", + "\n", + "# 초기 설정\n", + "keithley.write('*RST') # 장치 리셋\n", + "keithley.write(':SENS:FUNC \"CURR\"') # 전류 측정 모드 설정\n", + "keithley.write(':SOUR:FUNC VOLT') # 전압 소스 모드 설정\n", + "keithley.write(':FORM:ELEM CURR') # 전류만 읽기\n", + "keithley.write(':SENS:CURR:PROT 0.1')\n", + "# 전압 및 전류 측정 설정\n", + "start_voltage = 0\n", + "end_voltage = 10\n", + "step_voltage = 1\n", + "measurement_time = 1 # 초\n", + "\n", + "# 결과 저장을 위한 리스트\n", + "voltages = []\n", + "currents = []\n", + "\n", + "# 측정 루프\n", + "try:\n", + " for voltage in range(start_voltage, end_voltage + step_voltage, step_voltage):\n", + " # 전압 설정\n", + " keithley.write(f':SOUR:VOLT {voltage}')\n", + " keithley.write(':OUTP ON') # 출력 켜기\n", + "\n", + " # 안정화 시간 대기\n", + " time.sleep(0.5)\n", + "\n", + " # 전류 측정\n", + " current = keithley.query(':READ?')\n", + " # 측정값 저장\n", + " voltages.append(voltage)\n", + " currents.append(current)\n", + "\n", + " # 측정 시간 대기\n", + " time.sleep(measurement_time)\n", + "\n", + " # 출력 끄기 (선택사항)\n", + " keithley.write(':OUTP OFF')\n", + "\n", + " print(f'Voltage: {voltage} V, Current: {current} A')\n", + "\n", + "finally:\n", + " # 장치 리셋 및 연결 해제\n", + " keithley.write('*RST')\n", + " keithley.close()\n", + "\n", + "# 결과 출력\n", + "print(\"Measurements complete.\")\n", + "for v, c in zip(voltages, currents):\n", + " print(f\"Voltage: {v} V, Current: {c} A\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Samples/2600bTest.ipynb b/Samples/2600bTest.ipynb index dfbab24..bf80cf4 100644 --- a/Samples/2600bTest.ipynb +++ b/Samples/2600bTest.ipynb @@ -31,20 +31,23 @@ "import pyvisa\n", "\n", "rm = pyvisa.ResourceManager()\n", - "device26 = rm.open_resource('GPIB::26::INSTR')\n", + "keithley = rm.open_resource('GPIB::26::INSTR')\n", "\n", "#Check DeviceID\n", - "print(device26.query('*IDN?'))\n", + "print(keithley.query('*IDN?'))\n", + "\n", "\n", - "#Turns on SMU channel A source output.\n", - "device26.write('smua.source.output = smua.OUTPUT_ON')\n", "\n", "minRange = -60\n", "maxRange = 60\n", "\n", "volt = 1\n", - "currentLimit26 = 100\n", - "device26.write(f':SOUR:FUNC VOLT')\n", + "currentLimit26 = 0.1\n", + "keithley.write('smua.source.func = smua.OUTPUT_DCVOLTS ')\n", + "\n", + "#Turns on SMU channel A source output.\n", + "keithley.write('smua.source.output = smua.OUTPUT_ON')\n", + "\n", "for volt in range(minRange, maxRange+1):\n", " #\n", " \n", diff --git a/Samples/PyVisa-Keityley-2018-06-22.ipynb b/Samples/PyVisa-Keityley-2018-06-22.ipynb new file mode 100644 index 0000000..8827a83 --- /dev/null +++ b/Samples/PyVisa-Keityley-2018-06-22.ipynb @@ -0,0 +1,205 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pyvisa\n", + "import time\n", + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "rm=pyvisa.ResourceManager()\n", + "rm.list_resources()\n", + "keithley1= rm.open_resource('GPIB0::24::INSTR') # Keithley GPIB adress 25\n", + "keithley1.write('*RST')\n", + "# a=keithley1.query(\"*IDN?\")\n", + "# print (a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Test parameter set-up" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "start_current=0 #unit A\n", + "stop_current=10\n", + "step_current=1\n", + "volt_prot='0.1' #voltage protection level\n", + "ontime= 1 # turn on bias before measurement unit: sec\n", + "\n", + "#File to save\n", + "fname='test' # change file name\n", + "directory= \"C:\\\\temp\\\\\" # change folder name if necessary\n", + "dataf=directory+fname+'.csv'\n", + "# dataf" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Keithley current source setup" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "18" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "keithley1.write( \":SYST:CLE\")\n", + "keithley1.write(\"SYST:BEEP:STAT OFF\") # 'Beeper off\n", + "keithley1.write(\"SOUR:FUNC:MODE VOLT\")\n", + "keithley1.write(\"SENS:FUNC 'CURR:DC'\")\n", + "keithley1.write(\"SOUR:VOLT:MODE FIXED\")\n", + "\n", + "keithley1.write(\":SENS:FUNC:CONC OFF\")\n", + "# keithley1.write(\"SENS:FUNC:ON VOLT,CURR\")\n", + "keithley1.write(\"SENSE:VOLTAGE:DC:RANGE:AUTO ON\")\n", + "keithley1.write(\"SENSE:CURRENT:DC:RANGE:AUTO ON\")\n", + "\n", + "keithley1.write( \":SENSE:CURR:PROT \" + volt_prot)\n", + "keithley1.write( \":FORM:ELEM VOLT,CURR\")\n", + "keithley1.write(\":SENSE:RES:MODE MAN\")\n", + "keithley1.write(\":SYSTEM:RSEN OFF\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "V=[]\n", + "I=[]\n", + "R=[]\n", + "\n", + "def measureR(bias):\n", + " curr=str(bias)\n", + " keithley1.write(\":SOUR:CURR:LEV:IMM:AMPL \"+ curr )\n", + " keithley1.write(':OUTP ON')\n", + " time.sleep(ontime)\n", + " keithley1.write(\":READ?\")\n", + " vi=keithley1.read()\n", + " resistanceCal(vi)\n", + " keithley1.write(':OUTP OFF')\n", + "\n", + "def resistanceCal(vi):\n", + " volt_curr=vi.rstrip().split(',')\n", + " volt=float(volt_curr[0])\n", + " curr=float(volt_curr[1])\n", + " res=volt/curr\n", + " V.append(volt)\n", + " I.append(curr)\n", + " R.append(res)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "for i in np.arange(start_current, stop_current+step_current, step_current):\n", + " measureR(i)\n", + " \n", + "data=pd.DataFrame({'Volt (mV)':V,\n", + " 'Curr (mA)':I,\n", + " 'Resistance': R})\n", + "data.to_csv(dataf)\n", + "V.clear()\n", + "I.clear()\n", + "R.clear()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(data['Curr (mA)']*1000, data['Resistance'])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Samples/dataTest.py b/Samples/dataTest.py new file mode 100644 index 0000000..74cb9e9 --- /dev/null +++ b/Samples/dataTest.py @@ -0,0 +1,36 @@ +import sys +from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel +import pyqtgraph as pg + +class MainWindow(QWidget): + def __init__(self): + super().__init__() + + self.setWindowTitle('IV Curve Measurement') + + self.layout = QVBoxLayout() + + self.label = QLabel('IV Curve') + self.layout.addWidget(self.label) + + self.graph_widget = pg.PlotWidget() + self.layout.addWidget(self.graph_widget) + + self.setLayout(self.layout) + + self.plot_iv_curve() + + def plot_iv_curve(self): + voltages = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9.] + currents = [1.48303e-11, 2.441952e-11, 2.593309e-11, 1.331663e-11, 1.886785e-11, + 1.331674e-11, 2.391481e-11, 1.382156e-11, 1.83637e-11, 2.189599e-11] + + self.graph_widget.plot(voltages, currents, pen=pg.mkPen(color='b', width=2)) + +if __name__ == '__main__': + app = QApplication(sys.argv) + + window = MainWindow() + window.show() + + sys.exit(app.exec()) diff --git a/Samples/qthread.py b/Samples/qthread.py new file mode 100644 index 0000000..8b53bbb --- /dev/null +++ b/Samples/qthread.py @@ -0,0 +1,75 @@ +import sys +import time +import pyvisa +import numpy as np +from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget +from PyQt6.QtCore import QThread, pyqtSignal +from matplotlib.figure import Figure +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +import pyqtgraph as pg +# PyVisa 측정을 수행할 QThread 클래스 +class MeasurementThread(QThread): + data_acquired = pyqtSignal(list, list) # (voltages, currents) + + def run(self): + rm = pyvisa.ResourceManager() + keithley = rm.open_resource('GPIB0::24::INSTR') + + # 장치 ID 확인 (선택사항) + print(keithley.query('*IDN?')) + + # 초기 설정 + keithley.write('*RST') # 장치 리셋 + keithley.write(':SENS:FUNC "CURR"') # 전류 측정 모드 설정 + keithley.write(':SOUR:FUNC VOLT') # 전압 소스 모드 설정 + keithley.write(':FORM:ELEM CURR') # 전류만 읽기 + keithley.write(':SENS:CURR:PROT 0.1') + voltages = [] + currents = [] + for voltage in np.linspace(0, 10, 11): + keithley.write(f":SOUR:VOLT {voltage}") + keithley.write(':OUTP ON') + time.sleep(1) # 1초 대기 + current = keithley.query(":READ?") + voltages.append(voltage) + currents.append(current) + self.data_acquired.emit(voltages, currents) + keithley.write(':OUTP OFF') + + +# 메인 윈도우 클래스 +class MainWindow(QMainWindow): + def __init__(self): + super().__init__() + self.graph_widget = pg.PlotWidget() + self.plot = self.graph_widget.plot([], [], pen=None, symbol='o') + self.setWindowTitle("Voltage-Current Measurement") + + self.canvas = FigureCanvas(Figure(figsize=(5, 3))) + self.ax = self.canvas.figure.subplots() + + self.button = QPushButton("Run") + self.button.clicked.connect(self.start_measurement) + + layout = QVBoxLayout() + layout.addWidget(self.canvas) + layout.addWidget(self.button) + + container = QWidget() + container.setLayout(layout) + self.setCentralWidget(container) + + self.thread = MeasurementThread() + self.thread.data_acquired.connect(self.update_graph) + + def start_measurement(self): + self.plot.setData([], []) # 그래프 초기화 + self.thread.start() + + def update_graph(self, voltages, currents): + self.plot.setData(voltages, currents) + +app = QApplication(sys.argv) +window = MainWindow() +window.show() +sys.exit(app.exec()) diff --git a/Samples/qthread2.py b/Samples/qthread2.py new file mode 100644 index 0000000..909e100 --- /dev/null +++ b/Samples/qthread2.py @@ -0,0 +1,76 @@ +import sys +import time +import pyvisa +import numpy as np +from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget +from PyQt6.QtCore import QThread, pyqtSignal +import pyqtgraph as pg + +# PyVisa 측정을 수행할 QThread 클래스 +class MeasurementThread(QThread): + data_acquired = pyqtSignal(list, list) # (voltages, currents) + + def run(self): + rm = pyvisa.ResourceManager() + keithley = rm.open_resource('GPIB0::24::INSTR') + + # 장치 ID 확인 (선택사항) + print(keithley.query('*IDN?')) + + # 초기 설정 + keithley.write('*RST') # 장치 리셋 + keithley.write(':SENS:FUNC "CURR"') # 전류 측정 모드 설정 + keithley.write(':SOUR:FUNC VOLT') # 전압 소스 모드 설정 + keithley.write(':FORM:ELEM CURR') # 전류만 읽기 + keithley.write(':SENS:CURR:PROT 0.1') + voltages = [] + currents = [] + for voltage in np.linspace(0, 10, 11): + keithley.write(f":SOUR:VOLT {voltage}") + keithley.write("OUTP ON") + time.sleep(1) # 1초 대기 + current =float(keithley.query(":READ?")) + voltages.append(voltage) + currents.append(current) + + self.data_acquired.emit(voltages, currents) + keithley.write("OUTP OFF") + + + +# 메인 윈도우 클래스 +class MainWindow(QMainWindow): + def __init__(self): + super().__init__() + self.setWindowTitle("Voltage-Current Measurement") + + self.graph_widget = pg.PlotWidget() + self.plot = self.graph_widget.plot([], [], pen=None, symbol='o') + + self.button = QPushButton("Run") + self.button.clicked.connect(self.start_measurement) + + layout = QVBoxLayout() + layout.addWidget(self.graph_widget) + layout.addWidget(self.button) + + container = QWidget() + container.setLayout(layout) + self.setCentralWidget(container) + + self.thread = MeasurementThread() + self.thread.data_acquired.connect(self.update_graph) + + def start_measurement(self): + self.plot.setData([], []) # 그래프 초기화 + self.thread.start() + + def update_graph(self, voltages, currents): + print(voltages) + print(currents) + self.plot.setData(voltages, currents) + +app = QApplication(sys.argv) +window = MainWindow() +window.show() +sys.exit(app.exec()) diff --git a/Samples/sweepModeTest.py b/Samples/sweepModeTest.py new file mode 100644 index 0000000..99a250c --- /dev/null +++ b/Samples/sweepModeTest.py @@ -0,0 +1,29 @@ +import pyvisa +import numpy as np +import matplotlib.pyplot as plt +import time + +# GPIB 설정 +rm = pyvisa.ResourceManager() +keithley = rm.open_resource('GPIB::24::INSTR') # 적절한 GPIB 주소를 사용하세요 + +# KEITHLEY 초기화 및 설정 +keithley.write('*RST') # 장비 초기화 +keithley.write(':SOUR:FUNC VOLT') # 전압 소스 설정 +keithley.write(':SOUR:VOLT:MODE SWE') # 스윕 모드 설정 +keithley.write(':SOUR:VOLT:START 0') # 시작 전압 설정 +keithley.write(':SOUR:VOLT:STOP 5') # 종료 전압 설정 +keithley.write(':SOUR:VOLT:STEP 0.1') # 스텝 전압 설정 +keithley.write(':SENS:FUNC "CURR"') +keithley.write(':SENS:CURR:PROT 0.1') + +keithley.write(':SOUR:SWE:RANG AUTO') # 자동 범위 설정 +keithley.write(':SOUR:SWE:SPAC LIN') # 선형 스윕 설정 +keithley.write(':SOUR:DEL 1') # 각 측정 사이의 지연 시간 설정 (1초) +keithley.write(':TRIG:COUN 51') # 스윕 포인트 수 설정 (0부터 5까지 0.1 스텝이므로 51 포인트) +keithley.write(':OUTP ON') + + +keithley.write('READ?') +keithley.write(':OUTP OFF') +keithley.close() diff --git a/Samples/sweepModeTest3.py b/Samples/sweepModeTest3.py new file mode 100644 index 0000000..44b7c1f --- /dev/null +++ b/Samples/sweepModeTest3.py @@ -0,0 +1,66 @@ +import sys +import pyvisa +import numpy as np +import pyqtgraph as pg +from PyQt6.QtWidgets import QApplication, QMainWindow +from PyQt6.QtCore import QTimer + +class IVPlotter(QMainWindow): + def __init__(self): + super().__init__() + self.voltages = np.arange(0, 5.1, 0.1) # 초기화 위치 수정 + self.currents = [] + self.index = 0 + + self.initUI() + self.initKeithley() + + self.timer = QTimer() + self.timer.timeout.connect(self.update_plot) + self.timer.start(100) # 100 ms interval + + def initUI(self): + self.graphWidget = pg.PlotWidget() + self.setCentralWidget(self.graphWidget) + self.graphWidget.setTitle("Real-time IV Curve") + self.graphWidget.setLabel('left', 'Current (A)') + self.graphWidget.setLabel('bottom', 'Voltage (V)') + self.data_line = self.graphWidget.plot([], [], pen=pg.mkPen('r', width=2)) + + def initKeithley(self): + rm = pyvisa.ResourceManager() + self.keithley = rm.open_resource('GPIB0::24::INSTR') # GPIB 주소를 적절히 변경하세요 + try: + self.keithley.write('*RST') + self.keithley.write(':SOUR:FUNC VOLT') + self.keithley.write(':SOUR:VOLT:STAR 0') + self.keithley.write(':SOUR:VOLT:STOP 5') + self.keithley.write(':SOUR:VOLT:STEP 0.1') + self.keithley.write(':SOUR:VOLT:MODE SWE') + self.keithley.write(':SENS:FUNC "CURR"') + self.keithley.write(':SENS:CURR:PROT 0.1') + self.keithley.write(f':TRIG:COUN {len(self.voltages)}') + self.keithley.write(':OUTP ON') # Sweep 시작 + except Exception error: + + + def update_plot(self): + if self.index < len(self.voltages): + data = self.keithley.query(':TRAC:DATA? 1,1') # 최신 측정값 불러오기 + current = float(data.split(',')[1]) + self.currents.append(current) + self.data_line.setData(self.voltages[:self.index + 1], self.currents) + self.index += 1 + else: + self.timer.stop() + self.keithley.write(':OUTP OFF') + self.keithley.close() + +def main(): + app = QApplication(sys.argv) + plotter = IVPlotter() + plotter.show() + sys.exit(app.exec()) + +if __name__ == '__main__': + main() diff --git a/Samples/test b/Samples/test new file mode 100644 index 0000000..46670c5 --- /dev/null +++ b/Samples/test @@ -0,0 +1,2 @@ +0.000000000000000000e+00 1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00 6.000000000000000000e+00 7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00 +1.230799000000000035e-11 1.230815000000000062e-11 1.382216999999999946e-11 1.230792999999999964e-11 3.729073000000000099e-12 1.331761999999999995e-11 3.728961999999999838e-12 7.012169000000000431e-13 1.281296999999999927e-11 2.214949999999999968e-12 diff --git a/Samples/testSweep2.py b/Samples/testSweep2.py new file mode 100644 index 0000000..81e86d8 --- /dev/null +++ b/Samples/testSweep2.py @@ -0,0 +1,110 @@ +import sys +import pyvisa +import numpy as np +import time +from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel +from PyQt6.QtCore import QThread, pyqtSignal, QTimer +import pyqtgraph as pg +from scipy import stats +startv = 0 +stopv = 10 +stepv = 1 +steps= 11 +startvprime = float(startv) +stopvprime = float(stopv) +stepvprime = float(stepv) +xvalues = np.arange(startvprime,stopvprime,stepvprime) + + +class IVThread(QThread): + data_ready = pyqtSignal() + + def run(self): + + startvprime = float(startv) + stopvprime = float(stopv) + stepvprime = float(stepv) + steps = (stopvprime - startvprime) / stepvprime + rm = pyvisa.ResourceManager() + Keithley = rm.open_resource('GPIB::24::INSTR') + # Turn off concurrent functions and set sensor to current with fixed voltage + Keithley.write(":SENS:FUNC:CONC OFF") + Keithley.write(":SOUR:FUNC VOLT") + Keithley.write(":SENS:FUNC 'CURR:DC' ") + + # Voltage starting, ending, and spacing values based on input + Keithley.write(f":SOUR:VOLT:STAR {startv}") + Keithley.write(f":SOUR:VOLT:STOP {stopv}") + Keithley.write(f":SOUR:VOLT:STEP {stepv}") + Keithley.write(":SOUR:SWE:RANG AUTO") + + # Set compliance current (in A), sweep direction, and data acquisition + Keithley.write(":SENS:CURR:PROT 0.1") + Keithley.write(":SOUR:SWE:SPAC LIN") + Keithley.write(":SOUR:SWE:POIN ", str(int(steps))) + Keithley.write(":SOUR:SWE:DIR UP") + Keithley.write(":TRIG:COUN ", str(int(steps))) + Keithley.write(":FORM:ELEM CURR") + + # Set sweep mode and turn output on + Keithley.write(":SOUR:VOLT:MODE SWE") + Keithley.write(":OUTP ON") + + + result = Keithley.query(":READ?") + self.voltages = xvalues + self.currents = Keithley.query_ascii_values(":FETC?") + print(self.voltages) + print(self.currents) + self.data_ready.emit() + Keithley.write(":OUTP OFF") + Keithley.write(":SOUR:VOLT 0") + Keithley.close() + +class MainWindow(QWidget): + def __init__(self): + super().__init__() + + self.setWindowTitle('IV Curve Measurement') + + self.layout = QVBoxLayout() + + self.label = QLabel('Press "Run" to start IV measurement') + self.layout.addWidget(self.label) + + self.run_button = QPushButton('Run') + self.run_button.clicked.connect(self.start_measurement) + self.layout.addWidget(self.run_button) + + self.graph_widget = pg.PlotWidget() + self.graph_widget.setBackground('w') + self.layout.addWidget(self.graph_widget) + + self.setLayout(self.layout) + + self.iv_thread = IVThread() + self.iv_thread.data_ready.connect(self.update_plot) + + self.voltages = [] + self.currents = [] + + + + def start_measurement(self): + self.run_button.setEnabled(False) + self.label.setText('Measurement in progress...') + self.voltages = [] + self.currents = [] + self.iv_thread.start() + + def update_plot(self): + self.graph_widget.plot(self.voltages, self.currents) + + +if __name__ == '__main__': + app = QApplication(sys.argv) + + window = MainWindow() + window.show() + + sys.exit(app.exec()) \ No newline at end of file