Showing results for 
Search instead for 
Did you mean: 

Creating TTL signal with variation duration for controlling spark plug, injector and high speed camera for an optical engine

1TTL signal_50ms.JPG

Positive TTL signal.JPG

Hi All,


I am a ph.d student studying mechanical engineering.


I am trying to create a code that can send out TTL signal to control spark plug, injector and high speed camera of my optical GDI engine to observe spray development and combustion event.


I used DAQ Assist to generate a code that can produce TTL signal but, at the moment, I do not have a control over the duration of TTL signal and the signal is not generated consistently.


I want to generate a signal for a every cycle (One signal for 2 complete pressure cycle) but it seems that sometimes it does send out a signal for every cycle and sometimes it sends out a signal for every half cycle (1 complete pressure cycle).


I am using a LabVIEW version 2018 with cDAQ-9178 module. NI-9401 card is used for digital input/output signals.


If somebody can help me to improve my code, I would be much appreciated.


Many Thanks,



0 Kudos
Message 1 of 13

Hello, Dongsu.


     I took the liberty of making some "style" changes to your program.  I removed the Frame Sequences (you almost never need/want them), straightened the wires, made some suggestions, created an Icon for you, and pointed out that you mis-used the Quotient/Remainder function.


     I saved this for LabVIEW 2018, which is what I think you are using.


Bob Schor

0 Kudos
Message 2 of 13

Hi, Bob.


First of all, many thanks for the comments.


However, I realized that I can only control 2 components due to the limitation on the number of port available on NI-9401 card.


I have created another code which responds to my commands e.g. I can vary timing, duration, etc of the TTL signal (Please ignore the pressure signal represented in the oscilloscope).





But, somehow I cannot detect the TTL signal in my oscilloscope although I can observe it in the LabVIEW. By using NI-MAX, I can confirm that my connection is good.




Do you have any ideas why this is happening?

0 Kudos
Message 3 of 13

A colleague of yours pointed me over to this thread.  I'd highly recommend you read through this thread we were in (and another it links to) because it seems like you're working on the same kind of app.



-Kevin P

0 Kudos
Message 4 of 13

Hi Kevin,


First of all, many thanks for the comments.


I have read through the conservation between you and my friend.


However, there are some differences which makes it difficult to use his code.


Unlike James, I need to control 3 components which are spark plug, injector and high speed camera.


Unfortunately, NI-9401 card only allow me to utilise 2 counter ports. Also, among its 8 ports, only line 4-7 are configured as output which means the available counter port is Ctr 1 & 3 (Ctr 0 is used for the encoder and Ctr 2 cannot be used as its port line is set for input).


Therefore, I hoped that the camera works in toggle on/off mode (in this, I do not need an extra counter to control the camera) but the camera engineer confirmed that it is not possible to do so.


Nevertheless, the code did not work for me which was very strange. To reiterate, I am using LabVIEW 2018 along with cDAQ-9178. My colleague is using the same LabVIEW version but he is using PCle-6351.


That is why I am reverting back to the original code. This code has been working well with other mates in the lab but they all used LabVIEW 2015 along with PCle-6351.


I am not sure the difference in the hardware (card) and the software (version) would cause such issues but, based on the observation so far, it seems likely.


I guess there are 2 options to consider.


1. Improve the new code (Jame's code) so that I can use 3 counters without clashing

2. Fix the old code


If you need more explanation, please do not hesitate to contact me. Anyway, let me try your code once again.


Kind regards,



0 Kudos
Message 5 of 13

1. You could probably use DAQmx Export Signal to route the output of a 3rd counter to one of the 9401's output lines instead of to the default line that's configured for DI.


2. The code you posted showed only a single DO task with a single output line, no sign of counters anywhere.


3. A 6351 will have some capabilities and flexibility you can't get from your cDAQ devices.  But so far, I'd still be expecting your cDAQ setup to be able to work.


4.  Unsure what's "old code", what's "new code", and what the specific intentions are.  So I can't really give much more advice, except to emphasize that timing control will *usually* be more straightforward with counter tasks than DO.



-Kevin P

0 Kudos
Message 6 of 13

Apologies for the confusion.


The "old code" refers to the code that my colleagues have been using. It is the one that James showed at the very beginning. I have uploaded again as "Integration". Based on the conversation between you and my friend, you are not keen on this code but I would like to ask one thing before moving on.


Somehow, I am getting such error message (1.png) whenever I add another set of loops to the original one. For my case, the original would mean the loop that controls the spark plug (bottom loop of "Integration"). This problem has occurred to my other lab mates (those who are using LabVIEW 2015 with PCle-6351) and they had to find another PC to execute the new loop on a separate desktop. Is this related to LabVIEW issue? Also, is there any way to use this "Integration" code to generate TTL signals to control 3 components that I mentioned. By the way, if this code is going to be used, I have to reduce the array size (more like resolution) for the camera from 0.1 crank angle degree to 1 crank angle degree as the camera is not powerful enough to cope with such a large amount of data.


Anyway, the "new code" refers to the code that you helped my friend to build it (one with the counter). I named it as "BMW_Optical". I tried to run the code again yesterday but it did not work. Please have a look at the attached PDF file. This summarises what happened when I made my first attempt to adopt the code. I was lucky enough to find "9401 Nibble Config" code from NI website and modified a bit to suit "BMW_Optical" code to resolve issues related to the port configuration (2.png shows the changes that I have made on 9401 code). However, when I tried the code yesterday for the second time with new channel allocation (please refer to the attached excel file), somehow I cannot override the port configuration issue with the modified 9401 code. To be honest, I am not sure why am I getting such error messages as I stick with the recommended port setting for NI-9401 card (line0:3=input & line4:7=output). Can you spot any mistake in the code?


I presume "9401 code" is the one (or similar) that is able to route the output of a 3rd counter (The 1st point that you made). Am I right?


I really appreciate your help.


Kind regards,



0 Kudos
Message 7 of 13

1. The -50103 resource conflict error is because you are trying to make 3 separate, simultaneous hw-timed DO tasks.  I have limited cDAQ knowledge, but I thought most (and maybe all) cDAQ chassis only have 1 timing engine available for DO tasks.  To use code that looks like this, you'd need to include all 3 DO lines in 1 single task.

   (Note: the same issue holds true for the 6351 device which will also have only 1 DO timing engine.)


2.  Seems like slowing down your camera frame rate by a factor of 10 only depends on the pattern you generate for that digital line -- just have it make a pulse 1/10 as often.


3. The -200122 error you get about lines being configured for input is probably a limitation of your cDAQ equipment.  Here, a 6351 would provide more flexibility.


4. You worked your way through some other errors (such as trying to access a port while MAX was still in control of it).  Then you got error -89126.  I'm unsure of the exact reason for that one, but suspect that it's again a cDAQ limitation you wouldn't get with a 6351.  Also, I didn't get it with the code I'll attach that I ran on a simulated 9178 with a simulated 9401, though the code I worked from was what you posted which only had the 2 counter tasks, without the digital output task shown in the pdf.


5. The -200797 error is likely because when error -89126 showed up on the upper counter, then the query for CO.Pulse.Term would have put out any empty string for the terminal.  Then that empty string was fed into the lower counter as the trigger source, leading to that error.  See the description here.


6. -200279 is an error related to data acquisition.  I didn't see that error in your screencaps and I didn't see any acquisition tasks, only output tasks.  Are you sure you got that error?  Where?


Attached below are a couple simple mods to your posted  Changes are noted with teal-colored comments.  It ran without error using simulated devices *until* I tried to change pulse specs on-the-fly.  That led to errors.  That might be another cDAQ limitation but I'm not 100% sure.  It might also be a more general limitation for single pulse tasks or perhaps specifically for retriggerable ones.



-Kevin P

0 Kudos
Message 8 of 13

P.S.   I later got a chance to try out my posted code on an X-series device (6341).  I changed the device aliases as needed while keeping the PFI #'s.  With the X-series device, I was able to update pulse specs on the fly without generating errors.  I'm quite sure you'd find the same to be true with a 6351.



-Kevin P

0 Kudos
Message 9 of 13

Hi Kevin,


Many thanks for the comments.


First of all, I only saw "Error-200279" once and it did not occur afterwards. That was why I was not able to capture it and post it in the PDF file. I guess it was a temporary issue.


Anyway, I have some questions regarding the updated "BMW_Optical" code. As you are aware, I intend to use PFI4 (Spark), PFI5 (Injection) and PFI6 (General_in for camera). However, from the code, it seems that you are using PFI4 as a reference port to explicitly set output terminals away from the inputs. I am not sure whether I understood your intention correctly but, if this is the case, does that mean I have to leave PFI4 as a blank and reallocate the ports e.g. PFI5 (Spark), PFI6 (Injection) and PFI7 (General_in for camera).


I tried to modify the code based on the fact that I can only use 1 timing engine for DO tasks so that I can control all 3 components independently but it does not look right. I am sorry that I was not able to update the counter and port as the LabVIEW card was not connected to my laptop. "BMW_Optical_V2" is the initial stage of expanding the code and "BMW_Optical_V3" is the one that reflected the fact that only 1 timing engine is available for DO tasks.


Finally, as the code is running based on counter i.e. absolute timing basis, I am wondering whether there is a way to make it work under CAD (Crank Angle Degree) basis for the camera. This is due to fact that it is necessary to relate the image in terms of CAD rather than timing. To clarify, it would be better to control the duration in terms of CAD rather than timing (second) for the camera. I am absolutely fine with the duration of spark plug and injector being controlled by a timing basis.


Kind regards,



0 Kudos
Message 10 of 13