Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with a Java wrapper for NIDAQmxBase (using JNI and Linux)

No I'm sorry but I didn't try yet with daqmxbase 3.1 released in january. I hope this would resolved our issue.
0 Kudos
Message 11 of 20
(3,039 Views)
Here are the components I have :
PCI DIO 96
PC Pentium III running Fedora 6 Kernel 2.6.18.2
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)

I downloaded and installed daqmxbase 3.1

I have run into the exact same behavior.
I just want basic IO (Mode 0) but in order to do this I have 3 options :
1. wait till the problem is fixed (if ever)
2. write a C app service wrapper around the daqmxbase
3. write a PCI device driver for the card.


Does anyone have a "faster" idea ? Smiley Happy

Regards,
Ranoxerox.

0 Kudos
Message 12 of 20
(3,022 Views)
I did a little application who write the results on output and ask if it must continue or stop.
0 Kudos
Message 13 of 20
(3,018 Views)
Hi Franxois,
I take it, it by-passes the C interface but uses the daqmxbase driver?
Would you be willing to post it here?  I would certainly appreciate it Smiley Happy
Best Regards,
Ranoxerox.
0 Kudos
Message 14 of 20
(3,012 Views)


Escrito por Ranoxerox:
...
I just want basic IO (Mode 0) but in order to do this I have 3 options :
1. wait till the problem is fixed (if ever)
2. write a C app service wrapper around the daqmxbase
3. write a PCI device driver for the card.
...


I had the same problem months ago and the solution I choose was the second. I used a C wrapper that send the data stream through a listening Java socket in the local machine. This way, you can have the DAQ native program in a host and the Java application in another. Just assure to disable the Nagle algorithm in native part if you need "real-time" data stream. Another approach is to send the data through standard output and collect it in standard input on the Java app (only if the standard input is not already use for another thing, like the 99% of applications I have seen in Java).

This way, in unix you can do:

./nativeDAQ | java mypackage.MyApplication

Hope this help. Your options 1 (wait for support) and 3 (write PCI driver) seems worse to me 🙂
0 Kudos
Message 15 of 20
(3,011 Views)
Thanks maht,
Definately sound advice,
previously I was using a PC DIO instead of a PCI.  I can see there is a big difference from my point of view of writing a program which does a simple outb write to a know memory address (PC Card)  vs dealing with all the initialization of the PCI card.  Which card are you using?  And would you be will to share the your small wrapper?  Did you end up going with NODELAY sockets or stdin input, or both?
Best Regards,
Ranoxerox.
0 Kudos
Message 16 of 20
(3,005 Views)


Escrito por Ranoxerox:
Thanks maht,
Definately sound advice,
previously I was using a PC DIO instead of a PCI.  I can see there is a big difference from my point of view of writing a program which does a simple outb write to a know memory address (PC Card)  vs dealing with all the initialization of the PCI card.  Which card are you using?  And would you be will to share the your small wrapper?  Did you end up going with NODELAY sockets or stdin input, or both?
Best Regards,
Ranoxerox.


       In my previous job the device was a NI-6009 (USB interface) so nothing to do with PCI, and NI only have nidaqmx-base drivers in Linux, so the native part was a C program that uses nidaqmx-base to send the data to the no-delay sockets. The sampling rate was 10 Hz (so 10 nodelay packets, 96 bits/packet in TCP header) and 4 analog channels (32bits), so the bit rate was 10x(4x32+96)=2240 bit/s, not much. This was fine for me, but maybe it is not good for you. Callculate with your data or simply try it 🙂

I haven't tryed stdout/stdin option, but it would be even faster (no TCP header).

I cannot send the implementation (I did it for my employer, so it's not mine) but the implementation is very straighfoward. You only have to make an infinite loop that read some samples, calculate its size in bytes, and write that bytes to  stdout/socket and repeat again. In the Java part, you only have to make a listening socket, and once connected, make a reading loop.

In fact, the tricky part of this is don't forget to give NODELAY for native socket and give high priority to the native process (the device buffer in NI-6009 is very small and get full very fast if you don't make call nidaq's read sample often).

In the Java part, the tricky part is to convert binary bytes into Java doubles and floats. You have to choose the correct "endianness" of the binary data.

To avoid that, and if your application is not sampling data very fast, you can send the data in text form (ASCII, for example) and do a double

   data = Double.parseDouble(receivedText);

This way is much more slowly than binary, waste more bandwidth and have rounding loss, but if very much easy to implement without bugs!!

And if you are not programming for a resource limited device (like a mobile phone, embedded linux, etc) I'll give it the first try. The best of all is that you can try with ASCII and once working, switch to binary with a few changes if you feel more performance is needed.

I don't have much time but if you get stucked with some implementation detail feel free to post. I'll not make your work, but I can answer reasonable doubts.

Best regards! 🙂
0 Kudos
Message 17 of 20
(3,001 Views)
Thanks maht ,
I have started making a service wrapper for the DAQmxBase calls.  My initial design would be a multi-threaded socket server, however, I noticed when I put the DAQmxBaseWriteDigitalU32 & DAQmxBaseReadDigitalU32 calls would fail when called on by a thread.  Yet, if the wrapper function was called by the main thread which got the task handle - the
DAQmxBaseWriteDigitalU32 & DAQmxBaseReadDigitalU32 would succeed.

As I could not see any means around this, my design has changed so that the socket portion of the server is multi-threaded but each thread will append their data to a queue.  Only the main thread will process the queue and do the DAQmxBase calls.  I only see this or just being completely single threaded as a solution.

Do you have any suggestions to proceed?

Regards,
Ranoxerox.
0 Kudos
Message 18 of 20
(2,990 Views)


Escrito por Ranoxerox:
Thanks maht ,
I have started making a service wrapper for the DAQmxBase calls.  My initial design would be a multi-threaded socket server, however, I noticed when I put the DAQmxBaseWriteDigitalU32 & DAQmxBaseReadDigitalU32 calls would fail when called on by a thread.  Yet, if the wrapper function was called by the main thread which got the task handle - the
DAQmxBaseWriteDigitalU32 & DAQmxBaseReadDigitalU32 would succeed.

As I could not see any means around this, my design has changed so that the socket portion of the server is multi-threaded but each thread will append their data to a queue.  Only the main thread will process the queue and do the DAQmxBase calls.  I only see this or just being completely single threaded as a solution.

Do you have any suggestions to proceed?

Regards,
Ranoxerox.


Uhmm, it's true ... the multithreading stuff 🙂

I don't remember if I have ever tryed to execute nidaqmxbase calls in different threads ... after trying in vain to setup the JNI thing, I assumed that the library wasn't going to be very friendly to "exotic usages" (and multithreading is great in hanging apps ...) so I directly decided to do all the native part in only one native thread (a process) and redirect to a separated process before get multithread.

I moved the multiplexion of streams into a "datastream-server" written in Java. This "datastream-server" serves the clients in a new thread, parse its query, and subscribe its sockets to the desired data-stream. Another thread in the "datastream-server" is used to read the data and write it to the clients' sockets subscribed to it. The data is read from a input stream that is connected to the output stream of the native server.

Perhaps not for heavy load ... (threads instead of Async IO, written in Java, etc etc) but was simple and worked fine for me. Maybe you need a C version, or something.

Anyway, to me the key point to avoid problems, specially with propietary libraries, is to use only one thread for the native calls when possible. And much better if it can be a single process, this way it is exactly as the nidaqmxbase documentation examples.

So, your solution of using a queue to serialize the petitions to the main-thread seems going in a good direction. If you are not interested in data-streams like me but in a "remote-procedure-call" to nidaqmxbase functions, this could be a good solution. In any case, if you see unexplicable weird things ... try to switch the threads to another process and leave the main-thread alone as a main-process.

Best regards 😉


0 Kudos
Message 19 of 20
(2,983 Views)
Thanks again maht ,
I have come up with a simple single threaded c wrapper which supports only one connection.  I figured that my Java code could do all the threading, multi-tasking, and maintain/reconnect the single channel to the c wrapper.  If anyone has any suggestions or comments for improvements, or is interested in using it, i have posted the code here
http://www.gizmogarden.com/index.php/PCI-DIO-96

This will be for robotics applications (see http://www.gizmogarden.com)  - sensors, motor controllers etc.
I'm guessing that I probably won't get the speed I need to generate pulse width modulation (PWM) for motor speed control - I found that I needed ~38KHz to smoothly control the speed - unfortunately (at the moment) I have no real time drivers and the I noticed that the parallel port was erratic in its write frequency.  My guess is that this card will behave the same, but I'll do a little testing.

Cheers,
Ranoxerox.
0 Kudos
Message 20 of 20
(2,975 Views)