Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Equivalent DAQmx code for existing VB6 traditional legacy DAQ driver calls

Hi,

I've actually posted something about this question before, but moved on to other things for a while. Now I'm back and have a better idea of what I want to ask. So I have some VB6 that uses the traditional NI legacy drivers to access a DIO card that we have (PCI-DIO-32HS to be exact). Now the snippet of the old code that's important is the following:

// setup code

    ARRAY_SIZE = 2^14
    Dim piHalfBuffer(ARRAY_SIZE * 2) As Integer
    Dim iDevice As Integer
    Dim iGroup As Integer
    Dim iGroupSize As Integer
    Dim iPort As Integer

    iStatus% = Timeout_Config(iDevice%, lTimeout&)
    iRetVal% = NIDAQErrorHandler(iStatus%, "Timeout_Config", iIgnoreWarning%)
   
    iStatus% = DIG_Grp_Config(iDevice%, iGroup%, iGroupSize%, iPort%, iDir%)
    iRetVal% = NIDAQErrorHandler(iStatus%, "DIG_Grp_Config", iIgnoreWarning%)
   
    iStatus% = DIG_Block_PG_Config(iDevice%, iGroup%, 1, 1, -3, 2, 0)
    iRetVal% = NIDAQErrorHandler(iStatus%, "DIG_Block_PG_Config", iIgnoreWarning%)
   
    iStatus% = DIG_DB_Config(iDevice%, iGroup%, iDBModeON%, iOldDataStop%, iPartialTransfer%)
    iRetVal% = NIDAQErrorHandler(iStatus%, "DIG_DB_Config", iIgnoreWarning%)
   
    iStatus% = DIG_Block_In(iDevice%, iGroup%, piBuffer%(0), ulCount&)
    iRetVal% = NIDAQErrorHandler(iStatus%, "DIG_Block_In", iIgnoreWarning%)

// read code
    iStatus% = DIG_DB_Transfer(iDevice%, iGroup%, piHalfBuffer%(0), ulPtsTfr&)
    iRetVal% = NIDAQErrorHandler(iStatus%, "DIG_DB_Transfer", iIgnoreWarning%)

The basics of it is that the VB6 program asks for a buffer of data from the DIO card which is connected to an FPGA board which has stored time tags on it. Once it gets the buffer back then it parses it.

Alright, so someone gave me some example code before for digital reads in DAQmx. I'm in the process of going through it and customizing it to what I want. Here's what I have so far.

myDigitalTask = new Task("diTask");
myDigitalTask.DIChannels.CreateChannel(cbPhysicalChannel.Text,"",ChannelLineGrouping.OneChannelForAllLines);
myDigitalTask.Control(TaskAction.Verify);
myDigitalReader = new DigitalSingleChannelReader(myDigitalTask.Stream);
myDigitalReader.SynchronizingObject = this;
myDigitalAsyncCallback = new AsyncCallback(DigitalReaderCallback);
//myDigitalReader.BeginReadMultiSamplePortByte(numberOfSamples,myDigitalAsyncCallback,null);
myDigitalReader.BeginReadMultiSamplePortInt32(numberOfSamples,myDigitalAsyncCallback,null);

I create my tasks and channel, create a channel reader, assign a callback, now the example code originally used a byte read, but I got an error that there was 32 bit data there and I needed to use the Int32 method. So I've tried that. So I've made my callback and it does this:

int[] digitalData = myDigitalReader.EndReadMultiSamplePortInt32(ar);
// parsing stuff
myDigitalReader.BeginReadMultiSamplePortInt32(numberOfSamples,myDigitalAsyncCallback,null);

So as far as I can tell, what I've done seems correct, set up the channel, write my callback, start a read, parse the data in the callback and start another read. Couple of questions, the VB6 code never set a port it got set with some legacy code, do I have to worry about this? Secondly, there was no mention of lines (ie. /port0/line0) in the VB6 code, what do I do in the DAQmx with lines? (this is in my CreateChannel call)

Thanks for anyone that might be able to try and help me. Sorry that my explanation is a little lacking, I haven't done any traditional legacy driver programming before and I'm just getting into the DAQmx programming, so that's why I am appealing for help. If you need more info, or don't understand my question by all means ask. What I'm trying to do is port the traditional daq code to DAQmx calls in C#.NET.

Chris

0 Kudos
Message 1 of 5
(3,891 Views)
Hello ChrisErven,

Your first question: "The VB6 code never set a port it got set with some legacy code, do I have to worry about this?"

You are setting the port and lines to be sampled from within the
' myDigitalTask.DIChannels.CreateChannel(...)' method.  The first argument to that function, called 'lines', is a string that contains the physical device number, port, and line information for your task.  A digital I/O task can treat a whole port as one virtual channel or the task can be set to treat each line of a port as an individual channel.  The 'OneChannelForAllLines' argument is telling your task to treat the whole port as a virtual channel, and all you need to supply is a port number.  For a task to access each line individually you would use 'OneChannelForEachLine', and you will then need to supply port and line information for the task.  The standard syntax for DAQmx physical digital channels is "DevX\portX\lineX", where the X's are the numbers of the device, port, and line you want to access.  When using 'OneChannelForAllLines', simply exclude the "\lineX" part of the channel name. From the looks of your C# example code, it looks like the program is getting the device, port, and line information from a combo box on your main form titled 'cbPhysicalChannel'.  You can have a combo box on your form automatically populate with a list of appropriate channels (similar to how drop down boxes for physical channels work in MAX and LabVIEW) by including something similar to the following code in your MainForm section of code:

    DigitalPhysicalChannel.Items.AddRange(DaqSystem.Local.GetPhysicalChannels(PhysicalChannelTypes.DILine, PhysicalChannelAccess.External));
    if (DigitalPhysicalChannel.Items.Count > 0)
    DigitalPhysicalChannel.SelectedIndex = 0;

This method is used all throughout the example programs to have the combo boxes automatically populate with the appropriate channel names, so take a look at other example programs to see how this is done.  Finally, I would recommend checking out the example programs on our online database (www.ni.com/examples) for some more guidance on programming DAQmx programs in .NET.  I hope this information helps!

Regards,
Travis Gorkin
Applications Engineering
National Instruments
www.ni.com/support
0 Kudos
Message 2 of 5
(3,856 Views)
Hi Travis,

Thanks for taking a shot at it. I'm still confused, but have a better idea of what's going on now. I've got all the stuff with setting up a channel and assigning a port to it in DAQmx. But I think I need to setup up more configuration properties in DAQmx before I read.  I'm comparing the data generated from the card with the VB6 code to the .NET code, what I'm using is the fact that every second returned data entry should be a channel number either 1 or 2 (ie data[1] = 1, data[3] = 2), so I went as far as looking at each individual line from a particular port and trying to find two lines that alternate synchronously, ie. 01 and 10 to generate the 0 and 1. Hopefully you understand what I mean, basically the FPGA alternates which channel it looks at and records the current channel after the timestamp. Anyways, I couldn't even find that pattern. What I think is my problem now is the VB6 code sets up a couple of things, one is double buffer pattern generation. Now I've found one of the NI examples which does this under NI-DAQ\Examples\VisualC\Di\DIdoubleBufPatternGen653x.c. This program makes the same calls as the VB6 program that I have to the traditional daq functions. This is the function that sets the pattern generation:
    iStatus% = DIG_Block_PG_Config(iDevice%, iGroup%, 1, 1, -3, 2, 0)
Now I really don't know what this does, but I think it's important in how the data is read.

The next thing I need to know is the equivalent of this call:
    iStatus% = DIG_DB_Transfer(iDevice%, iGroup%, piHalfBuffer%(0), ulPtsTfr&)
Because I don't think the
    myDigitalTask.DIChannels.CreateChannel("/Dev2/port0","",ChannelLineGrouping.OneChannelForAllLines);
    myDigitalReader.BeginReadMultiSamplePortInt32(numberOfSamples,myDigitalAsyncCallback,null);
    int[] digitalData = myDigitalReader.EndReadMultiSamplePortInt32(ar);
calls do the same thing.

Anybody have any ideas? Anyone know how to find the guy who wrote the
NI-DAQ\Examples\VisualC\Di\DIdoubleBufPatternGen653x.c example and ask him how to update it to DAQmx?

Thanks,
Chris
0 Kudos
Message 3 of 5
(3,851 Views)
Hi,

Further on my problem. I've modified my old VB6 code to do port reads with this function
    iStatus% = DIG_In_Prt(iDevice%, iPort%, iPattern&)
And it gives me closer to what the DAQmx port reads are giving me. So this leads me to suspect that the function
    iStatus% = DIG_DB_Transfer(iDevice%, iGroup%, piHalfBuffer%(0), ulPtsTfr&)
does something fundamentally different then a port read. I need to know what this function does and how I can duplicate it's behaviour in DAQmx.

Thanks,
Chris
0 Kudos
Message 4 of 5
(3,851 Views)

Hi Chris,

The DAQmx driver automatically performs the double buffering for continuous digital input operations. Therefore, there is no extra programming/functions needed for this operation. You will only need a continuous digital input application.

I found a continuous digital input example configured for an external clock. Here is the link: C:\Program Files\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Digital\Read Values\Cont Read Dig Chan-Ext Clk. You will have to make some modifications which are documented in the NI-DAQmx C API Visual Basic 6.0 Help which is located in Start >> All Programs >> National Instruments >> NI-DAQ.

Here is the link to a tutorial which has some useful information about the DAQmx driver: Answers to Frequently Asked Questions about NI-DAQmx and Traditional NI-DAQ (Legacy). I hope that you find this information helpful.

Regards,

Hal L.

0 Kudos
Message 5 of 5
(3,820 Views)