Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

null TaskHandle in Python?

Hello,

my basic problem is that i can't get a task to initialize in linux+nidaqmxbase+python. 

here is a longer description, and i'm attaching various source code as well.

  i'm trying to write a custom application using the nidaqmx drivers. I'd like easy gui development and quick development for all the high-level stuff, so i thought it made sense to use python, which has the added advantage of being fairly similar to matlab, which is what my coworkers already know.  After some benchmarks, i found that python runs unacceptably slow on windows, but quite fast on linux.
So, i'm using the nidaqmxbase installed on mandriva. 

When i write a C program, i can call the function DAQmxBaseCreateTask and confirm that the taskHandle i give it is initialized to a valid memory address. However, all of my attempts to do this in python seem to result in no errors being reported, but the taskHandle still being null.   There are a couple examples of working python-nidaqmx code,  but everyone seems to be doing this on windows for some reason. I suspect, based on the commented line in nidaqmxbase.h that the TaskHandle typedef is different in the linux version than in the windows version (it's a pointer to an unsigned long in linux, and the commented-out line is a typedef to an unsigned long) - but, who knows!     basically my first attempt is just exactly the examples i found that people said were working for them using the windows nidaqmx drivers,  as opposed to the linux nidaqmxbase.

my first attempt was to use python's ctypes library, which is standard in current versions of python. This makes it hard to assess where the failure is, but it's clear that the task isn't running properly.

my second attempt was to use pyrex, which lets you write in a mix of python and C, and then compiles itself to c code, which you can compile to a .so file and use as a python module. this allowed me to determine that the task handle was null, and in fact, if i try to dereference the task handle in the pyrex version, DAQmx catches the segfault and reports it.
at this point i thought that perhaps the problem was in the marshalling of pointers between python and the native libraries.

my third attempt was to write a library in pure c, which i can compile to a .so file and then either write a C executable that links against it, or use ctypes to import it into python.  The frustrating thing is ... my C program gets an initialized taskHandle, but my python program does not!  So now i know it's the exact same calls, and they're all being made from within a C library, so there is no marshalling of anything but integers between python and C ...
so!

something is changing when the call initiates from within python. I know that the ctypes library is generally felt to work correctly, and for that matter so is pyrex. I suspect that NIDAQmxBase drivers do something that's a little bit non-standard, and none of my python tools can handle it ...

but i'm wondering a few things..
-is there an NI programmer who reads these things who has some insight into the internal workings and can suggest why my daqmx library calls are failing, and how to work around it?
-has anyone else encountered this error and worked around it?
-has anyone made a succesful program using python on linux with nidaqmxbase, and if so, how did you accomplish the interop between python and daqmxbase ?


thanks!
0 Kudos
Message 1 of 14
(8,354 Views)
Hey chicago_joe,

National Instruments does not support creating C modules for use with other programming languages. This does not mean that it is not possible, only that we have not tested it and cannot guarantee that it will work.

I don't have any suggestions for why your DAQmxBase calls are failing through python. One thing that you could try is the DAQmx driver for Linux. National Instruments now does support the DAQmx driver, rather than the DAQmx Base driver on Linux. I am assuming that your device is compatible with the driver. Using this driver you could test the python-daqmx examples that you found and see if you can get some better results. Please see the download link below.

NI-DAQmx 8.0 - Mandriva
http://joule.ni.com/nidu/cds/view/p/id/374/lang/en
Regards,

Chris Delvizis
National Instruments
0 Kudos
Message 2 of 14
(8,317 Views)
I was able to resolve my pointer initialization bugs by compiling my module into python.
I do have a question about daqmx versus daqmxBase --   i mean basically, which one should i be using?
i thought that daqmxbase was the only option for linux,
but you suggested i use regular daqmx ,  and it's my impression that there are many more functions in the full daqmx and that basically there's some functionality such as calibration and error handling that are included in daqmx but not daqmxbase?
but on the other hand, the daqmx 8.0 is from 2005, whereas the mxbase seems to be from 2008, so i might conclude it's more current?
is it possible to have both sets of drivers installed on the same machine, or would i need a separate computer to test the other drivers suite?


for general reference, here is how i'm wrapping python and daqmxbase:

1. a C wrapper uses a static array of tasks so that no TaskHandles need to be marshalled across,  and also so that i can write my own functions in C for speed as needed. i compile this to a .so file
2. a pyrex wrapper creates a python class that wraps the C wrapper. pyrex outputs c code for a module, which i compile to a .so
3. in the python source, the /Modules directory seems to need the source and the .o and .so files, and then by editing setup.local i can compile them all into the python executable
4. so now i can just "import nidaq" in python and get all of the daqmx functionality i've exposed in my wrappers.

anyway this seems to be working and i'm just mentioning it in case it helps someone else someday.

i appreciate your help with daqmx vs. daqmxbase


0 Kudos
Message 3 of 14
(8,285 Views)

Hey chicago_joe,

I am glad you got it working and thanks for posting your solution!  You would choose between DAQmx and DAQmx Base depending on your distro, hardware, and functionality you want. Certain hardware may only be supported by one driver or the other. You can check this in the readme file for each driver. The DAQmx driver does include much more functionality. You can see a comparison in the first link below. DAQmx Base does have the most recent release, but that does not necessarily make it the best candidate for your use. Again, it all depends on the things I have spoken about above. You can have both installed at the same time and I have attached a link below that describes how to switch between the two.

Data Acquisition (DAQ) Software Comparison
http://www.ni.com/dataacquisition/companion_software.htm

How To Switch Between NI-DAQmx Base and NI-DAQmx on Linux
http://digital.ni.com/public.nsf/allkb/A3C7200E881696FA862570AD0050E8D0?OpenDocument

NI-DAQmx for Linux Frequently Asked Questions
http://zone.ni.com/devzone/cda/tut/p/id/3695

Please let me know if you have further questions!

Regards,

Chris Delvizis
National Instruments
0 Kudos
Message 4 of 14
(8,267 Views)

Hello Chicago_Joe,

 

I'm not very fluent in c programming on Linux, actually all focus is going to python/numpy/scipy/matplotlib, that i start to use well.

 

Now i would like to implement a single NI usb-6008 device for some linux host applications.

 

I got lsdaq & nidaqmxbase working properly as root on debian lenny official release,

using all the good advise on this  board

- alien-ising nikal,nivisa & nidaqmxbase rpms from iso file nidaqmxbase320

- dpkg -i *.deb those deb files

- usr/lib/natinst/bin/FWUpdate to latest firmware

 

Now I still have 2 problems  :

1. how to get lsdaq finding the usb device when i'm not root

2. since i'm not that fluent on c programming & ctypes,

is it possible to get more detailed information about the way 

i should import 'nidaq' (just for usb device herebove)

 

Naturally i also am very eager to hear if you continued on this python approach,

since it looks like you have been creating the only mention of  python nidaq up to now.

 

thank you beforehand for your help

 

bogitux

0 Kudos
Message 5 of 14
(7,794 Views)

Hi bogitux,

 

Considering that you are posting on a relatively old thread, Chicago_Joe may not still be monitoring posts.  As such, should you not receive a response,  you may consider creating a new thread.  Good luck!

 

Regards,

David

Applications Engineer

National Instruments

David
Applications Engineer
National Instruments


Digital Multimeters
0 Kudos
Message 6 of 14
(7,776 Views)

hey all,

 

short story is that after all that,  i showed my boss how far i had gotten in time i had been working on it and he asked me to focus on other things,  so i haven't been back to it too much.  

 

the way i was able to 'import nidaq'  as i said was by compiling my wrapper-modules (first a C wrapper to handle the pointers and make calls to NIDAQ, and then a pyrex layer to interface between python and C) and placing them in the python path.  if you have a module called nidaq, you can import it!  I had written a makefile which should also be in the tarball,  so that shows how i was compiling everything.

 

i can look around and see if i have a more recent version of the code to post,  but i think the .tgz earlier in this thread is fairly current.   I had only wrapped a bare minimum of the NI functions,  and one issue that obviously needed to be dealt with promptly was the buffering - my group has also run into this in pure labview applications,  but basically you have to do some internal buffering of your incoming and outgoing data to make sure you don't fall behind the acquisition board, and you have to understand the rates at which your device can acquire.  

 

anyway if you have little or no experience with C programming,  looking at my code might help with a template but probably won't be enough.  on the other hand if you're capable of writing in C,  i think i made a decent start and it would save someone a little time to continue from where i left off rather than start from scratch.  but like i said it's not a full wrapper because i was asked to focus my time elsewhere. 

0 Kudos
Message 7 of 14
(7,771 Views)

Hi chicago_joe,

[It appears may still monitor this thread, so I'll take a shot in the dark.] Sounds like the workaround for accessing DAQmx in python was not trivial. I'm afraid I couldn't implement as complicated a wrapper-of-wrappers solution as you came to (plus, I am on Windows). However, you appear to be one of the few people anywhere who have tried to use DAQmx with python and I'm completely stuck (and will ship my NI device back if I can't get this to work): did you ever manage to perform digital output? Or, more generally, did you find a way to set the "reserved" parameters from python to some value they would accept? I have been able to read data from my device (NI USB-6259) with no trouble using the python ctypes wrapper, but I'm completely hung on usingDAQmxWriteDigitalLines(), and related functions, because they require a "NULL" value for the 'reserved' parameter, and I can't find a way to feed that properly from python. Any chance you succeeded in that task before you were pulled away? My non-working code (based on the ) looks like this:

import ctypes
nidaq = ctypes.windll.nicaiu

DAQmx_Val_ChanPerLine = ctypes.c_int(0)

enable = ctypes.c_uint32(3)
sampsPerChanWritten = ctypes.c_int32()
null = ctypes.c_int32(0)

nidaq.DAQmxCreateTask("",ctypes.byref(enable))
nidaq.DAQmxCreateDOChan(enable,"Dev1/port0/line1","", DAQmx_Val_ChanPerLine)
nidaq.DAQmxWriteDigitalLines(enable,
                                                   ctypes.c_int32(1),        # numSamplsPerChan
                                                   ctypes.c_int32(1),        # autostart=1
                                                   ctypes.c_float64(1),     # timeout
                                                   DAQmx_Val_GroupByChannel,
                                                   ctypes.c_uint8(1),        # VALUE TO BE WRITTEN
                                                   ctypes.byref(sampsPerChanWritten),
                                                   ctypes.byref(null)  )      # reserved, supposed to be NULL

This gives me a -200492 error: 'Measurements: Reserved parameter must be NULL.' I've also tried defining null as:

null = ctypes.POINTER(ctypes.c_int)()
null.value = 0

... and replacing the last line in the  DAQmxWriteDigitalLines call with "null )", but that fails on "WindowsError: exception: access violation reading 0x00000001". I have yet to come up with a combination of the definition of my 'null' variable and ctypes passing syntax that DAQmx accepts. Any insight you or others might have would be most appreciated.


-best

GaryS

0 Kudos
Message 8 of 14
(7,754 Views)

the way you set up your null pointer,  it's pointing to a value of zero - you need a pointer that IS zero.   it's basically a ctypes issue,  which... according to ctypes documentation,  you should get a null pointer just by calling the constructor with no arguments and then never setting a value,  so just the line:

null = ctypes.POINTER(ctypes.c_int)()

all by itself /should/  do it,   but if that doesn't work ...   best of luck! 

0 Kudos
Message 9 of 14
(7,748 Views)
Thanks for the input ... I must admit I've never fully understood NULL pointers. Your suggestion unfortunately also gives a WindowsError, so I'll have to go looking elsewhere I guess. Thanks again.
0 Kudos
Message 10 of 14
(7,743 Views)