I am using two hyperspectral line cameras. The idea is to capture an image from CAM1 and then from CAM2 and then rotate the stepper motor, and repeat. Using the following code I can save images from CAM1 and CAM2, but having two issues as follows:
I need a routine to open the camera mechanical shutter or to make sure it is already open. I assume there must be function that I couldn’t find in my search.
I am able to set exposure time for CAM1 but unable to set it for CAM2. the CAM2 is acquiring images using the same exposure time what was set in genicam browser. Please have a look at the following code and let me know what i am doing wrong
Thanks in advance
int fx17Viewer::ScanON()
{
cout << “Load first camera” << endl;
Cvb::Camera camera(“%CVB%/drivers/GenICam.vin”);
// get GenICam access
Cvb::GenICam genICam(camera);
cvbval_t exposureTime = 20000;
genICam.setExposureTime(exposureTime); // setting exposure time Camera 1
camera.switchCamPort(1);
genICam.setExposureTime(exposureTime); // setting exposure time Camera 2
for (int k = 0 ; k<4 ; k++)
{
camera.switchCamPort(0);
cout << “switching to port 0 (Camera 1)” << endl;
// Activate TriggerMode
if(!genICam.setTriggerMode(true))
{
LogError("Activating TriggerMode was not possible");
}
else
{
// Set "TriggerSource" to "Software"
if(!genICam.setTriggerSource("Software"))
{
LogError("Changing TriggerSource to Software was not possible");
}
else
{
TriggeredAcquisition(camera, genICam);
}
saveImage(camera, "NIR" , k);
// Disable TriggerMode
if(!genICam.setTriggerMode(false))
LogError("Disabling TriggerMode was not possible");
}
//*********************** Change of camera port now ***********************//
cout << "switching to port 1 (camera 2)" << endl;
camera.switchCamPort(1);
// Activate TriggerMode
if(!genICam.setTriggerMode(true))
{
LogError("Activating TriggerMode was not possible");
}
else
{
// Set "TriggerSource" to "Software"
if(!genICam.setTriggerSource("Software"))
{
LogError("Changing TriggerSource to Software was not possible");
}
else
{
TriggeredAcquisition(camera, genICam);
}
saveImage(camera, "VNIR" , k);
// Disable TriggerMode
if(!genICam.setTriggerMode(false))
LogError("Disabling TriggerMode was not possible");
}
Cvb::this_thread::sleep(50);
For this point we need more time since our product specialist for the camera is in vacation and would be available next week.
When you can change the exposure time in one camera you should as well be able to change it in the other one. Are they different cameras? Can you get images from both cameras? From the code it is not clear what exactly the SwitchCamPort() does. Basically when you need the images from both configured cameras using GenICam.vin, you should use the following code:
auto path = Cvb::InstallPath();
path += CVB_LIT("drivers/GenICam.vin");
// open devices
auto device = Cvb::DeviceFactory::Open(path, 0, 0);
auto device2 = Cvb::DeviceFactory::Open(path, 1, 0);
Yes, I can get images from both cameras. the cameras are not exactly same, but they are similar in functionalities. My script is based on tutorial: ComplexMultiOSConsoleExample
Following is the implementation of SwitchCamPort() function:
// ---------------------------------------------------------------------------
/// \brief Change port to the given camera port
///
/// \param [in] camPort Camera port to change to.
/// \throws CvbError thrown if an error occurred while switching the port.
// ---------------------------------------------------------------------------
void Cvb::Camera::switchCamPort(cvbval_t camPort)
{
// Check if current port is already the needed camPort
if(getPort() == camPort)
return;
if(camPort >= getNumCameras())
throw CvbError("Changing camera port not possible. Given port is not available");
// Change the port
IMG hImgNew = NULL;
cvbres_t result = CS2SetCamPort(cvbImage_.get(), camPort, 0, hImgNew);
if(result != 0)
throw CvbError("Changing camera port not possible. Error calling CS2SetCamPort", result);
// Set the new CvbImage Object to the original. The old image will be released automatically.
cvbImage_ = CvbImage(hImgNew, CvbImage::dontShare);
}
The constructor of the GenICam object set the internal parameter _nodemap. That means switching the camera ports gives you the correct images but does not assign a new nodemap. You should instantiate a second object of the class GenICam and give it the camera port1. :
Cvb::GenICam genICam(camera);
cvbval_t exposureTime = 20000;
genICam.setExposureTime(exposureTime); // setting exposure time Camera 1
Cvb::GenICam genICam2(camera.switchCamPort(1));
genICam2.setExposureTime(exposureTime); // setting exposure time Camera 2
In general for new applications we recommend not to use c-style wrapper located in VC folder but the Object-Oriented ones which can be found in Cvb++ folder.
thanks for the feedback. Concerning your motor shutter: How this is controlled is usually a highly device-dependent issue (specifically: motorized shutters are relatively uncommon).
I would guess that one of the following applies:
Either the shutter is being operated by an electronic pulse generated by the sensor; in that case, as long as the wiring is done correctly it should work more or less automatically.
Or the shutter might be controlled through a node map entry that can be set by regular means.
In either case it will probably be necessary to consult the camera’s manual as the answer cannot be given generically. If you want to pursue this topic here in the forum, then I think a separate post would be better suited.
“Std::MotorShutter_PulseFwd”
Closes the mechanical shutter by writing a value of 200/201.
“Std::MotorShutter_PulseRev”
Opens the mechanical shutter by writing a value of 200/201.
But in order to write the parameter you need to change its value. So you need to toggle between 200 and 201. Because if you set the parameter to 200 and it already was 200 the shutter state wont change.
Unfortunately there is no indicator available which shows the current state of it (open or closed).
So in order to make certain the shutter is open you need to set the parameter “Std::MotorShutter_PulseRev” twice. Once to 200, the second time to 201. This will make sure its opened.
The same applies for closing it. Change parameter “Std::MotorShutter_PulseFwd” twice, 200 and 201.
Many thanks for your replies. I am trying to narrow it down - I can open the motorized shutter using the following piece of code before calling int fx17Viewer::ScanON() //see the function in my initial question:
NODE nodeToSet = 0;
cvbres_t result = NMGetNode(hNodeMap, "MotorShutter_PulseRev", nodeToSet);
result = NSetAsInteger(nodeToSet, 200);
and it is working as needed for CAM1. Now the issue is: i need to open the shutter of the second camera after switching to port 1
here I am unable to use the code that works outside the function. I assume I need to get the nodemap through genICam2. Please correct me if I am thinking wrong or suggest me the possible solution/workaround, if you can
Every camera has their own node map, therefore yes, when you switch to a different camera you will need to get that camera’s node map to work on that camera’s shutter.
By the way: It might in fact be a better choice to open both cameras and keep them open instead of switching pack and forth.