visa-instrument-drivers 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- visa_instrument_drivers-0.1.4/.gitignore +7 -0
- visa_instrument_drivers-0.1.4/.idea/.gitignore +8 -0
- visa_instrument_drivers-0.1.4/.idea/inspectionProfiles/profiles_settings.xml +6 -0
- visa_instrument_drivers-0.1.4/.idea/misc.xml +7 -0
- visa_instrument_drivers-0.1.4/.idea/modules.xml +8 -0
- visa_instrument_drivers-0.1.4/.idea/vcs.xml +6 -0
- visa_instrument_drivers-0.1.4/.idea/visa_instrument_drivers.iml +10 -0
- visa_instrument_drivers-0.1.4/.idea/workspace.xml +87 -0
- visa_instrument_drivers-0.1.4/.python-version +1 -0
- visa_instrument_drivers-0.1.4/LICENSE +0 -0
- visa_instrument_drivers-0.1.4/PKG-INFO +37 -0
- visa_instrument_drivers-0.1.4/README.md +28 -0
- visa_instrument_drivers-0.1.4/_main.py +29 -0
- visa_instrument_drivers-0.1.4/_pyproject.toml +41 -0
- visa_instrument_drivers-0.1.4/pyproject.toml +16 -0
- visa_instrument_drivers-0.1.4/src/visa_instrument_drivers/__init__.py +4 -0
- visa_instrument_drivers-0.1.4/src/visa_instrument_drivers/keysight_e36150.py +28 -0
- visa_instrument_drivers-0.1.4/src/visa_instrument_drivers/rigol_dp800.py +75 -0
- visa_instrument_drivers-0.1.4/src/visa_instrument_drivers/rigol_mso5000.py +158 -0
- visa_instrument_drivers-0.1.4/uv.lock +35 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="Black">
|
|
4
|
+
<option name="sdkName" value="Python 3.12 (visa_instrument_drivers)" />
|
|
5
|
+
</component>
|
|
6
|
+
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
|
|
7
|
+
</project>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectModuleManager">
|
|
4
|
+
<modules>
|
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/visa_instrument_drivers.iml" filepath="$PROJECT_DIR$/.idea/visa_instrument_drivers.iml" />
|
|
6
|
+
</modules>
|
|
7
|
+
</component>
|
|
8
|
+
</project>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="PYTHON_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager">
|
|
4
|
+
<content url="file://$MODULE_DIR$">
|
|
5
|
+
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
|
6
|
+
</content>
|
|
7
|
+
<orderEntry type="jdk" jdkName="Python 3.13" jdkType="Python SDK" />
|
|
8
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
9
|
+
</component>
|
|
10
|
+
</module>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="AutoImportSettings">
|
|
4
|
+
<option name="autoReloadType" value="SELECTIVE" />
|
|
5
|
+
</component>
|
|
6
|
+
<component name="ChangeListManager">
|
|
7
|
+
<list default="true" id="1b9d8306-46eb-4f49-a77c-72d8b07063ff" name="Changes" comment="">
|
|
8
|
+
<change afterPath="$PROJECT_DIR$/src/visa_instrument_drivers/keysight_e36150.py" afterDir="false" />
|
|
9
|
+
</list>
|
|
10
|
+
<option name="SHOW_DIALOG" value="false" />
|
|
11
|
+
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
12
|
+
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
13
|
+
<option name="LAST_RESOLUTION" value="IGNORE" />
|
|
14
|
+
</component>
|
|
15
|
+
<component name="FileTemplateManagerImpl">
|
|
16
|
+
<option name="RECENT_TEMPLATES">
|
|
17
|
+
<list>
|
|
18
|
+
<option value="Python Script" />
|
|
19
|
+
</list>
|
|
20
|
+
</option>
|
|
21
|
+
</component>
|
|
22
|
+
<component name="Git.Settings">
|
|
23
|
+
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
|
24
|
+
</component>
|
|
25
|
+
<component name="ProjectColorInfo">{
|
|
26
|
+
"associatedIndex": 7
|
|
27
|
+
}</component>
|
|
28
|
+
<component name="ProjectId" id="321jFeavc3IaGNnvrXfw0ry68ba" />
|
|
29
|
+
<component name="ProjectViewState">
|
|
30
|
+
<option name="hideEmptyMiddlePackages" value="true" />
|
|
31
|
+
<option name="showLibraryContents" value="true" />
|
|
32
|
+
</component>
|
|
33
|
+
<component name="PropertiesComponent">{
|
|
34
|
+
"keyToString": {
|
|
35
|
+
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
|
36
|
+
"Python.main.executor": "Run",
|
|
37
|
+
"Python.rigol_dp800.executor": "Run",
|
|
38
|
+
"RunOnceActivity.ShowReadmeOnStart": "true",
|
|
39
|
+
"RunOnceActivity.git.unshallow": "true",
|
|
40
|
+
"git-widget-placeholder": "main",
|
|
41
|
+
"last_opened_file_path": "/Users/mborgh/github.com/mikeborgh/visa-instrument-drivers",
|
|
42
|
+
"node.js.detected.package.eslint": "true",
|
|
43
|
+
"node.js.detected.package.tslint": "true",
|
|
44
|
+
"node.js.selected.package.eslint": "(autodetect)",
|
|
45
|
+
"node.js.selected.package.tslint": "(autodetect)",
|
|
46
|
+
"nodejs_package_manager_path": "npm",
|
|
47
|
+
"vue.rearranger.settings.migration": "true"
|
|
48
|
+
}
|
|
49
|
+
}</component>
|
|
50
|
+
<component name="RecentsManager">
|
|
51
|
+
<key name="MoveFile.RECENT_KEYS">
|
|
52
|
+
<recent name="$PROJECT_DIR$/src/visa_instrument_drivers" />
|
|
53
|
+
</key>
|
|
54
|
+
</component>
|
|
55
|
+
<component name="SharedIndexes">
|
|
56
|
+
<attachedChunks>
|
|
57
|
+
<set>
|
|
58
|
+
<option value="bundled-js-predefined-d6986cc7102b-f27c65a3e318-JavaScript-PY-251.23774.444" />
|
|
59
|
+
<option value="bundled-python-sdk-890ed5b35930-d9c5bdb153f4-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-251.23774.444" />
|
|
60
|
+
</set>
|
|
61
|
+
</attachedChunks>
|
|
62
|
+
</component>
|
|
63
|
+
<component name="TaskManager">
|
|
64
|
+
<task active="true" id="Default" summary="Default task">
|
|
65
|
+
<changelist id="1b9d8306-46eb-4f49-a77c-72d8b07063ff" name="Changes" comment="" />
|
|
66
|
+
<created>1756594869221</created>
|
|
67
|
+
<option name="number" value="Default" />
|
|
68
|
+
<option name="presentableId" value="Default" />
|
|
69
|
+
<updated>1756594869221</updated>
|
|
70
|
+
<workItem from="1756594870240" duration="11799000" />
|
|
71
|
+
<workItem from="1756657832343" duration="1059000" />
|
|
72
|
+
<workItem from="1756854196801" duration="4745000" />
|
|
73
|
+
<workItem from="1758366158951" duration="24000" />
|
|
74
|
+
<workItem from="1767736572715" duration="16495000" />
|
|
75
|
+
<workItem from="1768163729441" duration="91000" />
|
|
76
|
+
<workItem from="1768164174885" duration="1672000" />
|
|
77
|
+
</task>
|
|
78
|
+
<servers />
|
|
79
|
+
</component>
|
|
80
|
+
<component name="TypeScriptGeneratedFilesManager">
|
|
81
|
+
<option name="version" value="3" />
|
|
82
|
+
</component>
|
|
83
|
+
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
|
84
|
+
<SUITE FILE_PATH="coverage/visa_instrument_drivers$main.coverage" NAME="main Coverage Results" MODIFIED="1756656650668" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
|
85
|
+
<SUITE FILE_PATH="coverage/visa_instrument_drivers$rigol_dp800.coverage" NAME="rigol_dp800 Coverage Results" MODIFIED="1756598317827" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/src/visa_instrument_drivers" />
|
|
86
|
+
</component>
|
|
87
|
+
</project>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: visa-instrument-drivers
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Requires-Dist: pyvisa>=1.16.0
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# visa-instrument-drivers
|
|
11
|
+
|
|
12
|
+
Tiny, pragmatic VISA instrument drivers built to use PyVISA.
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import pyvisa
|
|
16
|
+
from visa_instrument_drivers import RigolDP800
|
|
17
|
+
|
|
18
|
+
rm = pyvisa.ResourceManager()
|
|
19
|
+
instr = rm.open_resource("TCPIP::192.168.0.107::INSTR")
|
|
20
|
+
dp832a = RigolDP800(instr)
|
|
21
|
+
dp832a.write_source_voltage(13.5) # CH1
|
|
22
|
+
print(dp832a.read_source_voltage()) # 13.5 (setpoint)
|
|
23
|
+
instr.close()
|
|
24
|
+
rm.close()
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Build and publish
|
|
28
|
+
|
|
29
|
+
```shell
|
|
30
|
+
python -m pip install --upgrade pip build twine
|
|
31
|
+
# python -m build
|
|
32
|
+
# python -m twine upload --repository pypi dist/*
|
|
33
|
+
uv version --bump patch
|
|
34
|
+
uv build
|
|
35
|
+
# uv tool install uv-publish
|
|
36
|
+
uv-publish # looks for .pypirc file with PyPI credentials
|
|
37
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# visa-instrument-drivers
|
|
2
|
+
|
|
3
|
+
Tiny, pragmatic VISA instrument drivers built to use PyVISA.
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import pyvisa
|
|
7
|
+
from visa_instrument_drivers import RigolDP800
|
|
8
|
+
|
|
9
|
+
rm = pyvisa.ResourceManager()
|
|
10
|
+
instr = rm.open_resource("TCPIP::192.168.0.107::INSTR")
|
|
11
|
+
dp832a = RigolDP800(instr)
|
|
12
|
+
dp832a.write_source_voltage(13.5) # CH1
|
|
13
|
+
print(dp832a.read_source_voltage()) # 13.5 (setpoint)
|
|
14
|
+
instr.close()
|
|
15
|
+
rm.close()
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Build and publish
|
|
19
|
+
|
|
20
|
+
```shell
|
|
21
|
+
python -m pip install --upgrade pip build twine
|
|
22
|
+
# python -m build
|
|
23
|
+
# python -m twine upload --repository pypi dist/*
|
|
24
|
+
uv version --bump patch
|
|
25
|
+
uv build
|
|
26
|
+
# uv tool install uv-publish
|
|
27
|
+
uv-publish # looks for .pypirc file with PyPI credentials
|
|
28
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import pyvisa
|
|
2
|
+
from src.visa_instrument_drivers.rigol_dp800 import RigolDP800
|
|
3
|
+
|
|
4
|
+
def main():
|
|
5
|
+
rm = pyvisa.ResourceManager() #'/Users/mborgh/Downloads/nodevisa-v0.0.3-osx-arm64/liblibrary.dylib')
|
|
6
|
+
instr = rm.open_resource('Rigol DP832A SLC')
|
|
7
|
+
|
|
8
|
+
rigol_dp832a = RigolDP800(instr)
|
|
9
|
+
|
|
10
|
+
initial_current_limit = rigol_dp832a.query_source_current_level_immediate_amplitude(1)
|
|
11
|
+
initial_voltage_level = rigol_dp832a.query_source_voltage_level_immediate_amplitude(1)
|
|
12
|
+
initial_output_state = rigol_dp832a.query_output_state(1)
|
|
13
|
+
|
|
14
|
+
rigol_dp832a.write_source_current_level_immediate_amplitude(1, 3.0)
|
|
15
|
+
rigol_dp832a.write_source_voltage_level_immediate_amplitude(1, 5.0)
|
|
16
|
+
rigol_dp832a.write_output_state(1, 1)
|
|
17
|
+
|
|
18
|
+
final_current_limit = rigol_dp832a.query_source_current_level_immediate_amplitude(1)
|
|
19
|
+
final_voltage_level = rigol_dp832a.query_source_voltage_level_immediate_amplitude(1)
|
|
20
|
+
final_output_state = rigol_dp832a.query_output_state(1)
|
|
21
|
+
|
|
22
|
+
instr.close()
|
|
23
|
+
rm.close()
|
|
24
|
+
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if __name__ == '__main__':
|
|
29
|
+
main()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.25"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "visa-instrument-drivers" # 👇 The PyPI name
|
|
7
|
+
version = "0.1.1" # 👇 Bump each release
|
|
8
|
+
description = "Tiny, pragmatic VISA instrument drivers on top of PyVISA."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Michael", email = "michael@example.com" } # 👇
|
|
14
|
+
]
|
|
15
|
+
keywords = ["VISA", "SCPI", "PyVISA", "instruments", "automation", "rigol"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Topic :: Scientific/Engineering",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
# Core runtime deps
|
|
25
|
+
dependencies = [
|
|
26
|
+
"pyvisa>=1.13",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
# For users who want a pure-Python backend (no NI-VISA)
|
|
31
|
+
backends = ["pyvisa-py>=0.7"]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/fusaware/visa-instrument-drivers" # 👇
|
|
35
|
+
Issues = "https://github.com/fusaware/visa-instrument-drivers/issues"
|
|
36
|
+
|
|
37
|
+
[tool.hatch.build.targets.sdist]
|
|
38
|
+
include = ["src", "README.md", "LICENSE", "pyproject.toml"]
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["src/visa_instrument_drivers"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.25"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "visa-instrument-drivers"
|
|
7
|
+
version = "0.1.4"
|
|
8
|
+
description = "Add your description here"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"pyvisa>=1.16.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[tool.hatch.build.targets.wheel]
|
|
16
|
+
packages = ["src/visa_instrument_drivers"]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import pyvisa
|
|
2
|
+
|
|
3
|
+
class KeysightE36150:
|
|
4
|
+
class Channel:
|
|
5
|
+
class Number:
|
|
6
|
+
CH1 = 1
|
|
7
|
+
|
|
8
|
+
def __init__(self, instr: pyvisa.Resource):
|
|
9
|
+
self.instr = instr
|
|
10
|
+
return
|
|
11
|
+
|
|
12
|
+
def query_output_state(self, channel: int) -> int:
|
|
13
|
+
if channel not in KeysightE36150.Channel.Number:
|
|
14
|
+
raise ValueError(f"Channel {channel} is not supported")
|
|
15
|
+
|
|
16
|
+
msg = f":OUTP? (@{channel})"
|
|
17
|
+
resp = self.instr.query(msg)
|
|
18
|
+
state = int(resp.strip())
|
|
19
|
+
return state
|
|
20
|
+
|
|
21
|
+
def write_output_state(self, channel: int, state: int):
|
|
22
|
+
if channel not in KeysightE36150.Channel.Number:
|
|
23
|
+
raise ValueError(f"Channel {channel} is not supported")
|
|
24
|
+
|
|
25
|
+
msg = f":OUTP {state},(@{channel})"
|
|
26
|
+
self.instr.write(msg)
|
|
27
|
+
return
|
|
28
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
import pyvisa
|
|
3
|
+
|
|
4
|
+
class RigolDP800:
|
|
5
|
+
class Channel:
|
|
6
|
+
class Number(int, Enum):
|
|
7
|
+
CH1 = 1
|
|
8
|
+
CH2 = 2
|
|
9
|
+
CH3 = 3
|
|
10
|
+
|
|
11
|
+
class Output:
|
|
12
|
+
class State(int, Enum):
|
|
13
|
+
OFF = 0
|
|
14
|
+
ON = 1
|
|
15
|
+
|
|
16
|
+
def __init__(self, instr: pyvisa.Resource):
|
|
17
|
+
self.instr = instr
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
def query_source_current_level_immediate_amplitude(self, channel: int) -> float:
|
|
21
|
+
if channel not in RigolDP800.Channel.Number:
|
|
22
|
+
raise ValueError("Invalid channel number")
|
|
23
|
+
|
|
24
|
+
msg = f":SOUR{channel}:CURR?"
|
|
25
|
+
resp = self.instr.query(msg)
|
|
26
|
+
level = float(resp.strip())
|
|
27
|
+
return level
|
|
28
|
+
|
|
29
|
+
def write_source_current_level_immediate_amplitude(self, channel: int, amplitude: float):
|
|
30
|
+
if channel not in RigolDP800.Channel.Number:
|
|
31
|
+
raise ValueError("Invalid channel number")
|
|
32
|
+
|
|
33
|
+
msg = f":SOUR{channel}:CURR {amplitude}"
|
|
34
|
+
self.instr.write(msg)
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
def query_source_voltage_level_immediate_amplitude(self, channel: int) -> float:
|
|
38
|
+
if channel not in RigolDP800.Channel.Number:
|
|
39
|
+
raise ValueError("Invalid channel number")
|
|
40
|
+
|
|
41
|
+
msg = f":SOUR{channel}:VOLT?"
|
|
42
|
+
resp = self.instr.query(msg)
|
|
43
|
+
level = float(resp.strip())
|
|
44
|
+
return level
|
|
45
|
+
|
|
46
|
+
def write_source_voltage_level_immediate_amplitude(self, channel: int, amplitude: float):
|
|
47
|
+
if channel not in RigolDP800.Channel.Number:
|
|
48
|
+
raise ValueError("Invalid channel number")
|
|
49
|
+
|
|
50
|
+
msg = f":SOUR{channel}:VOLT {amplitude}"
|
|
51
|
+
self.instr.write(msg)
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
def query_output_state(self, channel: int) -> int:
|
|
55
|
+
if channel not in RigolDP800.Channel.Number:
|
|
56
|
+
raise ValueError("Invalid channel number")
|
|
57
|
+
|
|
58
|
+
msg = f":OUTP:STAT? CH{channel}"
|
|
59
|
+
resp = self.instr.query(msg)
|
|
60
|
+
state = int(resp.strip())
|
|
61
|
+
|
|
62
|
+
if state not in RigolDP800.Output.State:
|
|
63
|
+
raise ValueError("Invalid output state")
|
|
64
|
+
return state
|
|
65
|
+
|
|
66
|
+
def write_output_state(self, channel: int, state: int):
|
|
67
|
+
if channel not in RigolDP800.Channel.Number:
|
|
68
|
+
raise ValueError("Invalid channel number")
|
|
69
|
+
|
|
70
|
+
if state not in RigolDP800.Output.State:
|
|
71
|
+
raise ValueError("Invalid output state")
|
|
72
|
+
|
|
73
|
+
msg = f":OUTP:STAT CH{channel},{state}"
|
|
74
|
+
self.instr.write(msg)
|
|
75
|
+
return
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
import math
|
|
3
|
+
|
|
4
|
+
import pyvisa
|
|
5
|
+
|
|
6
|
+
class RigolMSO5000:
|
|
7
|
+
|
|
8
|
+
class Attenuation:
|
|
9
|
+
|
|
10
|
+
class Ratio(Enum):
|
|
11
|
+
AR100u = 0.0001
|
|
12
|
+
AR200u = 0.0002
|
|
13
|
+
AR500u = 0.0005
|
|
14
|
+
AR1m = 0.001
|
|
15
|
+
AR2m = 0.002
|
|
16
|
+
AR5m = 0.005
|
|
17
|
+
AR10m = 0.01
|
|
18
|
+
AR20m = 0.02
|
|
19
|
+
AR50m = 0.05
|
|
20
|
+
AR100m = 0.1
|
|
21
|
+
AR200m = 0.2
|
|
22
|
+
AR500m = 0.5
|
|
23
|
+
AR1 = 1
|
|
24
|
+
AR2 = 2
|
|
25
|
+
AR5 = 5
|
|
26
|
+
AR10 = 10
|
|
27
|
+
AR20 = 20
|
|
28
|
+
AR50 = 50
|
|
29
|
+
AR100 = 100
|
|
30
|
+
AR200 = 200
|
|
31
|
+
AR500 = 500
|
|
32
|
+
AR1000 = 1000
|
|
33
|
+
AR2000 = 2000
|
|
34
|
+
AR5000 = 5000
|
|
35
|
+
AR10000 = 10000
|
|
36
|
+
AR20000 = 20000
|
|
37
|
+
AR50000 = 50000
|
|
38
|
+
|
|
39
|
+
class Channel:
|
|
40
|
+
|
|
41
|
+
class Number(Enum):
|
|
42
|
+
CH1 = 1
|
|
43
|
+
CH2 = 2
|
|
44
|
+
CH3 = 3
|
|
45
|
+
CH4 = 4
|
|
46
|
+
|
|
47
|
+
class Display:
|
|
48
|
+
|
|
49
|
+
class State(Enum):
|
|
50
|
+
OFF = 0
|
|
51
|
+
ON = 1
|
|
52
|
+
|
|
53
|
+
class Units(Enum):
|
|
54
|
+
AMP = 'AMP'
|
|
55
|
+
UNKN = 'UNKN'
|
|
56
|
+
VOLT = 'VOLT'
|
|
57
|
+
WATT = 'WATT'
|
|
58
|
+
|
|
59
|
+
def __init__(self, instr: pyvisa.Resource):
|
|
60
|
+
self.instr = instr
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
def query_channel_offset(self, channel: int) -> float:
|
|
64
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
65
|
+
raise ValueError("Invalid channel number")
|
|
66
|
+
|
|
67
|
+
msg = f":CHAN{channel}:OFFS?"
|
|
68
|
+
resp = self.instr.query(msg)
|
|
69
|
+
level = float(resp.strip())
|
|
70
|
+
return level
|
|
71
|
+
|
|
72
|
+
def write_channel_offset(self, channel: int, offset: float):
|
|
73
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
74
|
+
raise ValueError("Invalid channel number")
|
|
75
|
+
|
|
76
|
+
msg = f":CHAN{channel}:OFFS {offset}"
|
|
77
|
+
self.instr.write(msg)
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
def query_channel_scale(self, channel: int) -> float:
|
|
81
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
82
|
+
raise ValueError("Invalid channel number")
|
|
83
|
+
|
|
84
|
+
msg = f":CHAN{channel}:SCAL?"
|
|
85
|
+
resp = self.instr.query(msg)
|
|
86
|
+
level = float(resp.strip())
|
|
87
|
+
return level
|
|
88
|
+
|
|
89
|
+
def write_channel_scale(self, channel: int, scale: float):
|
|
90
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
91
|
+
raise ValueError("Invalid channel number")
|
|
92
|
+
msg = f":CHAN{channel}:SCAL {scale}"
|
|
93
|
+
self.instr.write(msg)
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
def query_channel_probe(self, channel: int) -> float:
|
|
97
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
98
|
+
raise ValueError("Invalid channel number")
|
|
99
|
+
|
|
100
|
+
msg = f":CHAN{channel}:PROB?"
|
|
101
|
+
resp = self.instr.query(msg)
|
|
102
|
+
level = float(resp.strip())
|
|
103
|
+
return float(level)
|
|
104
|
+
|
|
105
|
+
def write_channel_probe(self, channel: int, attenuation: float):
|
|
106
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
107
|
+
raise ValueError("Invalid channel number")
|
|
108
|
+
|
|
109
|
+
attenuation_value = None
|
|
110
|
+
for option in RigolMSO5000.Attenuation.Ratio:
|
|
111
|
+
if math.isclose(option.value, attenuation):
|
|
112
|
+
attenuation_value = option.value
|
|
113
|
+
if attenuation_value is None:
|
|
114
|
+
raise ValueError("Invalid attenuation")
|
|
115
|
+
|
|
116
|
+
msg = f":CHAN{channel}:PROB {attenuation_value}"
|
|
117
|
+
self.instr.write(msg)
|
|
118
|
+
return
|
|
119
|
+
|
|
120
|
+
def query_channel_display(self, channel: int) -> int:
|
|
121
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
122
|
+
raise ValueError("Invalid channel number")
|
|
123
|
+
|
|
124
|
+
msg = f":CHAN{channel}:DISP?"
|
|
125
|
+
resp = self.instr.query(msg)
|
|
126
|
+
state = resp.strip()
|
|
127
|
+
if state not in RigolMSO5000.Display.State:
|
|
128
|
+
raise ValueError("Invalid display state")
|
|
129
|
+
return state
|
|
130
|
+
|
|
131
|
+
def write_channel_display(self, channel: int, state: int):
|
|
132
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
133
|
+
raise ValueError("Invalid channel number")
|
|
134
|
+
|
|
135
|
+
msg = f":CHAN{channel}:DISP {state}?"
|
|
136
|
+
self.instr.write(msg)
|
|
137
|
+
return
|
|
138
|
+
|
|
139
|
+
def query_channel_units(self, channel: int) -> str:
|
|
140
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
141
|
+
raise ValueError("Invalid channel number")
|
|
142
|
+
|
|
143
|
+
msg = f":CHAN{channel}:UNIT?"
|
|
144
|
+
resp = self.instr.query(msg)
|
|
145
|
+
units = resp.strip()
|
|
146
|
+
|
|
147
|
+
if units not in RigolMSO5000.Units:
|
|
148
|
+
raise ValueError("Invalid units")
|
|
149
|
+
|
|
150
|
+
return units
|
|
151
|
+
|
|
152
|
+
def write_channel_units(self, channel: int, units: str):
|
|
153
|
+
if channel not in RigolMSO5000.Channel.Number:
|
|
154
|
+
raise ValueError("Invalid channel number")
|
|
155
|
+
|
|
156
|
+
msg = f":CHAN{channel}:UNIT {units}?"
|
|
157
|
+
self.instr.write(msg)
|
|
158
|
+
return
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.12"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "pyvisa"
|
|
7
|
+
version = "1.16.0"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
dependencies = [
|
|
10
|
+
{ name = "typing-extensions" },
|
|
11
|
+
]
|
|
12
|
+
sdist = { url = "https://files.pythonhosted.org/packages/53/a1/c39c71aa453a0f68db672ab94f47cb06fb51265b2e66231987919e7d4b41/pyvisa-1.16.0.tar.gz", hash = "sha256:6daeb845fde2f9c095d02039ffd01dd27507c09376b1859dacb6b4f9a3aa3db0", size = 238604, upload-time = "2025-12-18T16:57:19.786Z" }
|
|
13
|
+
wheels = [
|
|
14
|
+
{ url = "https://files.pythonhosted.org/packages/96/81/cca605eebc44f30d8d6b7a7cdb4b69f8ae4f255811f7328d60df4e0aafc5/pyvisa-1.16.0-py3-none-any.whl", hash = "sha256:10b49ab9b04c5c6f3ea3b9e69398ab49133f46dbe827f0cea13ea934e092d3d0", size = 181351, upload-time = "2025-12-18T16:57:18.208Z" },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "typing-extensions"
|
|
19
|
+
version = "4.15.0"
|
|
20
|
+
source = { registry = "https://pypi.org/simple" }
|
|
21
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
|
22
|
+
wheels = [
|
|
23
|
+
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[[package]]
|
|
27
|
+
name = "visa-instrument-drivers"
|
|
28
|
+
version = "0.1.4"
|
|
29
|
+
source = { editable = "." }
|
|
30
|
+
dependencies = [
|
|
31
|
+
{ name = "pyvisa" },
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[package.metadata]
|
|
35
|
+
requires-dist = [{ name = "pyvisa", specifier = ">=1.16.0" }]
|