LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Counting multichannel TTL pulses with PCI-6250

Hi,

 

I need to count randomly generated pulses with pulse lengths of 1.2 micro seconds at 9 input channels. The pulses are created by a Asynchronous Multivibrator.

 

I am using ANSI C NI-DAQmx library.

 

What is the best way to implement a simple code to count them?

 

Thanks!

 

0 Kudos
Message 1 of 9
(4,706 Views)

Hey dudenukem (nice name!),

 

With your hardware it is going to be tricky. The PCI-6250 seems to have many digital inputs and 2 counters (according to page 9 of its Data Sheet).

 

Normally I'd let the hardware do the job using the counters. There, the only thing you need to do is configuring the counter task on your PCI-6250 and then read the current number or counted signals every now and then. Unfortunately, you want to read nine input channels but have only two counters available. So you need a solution for the other seven channels.

 

This can maybe done manually. Is your pulse with of at least 1.2 µs guaranteed? Reading every channel with sampling rate of e.g. 1 MHz should be enough to catch all pulses (Do you know how they look like? Are they square waves? Or more like washed out square waves, looking more like sine waves?). You'd still let the hardware do all the sampling, but then you stream the data of all 7 channels to a piece of software and does some processing to detect the pulses. Keep in mind that conventional PCI is limited to a data rate of 133 MB/s in total, this might become a bottleneck with your streaming. Same for your C program having to process 7 million samples per second.

 

 

About the programming itself: The structure for both tasks is the same: Configure the hardware task, start it, read the input repeatedly, stop the task, delete the task.

You can find good examples here:


Ingo – LabVIEW 2013, 2014, 2015, 2016, 2017, 2018, NXG 2.0, 2.1, 3.0
CLADMSD
0 Kudos
Message 2 of 9
(4,680 Views)

Hi

> Hey dudenukem (nice name!),

thanks it was my nickname then my education and of course the time when we were playing Duke Nukem 🙂

 

I tried measuremeents with the voltage channesls but the speed of the ADC and the Multiplexer is just not enough for me (for 9 channels I can have a max of about 700 000 S/s).

 

I decided to carry out a one digital channel read and do like 1.25 Mega reads / sec, but I still miss samples (I used a signal generator to check my measurements). The last resort was to set up a Digital Input and use the Port 0/line0:8 and one counter.

I am using DAQmxCfgChangeDetectionTiming() reading it every 10 miliseconds (my max counting rate is about 1000 S/s) and then parse the data.

The counter has the drawback that I need to restart the task in order to reset it (I need a real time indefinite time logging).

 

Now before to finalise my code, I need to know what happenes if two pulses come at the same time at the port 0? What is the behaviour of the DAQmxCfgChangeDetectionTiming in this case? accoring to the definition, it will create two samples in the buffer?

 

e.g.: is we have at P0

1100 0000

 

and the two pulses at P0.1 and P0.0 are separated by more than the time resolution, we will count them twice? If their temporal separation is less than the time resolution then they will generate 1 sample  and I am perfectly alright...what when I have more samples like this? I need to know how DAQmxCfgChangeDetectionTiming behaves. I did tests with a signal generator, and 1 of my random pulse real signals, and there was no correlation between the result (counts per minute).

 

Now I am measuring only one channel with my real signal ... it owrks nice ... but the number of events per minute is always even :). So I need to know again whats going on.

 

Thanks again for your help!

 

0 Kudos
Message 3 of 9
(4,671 Views)

If you want to count TTL pulses, why not use TTL logic?

E.G. a cascaded pair of 74HC590's for each channel. Being tri-state they can go onto a single input bus, and you use a pair of outputs for each channel to read enable & reset each channel. You then have low speed data to go into your data acquisition system.

 

You might have some luck with PLDs / FPGAs but most of them expect synchronous clocked inputs, and so rigorous design to avoid race conditions becomes necessary.

 

 

Message 4 of 9
(4,649 Views)

Hello dudenukem,

 

I understand your problem, your requirements exceed your hardware's analog channels capabilities by far. (According to the data sheet) It supports 1MS/s aggregated, but you need around 9 MS/s. Therefore you are looking for other approaches.

 

SteveD's suggestion is a good one, moving the high-speed part of your acquisition into dedicated (and standard, cheap) hardware.

 


 I decided to carry out a one digital channel read and do like 1.25 Mega reads / sec, but I still miss samples (I used a signal generator to check my measurements).

Do you have an explanation for this? Is this because of the acquisition itself, of due to the data transfer bottleneck of the PCI bus? If the latter, then only using counters or a solution like SteveD suggested will work around this.

 


The last resort was to set up a Digital Input and use the Port 0/line0:8 and one counter.

I am using DAQmxCfgChangeDetectionTiming() reading it every 10 miliseconds (my max counting rate is about 1000 S/s) and then parse the data.

The counter has the drawback that I need to restart the task in order to reset it (I need a real time indefinite time logging).

Now before to finalise my code, I need to know what happenes if two pulses come at the same time at the port 0? What is the behaviour of the DAQmxCfgChangeDetectionTiming in this case? accoring to the definition, it will create two samples in the buffer?

 

Just to clarify: You defined a DAQmxCfgChangeDetectionTiming task to detect changes on the nine input channels/lines you are interested in. You so-to-say misuse this function as a counter. You then read the value of this counter at roughly 1 kHz to get the number of changes that happened to your input lines within each 1 ms. Is this correct?

 

Sounds like a good approach, except for the caveat that you already mentioned: I understand the documentation on the function the same way as you do: It does detect changes on the total defined input, not per line. That is, a change from 0000 to 1111 (within one clock cycle) is counted as one, not as four changes. However, I don't know how small the time differences between individual lines flipping actually can be to have them detected as two individual events. Do you have the capability to test this?


Ingo – LabVIEW 2013, 2014, 2015, 2016, 2017, 2018, NXG 2.0, 2.1, 3.0
CLADMSD
0 Kudos
Message 5 of 9
(4,642 Views)

SteveD's suggestion is a good one, moving the high-speed part of your acquisition into dedicated (and standard, cheap) hardware.

 

Yes this is what I'll do - but I need a quick fix for now until I get the pieces and do the circuitry.


Just to clarify: You defined a DAQmxCfgChangeDetectionTiming task to detect changes on the nine input channels/lines you are interested in. You so-to-say misuse this function as a counter. You then read the value of this counter at roughly 1 kHz to get the number of changes that happened to your input lines within each 1 ms. Is this correct?

 

Yes - but on my card we can use only 8 lines for change detection because they are buffered - what it does is to read all lines we specify in the read function when there is a pulse on any of the lines in the change detection definition. It works quite well unless your pulses are overlapping - then you need to do some more parsing to get the correct results and probably to do a change detection on the falling edge.  Fortunately the pusle rate per minute I have is not that high so I Read the buffers and compile them to get the pulses per line.

 

 

The 9th line I read with on of the counters.

 

Sounds like a good approach, except for the caveat that you already mentioned: I understand the documentation on the function the same way as you do: It does detect changes on the total defined input, not per line. That is, a change from 0000 to 1111 (within one clock cycle) is counted as one, not as four changes. However, I don't know how small the time differences between individual lines flipping actually can be to have them detected as two individual events. Do you have the capability to test this?


yes 1111 will be counted as one, but when we parse the results (as we read all the lines) we can add the pulses to the corresponding line. Using threads makes this very easy. We should be careful in setting the Read Array sizes depending on the expected input signals.

 

Would be nice to have some more information about how chnagedetect function works but we might investigate it if we have at least two singal generators...that I don't have.

0 Kudos
Message 6 of 9
(4,640 Views)

Well there is a bit of a breakthrough.

 

Using DAQmxCfgChangeDetectionTiming(..) we can implement rather easy 8 input counter with my card.

 

Now the problem is:

DAQmxReadDigitalLines(...) always return EVEN number of samples.

 

The test I did is using a signal generator at 1.3 Hz in pulse mode sym 0.1 % at Port0/line5

The Read is executed every second:

 

DAQmxReadDigitalLines(d->taskHandle, -1 , 0 ,DAQmx_Val_GroupByChannel,
                     d->data,d->arraySizeInSamps,&d->sampsPerChanRead,&d->bytesPerSamp,NULL);

 

SamplesPerChannelRead: 4 bytesPerSample 1
samples: 0: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0
samples: 1: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0
samples: 2: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0
samples: 3: | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0

 

Whatever the settings and the configuration the sampsPerChanRead is always an even number.

 

 

 

0 Kudos
Message 7 of 9
(4,629 Views)

The solution is to set the DAQmxReadDigitalLines(...):

 

The default behaviour I have is that SamplesPerChannelRead is at least 4 and it is a multiple of 4 (as long as I could say).

 

Is it possible to alter this behaviour? Cos now I would have always +/-4 samples in the counts which is too EVEN :D.

 

 

0 Kudos
Message 8 of 9
(4,621 Views)

Hello dudenukem,

I do not fully understand from your last posting:

The solution is to set the DAQmxReadDigitalLines(...): 


What exactly are you setting?

 

 

Regarding the function it self, using this call:

DAQmxReadDigitalLines(d->taskHandle, -1 , 0 ,DAQmx_Val_GroupByChannel,
                     d->data,d->arraySizeInSamps,&d->sampsPerChanRead,&d->bytesPerSamp,NULL);

It should return all samples currently available for that continuous task, limited to the size of paramter arraySizeInBytes, which is d->arraySizeInSamps in your case. What is it in your case?

 

However, I do not understand why you get multiples of four every time. Maybe this is due to the timing you have in your application?

 

 


Ingo – LabVIEW 2013, 2014, 2015, 2016, 2017, 2018, NXG 2.0, 2.1, 3.0
CLADMSD
0 Kudos
Message 9 of 9
(4,563 Views)