08-23-2017 03:48 AM - edited 08-23-2017 04:01 AM
Hello, I need to control several PXI devices (basically DC sources and DMM) via Python but I'm unsure about what the sanest approach could be.
Firstly I tried to use pyvisa as I've always done for SCPI devices and although I can open the corresponding resources, these have read_memory/write_memory methods since for example PXI-4110 doesn't take SCPI commands but direct register access, and from what I understand this low level control is not supported.
My second approach was to try control it with ctypes (package on which I have very little experience). However I'm stuck there because I can't find any detailed information on how to do this. I tried using examples from C++ etc as a reference but without luck. In particular, I load nidcpower.dll; checking http://zone.ni.com/reference/en-XX/help/370736R-01/ni_dc_power_supplies_help/software_behavior/ I see I have to first open a session with niDCPower_InitializeWithChannels. The corresponding resourceName for this function would be 'PXI1Slot5_2' as identified from MAX, but all it returns is -1074134966 no matter what I do, whatever this code means. I imagine I'm not even passing the arguments correctly, but I don't know where to look.
I would like to know how to properly initialize my devices this way, or even if there's any other approach.
Thanks
Solved! Go to Solution.
08-24-2017 12:45 PM
This is one of those situations where you get frustrated and it takes you asking for help to realise what you were doing wrong in the first place. If it helps anybody else (not so many hits for "python" and "pxi"), my problem with ctypes was Python 3 uses unicode strings by default, so I needed to convert them to bytes for the DLL functions to work. So I'm now doing everything I need with ctypes, and everything works fine (I had seen some open source wrappers out there following this approach, but none was complete enough to be usable).
I'm still curious about whether there are other options for interfacing PXI out there, so if anyone has any opinions I'll stick around, but I must say the DLLs are very well documented and it takes very little work to customize with a Python-esque interface.
11-16-2017 03:07 AM
Hello,
I am also looking to run a pxi whith python.
would you be kind enough to share an example of driving the PXI-4110?
11-16-2017 03:35 AM - edited 11-16-2017 03:41 AM
I cannot post the actual code I'm using but here's a basic example to set the channel 0 to 3.3V (there may be mistakes but I hope you get the idea).
from ctypes import c_bool, c_int, c_double, c_char_p, byref, windll NIDCPOWER_VAL_DC_VOLTAGE = 1006 def c_string(s): return c_char_p(str(s).encode('utf-8')) dll = windll.LoadLibrary('nidcpower_64.dll') vi = c_int(0) # vi "declared" here to be set by reference in next line dll.niDCPower_InitializeWithChannels(c_string('PXI1Slot6'), c_string('0'), c_bool(True), c_string(''), byref(vi)) # Module name PXIxSloty will depend on your setup! dll.niDCPower_ConfigureOutputFunction(vi, c_string('0'), c_int(NIDCPOWER_VAL_DC_VOLTAGE)) dll.niDCPower_ConfigureVoltageLevel(vi, c_string('0'), c_double(3.3)) # Set output to 3.3V dll.niDCPower_Initiate(vi) dll.niDCPower_ConfigureOutputEnabled(vi, c_string('0'), c_bool(True))
The API is explained in http://zone.ni.com/reference/en-XX/help/370736R-01/ This is just to call DLL functions from Python. At this point I'd recommend using cffi with NI's C++ header files for the definitions (that's where NIDCPOWER_* constants come from) rather than copying everything by hand, but ctypes is enough to write your own wrapper.
11-16-2017 04:11 AM
thank you very much
11-29-2017 09:17 AM
Hello, I tried your code but I block on loading the .dll
#-*- coding: UTF-8-*-*
import os
from ctypes import c_bool, c_int, c_double, c_char_p, byref, windll, cdll
def c_string(s):
return c_char_p(str(s).encode('utf-8'))
file_name=r'C:\Program Files\IVI Foundation\IVI\Bin\nidcpower_32.dll'
print(file_name)
dll = windll.loadLibrary('nidcpower_32.dll') #C:\\Program Files\\IVI Foundation\\IVI\\Bin\\nidcpower_32.dll
I try with the full path name and only the name and have the same result :
Traceback (most recent call last):
File "C:/WinPython-32bit-3.6.3.0Qt5/PycharmsProject/test/test.py", line 10, in <module>
dll = windll.loadLibrary('nidcpower_32.dll') #C:\\Program Files\\IVI Foundation\\IVI\\Bin\\nidcpower_32.dll
File "C:\WinPython-32bit-3.6.3.0Qt5\python-3.6.3\Lib\ctypes\__init__.py", line 418, in __getattr__
dll = self._dlltype(name)
File "C:\WinPython-32bit-3.6.3.0Qt5\python-3.6.3\Lib\ctypes\__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] Le module spécifié est introuvable
11-29-2017 09:36 AM
I imagine you've copied the DLL to the directory where you're running Python? Otherwise you have to include the full path, and if the file is where it's supposed to be it should work.
11-29-2017 09:39 AM - edited 11-29-2017 09:52 AM
I have try to put file_name in arg of
windll.loadLibrary
but it doesn't work. and when i send the request
print(os.path.isfile(file_name))
answer is true
11-29-2017 10:10 AM
This works with this method
from ctypes import c_bool, c_int, c_double, c_char_p, byref, windll, cdll
from ctypes.util import find_library
def c_string(s):
return c_char_p(str(s).encode('utf-8'))
lib_name = find_library('nidcpower_32')
dll = cdll.LoadLibrary(lib_name)
11-29-2017 10:22 AM
I'll come back to this when I find the time because it's a bit strange. I don't remember having any path problems like this. I was thinking it might have something to do with DLL dependencies but I don't quite see why what you did changes that. Sorry I can't be of more help (for now?)