0

I have code to control the settings of and grab images from a Basler acA720-290gm camera. After a period of running, if the exposure time is changed, the Pylon::CBaslerUniversalInstantCamera.RetrieveResult call starts timing out and the camera becomes unresponsive to further requests to change the exposure time. The exposure time is not set to be large enough that it should be causing a timeout.

This is the heart of the code in question:

void process_pylon(Pylon::String_t serial_number, int64_t width, int64_t height, int64_t packet_size, int64_t inter_packet_delay) {
    try {
        Pylon::CBaslerUniversalInstantCamera camera;
        Pylon::CTlFactory& tlFactory = Pylon::CTlFactory::GetInstance();
        Pylon::CDeviceInfo info;
        Pylon::DeviceInfoList_t filter;
        info.SetSerialNumber(serial_number);
        filter.push_back(info);
        Pylon::DeviceInfoList_t devices;

        while (1) {
            try {
                while (1) {
                    if (tlFactory.EnumerateDevices(devices, filter) > 0) {
                        g_print("The camera is connected.\n");
                        break;
                    }
                    else {
                        g_printerr("The camera is not connected.\n");
                        Pylon::WaitObject::Sleep(5000);
                    }
                }

                g_print("Attaching camera.\n");
                camera.Attach(tlFactory.CreateFirstDevice(info));

                g_print("Opening camera.\n");
                camera.Open();

                g_print("Setting width: %li\n", width);
                camera.Width.TrySetValue(width);

                g_print("Setting height: %li\n", height);
                camera.Height.TrySetValue(height);

                g_print("Setting GevSCPSPacketSize (packet size): %li\n", packet_size);
                camera.GevSCPSPacketSize.TrySetValue(packet_size);

                g_print("Setting GevSCPD (inter-packet delay): %li\n", inter_packet_delay);
                camera.GevSCPD.TrySetValue(inter_packet_delay);

                g_print("Starting grabbing.\n");
                camera.StartGrabbing(Pylon::GrabStrategy_LatestImageOnly);

                Pylon::CGrabResultPtr ptrGrabResult;

                exposure_auto_set = 1;
                exposure_time_raw_set = 1;
                gain_auto_set = 1;
                gain_raw_set = 1;

                while (1) {
                    // Exposure Time

                    int32_t epics_exposure_auto_req = exposure_auto_req;
                    int32_t epics_exposure_auto_set = exposure_auto_set;

                    if (epics_exposure_auto_set > 0) {
                        g_print("Setting auto exposure: %i\n", epics_exposure_auto_req);
                        camera.ExposureAuto.SetIntValue((int64_t) epics_exposure_auto_req);
                        exposure_auto_set = 0;
                    }
                    exposure_auto = camera.ExposureAuto.GetIntValue();


                    int32_t epics_exposure_time_raw_req = exposure_time_raw_req;
                    int32_t epics_exposure_time_raw_set = exposure_time_raw_set;

                    if (epics_exposure_time_raw_set > 0) {
                        g_print("Setting exposure time: %i\n", epics_exposure_time_raw_req);
                        camera.ExposureTimeRaw.TrySetValue((int64_t) epics_exposure_time_raw_req, Pylon::IntegerValueCorrection_Nearest);
                        exposure_time_raw_set = 0;
                    }
                    exposure_time_raw = camera.ExposureTimeRaw.GetValue();


                    // Gain

                    int32_t epics_gain_auto_req = gain_auto_req;
                    int32_t epics_gain_auto_set = gain_auto_set;

                    if (epics_gain_auto_set > 0) {
                        g_print("Setting auto gain: %i\n", epics_gain_auto_req);
                        camera.GainAuto.SetIntValue((int64_t) epics_gain_auto_req);
                        gain_auto_set = 0;
                    }
                    gain_auto = camera.GainAuto.GetIntValue();


                    int32_t epics_gain_raw_req = gain_raw_req;
                    int32_t epics_gain_raw_set = gain_raw_set;

                    if (epics_gain_raw_set > 0) {
                        g_print("Setting gain: %i\n", epics_gain_raw_req);
                        camera.GainRaw.TrySetValue((int64_t) epics_gain_raw_req, Pylon::IntegerValueCorrection_Nearest);
                        gain_raw_set = 0;
                    }
                    gain_raw = camera.GainRaw.GetValue();


                    try {
                        camera.RetrieveResult((unsigned int) timeout_ms, ptrGrabResult, Pylon::TimeoutHandling_ThrowException);
                        if (ptrGrabResult->GrabSucceeded()) {
                            if (image_mutex.try_lock()) {
                                image.AttachGrabResultBuffer(ptrGrabResult);
                                image_mutex.unlock();
                            }
                        }
                        else {
                            g_printerr("The grab failed.\n");
                            g_printerr("%s\n", ptrGrabResult->GetErrorDescription().c_str());
                        }
                    }
                    catch (const Pylon::TimeoutException e) {
                        g_printerr("%s\n", e.GetDescription());
                    }
                }
            }
            catch (const Pylon::GenericException& e) {
                Pylon::WaitObject::Sleep(1000);

                if (camera.IsCameraDeviceRemoved()) {
                    g_printerr("The connection to the camera has been lost.\n");
                    camera.DestroyDevice();
                }
                else {
                    g_printerr("%s\n", e.GetDescription());
                }
            }
        }
    }
    catch (const Pylon::GenericException& e) {
        g_printerr("An exception occurred.\n");
        g_printerr("%s\n", e.GetDescription());
        exit(-1);
    }
}
Patrick
  • 147
  • 1
  • 15
  • Just for curiosity - why are you trying to set up AutoExposure and AutoGain feature every single frame loop iteration? And why are you trying to set up fixed exposure/gain values after you set up auto functions? When auto functions are enabled, setting raw values has no effect. I cannot imagine of any usecase for setting auto mode each and every frame. Also, for clear code view, can you pls use GainAutoEnums instead of int32_t? My guess is that you're simply overloading the camera with too much configuration commands at minimum 290 cycles/s as for this camera. Pls describe your usecase. – Marcin Kowalski Jul 16 '23 at 11:25
  • @MarcinKowalski The camera parameters are not being set in every frame, only a check to see if the user is requesting to change one of them. – Patrick Jul 17 '23 at 20:52
  • Sure, I see now. Anyway, you're reading out these values at each loop, that still could produce unstable operation. Pls consider using Data Chunks functionality instead. When turned on, Exp/Gain values are automatically received inside grab result structure and you get rid of excessive read calls to camera. https://docs.baslerweb.com/data-chunks – Marcin Kowalski Jul 17 '23 at 23:30

0 Answers0