It turns out that there was a typo in the Delphi Pascal 'header' file for the declaration of DAQmxCreateCOPulseChanTime that I inherited, resulting in the type of the 'units' parameter being wrong. Delphi had no way to know that a Double should have been an Integer. So the DLL function was being called with an invalid bit pattern - hence the message.
After correcting the declaration, the function now returns success. However, DAQmxWriteDigitalU32 is now failing with the message "Source terminal to be routed could not be found on the device" (despite not having any name arguments itself).
That suggests my signal/terminal naming is incorrect. To summarize what I am using at the moment:
Analog task channels: Dev1/AI0:3
Counter (in call to DAQmxCreateCOPulseChanTime): Dev1/ctr0
Trigger source for counter task (in call to DAQmxCfgDigEdgeStartTrig): /Dev1/ai/SampleClock
(The call to DAQmxSetDigLvlPauseTrigSource has been removed.)
Channels for digital task: Dev1/port0
Trigger source for digital (in call to DAQmxCfgSampClkTiming): /Dev1/Ctr0InternalOutput
Does anything jump out at you as obviously wrong? I'll continue to play around with permutations of the above.
Using an incorrect sample clock terminal for the digital output task (DAQmxCfgSampClkTiming) is all that I can think of which would result in the behavior you described (in your case, the task parameters are implicitly verified when you try to write to the output buffer making it look like the error is coming from the write itself). Could you verify that the source input to DAQmxCfgSampClkTiming is actually "/Dev1/Ctr0InternalOutput"?
I mentioned this in an earlier post, but in the initial example you posted you were using PChar(counter) for the digital output sample clock source as well as when creating the counter (but the counter task wants a different input: "Dev1/ctr0"). If this hasn't been corrected it would cause the behavior you are seeing now.
If you have an updated example I could take a look, but if the input to the sample clock source really is "/Dev1/Ctr0InternalOutput" then I'm not sure what else the issue could be. If you'd prefer, using "Ctr0InternalOutput" should also work (it will use the output of the counter on the same device used in the task).
"Dev1/ctr0" was being used correctly, according to your earlier post. However, unbelievably, I had "/Dev1/ai/Ctr0InternalOutput" as source input to DAQmxCfgSampClkTiming, which is invalid and meaningless of course. Changing that to "/Dev1/Ctr0InternalOutput" allows the tasks to start without error. I'm just about to check the pulse timings are sensible.
I can't thank you enough for you input which has been invaluable in the absence of NI documentation or examples in this area.
Well, the counter delay task seems to do what I want. I can delay the start of digital output until after the final sampling in the analog multi-channel scan.
There remains some rather puzzling behaviour, however. When I try to stop all three tasks (analog, digital and counter) with DAQmxStopTask, I get the error message "NIDAQ: Finite acquisition or generation has been stopped before the requested number of samples were acquired or generated". This occurs when I call DAQmxStopTask on the counter task, and appears no matter in which order I stop the three tasks. Adding calls to DAQmxWaitUntilTaskDone doesn't help, but maybe one wouldn't expect it to with continuous acquisition (see below).
I can then clear all three tasks (no errors), but when I create a new analog task and attempt to call DAQmxCreateAIVoltageChan a second time (part of the Analog task code in the listing above) in order to set up a new analog and digital configuration, I get the message "NIDAQ: Requested value is not a supported value for this property. The property value may be invalid because it conflicts with another value." This is unexpected because the function is called with the same parameter values as the first time. If I then call DAQmxCreateTask & DAQmxCreateAIVoltageChan a third time, everything works again!
I realize that I configure the analog task for continuous sampling (DAQmx_Val_ContSamps) and that, in a sense, the "requested number of samples" hasn't been acquired. But why should the counter task, which is simply waiting for /ai/SampleClock to go high, care about that? How does it even know about it?
(In contrast, if I trigger digital output on /ai/SampleClock without creating a counter task to act as intermediary between AI and DO, no such message appears when I stop the analog and digital tasks, and I can create them afresh without error.)
Is there a correct way to stop the counter task in this situation? Or can I simply create it once and leave it running indefinitely while I stop and restart the analog and digital tasks as part of changing the configuration?
Sorry for the additional questions. I'd really like to understand what I am doing (wrong) here.