IDS Peak comfortSDK, genericSDK, IPL, and AFL developer manuals are external documents. Please contact us if you need them.
When your system consists of multiple cameras, you might want to make them capture the images at the same time or in a defined time sequence.
1.If your requirements in terms or timing are not very high, you can use the software trigger mode and send the TriggerSoftware command to all cameras one by one. There will be a non-deterministic delay for each camera due to the different transmission times, but for some applications the timing is accurate enough.
3.Use one camera as master and trigger all other cameras with its output signal. Compared to hardware trigger, this solution needs no additional trigger source. Compared to software trigger, this solution has a deterministic trigger delay and all cameras start the exposure at the same time.
Note that the flash signal will not match precisely at very short exposure times, as almost all sensors have a jitter in the delay.
Note on I/O pinning and circuits
For I/O pin assignment and circuit information for your camera model, refer to the technical manual of the respective camera family.
You might need additional hardware for your synchronization signal if:
•Using USB3 cameras
•Connecting many slave cameras to one master camera
•Using long cables
NOTICE! You should not mix opto-coupled and non-opto-coupled lines (LineFormat = LVTTL or TriState) without signal processing hardware (level and direction). This could damage your camera.
Configuration
Each camera, master and slave, is configured to start the image capture on a signal on the physical line, as explained in hardware trigger mode.
Camera
Line
Description
Master
Line 0
Hardware trigger signal input
Line 2
Connected to Line 2 of slave camera
Slave
Line 2
Connected to Line 2 of master camera
Master camera configuration
The master camera uses a timer to generate the signal for the physical line. The duration of the timer corresponds to the duration of the signal on that line.
// Timer duration defines the signal duration for the slave cameras (us) TimerSelector=Timer0; TimerDuration=1000.0;// 1ms TimerTriggerSource=ExposureTrigger;
The source for the output line is this "Timer0Active" signal (or "Timer1Active", if you use "Timer1"). Using inverted GPIOs instead of opto-coupled inputs and outputs keeps delays as small as possible.
// Configure the output line, preferrably a GPIO LineSelector=Line2; LineMode=Output; LineSource=Timer0Active; LineInverter=True;
Now the "ExposureStart" trigger can use exactly the same signal on the output line, that is also sent to the slave cameras to synchronize capture times.
Now, the master camera's image acquisition can be started.
// Start Acquisition AcquisitionStart();
Slave camera configuration
The slave cameras receive the synchronization signal on one of the input lines. Using GPIOs instead of opto-coupled in- and outputs keeps delays as small as possible.
// Configure the input line, preferrably a GPIO LineSelector=Line2; LineMode=Input;
Use the synchronization signal for triggering "ExposureStart".
// Timer duration defines the signal duration for the slave cameras (us) TimerSelector=Timer0; TimerDuration=1000.0; TimerTriggerSource=Line3; TimerTriggerActivation=FallingEdge;
Slave camera configuration: The configuration for slave cameras is the same. Add the TriggerDelay to adjust slight timing differences between slave cameras, if necessary.
try { // Configuration of the master camera // Get RemoteDevice NodeMap automasterNodeMapRemoteDevice=masterDevice->RemoteDevice()->NodeMaps().at(0); // Configure the timer on the master camera to generate the synchronization signal // Timer duration defines the signal duration for the slave cameras (us) masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TimerSelector")->SetCurrentEntry("Timer0"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::FloatNode>("TimerDuration")->SetValue(1000.0); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TimerTriggerSource")->SetCurrentEntry("Off"); // Configure the synchronization signal on an output line, preferrably a GPIO masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineSelector")->SetCurrentEntry("Line2"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineMode")->SetCurrentEntry("Output"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineSource")->SetCurrentEntry("Timer0Active"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::BooleanNode>("LineInverter")->SetValue(true); // Configure ExposureStart Trigger masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSelector")->SetCurrentEntry("ExposureStart"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerMode")->SetCurrentEntry("On"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSource")->SetCurrentEntry("Line2"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerActivation")->SetCurrentEntry("FallingEdge"); // VARIATON: Add the TriggerDelay to adjust possible delays masterNodeMapRemoteDevice->FindNode<peak::core::nodes::FloatNode>("TriggerDelay")->SetValue(30.0); // Configuration of the slave camera(s) // Get RemoteDevice NodeMap autoslaveNodeMapRemoteDevice=slaveDevice->RemoteDevice()->NodeMaps().at(0); // Configure the synchronization signal on an output line, preferrably a GPIO slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineSelector")->SetCurrentEntry("Line2"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineMode")->SetCurrentEntry("Input"); // Configure ExposureStart Trigger slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSelector")->SetCurrentEntry("ExposureStart"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerMode")->SetCurrentEntry("On"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSource")->SetCurrentEntry("Line2"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerActivation")->SetCurrentEntry("FallingEdge"); // VARIATON: Add the TriggerDelay to adjust possible delays slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::FloatNode>("TriggerDelay")->SetValue(5.0); // Next step: start acquisition on all cameras // ... // If TimerSelector has been changed in the meantime, uncomment the following line // masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TimerSelector")->SetCurrentEntry("Timer0"); // Trigger the acquisition of an image masterNodeMapRemoteDevice->FindNode<peak::core::nodes::CommandNode>("TimerReset")->Execute(); // Stop acquisition // ... } catch(conststd::exception&e) { std::stringstrError=e.what(); // ... } // ALTERNATIVE: Hardware signal as master trigger signal try { // Configuration of the master camera // Get RemoteDevice NodeMap automasterNodeMapRemoteDevice=masterDevice->RemoteDevice()->NodeMaps().at(0); // Configure the timer on the master camera to generate the synchronization signal // Timer duration defines the signal duration for the slave cameras (us) masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TimerSelector")->SetCurrentEntry("Timer0"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::FloatNode>("TimerDuration")->SetValue(1000.0); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TimerTriggerSource")->SetCurrentEntry("Line3"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TimerTriggerActivation")->SetCurrentEntry("FallingEdge"); // Configure the synchronization signal on an output line, preferrably a GPIO masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineSelector")->SetCurrentEntry("Line2"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineMode")->SetCurrentEntry("Output"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineSource")->SetCurrentEntry("Timer0Active"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::BooleanNode>("LineInverter")->SetValue(true); // Configure ExposureStart Trigger masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSelector")->SetCurrentEntry("ExposureStart"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerMode")->SetCurrentEntry("On"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSource")->SetCurrentEntry("Line3"); masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerActivation")->SetCurrentEntry("FallingEdge"); // VARIATON: Add the TriggerDelay to adjust possible delays masterNodeMapRemoteDevice->FindNode<peak::core::nodes::FloatNode>("TriggerDelay")->SetValue(30.0); // Configuration of the slave camera(s) // Get RemoteDevice NodeMap autoslaveNodeMapRemoteDevice=slaveDevice->RemoteDevice()->NodeMaps().at(0); // Configure the synchronization signal on an output line, preferrably a GPIO slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineSelector")->SetCurrentEntry("Line2"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("LineMode")->SetCurrentEntry("Input"); // Configure ExposureStart Trigger slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSelector")->SetCurrentEntry("ExposureStart"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerMode")->SetCurrentEntry("On"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerSource")->SetCurrentEntry("Line2"); slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TriggerActivation")->SetCurrentEntry("FallingEdge"); // VARIATON: Add the TriggerDelay to adjust possible delays slaveNodeMapRemoteDevice->FindNode<peak::core::nodes::FloatNode>("TriggerDelay")->SetValue(5.0); // Next step: start acquisition on all cameras // ... // If TimerSelector has been changed in the meantime, uncomment the following line // masterNodeMapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("TimerSelector")->SetCurrentEntry("Timer0"); // Image Acquisition is triggered with each falling edge of the master signal (Line3 of master camera) // Stop acquisition // ... } catch(conststd::exception&e) { std::stringstrError=e.what(); // ... }