Machine Vision

cancel
Showing results for 
Search instead for 
Did you mean: 

[Failed] Integration of externally triggering a camera with generating a pulse train using DAQmx C API

I would like to make an integrated programming code of hardware-triggering a camera with generating a pulse train.

 

If anyone could address this issue or make a comment on this then, I would appreciate a lot.

 

Attached below is the snippet for this work.

 

Below are the hardware and software specifications that I am using now for this work.
---------------------------------------------------------------------------------------------------------------------------
DAQ board: NI USB-6363 (BNC)

Camera: IDS camera (Model: U3-38J1XLE-M-GL_Rev_1_1)

Camera feature: 'ReadOutStart' only surpported as a 'TriggerSelector' parameter

Camera pin: An external trigger input is supported only. There is no any flash light output.

Programming language: Visual Studio 2017, MFC (Microsoft Foundation Class)
---------------------------------------------------------------------------------------------------------------------------

 

In detail, I have already checked that an externally-triggered camera MFC code alone could capture image quite well by using a sample code of 'VC_DigPulseTrain_Cont' at DAQmx C API. According to the pulse frequency that I adjusted in the 'VC_DigPulseTrain_Cont', the frame rate of a real time image was reflected well. However, Those codes are not yet integrated but separated at present.

In the snippet that I attached, I had tried to integrate the two codes together for making one MFC code. Therefore, I tried to use a synchronization object of 'CEvent' in order not to monopolize a CPU from a worker thread of 'AcquisitionWorker()' so that I expected to do a pulse generation seamlessly. However, the integrated code is not working. That is, any pulse train does not be shown on an oscilloscope and thus the camera can not capture an image any more.

 

In Labview, in my memory, the synchronization between a camera and a DAQmx trigger signal is carried out by correctly deploying all the configurations on 'Merge Errors.vi' right before a 'while' loop. So, I tried to imitate the advanced synchronization Labview examples between devices.

 

Below is a representative snippet inserted in the attached.
 
// Start capture worker thread
m_threadAcquisition = AfxBeginThread(AcquisitionWorker, this);
g_EvCam_capture_ready.PulseEvent();
DAQmxStartTask(FTTaskHandle);
 

Kindest regards and many thanks in advance,

Headalma

0 Kudos
Message 1 of 5
(1,131 Views)

As shown in the 'Case A' below, such a 'DAQmxCfgDigEdgeStartTrig()' should be needed for an exact synchronization? However, my camera has only an external trigger 'input' port. There is no any flashlight 'output' port in the camera. Thus, I thought that the case B below would be enough for my application. Please let me know about any fault in my logic.

 

Case A:

// Configure the DAQmx task for pulse generation

DAQmxErrChk(DAQmxCreateCOPulseChanFreq(taskHandle, "Dev2/ctr0", "", DAQmx_Val_Hz, DAQmx_Val_Low, 0.0, 7.0, 0.5));

DAQmxErrChk(DAQmxCfgDigEdgeStartTrig(taskHandle, "/Dev2/PFI0", DAQmx_Val_Rising));

 

Case B:

DAQmxErrChk (DAQmxCreateCOPulseChanFreq(FTTaskHandle, "Dev2/ctr0", "", DAQmx_Val_Hz, DAQmx_Val_Low, 0.0, FRAME_TRIG_FREQ, 0.50)); // 12 fps
DAQmxErrChk (DAQmxCfgImplicitTiming(FTTaskHandle, DAQmx_Val_ContSamps, 1));

0 Kudos
Message 2 of 5
(1,095 Views)

Even though I tried to use 'DAQmxCfgDigEdgeStartTrig()' as shown below, it does not work yet.

 

A snippet of OnInitDialog():

 

// Generating a Frame Trigger signal
DAQmxErrChk(DAQmxCreateTask("Task_Trigger_Signal0", &FTTaskHandle0));
DAQmxErrChk(DAQmxCreateCOPulseChanFreq(FTTaskHandle0, "Dev2/ctr0", "", DAQmx_Val_Hz, DAQmx_Val_Low, 0.0, FRAME_TRIG_FREQ, 0.1)); //If exposure time is 10.0usec, 10.0*CounterFrequency/1000000
DAQmxErrChk(DAQmxCfgDigEdgeStartTrig(FTTaskHandle0, "/Dev2/Ctr1InternalOutput", DAQmx_Val_Rising));
DAQmxErrChk(DAQmxSetStartTrigRetriggerable(FTTaskHandle0, TRUE));
 
DAQmxErrChk (DAQmxCreateTask("Task_Trigger_Signal1", &FTTaskHandle1));
DAQmxErrChk (DAQmxCreateCOPulseChanFreq(FTTaskHandle1, "Dev2/ctr1", "", DAQmx_Val_Hz, DAQmx_Val_Low, 0.0, FRAME_TRIG_FREQ, 0.1)); // 12 fps
DAQmxErrChk (DAQmxCfgImplicitTiming(FTTaskHandle1, DAQmx_Val_ContSamps, 1));
 
A snippet of StartAcquisition(): 
 
m_stopThreadAcquisition = false;
m_threadAcquisitionRunning = true;
m_firstExecuting = true;
 
// Start capture worker thread
m_threadAcquisition = AfxBeginThread(AcquisitionWorker, this);
 
g_EvCam_capture_ready.PulseEvent();
 
DAQmxStartTask(FTTaskHandle0);
DAQmxStartTask(FTTaskHandle1);
0 Kudos
Message 3 of 5
(1,088 Views)

For your information, The camera external trigger 'input' port was directly connected with the PFI12 (i.e., Counter Output 0's terminal) on the DAQ board via BNC to Alligator clip cable.

0 Kudos
Message 4 of 5
(1,082 Views)

Regarding the above, I would like to revise one point. I mentioned that when the TTL pulse generation code and the externally-triggered camera are operating individually (named 'separate codes' situation), then the camera can capture an image. 

 

At that situation, frankly, I did not use 'Lock()' which belongs to 'CEvent' Synchronization Object.

 

In summary, even though the 'separate codes' are operating independently, when I insert the 'Lock()', then the TTL pulse signal was not generated any more and thus the camera did not capture any image.

 

Therefore, I conclude that the key to the solution might be depending on whether or not such a 'Lock()', which is one of synchronization object classes, would be utilized correctly.

 

Any comments on this would be much appreciated.

 

Below is a snippet in case the 'separate codes' are working well.

 

while (parent->m_threadAcquisitionRunning)
{
// g_EvCam_capture_ready.Lock();
 
bool acquired = false;
 
try
{
// Get buffer from device's datastream. The buffer is automatically locked until it is queued again.
const auto buffer = parent->m_dataStream->WaitForFinishedBuffer(5000);
 
auto image = parent->m_imageConverter->Convert(peak::BufferTo<peak::ipl::Image>(buffer), 
peak::ipl::PixelFormatName::Mono8);
 
// Queue buffer so that it can be used again
parent->m_dataStream->QueueBuffer(buffer);
 
// Rotate by 90 degrees
parent->m_imageTransformerIPL.RotateInPlace(image, peak::ipl::ImageTransformer::RotationAngle::Degree90Clockwise);
 
// Display buffer in window
parent->RenderBitmap(static_cast<unsigned char*>(image.Data()));
 
acquired = true;
}
0 Kudos
Message 5 of 5
(1,070 Views)