Thanks for your answer Jeremy.
I have two problems.
One is that pulse signal is not clear when vehicle is stop.
Other is it delaied.
So I post my program source code.
I referenced nidaq C++ source code for this routine.
At Start, I used ComponentWorks but unfortunately,
CWCTR(using two counters that Pulse train generation & output a counter pulse)component is not work with CWAI.
I tested example code of ComponentWorks, but it's not worked in delphi code.
I guess it is bug(?) of ComponentWorks.
(I hope that is wrong in my conjecture...)
So I use two methods(ComponentWork for analog signal acquisition and nidaq function for counter) at the same time.
This routine called in CWAI.OnAcquiredData Event.
Of course, it is thread funtion.
...
Next is explication of my system.
==============================================================
Acquistion Goal : 16ch A/I, GPS pulse(Speed of vehicle)
H/W : PCI-6033E, GPS
CNT0.Source = GPS pulse signal
CNT0.Gate = CTR1.Out
CNT1 = 20MH clock
S/W : WinXP, Delphi, ComponentWorks & ni-daq
==============================================================
Source Code
--------------------------------------------------------------
CNT_INTERNAL_CLOCK = 20000000;
CNT_HALF_GATE_W = 1000000;
CNT_BUFF_SIZE = 1;
CNT_DISTANCE_FACTOR = (1/(CNT_INTERNAL_CLOCK/(CNT_HALF_GATE_W * 2)))* CNT_BUFF_SIZE;
--------------------------------------------------------------
unit uCounter;
interface
uses
Windows, SysUtils, Classes, Forms, nidaqcns, nidaq,
SyncObjs, uCommon, Dialogs;
type
TSpeedCounter = class(TThread)
private
FSpeedList : TStringList;
FSync : TCriticalSection;
FEvent : TEvent;
FTriggerStarting : boolean;
FTriggerStarted : boolean;
FTriggerEnd : boolean;
FTriggerTick : dword;
function GetDevice : i16;
procedure SetDevice(const nDevice : i16);
function GetActive : boolean;
procedure SetActive(const Value: boolean);
function GetSamplingRate : integer;
procedure SetSamplingRate(const nSamplingRate : integer);
protected
FDevice : i16;
FStatus : i16;
FLowCount : u32;
FHighCount : u32;
FCounterOutput : u32;
FBufferCount : u32;
FArmed : u32;
FStop : boolean;
pulBuffer : array[0..CNT_BUFF_SIZE-1] of u32;
FSpeedMeter : double;
FSpeedPulse : double;
FSamplingRate : integer;
FSpeed : double;
FDistance : double;
FDistanceSum : double;
FPulseCount : integer;
FLoopCount : integer;
FPulseCountSum : integer;
FPulseCountTrigger : integer;
procedure ClearBuffer;
procedure InitAcq;
procedure PulseGenerate;
procedure StartAcq;
procedure Execute; override;
public
FSpeedArr : array [0..CNT_BUFF_SIZE-1] of double;
public
constructor Create( nDevice : i16;
dSpeedMeter : double;
dSpeedPulse : double;
nSamplingRate : integer); virtual;
destructor Destroy; override;
procedure TriggerStart;
procedure TriggerStop;
procedure StopAcq;
property Status : i16 read FStatus;
property LowCount : u32 read FLowCount;
property HighCount : u32 read FHighCount;
property CounterOutput : u32 read FCounterOutput;
property Speed : double read FSpeed;
property PulseCount : integer read FPulseCount;
property LoopCount : integer read FLoopCount;
property PulseCountSum : integer read FPulseCountSum;
property PulseCountTrigger : integer read FPulseCountTrigger;
property Distance : double read FDistance;
property DistanceSum : double read FDistanceSum;
published
property Active : boolean read GetActive write SetActive;
property Sync : TCriticalSection read FSync write FSync;
property SpeedList : TStringList read FSpeedList write FSpeedList;
property Device : i16 read GetDevice write SetDevice;
property SpeedMeter : double read FSpeedMeter write FSpeedMeter;
property SpeedPulse : double read FSpeedPulse write FSpeedPulse;
property SamplingRate : integer read GetSamplingRate write SetSamplingRate;
end;
implementation
uses
uMyFuncs;
{ TSpeedCounter }
constructor TSpeedCounter.Create( nDevice : i16;
dSpeedMeter : double;
dSpeedPulse : double;
nSamplingRate : integer);
begin
FDevice := nDevice;
FSpeedMeter := dSpeedMeter;
FSpeedPulse := dSpeedPulse;
FSamplingRate := nSamplingRate;
FSpeed := 0;
FDistance := 0;
FSpeedList := TStringList.Create;
FSync := TCriticalSection.Create;
FEvent := TEvent.Create(nil, False, False, '');
inherited Create(False);
end;
destructor TSpeedCounter.Destroy;
begin
Terminate;
FEvent.SetEvent;
WaitFor;
FEvent.Free;
FSpeedList.Free;
FSync.Free;
inherited Destroy;
end;
function TSpeedCounter.GetDevice : i16;
begin
Result := FDevice;
end;
procedure TSpeedCounter.SetDevice(const nDevice : i16);
begin
FDevice := nDevice;
end;
function TSpeedCounter.GetActive: boolean;
begin
Result := not FStop;
end;
procedure TSpeedCounter.SetActive(const Value: boolean);
begin
FStop := not Value;
end;
function TSpeedCounter.GetSamplingRate : integer;
begin
Result := FSamplingRate;
end;
procedure TSpeedCounter.SetSamplingRate(const nSamplingRate : integer);
begin
FSamplingRate := nSamplingRate;
end;
procedure TSpeedCounter.TriggerStart;
begin
FSync.Enter;
try
FTriggerStarting := True;
finally
FSync.Leave;
end;
end;
procedure TSpeedCounter.TriggerStop;
begin
FTriggerStarting := False;
FTriggerStarted := False;
FTriggerEnd := True;
end;
procedure TSpeedCounter.ClearBuffer;
var
i : integer;
begin
for i := Low(pulBuffer) to High(pulBuffer) do
begin
pulBuffer[i] := 0;
end;
end;
procedure TSpeedCounter.InitAcq;
begin
FBufferCount := CNT_BUFF_SIZE;
FLowCount := CNT_HALF_GATE_W;
FHighCount := CNT_HALF_GATE_W;
FCounterOutput := ND_GPCTR1_OUTPUT;
ClearBuffer;
end;
procedure TSpeedCounter.PulseGenerate;
begin
FStatus := 0;
// Pulse train generate.
FStatus := Select_Signal(FDevice, ND_RTSI_4, ND_IN_SCAN_START, ND_LOW_TO_HIGH); //6024
FStatus := GPCTR_Control(FDevice, ND_COUNTER_1, ND_RESET);
FStatus := GPCTR_Set_Application(FDevice, ND_COUNTER_1, ND_PULSE_TRAIN_GNR);
FStatus := GPCTR_Change_Parameter(FDevice, ND_COUNTER_1, ND_SOURCE, ND_INTERNAL_20_MHZ);
FStatus := GPCTR_Change_Parameter(FDevice, ND_COUNTER_1, ND_COUNT_1, FLowCount);
FStatus := GPCTR_Change_Parameter(FDevice, ND_COUNTER_1, ND_COUNT_2, FHighCount);
// To output a counter pulse, you must call Select_Signal.
FStatus := Select_Signal(FDevice, FCounterOutput, FCounterOutput, ND_LOW_TO_HIGH);
FStatus := GPCTR_Control(FDevice, ND_COUNTER_1, ND_PROGRAM);
end;
procedure TSpeedCounter.StartAcq;
var
ulInitCount : u32;
i : integer;
j : integer;
begin
ulInitCount := 0;
FArmed := ND_YES;
FStatus := 0;
FPulseCount := 0;
FDistance := 0;
FSpeed := 0;
// Buffered period meas.
FStatus := Set_DAQ_Device_Info(FDevice, ND_DATA_XFER_MODE_GPCTR0, ND_UP_TO_1_DMA_CHANNEL);
if FStatus <> 0 then
FStatus := Set_DAQ_Device_Info(FDevice, ND_DATA_XFER_MODE_GPCTR0, ND_INTERRUPTS);
FStatus := GPCTR_Control(FDevice, ND_COUNTER_0, ND_RESET);
FStatus := GPCTR_Set_Application(FDevice, ND_COUNTER_0, ND_BUFFERED_PERIOD_MSR);
// If you want to use a different GPCTR source, change the last parameter in this function.
FStatus := GPCTR_Change_Parameter(FDevice, ND_COUNTER_0, ND_SOURCE, ND_DEFAULT_PFI_LINE);
FStatus := GPCTR_Change_Parameter(FDevice, ND_COUNTER_0, ND_GATE, ND_DEFAULT_PFI_LINE);
// Load initial count.
FStatus := GPCTR_Change_Parameter(FDevice, ND_COUNTER_0, ND_INITIAL_COUNT, ulInitCount);
FStatus := GPCTR_Config_Buffer(FDevice, ND_COUNTER_0, 0, FBufferCount, @pulBuffer);
FStatus := GPCTR_Change_Parameter(FDevice, ND_COUNTER_0, ND_BUFFER_MODE, ND_CONTINUOUS);
FStatus := GPCTR_Control(FDevice, ND_COUNTER_0, ND_PROGRAM);
// Loop until 'ulGpctrNum' is no longer armed.
while (not Terminated) and (FStatus = 0) and (not FStop )do
begin
FStatus := GPCTR_Watch(FDevice, ND_COUNTER_0, ND_BUFFER_SIZE, @FArmed);
FPulseCount := 0;
FDistance := 0;
FSpeed := 0;
if FArmed = FBufferCount then
begin
FSync.Enter;
try
for i := Low(pulBuffer) to High(pulBuffer) do
begin
FPulseCount := pulBuffer[i];
FDistance := FPulseCount * (FSpeedMeter/FSpeedPulse);
FSpeed := FDistance * (3600 / CNT_DISTANCE_FACTOR / 1000) * CNT_BUFF_SIZE;
FLoopCount := 1;
end;
except
FPulseCount := 0;
FDistance := 0;
FSpeed := 0;
end;
FSync.Leave;
end
else
FPulseCount := FArmed;
Sleep(10);
end;
// Plot acquired count data. For your application, you may want to different representation of count data.
// CLEANUP - Don't check for errors on purpose.
// Reset GPCTR
FStatus := GPCTR_Control(FDevice, ND_COUNTER_0, ND_RESET);
FStatus := GPCTR_Control(FDevice, ND_COUNTER_1, ND_RESET);
end;
procedure TSpeedCounter.StopAcq;
begin
FStop := True;
end;
procedure TSpeedCounter.Execute;
begin
InitAcq;
PulseGenerate;
StartAcq;
end;
end.