Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Hardware Timed Interrupt

Solved!
Go to solution

Hi Michael,

 

It makes sense only to store and read only 1 sample, containing your count, in order to avoid filling up the buffer with the samples that you don't even need.

I am glad we were finally able to get to the bottom of this. Feel free to post on the forums if you have any additional questions and good luck with your project!

 

Regards,

Mikhail
RF Toolkits, Product Support Engineer
National Instruments
0 Kudos
Message 31 of 39
(3,965 Views)
Solution
Accepted by topic author DieselPower

Here is the code for anyone else that needs it.  It will require some modifications to work in your software.

 

    Public Sub CreateTimerTasks()
        ' ***********************************************************************************
        ' Subroutine:   CreateTimerTasks
        ' Parameters:   None
        ' Author:       Michael Chadwell
        ' Date:         03/28/13
        ' Version:      6.1.7
        ' Tested:       03/28/13
        ' Notes:        This subroutine configures a counter and a clock to run a hardware
        '               timed Interrupt Service Routine (ISR)
        ' ***********************************************************************************
        Try
            ' This code creates a task to call a function on the rising edge of an input clock.
            With DCChannels(ptrLoopTimer.Value)
                counterReadTask = New Task()

                ' .Device is a variable which holds a NI device identifier like Dev1
                ' .Channel is a variable which holds a NI channel identifier like ctr0
                ' Note that PFI8 is the CTR0 Source pin for many E-series devices
                counterReadTask.CIChannels.CreateCountEdgesChannel(.Device & "/" & .Channel, "Input", _
                        edgeType, 0, countDirection)

                ' The 10 in this statement is the desired frequency of your ISR
                counterReadTask.Timing.ConfigureSampleClock("/" & .Device & "/PFI8", _
                        10, SampleClockActiveEdge.Rising, _
                        SampleQuantityMode.ContinuousSamples, 1)

                runningCTRTask = counterReadTask
                myCounterReader = New CounterReader(counterReadTask.Stream)

                ' CounterReadCallback is the ISR
                myCallBack = New AsyncCallback(AddressOf CounterReadCallback)

                myCounterReader.SynchronizeCallbacks = True

                myCounterReader.BeginReadSingleSampleInt32(myCallBack, counterReadTask)
            End With
            ' This code creates the clock that the other counter will count.  You do not need this 
            ' clock if you use some other clock source, but for my case it was convient to use 
            ' two counter/timers from one DAQ card.
            With DCChannels(ptrLoopClock.Value)

                counterWriteTask = New Task

                ' The 10 in this statement is the frequency of the clock
                counterWriteTask.COChannels.CreatePulseChannelFrequency(.Device & "/" & .Channel, _
                    "Output", COPulseFrequencyUnits.Hertz, COPulseIdleState.Low, 0.0, _
                    10, 0.5)

                counterWriteTask.Timing.ConfigureImplicit(SampleQuantityMode.ContinuousSamples, 1)

                counterWriteTask.Start()
            End With
        Catch exception As DaqException
            counterReadTask.Dispose()
            runningTask = Nothing
            LoopTimerFrequency = 8
' Fall back to a software timer on error. Dim timerDelegate As TimerCallback = AddressOf ControlCode TenHzLoopTimer = New System.Threading.Timer(timerDelegate, inProcess, 0, 125) End Try End Sub

 

    Public Sub CounterReadCallback(ByVal ar As IAsyncResult)
        ' ***********************************************************************************
        ' Subroutine:   CounterReadCallback
        ' Parameters:   ByVal ar As IAsyncResult
        ' Author:       Michael Chadwell
        ' Date:         03/28/13
        ' Version:      6.1.7
        ' Tested:       03/28/13
        ' Notes:        This callback function is called on the rising edge of an input clock.
        '               It then calls the function that you want to run as a "hardware-timed" 
        '               loop.
        ' ***********************************************************************************
        Try
            If runningCTRTask Is ar.AsyncState Then
                HWTimerData = myCounterReader.EndReadSingleSampleInt32(ar)
                myCounterReader.BeginReadSingleSampleInt32(myCallBack, counterReadTask)

                ' Control code is the 10 Hz process that I want to run.
                ControlThread = New Thread(AddressOf ControlCode)
                ControlThread.Priority = ThreadPriority.AboveNormal
                ControlThread.Start()
            End If
        Catch exception As DaqException
            counterReadTask.Dispose()
            runningTask = Nothing
' Fall back to a software timer on an error Dim timerDelegate As TimerCallback = AddressOf ControlCode
LoopTimerFrequency = 8 TenHzLoopTimer = New System.Threading.Timer(timerDelegate, inProcess, 0, 125) End Try End Sub

 

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 32 of 39
(3,963 Views)

Thanks for contributing!

Mikhail
RF Toolkits, Product Support Engineer
National Instruments
0 Kudos
Message 33 of 39
(3,958 Views)

I hope you guys respond to updates on old threads...

 

I am having trouble with the timing using this method.  If you'll recall, I have a 10 Hz loop and a 1 Hz loop.  Throughout this thread I was only trying to get the 10 Hz loop on a hardware timer.  Recently I wanted to synchronize them, so I got rid of the software timer with 1000 ms period and added a loop counter to my 10 Hz loop (which is fired by the hardware timer).  When the loop counter = 0 (can be 0-9 before resetting to 0), I call my 1 Hz code as a thread.  I though it would be as easy as that, but I was wrong.  It appears as though this method is losing time.  If I run a cycle long enough, I notice it because the period is actually 1000.07 ms.

 

If my hardware timer is running at exactly 10 Hz, and every zeroth iteration (of 10) is calling some code that takes less than 1000 ms to complete, how am I losing time?  Even if there is a delay in windows responding to the callback, it should still be called once per second.

 

I hope this explanation makes sense.

 

Thank you.

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 34 of 39
(3,891 Views)

There could be a number of reasons.  Just because a while loop is set to run every second, does not mean that it will run once every second.  There could be another process finishing up before the resource is released for the while loop to tick.  This could be why you are seeing that 0.07 ms difference.  If you require something to be this specific, you might want to go to a Real-Time or FPGA solution.

Jesse S.
Applications Engineer
National Instruments
0 Kudos
Message 35 of 39
(3,881 Views)

Would you agree that the hardware timer set for 10 Hz will be 10.0000000 Hz?  If so, the hardware timer is calling the procedure every tenth iteration.  If that is the case, and as long as the procedure takes less than 1000 ms, then the procedure should keep time.  The ACTUAL time that the procedure occurs will dither, but the overall period should average around 1.000000 Hz, correct?

 

Worded differently, if a hardware timer that is the golden standard is calling a procedure, why would the frequency of the procedure call be something other than 1 Hz?

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 36 of 39
(3,876 Views)

Hi Michael,

 

Windows doesn't have the determinism available that is possible on a Real-Time or FPGA system. Even if the 1 Hz loop is given priority with its own thread, there will be other processes in the background that Windows will deem a higher priority. The disparity between the set 1 Hz and the actual frequency is most likely due to the other processes that are being performed in the background.

 

Regards,

Jordan G. 

LabVIEW Product Marketing Engineer
National Instruments
0 Kudos
Message 37 of 39
(3,844 Views)

I think I must explain the architecture a little better.

 

I have an asyncronous callback function that is tied to a hardware timer coming from an NI board.  On every rising edge an interrupt is called which runs the code in my "loop."  Regardless of how busy windows is, 10 times per second this function is called.  The part of my code that runs 10x/s takes far less than 100ms to complete, so there is no trouble with it.  The part that runs 1x/s takes less than 1000 ms to run (less than 500 ms).  I am fully aware of the differences between Windows sharing/allocating resources and a dedicated real time system (I have a PXI system sitting in my office). 

 

My point is that this call back function is happening 10 times per second coming from a hardware timer that should be running at 10.000000 Hz.  My question is how is is possible to lose time?  How is it possible for the period to be greater than one second if the hardware timed loop is calling it and the hardware timed loop is in fact running at one second.  I may need to put a scope on the 10 Hz loop as well to see what its true period is, although my scope my not have enough resolution to capture such a tiny offset.

 

Perhaps I should create an output file with the timing for each 10 Hz iteration and the timing for each 1 Hz iteration. 

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 38 of 39
(3,830 Views)

Hi Michael,

 

Could you provide a little more information? Is the "lost time" you're seeing consistently .07 ms every second, or does the amount of time lost vary?

 

70 microseconds is a fairly small error, and my instinct is that it can be attributed to jitter. Are you still using the PCI-6173 that you mentioned earlier in the thread?

 

I would recommend that you go ahead and try generating that output report and that you post the results here. The more information we have, the more likely it is that we can give you a more concrete answer.

 

Regards,

Ryan K.
Product Manager, ATCA and BEEcube
National Instruments
0 Kudos
Message 39 of 39
(3,806 Views)