diff --git a/C sharp/Thorlabs BP209 Beam Profiler 2D Output/Thorlabs.BP2_CSharpDemo/Form1.cs b/C sharp/Thorlabs BP209 Beam Profiler 2D Output/Thorlabs.BP2_CSharpDemo/Form1.cs index 5ccb7f4..36c65fe 100644 --- a/C sharp/Thorlabs BP209 Beam Profiler 2D Output/Thorlabs.BP2_CSharpDemo/Form1.cs +++ b/C sharp/Thorlabs BP209 Beam Profiler 2D Output/Thorlabs.BP2_CSharpDemo/Form1.cs @@ -1,20 +1,22 @@ // Title: BP209 2D Reconstruction C Sharp Example. // Created Date: 2024 - 10 - 12 -// Last modified date: 2024 - 10 - 12 +// Last modified date: 2025 - 11 - 26 // .NET version: 4.8 -// Thorlabs SDK Version: Beam version 9.1.5787.560 +// Thorlabs SDK Version: Beam version 9.3 // Notes: This example is based on the C sharp example which is installed to // C:\Program Files (x86)\IVI Foundation\VISA\WinNT\TLBP2\Examples during software installation. // This example has added the 2D reconstruction algorithm and the reconstructed beam image is displayed. namespace Thorlabs.BP2_CSharpDemo { - using System; + using System; + using System.Data; + using System.Drawing; + using System.Drawing.Imaging; + using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; - using System.Drawing; using Thorlabs.TLBP2.Interop; - using System.Runtime.InteropServices; /// /// Initializes the form @@ -36,16 +38,6 @@ public partial class Form1 : Form /// private Timer scanTimer = null; - /// - /// array of data structures for each slit. - /// - private bp2_slit_data[] bp2SlitData = new bp2_slit_data[4]; - - /// - /// array of calculation structures for each slit. - /// - private bp2_calculations[] bp2Calculations = new bp2_calculations[4]; - /// /// Initializes a new instance of the class. /// @@ -59,9 +51,6 @@ public Form1() // implementation with driver functions this.ConnectToTheFirstDevice(); - // alternative implementation - ////this.connectToTheFirstDeviceByRM(); - if (this.bp2Device != null) { // get the instrument information @@ -89,7 +78,6 @@ public Form1() ushort sampleCount; double sampleResolution; this.status = this.bp2Device.clear_drum_speed_offset(); - this.status = this.bp2Device.set_drum_speed(10.0); this.status = this.bp2Device.set_drum_speed_ex(10.0, out sampleCount, out sampleResolution); // activate the position correction to have the same calculation results as the Thorlabs Beam Application @@ -101,11 +89,8 @@ public Form1() // activate the drum speed correction this.status = this.bp2Device.set_speed_correction(true); - // use the offset for 10Hz to be compatible with the release version 5.0 - this.status = this.bp2Device.set_reference_position(0, 4, 100.0); - this.status = this.bp2Device.set_reference_position(1, 4, -100.0); - this.status = this.bp2Device.set_reference_position(2, 4, 100.0); - this.status = this.bp2Device.set_reference_position(3, 4, -100.0); + // return all position coordinates from -4500 µm to 4500 µm and flip the x scans + this.status = this.bp2Device.setThorlabsBeamCompatibleCoordinateSystem(true); // poll for a valid scan this.scanTimer = new Timer(); @@ -152,22 +137,6 @@ private void ConnectToTheFirstDevice() } } - /// - /// search for connected devices and connect to the first one. - /// Use the VISA resource manager and simple data types. - /// - private void ConnectToTheFirstDeviceByRM() - { - // get the resource string of the first device - string[] bp2Resources = BP2_ResourceManager.FindRscBP2(); - - if (bp2Resources.Length > 0) - { - // connect to the first device - this.bp2Device = new TLBP2(bp2Resources[0], false, false); - } - } - /// /// poll for a new measurement and fill the structures with the calculation results. /// @@ -177,7 +146,7 @@ private void GetMeasurement() double drumSpeed; try { - if (0 == this.bp2Device.get_drum_speed(out drumSpeed)) + if (0 == this.bp2Device.get_averaged_drum_speed(out drumSpeed)) { this.textBox_drumSpeed.Text = drumSpeed.ToString("f2"); } @@ -200,70 +169,87 @@ private void GetMeasurement() else if ((deviceStatus & 2) == 2) this.toolStripStatusLabel1.Text = "Instrument is ready"; } - - // the gain and drum speed will be corrected during the measurement + double power; - float powerWindowSaturation; - if ((deviceStatus & 1) == 1 && - 0 == this.bp2Device.get_slit_scan_data(this.bp2SlitData, this.bp2Calculations, out power, out powerWindowSaturation, null)) + float powerSaturation; + ushort peakIndex1, peakIndex2,sampleCount1,sampleCount2,centroidIndexSlit1, centroidIndexSlit2; + float peakPositionSlit1, peakPositionSlit2, centroidPositionSlit1, centroidPositionSlit2, peakIntensitySlit1, peakIntensitySlit2; + float darkLevelSlit1, darkLevelSlit2; + + if ((deviceStatus & 1) == 1 && 0 == this.bp2Device.request_scan_data(out power, out powerSaturation, null)) { - this.textBox_peakPositionSlit1.Text = this.bp2Calculations[0].PeakPosition.ToString("f2"); - this.textBox_peakIntensitySlit1.Text = (this.bp2Calculations[0].PeakIntensity * 100.0f / ((float)0x7AFF - this.bp2SlitData[0].SlitDarkLevel)).ToString("f2"); - this.textBox_centroidPositionSlit1.Text = this.bp2Calculations[0].CentroidPos.ToString("f2"); + // get the peak position and centriod position + + this.bp2Device.get_slit_peak(0, out peakIndex1, out peakPositionSlit1, out peakIntensitySlit1); + this.bp2Device.get_slit_peak(1, out peakIndex2, out peakPositionSlit2, out peakIntensitySlit2); + this.bp2Device.get_scan_data_information(0, out sampleCount1, out darkLevelSlit1); + this.bp2Device.get_scan_data_information(1, out sampleCount2, out darkLevelSlit2); + this.bp2Device.get_slit_centroid(0, out centroidIndexSlit1,out centroidPositionSlit1); + this.bp2Device.get_slit_centroid(1, out centroidIndexSlit2, out centroidPositionSlit2); + + this.textBox_peakPositionSlit1.Text = peakPositionSlit1.ToString("f2"); + this.textBox_peakIntensitySlit1.Text = (peakIntensitySlit1 * 100.0f / ((float)0x7AFF - darkLevelSlit1)).ToString("f2"); + this.textBox_centroidPositionSlit1.Text = centroidPositionSlit1.ToString("f2"); - this.textBox_peakPositionSlit2.Text = this.bp2Calculations[1].PeakPosition.ToString("f2"); - this.textBox_peakIntensitySlit2.Text = (this.bp2Calculations[1].PeakIntensity * 100.0f / ((float)0x7AFF - this.bp2SlitData[1].SlitDarkLevel)).ToString("f2"); - this.textBox_centroidPositionSlit2.Text = this.bp2Calculations[1].CentroidPos.ToString("f2"); + this.textBox_peakPositionSlit2.Text = peakPositionSlit2.ToString("f2"); + this.textBox_peakIntensitySlit2.Text = (peakIntensitySlit2 * 100.0f / ((float)0x7AFF - darkLevelSlit2)).ToString("f2"); + this.textBox_centroidPositionSlit2.Text = centroidPositionSlit2.ToString("f2"); - this.textBox_powerSaturation.Text = (powerWindowSaturation*100.0).ToString("f2"); + this.textBox_powerSaturation.Text = (powerSaturation*100.0).ToString("f2"); - this.chart25um.Series[0].Points.DataBindXY(bp2SlitData[0].SlitSamplesPositions, bp2SlitData[0].SlitSamplesIntensities); - this.chart25um.Series[1].Points.DataBindXY(bp2SlitData[1].SlitSamplesPositions, bp2SlitData[1].SlitSamplesIntensities); - this.chart5um.Series[0].Points.DataBindXY(bp2SlitData[2].SlitSamplesPositions, bp2SlitData[2].SlitSamplesIntensities); - this.chart5um.Series[1].Points.DataBindXY(bp2SlitData[3].SlitSamplesPositions, bp2SlitData[3].SlitSamplesIntensities); + GetChartAnd2DReconstruction(); - //Calculate and display the 2D reconstruction image - Get2DReconstruction(); } } /// /// Calculate the 2D reconstructed beam intensity distribution and display the image on the WinForm /// - private void Get2DReconstruction() + private void GetChartAnd2DReconstruction() { - double[] sampleIntensitiesX = new double[7500]; - double[] sampleIntensitiesY = new double[7500]; - double[] samplePositionX = new double[7500]; - double[] samplePositionY = new double[7500]; - double[] gaussianFitIntensitiesX = new double[7500]; - double[] gaussianFitIntensitiesY = new double[7500]; - double power; - float powerSaturation; + double[] sampleIntensities25umX = new double[7500]; + double[] sampleIntensities25umY = new double[7500]; + double[] samplePosition25umX = new double[7500]; + double[] samplePosition25umY = new double[7500]; + double[] sampleIntensities5umX = new double[7500]; + double[] sampleIntensities5umY = new double[7500]; + double[] samplePosition5umX = new double[7500]; + double[] samplePosition5umY = new double[7500]; + double[] gaussianFitIntensities25umX = new double[7500]; + double[] gaussianFitIntensities25umY = new double[7500]; float temp; - - //Request the scan data - this.bp2Device.request_scan_data(out power,out powerSaturation,null); + //Get the intensities from the 25um X slit and the 25um Y slit - this.bp2Device.get_sample_intensities(0, sampleIntensitiesX, samplePositionX); - this.bp2Device.get_sample_intensities(1, sampleIntensitiesY, samplePositionY); + this.bp2Device.get_sample_intensities(0, sampleIntensities25umX, samplePosition25umX); + this.bp2Device.get_sample_intensities(1, sampleIntensities25umY, samplePosition25umY); + + //Get the intensities from the 5um X slit and the 5um Y slit + this.bp2Device.get_sample_intensities(2, sampleIntensities5umX, samplePosition5umX); + this.bp2Device.get_sample_intensities(3, sampleIntensities5umY, samplePosition5umY); + + //Chart display + this.chart25um.Series[0].Points.DataBindXY(samplePosition25umX, sampleIntensities25umX); + this.chart25um.Series[1].Points.DataBindXY(samplePosition25umY, sampleIntensities25umY); + this.chart5um.Series[0].Points.DataBindXY(samplePosition5umX, sampleIntensities5umX); + this.chart5um.Series[1].Points.DataBindXY(samplePosition5umY, sampleIntensities5umY); //Get the gaussian fit intensites from the 25um X slit and the 25um Y slit - this.bp2Device.get_slit_gaussian_fit(0, out temp,out temp,out temp,gaussianFitIntensitiesX); - this.bp2Device.get_slit_gaussian_fit(1, out temp, out temp, out temp, gaussianFitIntensitiesY); + this.bp2Device.get_slit_gaussian_fit(0, out temp,out temp,out temp, gaussianFitIntensities25umX); + this.bp2Device.get_slit_gaussian_fit(1, out temp, out temp, out temp, gaussianFitIntensities25umY); //2D reconstruction - double[,] imageData = new double[750, 750]; + int imageSize = 750; + double[,] imageData = new double[imageSize, imageSize]; double imageDataMax = 0; int ixz, iyz; - for (int ix = 0; ix < 750; ix++) + for (int ix = 0; ix < imageSize; ix++) { - for (int iy = 0; iy < 750; iy++) + for (int iy = 0; iy < imageSize; iy++) { //2D reconstruction algorithm - ixz = (750 - ix - 1) * 10; - iyz = (750 - iy - 1) * 10; - imageData[ix, iy] = sampleIntensitiesX[ixz] * gaussianFitIntensitiesX[ixz] * sampleIntensitiesY[iyz] * gaussianFitIntensitiesY[iyz]; + ixz = (imageSize - ix - 1) * 7500 / imageSize; + iyz = (imageSize - iy - 1) * 7500 / imageSize; + imageData[ix, iy] = sampleIntensities25umX[ixz] * gaussianFitIntensities25umX[ixz] * sampleIntensities25umY[iyz] * gaussianFitIntensities25umY[iyz]; //set the negative values to zero if (imageData[ix, iy] < 0) @@ -279,22 +265,29 @@ private void Get2DReconstruction() } //Normalize intensity values and generate the Bitmap image - int imageGrayValue; - Bitmap bitmap = new Bitmap(750, 750); - for (int x = 0; x < 750; x++) + Bitmap bitmap = new Bitmap(imageSize, imageSize, PixelFormat.Format24bppRgb); + BitmapData bmpData = bitmap.LockBits( + new Rectangle(0, 0, imageSize, imageSize),ImageLockMode.WriteOnly,bitmap.PixelFormat); + + int stride = bmpData.Stride; + byte[] pixelData = new byte[stride * imageSize]; + + for (int y = 0; y < imageSize; y++) { - for (int y = 0; y < 750; y++) + for (int x = 0; x < imageSize; x++) { - imageGrayValue = (int)(imageData[x, y] * 255 / imageDataMax); - Color color = Color.FromArgb(imageGrayValue, imageGrayValue, imageGrayValue); - bitmap.SetPixel(x, y, color); + int gray = (int)(imageData[x, y] * 255 / imageDataMax); + gray = Math.Min(255, Math.Max(0, gray)); + int pixelIndex = y * stride + x * 3; + pixelData[pixelIndex + 0] = (byte)gray; + pixelData[pixelIndex + 1] = (byte)gray; + pixelData[pixelIndex + 2] = (byte)gray; } } - // set the bitmap to the Image property + Marshal.Copy(pixelData, 0, bmpData.Scan0, pixelData.Length); + bitmap.UnlockBits(bmpData); this.reconstructionPicture.Image = bitmap; - - } /// /// If a new scan is available, get the data from the instrument and display the calculation results on the form. @@ -329,5 +322,5 @@ private void Form1_FormClosing(object sender, FormClosingEventArgs e) this.bp2Device.Dispose(); } } - } + } } diff --git a/C++/BP209 2D Output/BP209_2D_output.cpp b/C++/BP209 2D Output/BP209_2D_output.cpp index 7f52170..fc0df71 100644 --- a/C++/BP209 2D Output/BP209_2D_output.cpp +++ b/C++/BP209 2D Output/BP209_2D_output.cpp @@ -1,7 +1,8 @@ -//Example Date of Creation(YYYY - MM - DD) 2024 - 04 - 24 -//Example Date of Last Modification on Github 2024 - 04 - 24 +//Example Date of Creation(YYYY - MM - DD) 2024 - 04 - 24 +//Example Date of Last Modification on Github 2025 - 11 - 05 //Version of C++ used for Testing and IDE: C++ 14, Visual Studio 2022 -//Version of the Thorlabs SDK used : Beam version 9.1.5787.560 +//Version of OpenCV: OpenCV 4.12.0 +//Version of the Thorlabs SDK used : Beam version 9.3 //Example Description: The sample code shows how to control a BP209 beam profiler in C++. //In the example the available beam profilers are found, a connection is established, several parameters are set, //several output values are displayed and a 2D image is shown. @@ -18,7 +19,7 @@ using namespace cv; // forward declaration void print_error_msg(ViStatus err); void Beam_Profile_Reconstruction(); -ViSession m_instrumentHandle; +ViSession m_instrumentHandle = 0; //set the measured laser wavelengh unit: nm double wavelength = 633; @@ -55,50 +56,74 @@ int main(int argc, char* argv) return 0; } + ViChar modelName[256]; + ViChar serialNo[256]; + ViChar manufacturer[256]; + ViBoolean isAvailable; + res = TLBP2_getRsrcInfo(0, 0, modelName, serialNo, manufacturer, &isAvailable); + // connect with the first device res = TLBP2_init(resStr[0].resourceString, VI_TRUE, VI_TRUE, &m_instrumentHandle); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); return 0; } - char serialNo[128]; - res = TLBP2_get_serial_number(m_instrumentHandle, serialNo); - printf("%s is connected. \n", serialNo); + + if (isAvailable) + { + printf("%s (SN: %s) is connected. \n", modelName, serialNo); + } + else + { + printf("%s (SN: %s) is not available.\n", modelName, serialNo); + // release the device + TLBP2_close(m_instrumentHandle); + return 0; + } + // release the buffer for the resource strings delete[] resStr; //set auto gain res = TLBP2_set_auto_gain(m_instrumentHandle, VI_TRUE); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } //set bandwidth ViReal64 bw_buffer[4] = { 125,125,125,125 }; res = TLBP2_set_bandwidths(m_instrumentHandle, bw_buffer); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } //set wavelength res = TLBP2_set_wavelength(m_instrumentHandle, wavelength); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } //set power factor res = TLBP2_set_user_power_factor(m_instrumentHandle, powerCorrectionFactor); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } @@ -113,22 +138,26 @@ int main(int argc, char* argv) res = TLBP2_set_scanning_method(m_instrumentHandle, 1, scanningMethod); res = TLBP2_set_scanning_method(m_instrumentHandle, 2, scanningMethod); res = TLBP2_set_scanning_method(m_instrumentHandle, 3, scanningMethod); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } } else { - printf("Invalid Input! The scanning method is set to slit scanning mode.\n"); + printf("Invalid Input! The scanning method is set to slit scanning method.\n"); res = TLBP2_set_scanning_method(m_instrumentHandle, 0, 0); res = TLBP2_set_scanning_method(m_instrumentHandle, 1, 0); res = TLBP2_set_scanning_method(m_instrumentHandle, 2, 0); res = TLBP2_set_scanning_method(m_instrumentHandle, 3, 0); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } } @@ -140,25 +169,41 @@ int main(int argc, char* argv) res = TLBP2_set_drum_speed_ex(m_instrumentHandle, 10, &sampleCount, &resolution); else //knife edge mode res = TLBP2_set_drum_speed_ex(m_instrumentHandle, 2, &sampleCount, &resolution); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } //set position correction res = TLBP2_set_position_correction(m_instrumentHandle, VI_TRUE); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) + { + print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); + return 0; + } + + //return all position coordinates from -4500 µm to 4500 µm and flip the x scans + res = TLBP2_setThorlabsBeamCompatibleCoordinateSystem(m_instrumentHandle, VI_TRUE); + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } //set speed correction res = TLBP2_set_speed_correction(m_instrumentHandle, VI_TRUE); - if ((res & _VI_ERROR) > 0) + if (res != VI_SUCCESS) { print_error_msg(res); + // release the device + TLBP2_close(m_instrumentHandle); return 0; } @@ -169,12 +214,10 @@ int main(int argc, char* argv) res = TLBP2_get_device_status(m_instrumentHandle, &device_status); } - static BP2_SLIT_DATA slit_data[4], slit_data_kinfe[4]; /// BP2_MAX_SLIT_COUNT = 4 - static BP2_CALCULATIONS calculation_result[4], calculation_result_knife[4]; static ViReal64 power_intensities[7500]; static ViBoolean slit_indices[4] = { VI_TRUE, VI_TRUE, VI_TRUE, VI_TRUE}; ViReal64 power; - ViReal32 powerSaturation; + ViReal32 powerSaturation,centroidPositionX, centroidPositionY,gaussianDiameterX,gaussianDiameterY; ViUInt8 gain[4]; ViUInt8 gainPower; @@ -183,7 +226,7 @@ int main(int argc, char* argv) printf("Adjusting Gain...\n"); for (int i = 0; i < 10; i++) { - res = TLBP2_get_slit_scan_data(m_instrumentHandle, slit_data, calculation_result, &power, &powerSaturation, power_intensities); + res = TLBP2_request_scan_data(m_instrumentHandle, &power, &powerSaturation, power_intensities); res = TLBP2_get_gains(m_instrumentHandle, gain, &gainPower); printf("Gain:\n"); printf(" 25um slit x: %d, 25um slit y: %d\n", gain[0],gain[1]); @@ -195,19 +238,25 @@ int main(int argc, char* argv) if (scanningMethod == 0)//slit scanning mode { //Get the slit scan data - res = TLBP2_get_slit_scan_data(m_instrumentHandle, slit_data, calculation_result, &power, &powerSaturation, power_intensities); + res = TLBP2_request_scan_data(m_instrumentHandle, &power, &powerSaturation, power_intensities); if (res == VI_SUCCESS) { + TLBP2_get_slit_centroid(m_instrumentHandle, 2, VI_NULL, ¢roidPositionX); + TLBP2_get_slit_centroid(m_instrumentHandle, 3, VI_NULL, ¢roidPositionY); + TLBP2_get_slit_gaussian_fit(m_instrumentHandle, 2, VI_NULL, &gaussianDiameterX, VI_NULL, VI_NULL); + TLBP2_get_slit_gaussian_fit(m_instrumentHandle, 3, VI_NULL, &gaussianDiameterY, VI_NULL, VI_NULL); printf("Corrected Power value: %.2f mW\n", power); - printf("5um Slit X Centroid Position: %.2f\n", calculation_result[2].centroidPosition); - printf("5um Slit Y Centroid Position: %.2f\n", calculation_result[3].centroidPosition); - printf("5um Slit X Gaussian Fit Diameter: %.2f\n", calculation_result[2].gaussianFitDiameter); - printf("5um Slit Y Gaussian Fit Diameter: %.2f\n", calculation_result[3].gaussianFitDiameter); + printf("5um Slit X Centroid Position: %.2f\n", centroidPositionX); + printf("5um Slit Y Centroid Position: %.2f\n", centroidPositionY); + printf("5um Slit X Gaussian Fit Diameter: %.2f\n", gaussianDiameterX); + printf("5um Slit Y Gaussian Fit Diameter: %.2f\n", gaussianDiameterY); Beam_Profile_Reconstruction(); } } else//knife edge mode { + static BP2_SLIT_DATA slit_data[4], slit_data_kinfe[4]; /// BP2_MAX_SLIT_COUNT = 4 + static BP2_CALCULATIONS calculation_result[4], calculation_result_knife[4]; //Calculate the knife edge data from the slit data. res = TLBP2_get_slit_scan_data(m_instrumentHandle, slit_data, calculation_result, &power, &powerSaturation, power_intensities); res = TLBP2_get_knife_edge_reconstruction(m_instrumentHandle, slit_data, calculation_result, slit_indices, slit_data_kinfe, calculation_result_knife); @@ -241,8 +290,6 @@ void Beam_Profile_Reconstruction() static ViReal64 gaussianFitIntensitiesY[7500]; ViReal32 gaussianFitPercentageX, gaussianFitPercentageY; - //Request the scan data - TLBP2_request_scan_data(m_instrumentHandle, VI_NULL, VI_NULL, VI_NULL); //Get the intensities from the 5um X slit and the 5um Y slit res = TLBP2_get_sample_intensities(m_instrumentHandle, 2, sampleIntensitiesX, samplePositionsX); res = TLBP2_get_sample_intensities(m_instrumentHandle, 3, sampleIntensitiesY, samplePositionsY); @@ -314,10 +361,12 @@ void Beam_Profile_Reconstruction() reconstructionImage.at(col, row) = (uchar)(255 * intensityTemp[row][col] / intensityMax); } } + imshow("X Intensity", IntensityXImage); imshow("X Gaussian Fit Intensity", GaussianXImage); imshow("2D Reconstruction", reconstructionImage); - waitKey(0); + + waitKey(8000); } // prints the error message from an error code diff --git a/Matlab/CCT Spectrometers/CCT_example.m b/Matlab/CCT Spectrometers/CCT_example.m new file mode 100644 index 0000000..27b8e61 --- /dev/null +++ b/Matlab/CCT Spectrometers/CCT_example.m @@ -0,0 +1,76 @@ +%% Header +% Title: CCT_example.m +% Created Date: 2025-12-10 +% Last modified date: 2025-12-10 +% Matlab Version:R2023a +% Thorlabs DLL version:1.0.20.4045 +%% Notes: The example shows how to connect to a CCT spectrometer, set the exposure time and acquire a spectrum +% Tested with CCT11 +% + +% Load the Compact Spectrometer SDK DLLs +dll_path='C:\Program Files\Thorlabs\ThorSpectra'; +NET.addAssembly(fullfile(dll_path, 'Thorlabs.ManagedDevice.CompactSpectrographDriver.dll')); +NET.addAssembly(fullfile(dll_path, 'Thorlabs.ManagedDevice.dll')); +NET.addAssembly(fullfile(dll_path, 'Microsoft.Extensions.Logging.Abstractions.dll')); +NET.addAssembly('System.Runtime'); + +import Thorlabs.ManagedDevice.CompactSpectrographDriver.Workflow.StartupHelperCompactSpectrometer.*; +import Thorlabs.ManagedDevice.Trace.ExampleLogger.*; +import Microsoft.Extensions.Logging.Abstractions.*; +import Thorlabs.ManagedDevice.CompactSpectrographDriver.ICompactSpectrographDriver.*; + +logger = Thorlabs.ManagedDevice.Trace.ExampleLogger('ML',Microsoft.Extensions.Logging.LogLevel.Trace,1==1,'MatLab'); +startupHelper = Thorlabs.ManagedDevice.CompactSpectrographDriver.Workflow.StartupHelperCompactSpectrometer(logger); + +cts = System.Threading.CancellationTokenSource(); +cancellationToken = cts.Token; + +%find devices +discoveredDevicestask=startupHelper.GetKnownDevicesAsync(cancellationToken); +discoveredDevicestask.Wait(); +discoveredDevices=discoveredDevicestask.Result; + +for i=0:discoveredDevices.Count-1 + disp("discovered devices:") + disp(discoveredDevices.Item(i)); +end + +%if spectrometers are found +if(discoveredDevices.Count>0) + + disp("connecting to first device ...") + + Deviceid=discoveredDevices.Item(0); + + spectrometer=startupHelper.GetCompactSpectrographById(Deviceid); + + %set exposure time + exposure=500; %exposure time in milliseconds + exposure_result=spectrometer.SetManualExposureAsync(exposure,cancellationToken).Result; + if exposure_result==1 + disp(['exposure time is set to ',num2str(exposure),' ms']); + end + + %acquire spectrum + spectrumtask=spectrometer.AcquireSingleSpectrumAsync(cancellationToken); + spectrumtask.Wait(); + spectrum=spectrumtask.Result; + + %dispose startup helper + startupHelper.Dispose(); + + %plot spectrum + figure; plot(spectrum.Wavelength,spectrum.Intensity) + + +else + disp("No CCT spectrometer connected") +end + + + + + + +