Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Edge counting using nicaiu.dll

Solved!
Go to solution

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

 

0 Kudos
Message 1 of 5
(5,928 Views)

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,

0 Kudos
Message 2 of 5
(5,909 Views)

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.

 

 

0 Kudos
Message 3 of 5
(5,889 Views)
Solution
Accepted by chvogt

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,

John Passiak
Message 4 of 5
(5,804 Views)

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.

0 Kudos
Message 5 of 5
(5,787 Views)