03-25-2013 12:56 PM - edited 03-25-2013 12:56 PM
Thank you for that explanation. I thought that everything was going on in hardware until the counter reached the number of counts I requested in which case it would fire off a message through the PCI bus. This information certainly helps me to understand what is going on, though it spurs a few questions... Please note I am programming in VB.NET.
1. What determines the sample clock rate? The hardware model?
2. What interrupt causes the callback function to execute? The function should execute upon reaching the number of counts requested (i. e. X counts). Does this mean that all of the values in the buffer need to add up to X counts? Can the sum possibly be slightly more due to the sample clock rate and extra counts in between the sample clock?
3. What clears the buffer? Entering the callback method?
My program is set up for "real time," and the processor usage runs mostly in the < 10% range.
03-25-2013 01:38 PM
Hi Michael,
To monitor the number of available samples in the buffer in VB.NET you can use the following property:
| Visual Basic (Declaration) |
|---|
Public ReadOnly Property AvailableSamplesPerChannel As Long |
Let me address your questions.
1. What determines the sample clock rate? The hardware model?
You set the sample clock rate using ConfigureSampleClock function.The sample clock source determines when a sample will be inserted into the buffer. The edge parameter can be used to determine when a sample is taken.
2. What interrupt causes the callback function to execute? The function should execute upon reaching the number of counts requested (i. e. X counts). Does this mean that all of the values in the buffer need to add up to X counts? Can the sum possibly be slightly more due to the sample clock rate and extra counts in between the sample clock?
For continuous measurements, the counter will continually read new data every time the set number of samples (which you have specified in counterReadTask.Timing.ConfigureSampleClock) becomes available in the buffer.
3. What clears the buffer? Entering the callback method?
Calling Task.Dispose method stops the task and de-allocate any resources used by the task
Also, I attaching a standard VB.NET shipping example which demostrates how to count buffered digital events on a Counter Input channel (CountDigEventsBuffContinuous_ExtClk).
03-25-2013 02:01 PM - edited 03-25-2013 02:04 PM
We're getting closer.
1. So would there be any repercussions if the sample clock is running at the same rate and the clock that is being read? In the graphic you pasted above, the sample clock was running slower. From the ObjectBrowser: "rate: The sampling rate in samples per second. If you use an external source for the sample clock, set this input to the maximum expected rate of that clock." I am not running an external clock, and it doesn't give any recommendations for rate. I want the best resolution possible so that I can be as near to 10 Hz in my loop as possible.
2. Again from the sample above, a value is placed in the buffer each time the sample clock rises. The callback function does not fire until the counter has counted X samples, however, so what does the buffer actually look like? For example, if my sample clock is 1/10th the rate of my input clock, then I would have numbers of 10,20,30,40,50.... presumably until the total value meets or exceeds 200. Conversely, if my sample clock is 10X faster, I'd have values like 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2..... Correct?
3. How are these numbers never removed from the buffer under normal continuous operation? Wouldn't I eventually run out of space if I ran this process for 24 hours without stopping? I would think that the buffer would be cleared when X pulses were counted.
I am going to run this example because is looks a little newer than the one I used to create the code I'm trying to use. I'll also output the "data" that I poll from the EndMemoryOptimizedReadMultiSampleDouble call so I can see just what it looks like. I guess I should expect the number 200.
03-26-2013 06:40 PM - edited 03-26-2013 06:41 PM
Hi Michael,
1. So would there be any repercussions if the sample clock is running at the same rate and the clock that is being read? In the graphic you pasted above, the sample clock was running slower. From the ObjectBrowser: "rate: The sampling rate in samples per second. If you use an external source for the sample clock, set this input to the maximum expected rate of that clock." I am not running an external clock, and it doesn't give any recommendations for rate. I want the best resolution possible so that I can be as near to 10 Hz in my loop as possible.
If your sample clock is running at the same rate as the clock that is being read and they are both perfectly phase aligned (i.e. rising edges occur at the same time) then no count would be registered. However if they are not phase aligned a count will be registered for every transition of the clock that is being read. Now if you are using the counter to count the edges an external sample clock must be used. Counters do not have an internal sample clock available. You can use the GenDigPulseTrain_Continuous example to generate a pulse train on another counter and connect it to the sample clock source that you use in your code. When you use ConfigureSampleClock within counter task you have to specify the external clock source.
ConfigureSampleClock(
"/Dev1/PFI8", // external clock source line or use "" for internal clock
10000, // expected rate of external clock
SampleClockActiveEdge.Rising, // acquire on rising or falling edge of ticks
SampleQuantityMode.ContinuousSamples, // continuous or finite samples
1000 // number of finite samples to acquire or used for buffer size if continuous
);
2. Again from the sample above, a value is placed in the buffer each time the sample clock rises. The callback function does not fire until the counter has counted X samples, however, so what does the buffer actually look like? For example, if my sample clock is 1/10th the rate of my input clock, then I would have numbers of 10,20,30,40,50.... presumably until the total value meets or exceeds 200. Conversely, if my sample clock is 10X faster, I'd have values like 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2..... Correct?
Yes. That is correct.
3. How are these numbers never removed from the buffer under normal continuous operation? Wouldn't I eventually run out of space if I ran this process for 24 hours without stopping? I would think that the buffer would be cleared when X pulses were counted.
Each time you read the samples with a callback function, it pulls those samples out of the buffer to make room for new samples to come in. For example, if you are not reading your samples fast enough, the samples in the buffer will accumulate. Now if you were in that situation, and you choose to cut off your edge count source (i.e. clock that is being read) your code would still keep running as it would be still unloading the unread samples from the buffer. It will stop once it has read all the samples in the buffer and since there is not edge count source to put edge count on the buffer your code will time out.
Let me know if you have any further questions.
03-26-2013 09:00 PM
Regarding #1, if you refer to the code I pasted, I am using one counter/timer channel to output a 2 kHz clock and the other to count 200 pulses. Everything works, though I get a random error where the buffer is overrun. What would a good sample rate be in order to read this 2 kHz signal and not overrun my buffer while maintaining good resolution?
How many pins should I need on a counter in order to do this? It is clear that one counter needs a wire coming out of CTRX Out, and the other needs a wire going into CTRY Source. Does the sample clock ALSO need to come from somewhere else?
My clock is coming from CTR0 and my input counter is CTR1. Now I am curious as to what is the sample clock. PFI8 is CTR0 source. Does that mean that my input is also my sample clock???
Do I need to create two different clocks to do what I am going?
I need to generate a clock and then count 1/10th of its pulses per second to have a 10Hz hardware timed interrupt (loop). What should I use for my sample clock?
This is my read task:
counterReadTask = New Task()
counterReadTask.CIChannels.CreateCountEdgesChannel(.Device & "/" & .Channel, "Input", _
edgeType, 0, countDirection)
counterReadTask.Timing.ConfigureSampleClock("/" & .Device & "/PFI8", _
2000, SampleClockActiveEdge.Rising, _
SampleQuantityMode.ContinuousSamples, 200)
03-27-2013 10:58 AM
I'm learning a little more by playing with this.
1. My input clock is the same signal as my sample clock. It is counting, though this could be the source of my problem.
2. I set my task up to read 2000 samples thinking that samples meant counts. I was always confused about this number vs. the actual call to start reading X counts. I really only want to read 1 sample at the sample rate I select.
So now my question is:
Is it possible to do what I am doing with one device that has two counters by using any internal clock or do I need three individual clocks? My explicit rates below don't really matter. I need to count 1/10th of the pulses per second from the first pulse train, regardless of the rate within the limits of the board.
I need a pulse train at 20 kHz (CTR1 Out)\
I need a pulse train at 100 Hz for my sample clock. (______ into CTR0 Gate)
I need to count the 20 kHz pulse train (CTR0 Source)
I'm currently using a function generator for ______ in my office and it is working as expected.
Does this mean I need a third counter to generate the sample clock?
03-27-2013 04:05 PM - edited 03-27-2013 04:26 PM
The latest revelation in my quest to figure this out:
When I select CTR0 as my count edges channel and set the sample clock to PFI8 (CTR0 Source) it works, though that is how I have been doing it.
When I select CTR0 as my count edges channel and set the sample clock to PFI9 (CTR0 Gate), it counts the pulses on CTR0 Gate.
Does this mean that I do not need to provide a sample clock pulse?
Here is a graphic of my wiring diagram..
03-27-2013 04:27 PM - edited 03-27-2013 04:28 PM
03-28-2013 08:28 AM - edited 03-28-2013 08:35 AM
Hi Michael,
Let me address your question.
Is it possible to do what I am doing with one device that has two counters by using any internal clock or do I need three individual clocks?
You don't need three individual clocks.
For simple edge counting you do not need to use the gate terminal of CTR0. The gate is used to control when the counting occurs. In other words, the gate is an input signal that decides if an active edge on the source will change the count. Counting can occur when the gate is high, low, or between various combinations of rising and falling edges. Gate settings are made in software. The gate is similar to a line mask in digital I/O, because it allows you to either acknowledge or ignore active edges on the source.
If you use the CTR0 gate as a sample clock source, however there is no clock signal wired into it your program will not work. However, if you do have a clock signal coming into CTR0 gate then it will be used as a sample clock as CTR0 Gate is like any other PFI line which can be used to import an external clock.
Now, you do need a sample clock as it determines when a sample (i.e. number of edges counted) should be inserted into the buffer. The faster is the rate of this sample clock, the faster the samples are inserted in the buffer. If you sample rate is too high and you don't read the samples fast enough from your buffer you will run into buffer overflow errors.
Now, you have several options of what to use for your sample clock. You can use:
- an external 3rd party clock fed into one of the PFI lines
- you source signal as the sample clock
- analog clock if available on your device.
I ran couple of tests on my end and I had no problems with counting edges generated by CTR1 on CTR0. I ran tests in LabVIEW since it was easier to setup for me, however the same tests can be easily setup in VB.NET.
Test #1: CTR1 generates 20KHz pulse train on PFI13 (CTR1 out) and CTR0 counts the edges of the pulse train and also uses the same pulse train as the sample clock source.
Test #2: CTR1 generates 20KHz pulse train on PFI13 (CTR1 out) and CTR0 counts the edges of the pulse train, however this time Analog Input Sample clock is used as a the sample clock source. For this clock to be active you need to have a "dummy" analog input task running in parallel with CTR0 edge counting code. To create dummy analog input I simply used MAX test panels.
Hopefully this explains the role of the sample clock in the buffered edge counting task.
Let me know if you have any further questions.
03-28-2013 09:07 AM - edited 03-28-2013 09:14 AM
OK. So Test 1 is the way I have been doing this at the cell. The problem is that it runs for a while working perfectly and then overruns the buffer. I have been struggling to figure out how to minimize the load on the buffer. I've tried manually increasing the size of the buffer and also reducing the clock frequency and value to count.
My original clock frequency was 20 kHz and I was counting 2000 pulses for an interrupt. I cut both by a factor of 10 and the program ran longer before overruning the buffer. I don't want to slow it down too much because I'll lose resolution. Now I've cut it to 1 kHz and 100 samples on my development machine.
One thing I noticed is that I get 100 "samples" on this statement: data = myCounterReader.EndReadMultiSampleDouble(ar)
but when I tried myCounterReader.BeginReadSingleSampleInt32 it doesn't ask for a number of samples.
I guess this means that I have to get an array with X values in it where X is the number of counts I want. These values are stored in a buffer until I call that statement in which case the buffer is cleared. So now I'm getting a buffer overrun on a buffer I don't even want. All I want is for the DAQ card to fire an interrupt when it counts pulses over a period that is 100ms. I don't want an array of the counts because I'm going to dump them anyway. I've done this many times in college using a microcontroller to demonstrate ISRs as a better alternative to software based timer loops. If I am forced to do it this way then I must figure out how to stop the buffer overrun. Should I make my buffer size 25X the number of samples that I want? I will try this today.
Actually, would it be possible to set my clock at 10 Hz and then try the single sample so that it fires on a rising pulse and returns only the count? Oh I think I just figured it out. I changed to readsingle sample on a 10Hz loop and it is working. Now I just need to put it to the test in the cell, but I think this is a much better way anyway. I know it will always fire at exactly 10Hz and I think I've just solved my problem!!!!
Thank you so much for your persistence in this matter.