Sign in Join
Wiki copytemporary

NI-DAQmx and NI-DAQmx Base examples: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## INTRODUCTION
22
33National Instruments produce a wide range of [DAQ cards](http://www.ni.com/data-acquisition/multifunction/), which are generally used for acquiring and generating signals.
44
55These cards usually have a few analog inputs/outputs, digital inputs/outputs, counters and a frequency generator with hardware/software timing. Exact features (type, number, parameters) depends on the card type.
66
77NIDAQmxBase.pas and NIDAQmx.pas are provided pascal bindings to National Instruments libraries and enable control of NI DAQ cards from programs written in Free Pascal.
88
99### What National Instruments Hardware is supported
1010
1111[Supported hardware list](http://www.ni.com/white-paper/6910/en/) by NI-DAQmx and NI-DAQ Driver for different operating systems.
1212
1313### NI-DAQmxBase library
1414
1515NI-DAQmxBase library or driver is multiplatform library for Windows (Windows XP 32 bit, Windows 7 32/64 bit, Windows Vista 32/64 bit, Windows 8 32/64 bit), macOS 32/64 bit and Linux 32/64 bit (SUSE, Scientific Linux, RedHat, CentOS), but doesn't implement all device features. For example, digital input/output ports speed is limited by computer speed ~100kHz, because DMA data transfer is not supported.
1616
1717Download library [from here](https://www.ni.com/en-au/support/downloads/drivers/download.ni-daqmx-base.html). Read [readme file](http://download.ni.com/support/softlib/multifunction_daq/nidaqmxbase/15.0/windows/readme.htm) to find the list of supported hardware and hardware features.
1818
1919```text
2020 Latest Linux version 15.0 supports 64-bit OS, but you still need to install some 32-bit library.
2121
2222 LIST OF LIBRARIES:
2323
2424 compat-libstdc++.i686
2525 expat.i686
2626 glibc.i686
2727 glibc-devel.i686
2828 libdrm.i686
2929 libgcc.i686
3030 libselinux.i686
3131 libstdc++.i686
3232 libX11.i686
3333 libXau.i686
3434 libxcb.i686
3535 libXdamage.i686
3636 libXext.i686
3737 libXinerama.i686
3838 libXfixes.i686
3939 libXxf86vm.i686
4040 mesa-dri-drivers.i686
4141 mesa-libGL.i686
4242 nss-softokn-freebl.i686
4343 zlib.i686
4444```
4545
4646### NI-DAQmx library
4747
4848The NI-DAQmx library is only available for Windows 7 (SP1) 32/64 bit, Windows 8.1 32/64 bit, Windows 10 32/64 bit, Windows Embedded Standard 7 (SP1), Windows Server 2008 R2 (SP1) 32/64 bit). [Download here)](https://www.ni.com/en-au/support/downloads/drivers/download.ni-daqmx.html)
4949
5050Read [readme file](http://download.ni.com/support/softlib/multifunction_daq/nidaqmx/9.0/readme.html) to find the list of supported hardware and hardware features.
5151
5252## HOW TO IDENTIFY PRESENT HARDWARE
5353
5454To get list of devices present in your system Under Linux operation system use
5555
56-`1) `**`nilsdev`**` utility with NIDAQmx driver installed,`\
57-`2) `**`lsdaq`**` utility with NIDAQmxBase driver installed.`
56+```text
57+1) nilsdev utility with NIDAQmx driver installed,
58+2) lsdaq utility with NIDAQmxBase driver installed.
59+```
5860
5961Under Windows use **NIMAX** utility to get device list or set device alias etc.
6062
6163## Library documentation
6264
6365You can find description of functions and properties in NI-DAQmx and NI-DAQmx Base C reference Help:
6466
6567- [NI-DAQmx](http://digital.ni.com/manuals.nsf/websearch/934F66A25EB3831586257AFD00741B13?OpenDocument&seen=1)
6668- [NI-DAQmx Base](http://digital.ni.com/manuals.nsf/websearch/C4B5B92E74F160C6862574560065F8BC)
6769
6870## PASCAL bindings
6971
7072Your can download pascal bindings nidaqmxbase.pas and nidaqmx.pas in this forum thread [1](http://forum.lazarus.freepascal.org/index.php/topic,7894.msg161883.html#msg161883) or as a [part of the LazMer](http://sourceforge.net/p/lazmer/code/HEAD/tree/trunk/daqlibs/) project.
7173
7274## FUNCTION CALLING
7375
7476Generally, when you need to acquire or gerenate data, call functions from **nidaqmx.pas** as follow
7577
7678```text
77791. Create task: DAQmxCreateTask
78802. Channel create:
7981 a)DAQmxCreateDIChan/DAQmxCreateDOChan (digital input(s)/output(s))
8082 b)DAQmxCreateAIVoltageChan/DAQmxCreateAOVoltageChan (analog input(s)/output(s))
81833. Set timing if you need hardware timimg: DAQmxCfgSamplClkTiming
82844. Start task: DAQmxStartTask
83855. Read or write data from/to channel:
8486 a)read data from digital port: DAQmxReadDigitalU8(8-bit port),DAQmxReadDigitalU32 (32-bit port),
8587 b)write data to digital port: DAQmxWriteDigitalU8(8-bit port),DAQmxWriteDigitalU32 (32-bit port),
8688 c)read data from analog input(s): DAQmxReadAnalogF64,
8789 d)write data to analog output(s): DAQmxWriteAnalogF64.
88906. Do job
89917. End of program - stop and clear task: DAQmxStopTask and DAQmxClearTask
9092
9193For error handling create function like ErrorCheck.
9294```
9395
9496from **nidaqmxbase.pas** as follow
9597
9698```text
97991. Create task: DAQmxBaseCreateTask
981002. Channel create:
99101 a)DAQmxBaseCreateDIChan/DAQmxBaseCreateDOChan (digital input(s)/output(s))
100102 b)DAQmxBaseCreateAIVoltageChan/DAQmxBaseCreateAOVoltageChan (analog input(s)/output(s))
1011033. Set timing if you need hardware timimg: DAQmxBaseCfgSamplClkTiming
1021044. Start task: DAQmxBaseStartTask
1031055. Read or write data from/to channel:
104106 a)read data from digital port: DAQmxBaseReadDigitalU8(8-bit port),DAQmxBaseReadDigitalU32 (32-bit port),
105107 b)write data to digital port: DAQmxBaseWriteDigitalU8(8-bit port),DAQmxBaseWriteDigitalU32 (32-bit port),
106108 c)read data from analog input(s): DAQmxBaseReadAnalogF64,
107109 d)write data to analog output(s): DAQmxBaseWriteAnalogF64.
1081106. Do job
1091117. End of program - stop and clear task: DAQmxBaseStopTask and DAQmxBaseClearTask
110112
111113For error handling create function like ErrorCheck.
112114```
113115
114116```text
115117 Probably, some examples need to add @ before variable, which use as function parameter!!!
116118```
117119
118120## NI-DAQmx examples
119121
120122### DEVICE INFO
121123
122124#### Get device list
123125
124126You can check device list names using NI MAX program under Windows or nilsdev utility under Linux.
125127
126128``` pascal
127129program devicelist;
128130
129131{$mode objfpc}{$H+}
130132
131133uses
132134 {$IFDEF UNIX}{$IFDEF UseCThreads}
133135 cthreads,
134136 {$ENDIF}{$ENDIF}
135137 Classes,nidaqmx,SysUtils
136138 { you can add units after this };
137139var
138140 devicenames:array of Char;
139141 infostr:string;
140142 DeviceNamesList:TStringList;
141143 buffersize:longint;
142144 product_type:array of char;
143145 devserialnum,is_simulated:longint;
144146 is_simulated_str:string;
145147 i:byte;
146148begin
147149 DeviceNamesList:=TStringList.Create;
148150 try
149151 {**************************************************************************
150152 Get device names present in the system
151153 **************************************************************************}
152154 //get buffer size or length of string of device list
153155 buffersize:=DAQmxGetSystemInfoAttribute(DAQmx_Sys_DevNames,devicenames[0],[0]);
154156 //set array of Char lenght
155157 if Buffersize<>0 then begin
156158 writeln('-------------------------------------------------------------');
157159 writeln('|Device name | Product Type | # Serial number | Is Simulated?');
158160 writeln('-------------------------------------------------------------');
159161 SetLength(devicenames,buffersize);
160162 //get the device list
161163 DAQmxGetSystemInfoAttribute(DAQmx_Sys_DevNames,devicenames[0],[buffersize]);
162164 //convert it to string: names are separated by comma
163165 SetString(infostr,PChar(@devicenames[0]),buffersize);
164166 //add names to TStringList
165167 DeviceNamesList.CommaText:=infostr;
166168 {************************************************************************
167169 Get Product info
168170 ***********************************************************************}
169171 for i:=0 to DeviceNamesList.Count-1 do begin
170172 //get buffer size or length of string of product type
171173 buffersize:=DAQmxGetDeviceAttribute(@DeviceNamesList.Strings[i][1],DAQmx_Dev_ProductType,Nil);
172174 //set lenght of array of char
173175 SetLength(product_type,buffersize);
174176 //get product type info
175177 DAQmxGetDeviceAttribute(@DeviceNamesList.Strings[i][1],DAQmx_Dev_ProductType,product_type[0],[buffersize]);
176178 {***********************************************************************
177179 Get Serial Number
178180 **********************************************************************}
179181 DAQmxGetDeviceAttribute(@DeviceNamesList.Strings[i][1],DAQmx_Dev_SerialNum,devserialnum,[1]);
180182 //DeviceInfoGrid.Cells[3,i+1]:=IntToHex(devserialnum,8);
181183 {***********************************************************************
182184 Is simulated?
183185 ***********************************************************************}
184186 DAQmxGetDeviceAttribute(@DeviceNamesList.Strings[i][1],DAQmx_Dev_IsSimulated,is_simulated,[1]);
185187 if is_simulated = 0 then is_simulated_str:='No'
186188 else is_simulated_str:='Yes';
187189 //Show info
188190 writeln('| ',DeviceNamesList.Strings[i],' | ',PChar(@product_type[0]),' | $',IntToHex(devserialnum,8),' |',is_simulated_str);
189191 end;
190192 end
191193 else writeln('any device found');
192194 finally
193195 DeviceNamesList.Free;
194196 end;
195197end.
196198```
197199
198200Output example
199201
200202```text
201203-------------------------------------------------------------
202204|Device name | Product Type | # Serial number | Is Simulated?
203205-------------------------------------------------------------
204206| Dev1 | PCI-6250 | $018D0B90 |No
205207```
206208
207209#### Get channel names
208210
209211``` pascal
210212program chaninfo;
211213
212214{$mode objfpc}{$H+}
213215
214216uses
215217 {$IFDEF UNIX}{$IFDEF UseCThreads}
216218 cthreads,
217219 {$ENDIF}{$ENDIF}
218220 Classes,nidaqmx
219221 { you can add units after this };
220222var
221223 buffersize,infotype:longint;
222224 channelnames:array of char;
223225 MsgChannelNames:array [0..255] of char;
224226 MsgNoChannelsText:array [0..255] of char;
225227 channeltype:byte;
226228 DeviceName:string;
227229begin
228230 {**********INPUT Device name and interested channel type **********************
229231 **********WITHOUT CHEKING IF DEVICE EXITS IN THE SYSTEM**********************}
230232 write('Enter device name, for example Dev1, Dev2 etc.: ');
231233 readln(Devicename);
232234 writeln('0 - analog inputs');
233235 writeln('1 - analog outputs');
234236 writeln('2 - digital inputs');
235237 writeln('3 - digital outputs');
236238 writeln('4 - counter inputs');
237239 writeln('5 - counter outputs');
238240 write('choose the number of required channel type:');
239241 readln(channeltype);
240242 {**********CHANNEL TYPE CHOSEN**********************************************}
241243 case channeltype of
242244 {********************ANALOG INPUTS NAMES*************************************}
243245 0: begin
244246 infotype:=DAQmx_Dev_AI_PhysicalChans;
245247 MsgChannelNames:='Analog input names';
246248 MsgNoChannelsText:='There are no analog inputs';
247249 end;
248250 {********************ANALOG OUTPUTS NAMES************************************}
249251 1: begin
250252 infotype:=DAQmx_Dev_AO_PhysicalChans;
251253 MsgChannelNames:='Analog output names';
252254 MsgNoChannelsText:='There are no analog outputs';
253255 end;
254256 {********************DIGITAL INPUT PORTS NAMES*******************************}
255257 2: begin
256258 infotype:=DAQmx_Dev_DI_Ports;
257259 MsgChannelNames:='Digital input ports';
258260 MsgNoChannelsText:='There are no digital input ports';
259261 end;
260262 {********************DIGITAL OUTPUT PORTS NAMES******************************}
261263 3:begin
262264 infotype:=DAQmx_Dev_DO_Ports;
263265 MsgChannelNames:='Digital output ports';
264266 MsgNoChannelsText:='There are no digital output ports';
265267 end;
266268 {********************COUNTER INPUT NAMES******************************}
267269 4:begin
268270 infotype:= DAQmx_Dev_CI_PhysicalChans;
269271 MsgChannelNames:='Digital counter inputs';
270272 MsgNoChannelsText:='There are no counter inputs ';
271273 end;
272274 {********************COUNTER OUTPUT NAMES******************************}
273275 5:begin
274276 infotype:= DAQmx_Dev_CO_PhysicalChans;
275277 MsgChannelNames:='Digital counter outputs';
276278 MsgNoChannelsText:='There are no counter outputs ';
277279 end;
278280 end;
279281{************GET CHANNEL NAMES*********************************************}
280282 if (channeltype>=0) and (channeltype<6) then begin
281283 //get buffer size or length of channelnames
282284 buffersize:=DAQmxGetDeviceAttribute(@DeviceName[1],infotype,Nil);
283285 if buffersize<>0 then begin
284286 SetLength(channelnames,buffersize);
285287 //get analog channel names separated by comma
286288 DAQmxGetDeviceAttribute(@DeviceName[1],infotype,channelnames[0],[buffersize]);
287289 //show info
288290 writeln(MsgChannelNames+': '+PChar(@channelnames[0]));
289291 end
290292 else writeln(MsgNoChannelsText);
291293 end;
292294end.
293295```
294296
295297Output example
296298
297299```text
298300Enter device name, for example Dev1, Dev2 etc.: Dev1
2993010 - analog inputs
3003021 - analog outputs
3013032 - digital inputs
3023043 - digital outputs
3033054 - counter inputs
3043065 - counter outputs
305307choose the number of required channel type:0
306308Analog input names: Dev1/ai0, Dev1/ai1, Dev1/ai2, Dev1/ai3, Dev1/ai4, Dev1/ai5, Dev1/ai6, Dev1/ai7, Dev1/ai8, Dev1/ai9, Dev1/ai10, Dev1/ai11, Dev1/ai12, Dev1/ai13, Dev1/ai14, Dev1/ai15
307309```
308310
309311### ANALOG INPUTS/OUTPUTS
310312
311313#### Acquire finite number of samples from one analog input
312314
313315``` pascal
314316program aichan;
315317
316318{$mode objfpc}{$H+}
317319
318320uses
319321 {$IFDEF UNIX}{$IFDEF UseCThreads}
320322 cthreads,
321323 {$ENDIF}{$ENDIF}
322324 Classes, nidaqmx
323325 { you can add units after this };
324326var
325327 AITaskHandle:TaskHandle;
326328 data:array[1..1000] of double;
327329 reads,i:longint;
328330
329331{************Error handling procedure *****************************************
330332 Example:
331333 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
332334
333335*******************************************************************************}
334336
335337procedure ErrorCheck(AError:longint;ATaskHandle:longint);
336338var
337339 errBuffer:array[0..2048] of char;
338340begin
339341 //get error description
340342 if Aerror<>0 then begin
341343 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
342344 writeln(PChar(@ErrBuffer[0]));
343345 //stop and cleat task
344346 if Assigned(@ATaskHandle) then begin
345347 DAQmxStopTask(ATaskHandle);
346348 DAQmxClearTask(ATaskHandle);
347349 end;
348350 //stop program
349351 Halt;
350352 end;
351353end;
352354{*********************MAIN PROGRAM*********************************************
353355 ******************* without error handling************************************}
354356begin
355357 //create task
356358 DAQmxCreateTask('',@AITaskHandle);
357359 //create analog input channel Dev1/ai0 (activate it)
358360 //voltage range -10 - 10
359361 DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL);
360362 //set timing
361363 //Sample rate = 10000 (10 kHz), sample per channel =1000
362364 //acquire finite samples (1000 samples) defined by DAQmx_Val_FiniteSamps
363365 DAQmxCfgSampClkTiming(AITaskHandle,'OnboardClock',10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000);
364366 //start task
365367 DAQmxStartTask(AITaskHandle);
366368 //acquire 1000 samples
367369 DAQmxReadAnalogF64(AITaskHandle,1000,10.0,DAQmx_Val_GroupByChannel,@data[1],1000,@reads,NIL);
368370 //show first 10 samples
369371 writeln(reads,' samples were acquired');
370372 writeln('');
371373 writeln('Value of first 10 samples');
372374 for i:=1 to 10 do writeln('sample[',i,'] = ',data[i]:4:2,' V');
373375 //stop and clear task
374376 DAQmxStopTask(AITaskHandle);
375377 DAQmxClearTask(AITaskHandle);
376378end.
377379```
378380
379381Output example
380382
381383```text
3823841000 samples were acquired
383385
384386Value of first 10 samples
385387sample[1] = 0.23 V
386388sample[2] = 0.23 V
387389sample[3] = 0.23 V
388390sample[4] = 0.23 V
389391sample[5] = 0.23 V
390392sample[6] = 0.23 V
391393sample[7] = 0.23 V
392394sample[8] = 0.23 V
393395sample[9] = 0.23 V
394396sample[10] = 0.23 V
395397```
396398
397399#### Continuously acquire samples from three analog inputs
398400
399401``` pascal
400402program multiaichannel;
401403
402404{$mode objfpc}{$H+}
403405
404406uses
405407 {$IFDEF UNIX}{$IFDEF UseCThreads}
406408 cthreads,
407409 {$ENDIF}{$ENDIF}
408410 Classes, nidaqmx,crt
409411 { you can add units after this };
410412var
411413 AITaskHandle:TaskHandle;
412414 data:array of double;
413415 reads:longint;
414416 totalsamplereads:longint=0;
415417 i:longint;
416418
417419{************Error handling procedure *****************************************
418420 Example:
419421 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
420422
421423*******************************************************************************}
422424
423425procedure ErrorCheck(AError:longint;ATaskHandle:longint);
424426var
425427 errBuffer:array[0..2048] of char;
426428begin
427429 //get error description
428430 if Aerror<>0 then begin
429431 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
430432 writeln(PChar(@ErrBuffer[0]));
431433 //stop and cleat task
432434 if Assigned(@ATaskHandle) then begin
433435 DAQmxStopTask(ATaskHandle);
434436 DAQmxClearTask(ATaskHandle);
435437 end;
436438 //stop program
437439 Halt;
438440 end;
439441end;
440442{*********************MAIN PROGRAM*********************************************
441443 ******************* without error handling************************************}
442444begin
443445 //Set buffer size for data acquiring, sample per channel 1000
444446 //buffer size(data -array variable) = 3 channel * 1000 samples per channel
445447 Setlength(data,3*1000);
446448 //create task
447449 DAQmxCreateTask('',@AITaskHandle);
448450 //create analog input channel Dev1/ai0:2 (activate 3 channels)
449451 //voltage range -10 - 10
450452 DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0:2','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL);
451453 //set timing
452454 //Sample rate = 10000 (10 kHz), sample per channel =1000
453455 //acquire finite samples (1000 samples) defined by DAQmx_Val_Cont_Samps
454456 DAQmxCfgSampClkTiming(AITaskHandle,'OnboardClock',10000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000);
455457 //start task
456458 DAQmxStartTask(AITaskHandle);
457459 //acquire 10000 samples for each channel
458460 while totalsamplereads<10000 do begin
459461 //1000- sample rate, 3000 - buffer size(data -array variable) = 3 channel * 1000 samples per channel
460462 DAQmxReadAnalogF64(AITaskHandle,1000,10.0,DAQmx_Val_GroupByChannel,@data[0],3000,@reads,NIL);
461463 totalsamplereads:=totalsamplereads+reads;
462464 writeln('aquired number of samples: ',totalsamplereads);
463465 end;
464466 //show first 10 samples from last 1000 samples acquired from each channel
465467 writeln('');
466468 writeln('Value of first 10 samples of last 1000 samples for each channel');
467469 writeln('| chan0 | chan1 | chan2 | ');
468470 for i:= 0 to 9 do writeln('|',data[i]:5:2,' V| ',data[i+1000]:5:2,' V| ',data[i+2000]:5:2,' V|');
469471 //stop and clear task
470472 DAQmxStopTask(AITaskHandle);
471473 DAQmxClearTask(AITaskHandle);
472474end.
473475```
474476
475477Output example
476478
477479```text
478480acquired number of samples: 1000
479481aquired number of samples: 2000
480482acquired number of samples: 3000
481483acquired number of samples: 4000
482484acquired number of samples: 5000
483485acquired number of samples: 6000
484486acquired number of samples: 7000
485487acquired number of samples: 8000
486488acquired number of samples: 9000
487489acquired number of samples: 10000
488490
489491Value of first 10 samples of last 1000 samples for each channel
490492| chan0 | chan1 | chan2 |
491493| 5.07 V| 5.07 V| 5.06 V|
492494| 5.07 V| 5.07 V| 5.06 V|
493495| 5.07 V| 5.06 V| 5.07 V|
494496| 5.06 V| 5.06 V| 5.07 V|
495497| 5.06 V| 5.07 V| 5.07 V|
496498| 5.07 V| 5.07 V| 5.06 V|
497499| 5.07 V| 5.07 V| 5.07 V|
498500| 5.06 V| 5.06 V| 5.07 V|
499501| 5.06 V| 5.06 V| 5.06 V|
500502| 5.07 V| 5.07 V| 5.06 V|
501503```
502504
503505#### Start acquisition on analog input by digital trigger
504506
505507This example demonstrates how to start acquisition by digital trigger.
506508
507509``` pascal
508510program aidigtrig;
509511
510512{$mode objfpc}{$H+}
511513
512514uses
513515 {$IFDEF UNIX}{$IFDEF UseCThreads}
514516 cthreads,
515517 {$ENDIF}{$ENDIF}
516518 Classes,nidaqmx,crt
517519 { you can add units after this };
518520var
519521 AITaskHandle:TaskHandle;
520522 channel:string = 'Dev1/ai0';
521523 SampleRate:double = 10000;
522524 SamplePerChannel:longint = 1000;
523525 PretriggerSamples: longint= 100; //MUST be > 2
524526 reads:longint = 0;
525527 i:longint;
526528 data:array of double;
527529procedure ErrorCheck(AError:longint;ATaskHandle:longint);
528530var
529531 errBuffer:array[0..2048] of char;
530532begin
531533 //get error description
532534 if Aerror<>0 then begin
533535 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
534536 writeln(ErrBuffer);
535537 //stop and cleat task
536538 if Assigned(@ATaskHandle) then begin
537539 DAQmxStopTask(ATaskHandle);
538540 DAQmxClearTask(ATaskHandle);
539541 end;
540542 //stop acquisition
541543 writeln('Program stoped');
542544 Halt;
543545 end;
544546end;
545547
546548begin
547549 //set buffer length
548550 SetLength(data,SamplePerChannel);
549551 //create take
550552 DAQmxCreateTask('',@AITaskHandle);
551553 //create ai channel
552554 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,@channel[1],'',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,Nil),AITaskHandle);
553555 //configure sample clock
554556 ErrorCheck(DAQmxCfgSampClkTiming(AITaskHandle,'',SampleRate,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,SamplePerChannel),AITaskHandle);
555557 //configure triger with 100 pretriggered samples
556558 ErrorCheck(DAQmxCfgDigEdgeRefTrig(AITaskHandle,'/Dev1/PFI0',DAQmx_Val_Rising,PretriggerSamples),AITaskHandle);
557559 //start task
558560 ErrorCheck(DAQmxStartTask(AITaskHandle),AITaskHandle);
559561 //acquire data
560562 writeln('Press any key to stop acquisition');
561563 i := 0;
562564 repeat
563565 ErrorCheck(DAQmxReadAnalogF64(AITaskHandle,SamplePerChannel,10.0,DAQmx_Val_GroupByChannel,@data[0],Length(data),@reads,Nil),AITaskHandle);
564566 i := i + reads;
565567 writeln('Number of acquired samples: ', i);
566568 until keypressed;
567569 //show last readed number of samples
568570 for i:=Low(data) to High(data) do writeln('data[',i,'] = ', data[i]:4:2);
569571
570572 //stop and clear task
571573 if Assigned(@AITaskHandle) then begin
572574 DAQmxStopTask(AITaskHandle);
573575 DAQmxClearTask(AITaskHandle);
574576 end;
575577end.
576578```
577579
578580#### Analog output software controlled
579581
580582This example demonstrates sinusoidal waveform generation with software timed control analog output.
581583
582584``` pascal
583585program aochansw;
584586
585587{$mode objfpc}{$H+}
586588
587589uses
588590 {$IFDEF UNIX}{$IFDEF UseCThreads}
589591 cthreads,
590592 {$ENDIF}{$ENDIF}
591593 Classes,Crt,SysUtils,nidaqmx
592594 { you can add units after this };
593595var
594596 AOTaskHandle:TaskHandle;
595597 //data writted to analog output
596598 data:array [0..999] of double;
597599 writtensamples:integer;
598600 i:integer;
599601
600602 {************Error handling procedure *****************************************
601603 Example:
602604 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
603605 *******************************************************************************}
604606procedure ErrorCheck(AError:longint;ATaskHandle:longint);
605607var
606608 errBuffer:array[0..2048] of char;
607609begin
608610 //get error description
609611 if Aerror<>0 then begin
610612 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
611613 writeln(PChar(@ErrBuffer[0]));
612614 //stop and cleat task
613615 if Assigned(@ATaskHandle) then begin
614616 DAQmxStopTask(ATaskHandle);
615617 DAQmxClearTask(ATaskHandle);
616618 end;
617619 //stop program
618620 Halt;
619621 end;
620622end;
621623
622624begin
623625 //prepare data for analog output
624626 //sin waveform
625627 for i:=Low(data) to High(data) do data[i]:=9.95*sin(i*2.0*Pi/1000.0);
626628 //create task
627629 DAQmxCreateTask('',@AOTaskHandle);
628630 //configure analog output channel
629631 ErrorCheck(DAQmxCreateAOVoltageChan(AOTaskHandle,'Dev1/ao0','',-10.0,10.0,DAQmx_Val_Volts,Nil),AOTaskHandle);
630632 //start task
631633 ErrorCheck(DAQmxStartTask(AOTaskHandle),AOTaskHandle);
632634
633635 writeln('Press any key to stop generation');
634636 //continuosly waveform generation
635637 //if you call task start function (DAQmxStartTask)
636638 //before output write function (for example DAQmxWriteAnalogScalarF64)
637639 //set AutoStart parameter to 1
638640 //if output function berofe start AutoStart = 0
639641 i:=0;
640642 repeat
641643 sleep(1);
642644 ErrorCheck(DAQmxWriteAnalogScalarF64(AOTaskHandle,1,10.0,data[i],Nil),AOTaskHandle);
643645 inc(i);
644646 if i >=1000 then i:=0;
645647 until keypressed;
646648
647649 //stop and clear task
648650 if Assigned(@AOTaskHandle) then begin
649651 DAQmxStopTask(AOTaskHandle);
650652 DAQmxClearTask(AOTaskHandle);
651653 end;
652654end.
653655```
654656
655657#### Analog output hardware controlled
656658
657659This example demonstrates how to generate finite number of samples on analog output channel.
658660
659661``` pascal
660662program aochannel;
661663
662664{$mode objfpc}{$H+}
663665
664666uses
665667 {$IFDEF UNIX}{$IFDEF UseCThreads}
666668 cthreads,
667669 {$ENDIF}{$ENDIF}
668670 Classes,nidaqmx
669671 { you can add units after this };
670672
671673var
672674 AOTaskHandle:TaskHandle;
673675 //data writted to analog output
674676 data:array [0..3999] of double;
675677 writtensamples:integer;
676678 i:integer;
677679
678680 {************Error handling procedure *****************************************
679681 Example:
680682 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
681683
682684*******************************************************************************}
683685
684686procedure ErrorCheck(AError:longint;ATaskHandle:longint);
685687var
686688 errBuffer:array[0..2048] of char;
687689begin
688690 //get error description
689691 if Aerror<>0 then begin
690692 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
691693 writeln(PChar(@ErrBuffer[0]));
692694 //stop and cleat task
693695 if Assigned(@ATaskHandle) then begin
694696 DAQmxStopTask(ATaskHandle);
695697 DAQmxClearTask(ATaskHandle);
696698 end;
697699 //stop program
698700 Halt;
699701 end;
700702end;
701703
702704{*********************MAIN PROGRAM*********************************************
703705 }
704706begin
705707 //prepare data for analog output
706708 for i:=Low(data) to High(data) do data[i]:= 5.0*i/4000.0;
707709 //create task
708710 DAQmxCreateTask('',@AOTaskHandle);
709711 //configure analog output channel
710712 ErrorCheck(DAQmxCreateAOVoltageChan(AOTaskHandle,'Dev1/ao0','',-10.0,10.0,DAQmx_Val_Volts,Nil),AOTaskHandle);
711713 //configure clock
712714 ErrorCheck(DAQmxCfgSampClkTiming(AOTaskHandle,'',1000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,4000),AOTaskHandle);
713715 //write data to buffer
714716 ErrorCheck(DAQmxWriteAnalogF64(AOTaskHandle,4000,0,10.0,DAQmx_Val_GroupByChannel,data,@writtensamples,Nil),AOTaskHandle);
715717 //start task
716718 ErrorCheck(DAQmxStartTask(AOTaskHandle),AOTaskHandle);
717719 //wait until all samples are generated
718720 ErrorCheck(DAQmxWaitUntilTaskDone(AOTaskHandle,10.0),AOTaskHandle);
719721 //stop and clear task
720722 if Assigned(@AOTaskHandle) then begin
721723 DAQmxStopTask(AOTaskHandle);
722724 DAQmxClearTask(AOTaskHandle);
723725 end;
724726end.
725727```
726728
727729### DIGITAL INPUTS/OUTPUTS
728730
729731Most of DAQ cards have two types of digital ports (input/output): correlated and static. Static ports are software timed, correlated are software or hardware timed by the external or internal clock for example couter output signal (**/Dev1/Ctr0InternalOutput** - couter0 as clock ). Check the documention to find it, for example NI-PCI6250 have three 8-bit ports: port0 - correlated, port1,port2 - static; NI-PCI6224 two ports: 32-bit port0 - correlated, 8-bit port1 - static.
730732
731733Read/Write data from/to 8-bit and 32-bit digital port use an appropriate function **DAQmxReadDigitalU8**, **DAQmxWriteDigitalU8** and **DAQmxReadDigitalU32**, **DAQmxWriteDigitalU32**.
732734
733735*Different behaviour of collerated port0, when it sets as input, occured under Linux and Windows: software timed works only under Windows, with external clock works under Windows and Linux!!!*
734736
735737#### Software timed digital input
736738
737739To check it, connected +5V(depend on hardware) to one of available port pins.
738740
739741``` pascal
740742program diport;
741743
742744{$mode objfpc}{$H+}
743745
744746uses
745747 {$IFDEF UNIX}{$IFDEF UseCThreads}
746748 cthreads,
747749 {$ENDIF}{$ENDIF}
748750 Classes,nidaqmx,SysUtils,StrUtils
749751 { you can add units after this };
750752var
751753 DITaskHandle:TaskHandle;
752754 data:array [0..9] of byte;
753755 reads:longint = 0;
754756 totalreads:longint = 0;
755757 i:longint ;
756758{************Error handling procedure *****************************************
757759 Example:
758760 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
759761
760762 *******************************************************************************}
761763
762764 procedure ErrorCheck(AError:longint;ATaskHandle:longint);
763765 var
764766 errBuffer:array[0..2048] of char;
765767 begin
766768 //get error description
767769 if Aerror<>0 then begin
768770 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
769771 writeln(PChar(@ErrBuffer[0]));
770772 //stop and cleat task
771773 if Assigned(@ATaskHandle) then begin
772774 DAQmxStopTask(ATaskHandle);
773775 DAQmxClearTask(ATaskHandle);
774776 end;
775777 //stop program
776778 Halt;
777779 end;
778780 end;
779781{*******************MAIN PROGRAM WITH ERROR HANDLING*************************}
780782begin
781783 //task create
782784 ErrorCheck(DAQmxCreateTask('',@DITaskHandle),DITaskHandle);
783785 //digital input port create
784786 ErrorCheck(DAQmxCreateDIChan(DITaskHandle,'Dev1/port1','',DAQmx_Val_ChanForAllLines),DITaskHandle);
785787 //Start Task
786788 ErrorCheck(DAQmxStartTask(DITaskHandle),DITaskHandle);
787789 //read 10 samples from 8-bit digital port (for example NI PCI-6250 card port1(pins P1.0-P1.7))
788790 //for 32-bit digital port use DAQmxReadDigitalU32 function
789791 ErrorCheck(DAQmxReadDigitalU8(DITaskHandle,10,10.0,DAQmx_Val_GroupByChannel,@data,10,@reads,Nil),DITaskHandle);
790792 writeln('number of readed samples: ',reads);
791793 for i:=0 to 9 do writeln('data [',i,'] = %',IntToBin(data[i],8));
792794 //stop and clear task
793795 if DITaskHandle<>0 then begin
794796 DAQmxStopTask(DITaskHandle);
795797 DAQmxClearTask(DITaskHandle);
796798 end;
797799end.
798800```
799801
800802Output example: +5V connected to pin P1.2 port1 on NI-PCI6250 card.
801803
802804```text
803805number of readed samples: 10
804806data [0] = %00000100
805807data [1] = %00000100
806808data [2] = %00000100
807809data [3] = %00000100
808810data [4] = %00000100
809811data [5] = %00000100
810812data [6] = %00000100
811813data [7] = %00000100
812814data [8] = %00000100
813815data [9] = %00000100
814816```
815817
816818#### Hardware timed digital input
817819
818820This example shows using of counter output signal as a clock for digital inputs port for hardware timed acquire data on digital inputs. This feature is supported only for correlated digital port. In this example 8-bit port0 on NI-PCI6250 card is used to check this function.
819821
820822To check it, connected +5V(depend on hardware) to one of available pins on correlated digital port.
821823
822824``` pascal
823825program diporttimed;
824826
825827{$mode objfpc}{$H+}
826828
827829uses
828830 {$IFDEF UNIX}{$IFDEF UseCThreads}
829831 cthreads,
830832 {$ENDIF}{$ENDIF}
831833 Classes,nidaqmx,SysUtils,StrUtils
832834 { you can add units after this };
833835var
834836 DITaskHandle,CtrTaskHandle:TaskHandle;
835837 data:array [0..9] of byte;
836838 reads:longint = 0;
837839 totalreads:longint = 0;
838840 i:longint ;
839841{************Error handling procedure *****************************************
840842 Example:
841843 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
842844
843845 *******************************************************************************}
844846
845847 procedure ErrorCheck(AError:longint;ATaskHandle:longint);
846848 var
847849 errBuffer:array[0..2048] of char;
848850 begin
849851 //get error description
850852 if Aerror<>0 then begin
851853 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
852854 writeln(PChar(@ErrBuffer[0]));
853855 //stop and cleat task
854856 if Assigned(@ATaskHandle) then begin
855857 DAQmxStopTask(ATaskHandle);
856858 DAQmxClearTask(ATaskHandle);
857859 end;
858860 //stop program
859861 Halt;
860862 end;
861863 end;
862864{*******************MAIN PROGRAM WITH ERROR HANDLING*************************}
863865begin
864866 {******CREATE COUNTER OUTPUT TO USE IT AS CLOCK FOR DIGITAL PORT INPUTS******
865867 *******INTERNALLY CONNECTED ON M-SERIES as /Dev1/Ctr0InternalOutput**********}
866868 //create couter task
867869 ErrorCheck(DAQmxCreateTask('Counter Task',@CtrTaskHandle),CtrTaskHandle);
868870 //create counter output channel
869871 //Frequency 1000 Hz, duty 0.5
870872 ErrorCheck(DAQmxCreateCOPulseChanFreq(CtrTaskHandle,'Dev1/ctr0','',DAQmx_Val_Hz,DAQmx_Val_Low,0,1000,0.5),CtrTaskHandle);
871873 //timing 1000 samples per second
872874 ErrorCheck(DAQmxCfgImplicitTiming(CtrTaskHandle,DAQmx_Val_ContSamps,1000),CtrTaskHandle);
873875 //start counter task
874876 ErrorCheck(DAQmxStartTask(CtrTaskHandle),CtrTaskHandle);
875877
876878 //digital input task create
877879 ErrorCheck(DAQmxCreateTask('Digital input task',@DITaskHandle),DITaskHandle);
878880 //digital input port create
879881 ErrorCheck(DAQmxCreateDIChan(DITaskHandle,'Dev1/port0','',DAQmx_Val_ChanForAllLines),DITaskHandle);
880882 //timing use counter output as clock source internally connected
881883 //as /Dev1/Ctr0InternalOutput
882884 ErrorCheck(DAQmxCfgSampClkTiming(DITaskHandle,'/Dev1/Ctr0InternalOutput',1000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000),DITaskHandle);
883885 //Start digital input Task
884886 ErrorCheck(DAQmxStartTask(DITaskHandle),DITaskHandle);
885887 //read 10 samples from 8-bit digital port for example correlated port0
886888 //for 32-bit digital port use DAQmxReadDigitalU32 function
887889 ErrorCheck(DAQmxReadDigitalU8(DITaskHandle,10,10.0,DAQmx_Val_GroupByChannel,@data,10,@reads,Nil),DITaskHandle);
888890 writeln('number of readed samples: ',reads);
889891 for i:=0 to 9 do writeln('data [',i,'] = %',IntToBin(data[i],8));
890892 //stop and clear task
891893 DAQmxStopTask(DITaskHandle);
892894 DAQmxClearTask(DITaskHandle);
893895 DAQmxStopTask(CtrTaskHandle);
894896 DAQmxClearTask(CtrTaskHandle);
895897end.
896898```
897899
898900Output example: +5V connected to pin P0.5 on port0 on NI-PCI6250 card.
899901
900902```text
901903number of readed samples: 10
902904data [0] = %00100000
903905data [1] = %00100000
904906data [2] = %00100000
905907data [3] = %00100000
906908data [4] = %00100000
907909data [5] = %00100000
908910data [6] = %00100000
909911data [7] = %00100000
910912data [8] = %00100000
911913data [9] = %00100000
912914```
913915
914916#### Software controlled digital output
915917
916918To check it connect digital output(s) to oscilloscope or to card analog input.
917919
918920``` pascal
919921program doportlpi;
920922
921923{$mode objfpc}{$H+}
922924
923925uses
924926 {$IFDEF UNIX}{$IFDEF UseCThreads}
925927 cthreads,
926928 {$ENDIF}{$ENDIF}
927929 Classes,nidaqmx,SysUtils,StrUtils
928930 { you can add units after this };
929931var
930932 DOTaskHandle:TaskHandle;
931933 data: byte;
932934 written:longint = 0;
933935{************Error handling procedure *****************************************
934936 Example:
935937 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev0/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
936938
937939 *******************************************************************************}
938940
939941 procedure ErrorCheck(AError:longint;ATaskHandle:longint);
940942 var
941943 errBuffer:array[0..2048] of char;
942944 begin
943945 //get error description
944946 if Aerror<>0 then begin
945947 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
946948 writeln(PChar(@ErrBuffer[0]));
947949 //stop and cleat task
948950 if Assigned(@ATaskHandle) then begin
949951 DAQmxStopTask(ATaskHandle);
950952 DAQmxClearTask(ATaskHandle);
951953 end;
952954 //stop program
953955 Halt;
954956 end;
955957 end;
956958{*******************MAIN PROGRAM WITH ERROR HANDLING*************************}
957959begin
958960 //task create
959961 ErrorCheck(DAQmxCreateTask('',@DOTaskHandle),DOTaskHandle);
960962 //digital input port create
961963 ErrorCheck(DAQmxCreateDOChan(DOTaskHandle,'Dev1/port0','',DAQmx_Val_ChanForAllLines),DOTaskHandle);
962964 //task start
963965 //no need to start task
964966 ErrorCheck(DAQmxStartTask(DOTaskHandle),DOTaskHandle);
965967 //for 32-bit digital port use DAQmxReadDigitalU32 function
966968 //set 1 on all lines of digital port
967969 //change data:=0 to set 0 or use DAQmxResetDevice function to
968970 data:=0;
969971 ErrorCheck(DAQmxWriteDigitalU8(DOTaskHandle,1,1,10.0,DAQmx_Val_GroupByChannel,@data,@written,Nil),DOTaskHandle);
970972 //use DAQmxResetDevice function here to set signal on Low state
971973 writeln('number of written samples: ',written);
972974 //stop and clear task
973975 if DOTaskHandle<>0 then begin
974976 DAQmxStopTask(DOTaskHandle);
975977 DAQmxClearTask(DOTaskHandle);
976978 end;
977979end.
978980```
979981
980982#### Hardware timed digital outputs with counter output used as source clock
981983
982984To check it connect digital output(s) to oscilloscope or to card analog input.
983985
984986``` pascal
985987program doporttimed;
986988
987989{$mode objfpc}{$H+}
988990
989991uses
990992 {$IFDEF UNIX}{$IFDEF UseCThreads}
991993 cthreads,
992994 {$ENDIF}{$ENDIF}
993995 Classes,nidaqmx,SysUtils,StrUtils,Crt
994996 { you can add units after this };
995997var
996998 DOTaskHandle,CtrTaskHandle:TaskHandle;
997999 data:array[0..7] of byte = (1,2,4,8,16,32,64,128);
9981000 written:longint = 0;
9991001{************Error handling procedure *****************************************
10001002 Example:
10011003 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev0/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
10021004
10031005 *******************************************************************************}
10041006
10051007 procedure ErrorCheck(AError:longint;ATaskHandle:longint);
10061008 var
10071009 errBuffer:array[0..2048] of char;
10081010 begin
10091011 //get error description
10101012 if Aerror<>0 then begin
10111013 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
10121014 writeln(PChar(@ErrBuffer[0]));
10131015 //stop and cleat task
10141016 if Assigned(@ATaskHandle) then begin
10151017 DAQmxStopTask(ATaskHandle);
10161018 DAQmxClearTask(ATaskHandle);
10171019 end;
10181020 //stop program
10191021 Halt;
10201022 end;
10211023 end;
10221024{*******************MAIN PROGRAM WITH ERROR HANDLING*************************}
10231025begin
10241026 {******CREATE COUNTER OUTPUT TO USE IT AS CLOCK FOR DIGITAL PORT OUTPUTS******
10251027 *******INTERNALLY CONNECTED ON M-SERIES as /Dev1/Ctr0InternalOutput**********}
10261028 //create couter task
10271029 ErrorCheck(DAQmxCreateTask('Counter Task',@CtrTaskHandle),CtrTaskHandle);
10281030 //create counter output channel
10291031 //Frequency 1000 Hz, duty 0.5
10301032 ErrorCheck(DAQmxCreateCOPulseChanFreq(CtrTaskHandle,'Dev1/ctr0','',DAQmx_Val_Hz,DAQmx_Val_Low,0,10000,0.5),CtrTaskHandle);
10311033 //timing 1000 samples per second
10321034 ErrorCheck(DAQmxCfgImplicitTiming(CtrTaskHandle,DAQmx_Val_ContSamps,1000),CtrTaskHandle);
10331035 //start task
10341036 //start counter task
10351037 ErrorCheck(DAQmxStartTask(CtrTaskHandle),CtrTaskHandle);
10361038
10371039 //task create
10381040 ErrorCheck(DAQmxCreateTask('',@DOTaskHandle),DOTaskHandle);
10391041 //digital input port create
10401042 ErrorCheck(DAQmxCreateDOChan(DOTaskHandle,'Dev1/port0','',DAQmx_Val_ChanForAllLines),DOTaskHandle);
10411043 //timing
10421044 //frequency 1000Hz
10431045 ErrorCheck(DAQmxCfgSampClkTiming(DOTaskHandle,'/Dev1/Ctr0InternalOutput',1000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000),DOTaskHandle);
10441046 //for 32-bit digital port use DAQmxWriteDigitalU32 function
10451047 //function sets to start task automaticly 3-rd parameter
10461048 //write 8 samples
10471049 ErrorCheck(DAQmxWriteDigitalU8(DOTaskHandle,8,1,10.0,DAQmx_Val_GroupByChannel,data,@written,Nil),DOTaskHandle);
10481050 writeln('number of written samples: ',written);
10491051 //stop and clear task
10501052 DAQmxStopTask(DOTaskHandle);
10511053 DAQmxClearTask(DOTaskHandle);
10521054 DAQmxStopTask(CtrTaskHandle);
10531055 DAQmxClearTask(CtrTaskHandle);
10541056end.
10551057```
10561058
10571059### COUNTER INPUTS/OUTPUTS
10581060
10591061#### Pulse generation
10601062
10611063This example demonstrates pwm generaton with frequency 1000Hz and duty circle 0.5.
10621064
10631065``` pascal
10641066program doporttimed;
10651067
10661068{$mode objfpc}{$H+}
10671069
10681070uses
10691071 {$IFDEF UNIX}{$IFDEF UseCThreads}
10701072 cthreads,
10711073 {$ENDIF}{$ENDIF}
10721074 Classes,nidaqmx,SysUtils,StrUtils,Crt
10731075 { you can add units after this };
10741076var
10751077 CtrTaskHandle:TaskHandle;
10761078 {************Error handling procedure *****************************************
10771079 Example:
10781080 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev0/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
10791081
10801082 *******************************************************************************}
10811083
10821084 procedure ErrorCheck(AError:longint;ATaskHandle:longint);
10831085 var
10841086 errBuffer:array[0..2048] of char;
10851087 begin
10861088 //get error description
10871089 if Aerror<>0 then begin
10881090 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
10891091 writeln(PChar(@ErrBuffer[0]));
10901092 //stop and cleat task
10911093 if Assigned(@ATaskHandle) then begin
10921094 DAQmxStopTask(ATaskHandle);
10931095 DAQmxClearTask(ATaskHandle);
10941096 end;
10951097 //stop program
10961098 Halt;
10971099 end;
10981100 end;
10991101{*******************MAIN PROGRAM WITH ERROR HANDLING*************************}
11001102begin
11011103 //create couter task
11021104 ErrorCheck(DAQmxCreateTask('Counter Task',@CtrTaskHandle),CtrTaskHandle);
11031105 //create counter output channel
11041106 //Frequency 1000 Hz, duty 0.5
11051107 ErrorCheck(DAQmxCreateCOPulseChanFreq(CtrTaskHandle,'Dev1/ctr0','',DAQmx_Val_Hz,DAQmx_Val_Low,0,10000,0.5),CtrTaskHandle);
11061108 //timing 1000 samples per second
11071109 ErrorCheck(DAQmxCfgImplicitTiming(CtrTaskHandle,DAQmx_Val_ContSamps,1000),CtrTaskHandle);
11081110 //start task
11091111 ErrorCheck(DAQmxStartTask(CtrTaskHandle),CtrTaskHandle);
11101112
11111113 writeln('Press any key to stop generation');
11121114 repeat
11131115 until keypressed;
11141116
11151117 DAQmxStopTask(CtrTaskHandle);
11161118 DAQmxClearTask(CtrTaskHandle);
11171119end.
11181120```
11191121
11201122#### Event counting
11211123
11221124In this example first counter(Dev1/ctr0) is configurated as counter output for frequency generation, second (Dev1/ctr1) as counter input for pulse counting. First counter also used as clock source for second one.
11231125
11241126``` pascal
11251127program eventcounting;
11261128
11271129{$mode objfpc}{$H+}
11281130
11291131uses
11301132 {$IFDEF UNIX}{$IFDEF UseCThreads}
11311133 cthreads,
11321134 {$ENDIF}{$ENDIF}
11331135 Classes,nidaqmx,SysUtils,StrUtils,Crt
11341136 { you can add units after this };
11351137var
11361138 CtrOutTaskHandle,CtrInTaskHandle:TaskHandle;
11371139 reads:cardinal=0;
11381140 data:array [0..999] of longint;
11391141 i:longint;
11401142{************Error handling procedure *****************************************
11411143 Example:
11421144 ErrorCheck(DAQmxCreateAIVoltageChan(AITaskHandle,'Dev0/ai0','',DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NIL),AITaskHandle);
11431145
11441146 *******************************************************************************}
11451147 procedure ErrorCheck(AError:longint;ATaskHandle:longint);
11461148 var
11471149 errBuffer:array[0..2048] of char;
11481150 begin
11491151 //get error description
11501152 if Aerror<>0 then begin
11511153 DAQmxGetExtendedErrorInfo(@ErrBuffer[0],2048);
11521154 writeln(PChar(@ErrBuffer[0]));
11531155 //stop and cleat task
11541156 if Assigned(@ATaskHandle) then begin
11551157 DAQmxStopTask(ATaskHandle);
11561158 DAQmxClearTask(ATaskHandle);
11571159 end;
11581160 //stop program
11591161 Halt;
11601162 end;
11611163 end;
11621164{*******************MAIN PROGRAM WITH ERROR HANDLING*************************}
11631165begin
11641166 {****************CREATE COUNTER OUTPUT***************************************}
11651167 //create couter output task
11661168 ErrorCheck(DAQmxCreateTask('Counter output task',@CtrOutTaskHandle),CtrOutTaskHandle);
11671169 //create counter output channel
11681170 //Frequency 1000 Hz, duty 0.5
11691171 ErrorCheck(DAQmxCreateCOPulseChanFreq(CtrOutTaskHandle,'Dev1/ctr0','',DAQmx_Val_Hz,DAQmx_Val_Low,0,10000,0.5),CtrOutTaskHandle);
11701172 //timing 1000 samples per second
11711173 ErrorCheck(DAQmxCfgImplicitTiming(CtrOutTaskHandle,DAQmx_Val_ContSamps,1000),CtrOutTaskHandle);
11721174 //start counter output task
11731175 ErrorCheck(DAQmxStartTask(CtrOutTaskHandle),CtrOutTaskHandle);
11741176
11751177 {*****************CREATE COUNTER INPUT***************************************}
11761178 //create couter output task
11771179 ErrorCheck(DAQmxCreateTask('Counter input task',@CtrInTaskHandle),CtrInTaskHandle);
11781180 //create input counter for pulse counting
11791181 ErrorCheck(DAQmxCreateCICountEdgesChan(CtrInTaskHandle,'Dev1/ctr1','',DAQmx_Val_Rising,0,DAQmx_Val_CountUp),CtrInTaskHandle);
11801182 //timing
11811183 ErrorCheck(DAQmxCfgSampClkTiming(CtrInTaskHandle,'/Dev1/Ctr0InternalOutput',1000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000),CtrInTaskHandle);
11821184 //start counter input task
11831185 ErrorCheck(DAQmxStartTask(CtrInTaskHandle),CtrInTaskHandle);
11841186 //counting pulses
11851187 ErrorCheck(DAQmxReadCounterU32(CtrIntaskHandle,1000,10.0,@data,1000,@reads,Nil),CtrIntaskHandle);
11861188 writeln('acquired samples: ',reads);
11871189 for i:=0 to 10 do writeln('sample[',i,'] = ',data[i]);
11881190
11891191 //stop and clear tasks
11901192 DAQmxStopTask(CtrInTaskHandle);
11911193 DAQmxClearTask(CtrInTaskHandle);
11921194 DAQmxStopTask(CtrOutTaskHandle);
11931195 DAQmxClearTask(CtrOutTaskHandle);
11941196end.
11951197```
11961198
11971199### TESTED HARDWARE
11981200
11991201Examples were tested under Linux 32-bit (kernel 2.6.32) NI-DAQmx 8.0.2 and Windows 7 32-bit NI-DAQmx 14 on cards:
12001202
12011203- **NI PCI-6250**
12021204- **NI PCI-6224**
12031205
12041206- **NI PXIe-6612 (Windows only)**
12051207
12061208- **NI USB-6356 (Windows only)**
12071209
12081210- **NI USB-6003 (Windows only)**
12091211
12101212## NI-DAQxmxBase examples
12111213
12121214Generally, NI-DAQmxBase is a light version of NI-DAQmx, but this library is **multiplatform**. You can use it under all supported operation systems without modification of NI-DAQmxBase function call.
12131215
12141216**Read readme file to check card supported features!!!**
12151217
12161218### DEVICE INFO
12171219
12181220Functions, which provide device and channel information, are not implemented in this library, yet.
12191221
12201222### ANALOG INPUTS/OUTPUTS
12211223
12221224#### Acquire finite number of samples from one analog channel
12231225
12241226``` pascal
12251227program aichannel;
12261228
12271229{$mode objfpc}{$H+}
12281230
12291231uses
12301232 {$IFDEF UNIX}{$IFDEF UseCThreads}
12311233 cthreads,
12321234 {$ENDIF}{$ENDIF}
12331235 Classes,nidaqmxbase;
12341236 { you can add units after this }
12351237var
12361238 AITaskHandle: PTaskHandle;
12371239 NiBool:Pnibool;
12381240 reads:longint=0;
12391241 i:byte;
12401242 data:array [1..1000] of double;
12411243procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
12421244var
12431245 errBuffer:array[0..2048] of char;
12441246 errMessage:string;
12451247begin
12461248 //get error description
12471249 if DAQmxFailed(AError) = niTrue then begin
12481250 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
12491251 writeln(ErrBuffer);
12501252 //stop and cleat task
12511253 if Assigned(ATaskHandle) then begin
12521254 DAQmxBaseStopTask(ATaskHandle);
12531255 DAQmxBaseClearTask(ATaskHandle);
12541256 end;
12551257 //stop program
12561258 Halt;
12571259 end;
12581260end;
12591261
12601262begin
12611263 //create task
12621264 ErrorCheck(DAQmxBaseCreateTask ('', AITaskHandle),AITaskHandle);
12631265 //create analog input channel
12641266 ErrorCheck(DAQmxBaseCreateAIVoltageChan(AITaskHandle,'Dev1/ai0','', DAQmx_Val_RSE,-10, 10,DAQmx_Val_Volts,''),AITaskHandle);
12651267 //timing
12661268 //clock frequency 1000 Hz, sample rate 1000 per second
12671269 //if you use more than one active channel, generally sample rate = clock frequency/(active analog channles*10);
12681270 ErrorCheck(DAQmxBaseCfgSampClkTiming (AITaskHandle,'OnboardClock',1000,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000),AITaskHandle);
12691271 //start task
12701272 ErrorCheck(DAQmxBaseStartTask(AITaskHandle),AITaskHandle);
12711273 //read 1000 samples
12721274 ErrorCheck(DAQmxBaseReadAnalogF64 (AITaskHandle, 1000, 10.0,DAQmx_Val_GroupByChannel,data,1000,reads,NIBool^),AITaskHandle);
12731275 //acquired sample number
12741276 writeln(reads,' samples were acqiured');
12751277 //show value of first ten samples
12761278 for i:=1 to 10 do writeln('sample[',i,'] = ',data[i]:4:2,' V');
12771279 //stop and clear task
12781280 DAQmxBaseStopTask(AITaskHandle);
12791281 DAQmxBaseClearTask(AITaskHandle);
12801282end.
12811283```
12821284
12831285Output example +5V connected to pin 68 on NI PCI-6250
12841286
12851287```text
128612881000 samples were acqiured
12871289sample[1] = 5.07 V
12881290sample[2] = 5.06 V
12891291sample[3] = 5.06 V
12901292sample[4] = 5.06 V
12911293sample[5] = 5.06 V
12921294sample[6] = 5.06 V
12931295sample[7] = 5.06 V
12941296sample[8] = 5.06 V
12951297sample[9] = 5.06 V
12961298sample[10] = 5.07 V
12971299```
12981300
12991301#### Continuously acquire samples from three analog inputs
13001302
13011303``` pascal
13021304program ai3contacq;
13031305
13041306{$mode objfpc}{$H+}
13051307
13061308uses
13071309 {$IFDEF UNIX}{$IFDEF UseCThreads}
13081310 cthreads,
13091311 {$ENDIF}{$ENDIF}
13101312 Classes,nidaqmxbase;
13111313 { you can add units after this }
13121314var
13131315 AITaskHandle: PTaskHandle;
13141316 NiBool:Pnibool;
13151317 reads:longint=0;
13161318 totalreads:longint=0;
13171319 i:byte;
13181320 data:array of double;
13191321 acqnumsamples:longint;
13201322procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
13211323var
13221324 errBuffer:array[0..2048] of char;
13231325 errMessage:string;
13241326begin
13251327 //get error description
13261328 if DAQmxFailed(AError) = niTrue then begin
13271329 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
13281330 writeln(ErrBuffer);
13291331 //stop and cleat task
13301332 if Assigned(ATaskHandle) then begin
13311333 DAQmxBaseStopTask(ATaskHandle);
13321334 DAQmxBaseClearTask(ATaskHandle);
13331335 end;
13341336 //stop program
13351337 Halt;
13361338 end;
13371339end;
13381340
13391341begin
13401342 //enter number of total samples for each channel to be acquired
13411343 write('Enter a number of samples for each channel to be acquired: ');
13421344 readln(acqnumsamples);
13431345 //Set buffer size = length of data array:=number of active channels * sample per channel
13441346 Setlength(data,3*1000);
13451347 //create task
13461348 ErrorCheck(DAQmxBaseCreateTask ('', AITaskHandle),AITaskHandle);
13471349 //create analog input channel - 3 active analog inputs
13481350 ErrorCheck(DAQmxBaseCreateAIVoltageChan(AITaskHandle,'Dev1/ai0:2','', DAQmx_Val_RSE,-10, 10,DAQmx_Val_Volts,''),AITaskHandle);
13491351 //timing
13501352 //clock frequency 10000 Hz, sample rate 1000 per second
13511353 //if you use more than one active channel, generally sample rate = clock frequency/(active analog channles*10);
13521354 ErrorCheck(DAQmxBaseCfgSampClkTiming (AITaskHandle,'OnboardClock',10000,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000),AITaskHandle);
13531355 //start task
13541356 ErrorCheck(DAQmxBaseStartTask(AITaskHandle),AITaskHandle);
13551357 //read samples
13561358 while totalreads<acqnumsamples do begin
13571359 ErrorCheck(DAQmxBaseReadAnalogF64(AITaskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel,data,Length(data),reads,NIBool^),AITaskHandle);
13581360 totalreads:=totalreads+reads;
13591361 writeln('total samples readed for each channel: ',totalreads);
13601362 //show first five values for each channel
13611363 for i:=0 to 5 do writeln('chan1[',i,'] = ',data[i]:4:2,' V ','chan2[',i,'] = ',data[i+1000]:4:2,' V ','chan3[',i,'] = ',data[i+2000]:4:2,' V ');
13621364 end;
13631365 //stop and clear task
13641366 DAQmxBaseStopTask(AITaskHandle);
13651367 DAQmxBaseClearTask(AITaskHandle);
13661368end.
13671369```
13681370
13691371Output example +5V connected to pin 68 on NI PCI-6250
13701372
13711373```text
13721374Enter a number of samples for each channel to be acquired: 2000
13731375total samples readed for each channel: 1000
13741376chan1[0] = 5.07 V chan2[0] = 0.00 V chan3[0] = 0.03 V
13751377chan1[1] = 5.06 V chan2[1] = -0.00 V chan3[1] = 0.03 V
13761378chan1[2] = 5.07 V chan2[2] = -0.00 V chan3[2] = 0.02 V
13771379chan1[3] = 5.07 V chan2[3] = -0.00 V chan3[3] = 0.02 V
13781380chan1[4] = 5.06 V chan2[4] = -0.00 V chan3[4] = 0.02 V
13791381chan1[5] = 5.06 V chan2[5] = -0.00 V chan3[5] = 0.01 V
13801382total samples readed for each channel: 2000
13811383chan1[0] = 5.06 V chan2[0] = -0.00 V chan3[0] = -0.02 V
13821384chan1[1] = 5.07 V chan2[1] = -0.00 V chan3[1] = -0.02 V
13831385chan1[2] = 5.06 V chan2[2] = -0.00 V chan3[2] = -0.02 V
13841386chan1[3] = 5.07 V chan2[3] = -0.00 V chan3[3] = -0.02 V
13851387chan1[4] = 5.06 V chan2[4] = -0.00 V chan3[4] = -0.02 V
13861388chan1[5] = 5.06 V chan2[5] = -0.00 V chan3[5] = -0.02 V
13871389```
13881390
13891391### DIGITAL INPUTS/OUTPUTS
13901392
13911393Read readme file to check supported card features by NI-DAQmxBase.
13921394
13931395In case of M-series cards, correlated digital input/output is limited to about 100kHz, because DMA data transfer is not supported.
13941396
13951397#### Software timed digital input
13961398
13971399``` pascal
13981400program diport;
13991401
14001402{$mode objfpc}{$H+}
14011403
14021404uses
14031405 {$IFDEF UNIX}{$IFDEF UseCThreads}
14041406 cthreads,
14051407 {$ENDIF}{$ENDIF}
14061408 Classes,nidaqmxbase,StrUtils
14071409 { you can add units after this };
14081410var
14091411 DITaskHandle:PTaskHandle;
14101412 NiBool:Pnibool;
14111413 data:byte;
14121414 reads:longint=0;
14131415procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
14141416var
14151417 errBuffer:array[0..2048] of char;
14161418begin
14171419 //get error description
14181420 if DAQmxFailed(AError) = niTrue then begin
14191421 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
14201422 writeln(ErrBuffer);
14211423 //stop and cleat task
14221424 if Assigned(ATaskHandle) then begin
14231425 DAQmxBaseStopTask(ATaskHandle);
14241426 DAQmxBaseClearTask(ATaskHandle);
14251427 end;
14261428 //stop program
14271429 Halt;
14281430 end;
14291431end;
14301432begin
14311433 //create task
14321434 ErrorCheck(DAQmxBaseCreateTask('', DITaskHandle),DITaskHandle);
14331435 //create digital input port
14341436 ErrorCheck(DAQmxBaseCreateDIChan(DITaskHandle,'Dev1/port0','',DAQmx_Val_ChanForAllLines),DITaskHandle);
14351437 //start task
14361438 ErrorCheck(DAQmxBaseStartTask(DITaskHandle),DITaskHandle);
14371439 //read dat form port
14381440 //use DAQmxBaseReadDigitalU8 for 8 bit port
14391441 //use DAQmxBaseReadDigitalU32 for 32 bit port
14401442 ErrorCheck(DAQmxBaseReadDigitalU8(DITaskHandle,1,10.0,DAQmx_Val_GroupByChannel,data,1,reads,NiBool^),DITaskHandle);
14411443 writeln('digital port value %',IntToBin(data,8));
14421444 //stop and clear task
14431445 DAQmxBaseStopTask(DITaskHandle);
14441446 DAQmxBaseClearTask(DITaskHandle);
14451447end.
14461448```
14471449
14481450Output example: +5V connected to line 1 of 8-bit digital port
14491451
14501452```text
14511453digital port value %00000010
14521454```
14531455
14541456#### Hardware timed digital input
14551457
14561458``` pascal
14571459program diporthwtimed;
14581460
14591461{$mode objfpc}{$H+}
14601462
14611463uses
14621464 {$IFDEF UNIX}{$IFDEF UseCThreads}
14631465 cthreads,
14641466 {$ENDIF}{$ENDIF}
14651467 Classes,nidaqmxbase,StrUtils
14661468 { you can add units after this };
14671469var
14681470 DITaskHandle,CtrTaskHandle:PTaskHandle;
14691471 NiBool:Pnibool;
14701472 data:array of byte;
14711473 reads:longint=0;
14721474 i:longint;
14731475procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
14741476var
14751477 errBuffer:array[0..2048] of char;
14761478begin
14771479 //get error description
14781480 if DAQmxFailed(AError) = niTrue then begin
14791481 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
14801482 writeln(ErrBuffer);
14811483 //stop and cleat task
14821484 if Assigned(ATaskHandle) then begin
14831485 DAQmxBaseStopTask(ATaskHandle);
14841486 DAQmxBaseClearTask(ATaskHandle);
14851487 end;
14861488 //stop program
14871489 Halt;
14881490 end;
14891491end;
14901492begin
14911493
14921494 {********CONFIGURE COUNTER TO USE AS CLOCK FOR DIGITAL INPUT*****************}
14931495 //create counter task
14941496 ErrorCheck(DAQmxBaseCreateTask('', CtrTaskHandle),CtrTaskHandle);
14951497 //create counter output channel
14961498 //Frequency 10000 Hz, duty 0.5
14971499 ErrorCheck(DAQmxBaseCreateCOPulseChanFreq(CtrTaskHandle,'Dev1/ctr0','',DAQmx_Val_Hz,DAQmx_Val_Low,0,10000,0.5),CtrTaskHandle);
14981500 //timing
14991501 //last value is not important for continuesly sample mode, for finite sample mode = generate 10000 samples
15001502 ErrorCheck(DAQmxBaseCfgImplicitTiming(CtrTaskHandle,DAQmx_Val_ContSamps,10000),CtrTaskHandle);
15011503 //start counter task
15021504 ErrorCheck(DAQmxBaseStartTask(CtrTaskHandle),CtrTaskHandle);
15031505
15041506 {*******************HW TIMED DIGITAL INPUT***********************************
15051507 **********LIMITED TO 10kHz,DMA IS NOT IMPLEMENTED****************************}
15061508 //configure buffer for 1000 samples
15071509 SetLength(data,1000);
15081510 //create task
15091511 ErrorCheck(DAQmxBaseCreateTask('', DITaskHandle),DITaskHandle);
15101512 //create digital input port
15111513 ErrorCheck(DAQmxBaseCreateDIChan(DITaskHandle,'Dev1/port0','',DAQmx_Val_ChanForAllLines),DITaskHandle);
15121514 //timing frequency 10000Hz, 1000 sample per channel
15131515 ErrorCheck(DAQmxBaseCfgSampClkTiming(DITaskHandle,'/Dev1/Ctr0InternalOutput',10000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,10000),DITaskHandle);
15141516 //start task
15151517 ErrorCheck(DAQmxBaseStartTask(DITaskHandle),DITaskHandle);
15161518 //read dat form port
15171519 //use DAQmxBaseReadDigitalU8 for 8 bit port
15181520 //use DAQmxBaseReadDigitalU32 for 32 bit port
15191521 ErrorCheck(DAQmxBaseReadDigitalU8(DITaskHandle,10000,10.0,DAQmx_Val_GroupByChannel,data,10000,reads,NiBool^),DITaskHandle);
15201522 writeln(reads,' samples were readed');
15211523 //show first 10 samples
15221524 for i:=0 to 9 do writeln('sample[',i,'] = %',IntToBin(data[i],8));
15231525 //stop and clear task
15241526 DAQmxBaseStopTask(DITaskHandle);
15251527 DAQmxBaseClearTask(DITaskHandle);
15261528 DAQmxBaseStopTask(CtrTaskHandle);
15271529 DAQmxBaseClearTask(CtrTaskHandle);
15281530end.
15291531```
15301532
15311533Output example: +5V connected to line 1 of 8-bit digital port, executed with time command under Linux.
15321534
15331535```text
1534153610000 samples were readed
15351537sample[0] = %00000010
15361538sample[1] = %00000010
15371539sample[2] = %00000010
15381540sample[3] = %00000010
15391541sample[4] = %00000010
15401542sample[5] = %00000010
15411543sample[6] = %00000010
15421544sample[7] = %00000010
15431545sample[8] = %00000010
15441546sample[9] = %00000010
15451547
15461548real 0m4.483s
15471549user 0m4.261s
15481550sys 0m0.100s
15491551```
15501552
15511553#### Software timed digital output
15521554
15531555``` pascal
15541556program doport;
15551557
15561558{$mode objfpc}{$H+}
15571559
15581560uses
15591561 {$IFDEF UNIX}{$IFDEF UseCThreads}
15601562 cthreads,
15611563 {$ENDIF}{$ENDIF}
15621564 Classes,nidaqmxbase,StrUtils,SysUtils
15631565 { you can add units after this };
15641566var
15651567 DOTaskHandle,CtrTaskHandle:PTaskHandle;
15661568 NiBool:Pnibool;
15671569 data: byte;
15681570 written:longint=0;
15691571 i:longint;
15701572procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
15711573var
15721574 errBuffer:array[0..2048] of char;
15731575begin
15741576 //get error description
15751577 if DAQmxFailed(AError) = niTrue then begin
15761578 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
15771579 writeln(ErrBuffer);
15781580 //stop and cleat task
15791581 if Assigned(ATaskHandle) then begin
15801582 DAQmxBaseStopTask(ATaskHandle);
15811583 DAQmxBaseClearTask(ATaskHandle);
15821584 end;
15831585 //stop program
15841586 Halt;
15851587 end;
15861588end;
15871589begin
15881590 //write data to buffer, produce digital waveform on all port lines
15891591 data:=255;
15901592 //create task
15911593 ErrorCheck(DAQmxBaseCreateTask('', DOTaskHandle),DOTaskHandle);
15921594 //create digital input port
15931595 ErrorCheck(DAQmxBaseCreateDOChan(DOTaskHandle,'Dev1/port0','',DAQmx_Val_ChanForAllLines),DOTaskHandle);
15941596 //use DAQmxBaseWriteDigitalU8 for 8 bit port
15951597 //use DAQmxBaseWriteDigitalU32 for 32 bit port
15961598 //set third parametr to 1 to enable autostart or set to 0 and use DAQmxBaseStartTask before
15971599 //set digital "1"
15981600 writeln('set digital 1 on all port lines');
15991601 writeln('sleep 10s');
16001602 ErrorCheck(DAQmxBaseWriteDigitalU8(DOTaskHandle,1000,1,1000,DAQmx_Val_GroupByChannel,data,written,NiTrue),DOTaskHandle);
16011603 sleep(10000);
16021604 writeln(written,' samples were written');
16031605 //set digital "0"
16041606 writeln('set digital 0 on all port lines');
16051607 writeln('sleep 10s');
16061608 sleep(10000);
16071609 ErrorCheck(DAQmxBaseWriteDigitalU8(DOTaskHandle,1000,1,1000,DAQmx_Val_GroupByChannel,data,written,NiTrue),DOTaskHandle);
16081610 writeln(written,' samples were written');
16091611 //stop and clear task
16101612 DAQmxBaseStopTask(DOTaskHandle);
16111613 DAQmxBaseClearTask(DOTaskHandle);
16121614 DAQmxBaseStopTask(CtrTaskHandle);
16131615 DAQmxBaseClearTask(CtrTaskHandle);
16141616end.
16151617```
16161618
16171619#### Hardware timed digital output
16181620
16191621Digital output generation frequency is limited to ~100kHz, because DMA is not supported by the driver .
16201622
16211623``` pascal
16221624program doporthwtimed;
16231625
16241626{$mode objfpc}{$H+}
16251627
16261628uses
16271629 {$IFDEF UNIX}{$IFDEF UseCThreads}
16281630 cthreads,
16291631 {$ENDIF}{$ENDIF}
16301632 Classes,nidaqmxbase,StrUtils
16311633 { you can add units after this };
16321634var
16331635 DOTaskHandle,CtrTaskHandle:PTaskHandle;
16341636 NiBool:Pnibool;
16351637 data:array of byte;
16361638 written:longint=0;
16371639 i:longint;
16381640procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
16391641var
16401642 errBuffer:array[0..2048] of char;
16411643begin
16421644 //get error description
16431645 if DAQmxFailed(AError) = niTrue then begin
16441646 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
16451647 writeln(ErrBuffer);
16461648 //stop and cleat task
16471649 if Assigned(ATaskHandle) then begin
16481650 DAQmxBaseStopTask(ATaskHandle);
16491651 DAQmxBaseClearTask(ATaskHandle);
16501652 end;
16511653 //stop program
16521654 Halt;
16531655 end;
16541656end;
16551657begin
16561658 {********CONFIGURE COUNTER TO USE AS CLOCK FOR DIGITAL INPUT*****************}
16571659 //create counter task
16581660 ErrorCheck(DAQmxBaseCreateTask('', CtrTaskHandle),CtrTaskHandle);
16591661 //create counter output channel
16601662 //Frequency 10000 Hz, duty 0.5
16611663 ErrorCheck(DAQmxBaseCreateCOPulseChanFreq(CtrTaskHandle,'Dev1/ctr0','',DAQmx_Val_Hz,DAQmx_Val_Low,0,10000,0.5),CtrTaskHandle);
16621664 //timing
16631665 //last value is not important for continuesly sample mode, for finite sample mode = generate 10000 samples
16641666 ErrorCheck(DAQmxBaseCfgImplicitTiming(CtrTaskHandle,DAQmx_Val_ContSamps,10000),CtrTaskHandle);
16651667 //start counter task
16661668 ErrorCheck(DAQmxBaseStartTask(CtrTaskHandle),CtrTaskHandle);
16671669 {*******************HW TIMED DIGITAL INPUT***********************************
16681670 **********LIMITED TO 10kHz,DMA IS NOT IMPLEMENTED****************************}
16691671 //configure buffer for 1000 samples
16701672 SetLength(data,1000);
16711673 //write data to buffer, produce digital waveform on all port lines
16721674 for i:=0 to 999 do if (i mod 2 = 0) then data[i]:=255;
16731675 //create task
16741676 ErrorCheck(DAQmxBaseCreateTask('', DOTaskHandle),DOTaskHandle);
16751677 //create digital input port
16761678 ErrorCheck(DAQmxBaseCreateDOChan(DOTaskHandle,'Dev1/port0','',DAQmx_Val_ChanForAllLines),DOTaskHandle);
16771679 //timing frequency 10000Hz, 1000 sample per channel
16781680 ErrorCheck(DAQmxBaseCfgSampClkTiming(DOTaskHandle,'/Dev1/Ctr0InternalOutput',10000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000),DOTaskHandle);
16791681 //use DAQmxBaseWriteDigitalU8 for 8 bit port
16801682 //use DAQmxBaseWriteDigitalU32 for 32 bit port
16811683 //set third parametr to 1 to enable autostart or set to 0 and use DAQmxBaseStartTask before
16821684 ErrorCheck(DAQmxBaseWriteDigitalU8(DOTaskHandle,1000,1,1000,DAQmx_Val_GroupByChannel,data,written,NiTrue),DOTaskHandle);
16831685 writeln(written,' samples were written');
16841686 //stop and clear task
16851687 DAQmxBaseStopTask(DOTaskHandle);
16861688 DAQmxBaseClearTask(DOTaskHandle);
16871689 DAQmxBaseStopTask(CtrTaskHandle);
16881690 DAQmxBaseClearTask(CtrTaskHandle);
16891691end.
16901692```
16911693
16921694### COUNTER INPUTS/OUTPUTS
16931695
16941696Counter input of M-series cards is limited to computer speed.
16951697
16961698#### COUNTER OUTPUT
16971699
16981700Counter output can be timed by software or hardware.
16991701
17001702Example demontrate how to use couter ouput as frequency generator(clock signal for other hardware) or as basic pwm regulation.
17011703
17021704In this example counter output is hardware timed.
17031705
17041706``` pascal
17051707program ctrout;
17061708
17071709{$mode objfpc}{$H+}
17081710
17091711uses
17101712 {$IFDEF UNIX}{$IFDEF UseCThreads}
17111713 cthreads,
17121714 {$ENDIF}{$ENDIF}
17131715 Classes,nidaqmxbase,StrUtils,SysUtils
17141716 { you can add units after this };
17151717var
17161718 CtrTaskHandle:PTaskHandle;
17171719 NiBool:Pnibool;
17181720 data:array of byte;
17191721 reads:longint=0;
17201722procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
17211723var
17221724 errBuffer:array[0..2048] of char;
17231725begin
17241726 //get error description
17251727 if DAQmxFailed(AError) = niTrue then begin
17261728 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
17271729 writeln(ErrBuffer);
17281730 //stop and cleat task
17291731 if Assigned(ATaskHandle) then begin
17301732 DAQmxBaseStopTask(ATaskHandle);
17311733 DAQmxBaseClearTask(ATaskHandle);
17321734 end;
17331735 //stop program
17341736 Halt;
17351737 end;
17361738end;
17371739begin
17381740
17391741 {********CONFIGURE COUNTER TO USE AS CLOCK FOR DIGITAL INPUT*****************}
17401742 //create counter task
17411743 ErrorCheck(DAQmxBaseCreateTask('', CtrTaskHandle),CtrTaskHandle);
17421744 //create counter output channel
17431745 //Frequency 10000 Hz, duty 0.5
17441746 ErrorCheck(DAQmxBaseCreateCOPulseChanFreq(CtrTaskHandle,'Dev1/ctr0','',DAQmx_Val_Hz,DAQmx_Val_Low,0,10000,0.5),CtrTaskHandle);
17451747 //timing
17461748 //last value is not important for continuesly sample mode, for finite sample mode = generate 10000 samples
17471749 ErrorCheck(DAQmxBaseCfgImplicitTiming(CtrTaskHandle,DAQmx_Val_ContSamps,10000),CtrTaskHandle);
17481750 //start counter task
17491751 ErrorCheck(DAQmxBaseStartTask(CtrTaskHandle),CtrTaskHandle);
17501752 //generate frequency signal for 10 seconds
17511753 sleep(10000);
17521754 DAQmxBaseStopTask(CtrTaskHandle);
17531755 DAQmxBaseClearTask(CtrTaskHandle);
17541756end.
17551757```
17561758
17571759#### COUNTER INPUT
17581760
17591761Counter input is only software operated. It is limited by hardware driver.
17601762
17611763``` pascal
17621764program ctrin;
17631765
17641766{$mode objfpc}{$H+}
17651767
17661768uses
17671769 {$IFDEF UNIX}{$IFDEF UseCThreads}
17681770 cthreads,
17691771 {$ENDIF}{$ENDIF}
17701772 Classes,nidaqmxbase,StrUtils,SysUtils,Crt
17711773 { you can add units after this };
17721774var
17731775 CtrInTaskHandle:PTaskHandle;
17741776 NiBool:Pnibool;
17751777 data:dword=0;
17761778 reads:longint=0;
17771779procedure ErrorCheck(AError:longint;ATaskHandle:PTaskHandle);
17781780var
17791781 errBuffer:array[0..2048] of char;
17801782begin
17811783 //get error description
17821784 if DAQmxFailed(AError) = niTrue then begin
17831785 DAQmxBaseGetExtendedErrorInfo(ErrBuffer,2048);
17841786 writeln(ErrBuffer);
17851787 //stop and cleat task
17861788 if Assigned(ATaskHandle) then begin
17871789 DAQmxBaseStopTask(ATaskHandle);
17881790 DAQmxBaseClearTask(ATaskHandle);
17891791 end;
17901792 //stop program
17911793 Halt;
17921794 end;
17931795end;
17941796begin
17951797 {*****************CREATE COUNTER INPUT***************************************}
17961798 //create couter input task
17971799 ErrorCheck(DAQmxBaseCreateTask('Counter input task',CtrInTaskHandle),CtrInTaskHandle);
17981800 //create input counter for pulse counting
17991801 ErrorCheck(DAQmxBaseCreateCICountEdgesChan(CtrInTaskHandle,'Dev1/ctr1','',DAQmx_Val_Rising,0,DAQmx_Val_CountUp),CtrInTaskHandle);
18001802 //timing
18011803 //ErrorCheck(DAQmxBaseCfgSampClkTiming(CtrInTaskHandle,'/Dev1/Ctr0InternalOutput',1000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000),CtrInTaskHandle);
18021804 //start counter input task
18031805 ErrorCheck(DAQmxBaseStartTask(CtrInTaskHandle),CtrInTaskHandle);
18041806 //counting pulses
18051807 writeln('press any key to stop counting');
18061808 repeat
18071809 ErrorCheck(DAQmxBaseReadCounterU32(CtrIntaskHandle,1,10.0,data,1,reads,NiTrue),CtrIntaskHandle);
18081810 writeln('counter value: ',data);
18091811 until keypressed;
18101812 //clear and stop task
18111813 DAQmxBaseStopTask(CtrInTaskHandle);
18121814 DAQmxBaseClearTask(CtrInTaskHandle);
18131815end.
18141816```
18151817
18161818### TESTED HARDWARE
18171819
18181820Examples were tested under Scientific Linux 6.4, Mageia 2 32-bit and Windows 32-bit and should work under MacOS (**need test**) on cards:
18191821
18201822- **NI PCI-6250**
18211823- **NI PCI-6224**
18221824- **NI USB-6356** (Windows only)
18231825
18241826---
18251827*From the Free Pascal wiki, page "NI-DAQmx and NI-DAQmx Base examples", as it stood on 2019-12-23 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
18261828Category: FPC in Science and Technology
18271829Category: Hardware
18281830Category: Measuring and Instrumentation

Back to history