Difference between revisions of "VUV code overview"

From Vacuum Ultra Violet
Jump to navigation Jump to search
 
(6 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
==User interface==
 
==User interface==
  
The user interface is written using PyQt5 - python binding for Qt v5. The main code can be found inside ''main.py''. The layout file is made using QT Creator and can be found in UI->mainWindow.ui.
+
The user interface is written using PyQt5 - python binding for Qt v5. The main code can be found inside ''main.py''. The layout of the interface is made using QT Creator and can be found in UI->mainWindow.ui (A new .ui file can be generated by choosing '''QT Designer Form''' in '''Files and Classes''' category in QT Creator).
  
 
The interface is divided into three sections:
 
The interface is divided into three sections:
Line 12: Line 12:
 
<br>
 
<br>
 
'''Code overview''':
 
'''Code overview''':
 +
 
The main skeleton of the GUI is inside the ''UI()'' class that must be called from the main function.  
 
The main skeleton of the GUI is inside the ''UI()'' class that must be called from the main function.  
 
This class has a function ''initUI()'' that  
 
This class has a function ''initUI()'' that  
Line 17: Line 18:
 
* declares different elements of the mainWindow.ui like buttons, plots, and data lists,
 
* declares different elements of the mainWindow.ui like buttons, plots, and data lists,
 
* connects buttons to the functions that must be called when these buttons are pressed,
 
* connects buttons to the functions that must be called when these buttons are pressed,
* starts a ''Qtimer()'' to update the GUI, and save slow control parameter values at fixed refresh rate.
+
* starts a ''Qtimer()'' to update the GUI.
 +
 
 +
For a continuous update from multiple sensors and responsive GUI, we also need to run multiple threads in this code. A few different ways exist [https://www.pythonguis.com/tutorials/multithreading-pyqt-applications-qthreadpool/], and the ''Worker'' class is added in the code to use new threads for calling different functions in their own thread.
 +
 
 +
Currently, the temperature and pressure are monitored by worker threads that are created at the start of the application, sleep for a fixed time and then read the sensor values in a loop until the application is closed. For motor/wavelength, a new thread is created every time the motor is asked to change its position and destroyed once the motor action is complete.
  
For a continuous update from multiple sensors and responsive GUI, we also need to run multiple threads in this code. A few different ways exist [https://www.pythonguis.com/tutorials/multithreading-pyqt-applications-qthreadpool/], and the ''Worker'' class is added in the code to use new threads for calling different function in their own thread but the code is not complete yet.
+
Note: In python, only one thread can access the interpreter by design, thus different threads can't run concurrently. This is not a problem when the workload of each thread isn't computationally intensive but I/0 heavy (which is the case for reading different sensors). If we do need concurrency for the SIPM readout, it is possible to use multiple processes in the future.
  
 
==Motor control==
 
==Motor control==
  
The stepper motor is controlled using an Arduino sketch that can be found in motorcontrol->motor.ino. The sketch is uploaded only once and then the code inside ''loop()'' runs indefinitely until the code needs to be modified or if we need to run the code inside the ''setup()'' again (this shouldn't happen ideally). The sketch can be uploaded using:
+
The stepper motor is controlled using an Arduino ''sketch'' written in C++ that can be found in motorcontrol->motor.ino. After making any changes to the sketch, it must be uploaded to the Arduino using:
* the Makefile (with hardcoded path) provided in the same folder  
+
*Makefile (with hardcoded path) provided in the same folder (to understand how to upload a sketch using a Makefile, see [https://www.youtube.com/watch?v=qAM2S27FWAI])
 
* the Arduino IDE.
 
* the Arduino IDE.
  
 
'''Code overview''':
 
'''Code overview''':
  
The Arduino reads the serial input request from the Raspberry Pi (routines defined in daq->arduino.py) on a loop and can perform the following actions:
+
Any Arduino sketch comprises of:
* Read the current wavelength
+
*''setup()'' - to initialize all the code variables and the Arduino pin that we will use for different input and output.
* Go to a new wavelength (if the movement does not require going beyond the allowed range)
+
*''loop()'' -  runs indefinitely after the setup is done.  The Arduino reads the serial input request from the Raspberry Pi (all communication functions are defined in daq->arduino.py) in the loop and performs the following actions:
* Calibrate the wavelength measurement ( needs the infrared laser input)
+
** Read current wavelength - returns the current position of the motor.
 +
** Go to a new wavelength - moves the motor if the movement does not require going beyond the allowed range.
 +
** Calibrate the wavelength - currently only used the input wavelength. In the future, it should use the infrared laser input to calibrate properly.
  
 
NOTE: The current setup (without the infrared input) requires reading the starting wavelength from the dial in the monochromator and providing it to the motor control interface as the starting value. All later wavelength values are calculated with respect to this initial value.  
 
NOTE: The current setup (without the infrared input) requires reading the starting wavelength from the dial in the monochromator and providing it to the motor control interface as the starting value. All later wavelength values are calculated with respect to this initial value.  
  
TODO: Cross-check that the dial readings are accurate before real measurements.
+
TODO: We still need to do a measurement with the SIPM that confirms the accuracy of monochromator dial readings. This is important as we are using the dial reading as the starting value.
  
 
==Pressure==
 
==Pressure==
Line 64: Line 71:
  
 
==SiPM==
 
==SiPM==
 +
 +
A basic skeleton exists to handle measurement data of count rate vs time stamps in the file daq->Measurement.py. The data can be saved to a file or displayed in the GUI (but uses fake data generated using random numbers for now).

Latest revision as of 10:00, 13 July 2022

User interface

The user interface is written using PyQt5 - python binding for Qt v5. The main code can be found inside main.py. The layout of the interface is made using QT Creator and can be found in UI->mainWindow.ui (A new .ui file can be generated by choosing QT Designer Form in Files and Classes category in QT Creator).

The interface is divided into three sections:

  • Setup control - Displays current value of slow control parameter (temperature, pressure, and monochromator wavelength) since the start of measurement. Also provides an interface to control the motor and for specifying file save location.
  • Measurement - New measurements can be scheduled and started using this page. The details of the measurement completed are also shown in the bottom half of the page.
  • Results - Completed measurements from the current run can be accessed with a simple plot showing the count rate of photons measured by the SiPM. It is also possible to add existing measurements by providing the directory where the measurements are saved.


Code overview:

The main skeleton of the GUI is inside the UI() class that must be called from the main function. This class has a function initUI() that

  • defines the initial state of the program,
  • declares different elements of the mainWindow.ui like buttons, plots, and data lists,
  • connects buttons to the functions that must be called when these buttons are pressed,
  • starts a Qtimer() to update the GUI.

For a continuous update from multiple sensors and responsive GUI, we also need to run multiple threads in this code. A few different ways exist [1], and the Worker class is added in the code to use new threads for calling different functions in their own thread.

Currently, the temperature and pressure are monitored by worker threads that are created at the start of the application, sleep for a fixed time and then read the sensor values in a loop until the application is closed. For motor/wavelength, a new thread is created every time the motor is asked to change its position and destroyed once the motor action is complete.

Note: In python, only one thread can access the interpreter by design, thus different threads can't run concurrently. This is not a problem when the workload of each thread isn't computationally intensive but I/0 heavy (which is the case for reading different sensors). If we do need concurrency for the SIPM readout, it is possible to use multiple processes in the future.

Motor control

The stepper motor is controlled using an Arduino sketch written in C++ that can be found in motorcontrol->motor.ino. After making any changes to the sketch, it must be uploaded to the Arduino using:

  • Makefile (with hardcoded path) provided in the same folder (to understand how to upload a sketch using a Makefile, see [2])
  • the Arduino IDE.

Code overview:

Any Arduino sketch comprises of:

  • setup() - to initialize all the code variables and the Arduino pin that we will use for different input and output.
  • loop() - runs indefinitely after the setup is done. The Arduino reads the serial input request from the Raspberry Pi (all communication functions are defined in daq->arduino.py) in the loop and performs the following actions:
    • Read current wavelength - returns the current position of the motor.
    • Go to a new wavelength - moves the motor if the movement does not require going beyond the allowed range.
    • Calibrate the wavelength - currently only used the input wavelength. In the future, it should use the infrared laser input to calibrate properly.

NOTE: The current setup (without the infrared input) requires reading the starting wavelength from the dial in the monochromator and providing it to the motor control interface as the starting value. All later wavelength values are calculated with respect to this initial value.

TODO: We still need to do a measurement with the SIPM that confirms the accuracy of monochromator dial readings. This is important as we are using the dial reading as the starting value.

Pressure

The pressure is measured using MPT 200 and can be read visually from the inbuilt display. The pressure can also be read via serial communication with the protocol defined in the operating manual of the sensor in [3].

The communication is done by sending and receiving a telegram to the sensor. The code that defines and reads these telegrams can be found in daq->pressure_sensor.py. Many simple routines can be created to control the sensor and read different parameter values but the most useful routine is readpressurevalue() which requests the current pressure in the vacuum chamber.

Temperature

The temperature of the sample will be measured using a PT 100 sensor. The resistance of PT100 is 100 Ω at 0°C and increases linearly with temperature (138.5 Ω at 100°C).

Using another resistor (1 kΩ) in series with the PT100 and applying known voltage (3.3 V) on the PT100, the current resistance of PT 100 can be calculated. The external resistor is connected to the ground and the voltage across the resistor is measured (as shown in [4]).

The voltage V can be converted to the resistance R of PT100 using:

R = (V)*1000 / (3.3-V).

Now, the temperature T of PT100 can be calculated from R as:

T = (R - 100) / 0.385,

where the factor 0.385 is calculated using R100°C = R0°C ( 1 + α*100°C ).

NOTE: The circuit is perhaps too simplistic [5] and we should check if the temperature reading is accurate enough for our setup.

SiPM

A basic skeleton exists to handle measurement data of count rate vs time stamps in the file daq->Measurement.py. The data can be saved to a file or displayed in the GUI (but uses fake data generated using random numbers for now).