10-21-2014 09:26 AM
I am trying to create an edge counter by directly calling the functions in nicaiu.dll from VB.NET. I am able to read the counter value OK but the counts always return back to the original value set when I created the channel. For example, I create the counter task using DAQmxCreateCICountEdgesChan and set the initial count to 100000. I then read the counter using DAQmxReadCounterScalarU32. The count changes when I turn the encoder wired to the counter channel but returns to 100000 after the encoder stops moving.
The wiring is correct because this works correctly using the Counter I/O Test Panel in NI-MAX. The count increases as I turn the encoder and never resets when the encoder stops moving.
Eventually I will need to get this working using DAQmxCreateCILinEncoderChan but I'm seeing the same behavior when I use that channel type. For now, I'm using DAQmxCreateCICountEdgesChan since it is more straight-forward and mimics the function in the NI-MAX Test Panel.
I have made this work using the DAQmx .NET API. However, there are errors when my application runs on a computer with a different version of NI-DAQmx than what was used when the application was compiled. Calling the DLL directly seems to eliminate the problems with different DAQmx versions.
Any idea what I am missing?
Public Class Form1
Private Declare Function DAQmxCreateTask Lib "nicaiu.dll" (ByVal TaskName As String, ByRef NITaskHandle As IntPtr) As Integer
Private Declare Function DAQmxCreateCICountEdgesChan Lib "nicaiu.dll" (ByVal TaskHandle As IntPtr, ByVal PhysicalChannel As String, ByVal NameToAssignToChannel As String, ByVal Edge As Integer, ByVal InitialCount As UInteger, ByVal CountDirection As Integer) As Integer
Private Declare Function DAQmxReadCounterScalarU32 Lib "nicaiu.dll" (ByVal TaskHandle As IntPtr, ByVal Timeout As Double, ByRef ReadVal As UInteger, ByVal Reserved As IntPtr) As Integer
Private Const DAQmx_Val_Rising = 10280
Private Const DAQmx_Val_Falling = 10171
Private Const DAQmx_Val_CountUp = 10128
Private Const DAQmx_Val_CountDown = 10124
Private Const DAQmx_Val_ExtControlled = 10326
Private TaskHandle As IntPtr
Private Const STARTCOUNT = 100000
Private Const DEVICECHAN = "DEV1/CTR0"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ErrVal As Integer
ErrVal = DAQmxCreateTask("ENCODER", TaskHandle)
Debug.WriteLineIf(ErrVal <> 0, "Error " & ErrVal.ToString)
ErrVal = DAQmxCreateCICountEdgesChan(TaskHandle, DEVICECHAN, "ENCODER", DAQmx_Val_Rising, STARTCOUNT, DAQmx_Val_CountUp)
Debug.WriteLineIf(ErrVal <> 0, "Error " & ErrVal.ToString)
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim ErrVal As Integer
Dim InVal As UInteger
ErrVal = DAQmxReadCounterScalarU32(TaskHandle, 0, InVal, Nothing)
Debug.WriteLineIf(ErrVal <> 0, "Error " & ErrVal.ToString)
Label1.Text = InVal.ToString
End Sub
End Class
Solved! Go to Solution.
10-22-2014 06:20 PM
Hello chvogt,
I'm not very familiar with Visual Basic, but it sounds like Form1 might be loading multiple times. Have you tried debugging the code to see why this would happen? What is calling Form1_Load?
As for having errors with different versions of the DAQmx driver, there may have been some functions that were added or removed between the two versions that your application calls.
Have a nice day,
10-24-2014 07:28 AM
Hello Siana-
Thank you for your reply.
Form1_Load handles the event that occurs when Form1 is loaded. It is called once when the program starts. I verified it is only called once by adding a line in Form1_Load to write the current time to the IDE output window. Only one line is written.
I've attached a ZIP file with 2 screen videos to show what I am seeing. The TestPanel.mp4 video shows the counter behavior working correctly using a Test Panel in NI-MAX. I am turning the encoder connected to the counter and the counter increases while I am turning and stops when I am not. The MyEnc.mp4 video shows the results of my VB.NET program. The count changes as I turn the encoder but always returns back to the initial count of 100000 when I stop turning.
What would cause my counter to always return to the initial count when the input signal pulses stop? It almost looks like the counter is set to calculate the frequency of the input signal because the number gets higher the faster the encoder spins.
10-30-2014 03:31 PM
Try explicitly starting your task (DAQmxStartTask) after you create the counter channel. If you don't explicitly start your task, the read call starts the task instead, which would reset the count value.
As far as I'm aware though this should only happen once (on the first read call), so maybe there's something else going on.
Out of curiosity, have you considered using the DAQmx VB.NET API instead of the unmanaged C dll?
Best Regards,
10-31-2014 07:51 AM
John-
Thanks for the reply and the solution to my problem. Here is my code now with the new lines added:
Public Class Form1
Private Declare Function DAQmxCreateTask Lib "nicaiu.dll" (ByVal TaskName As String, ByRef NITaskHandle As IntPtr) As Integer
Private Declare Function DAQmxStartTask Lib "nicaiu.dll" (ByVal NITaskHandle As IntPtr) As Integer
Private Declare Function DAQmxCreateCICountEdgesChan Lib "nicaiu.dll" (ByVal TaskHandle As IntPtr, ByVal PhysicalChannel As String, ByVal NameToAssignToChannel As String, ByVal Edge As Integer, ByVal InitialCount As UInteger, ByVal CountDirection As Integer) As Integer
Private Declare Function DAQmxReadCounterScalarU32 Lib "nicaiu.dll" (ByVal TaskHandle As IntPtr, ByVal Timeout As Double, ByRef ReadVal As UInteger, ByVal Reserved As IntPtr) As Integer
Private Const DAQmx_Val_Rising = 10280
Private Const DAQmx_Val_Falling = 10171
Private Const DAQmx_Val_CountUp = 10128
Private Const DAQmx_Val_CountDown = 10124
Private Const DAQmx_Val_ExtControlled = 10326
Private TaskHandle As IntPtr
Private Const STARTCOUNT = 100000
Private Const DEVICECHAN = "DEV1/CTR0"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ErrVal As Integer
ErrVal = DAQmxCreateTask("ENCODER", TaskHandle)
Debug.WriteLineIf(ErrVal <> 0, "Error " & ErrVal.ToString)
ErrVal = DAQmxCreateCICountEdgesChan(TaskHandle, DEVICECHAN, "ENCODER", DAQmx_Val_Rising, STARTCOUNT, DAQmx_Val_CountUp)
Debug.WriteLineIf(ErrVal <> 0, "Error " & ErrVal.ToString)
ErrVal = DAQmxStartTask(TaskHandle) ' <======= ADDED THIS TO FIX
Debug.WriteLineIf(ErrVal <> 0, "Error " & ErrVal.ToString) ' <======= ADDED THIS TO FIX
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim ErrVal As Integer
Dim InVal As UInteger
ErrVal = DAQmxReadCounterScalarU32(TaskHandle, 0, InVal, Nothing)
Debug.WriteLineIf(ErrVal <> 0, "Error " & ErrVal.ToString)
Label1.Text = InVal.ToString
End Sub
End Class
Regaring the NI-DAQmx VB.NET API, I am currently using it for all my software but I've ran into some problems which is why I want to call the DLL directly. There may be solutions for these issues, but I haven't found them yet:
1. The API seems very dependent on the version of NI-DAQmx installed. I can't compile changes to my program on a computer with NI-DAQmx 9.5 and run it on a computer with version 9.2. Some of my software was developed several years ago with version 9.2 so our machine computer has NI-DAQmx 9.2 installed on it. However, my current desktop computer has version 9.5 so there will be a problem if I need to make changes to my software on my computer using 9.5 and send it to our customer who is using 9.2. I will either have to install version 9.2 on my computer while I make the changes or require our customer to install version 9.5. Neither of these options are desirable.
2. There are instances where I would like to run our software on a computer that doesn't have NI-DAQmx installed for demo purposes. This cannot be done if my software was developed using the API but can be handled if I am calling the DLL directly. Currently, I have to make a different version of my software with all of the NI-DAQmx references removed so it can run on a computer without the NI-DAQmx driver installed.
3. I would like to start using the NI-DAQmx Runtime installer instead of the full NI-DAQmx installer to reduce the size of the installer and simplify the installation process. The full NI-DAQmx driver is currently 1.6 GB versus 163 MB for the runtime version. The option for installing the VB.NET API that my software currently requires is buried under the custom installation option which makes the installation process a bit harder.
The old Traditional NI-DAQ driver (now called NI-DAQ Legacy) used to be called directly and my software did not have any of the issues listed above. My hope is that returning to directly calling the DLL will solve these problems for me.