2021-12-06 11:58:41 +01:00
#+TITLE : ESRF Double Crystal Monochromator - Lookup Tables
:DRAWER:
#+LANGUAGE : en
#+EMAIL : dehaeze.thomas@gmail.com
#+AUTHOR : Dehaeze Thomas
#+HTML_LINK_HOME : ../index.html
#+HTML_LINK_UP : ../index.html
#+HTML_HEAD : <link rel="stylesheet" type="text/css" href="https://research.tdehaeze.xyz/css/style.css"/>
#+HTML_HEAD : <script type="text/javascript" src="https://research.tdehaeze.xyz/js/script.js"></script>
#+BIND : org-latex-image-default-option "scale=1"
#+BIND : org-latex-image-default-width ""
#+LaTeX_CLASS : scrreprt
#+LaTeX_CLASS_OPTIONS : [a4paper, 10pt, DIV=12, parskip=full]
#+LaTeX_HEADER_EXTRA : \input{preamble.tex}
#+LATEX_HEADER_EXTRA : \bibliography{ref}
#+PROPERTY : header-args:matlab :session *MATLAB*
#+PROPERTY : header-args:matlab+ :comments org
#+PROPERTY : header-args:matlab+ :exports both
#+PROPERTY : header-args:matlab+ :results none
#+PROPERTY : header-args:matlab+ :tangle no
#+PROPERTY : header-args:matlab+ :eval no-export
#+PROPERTY : header-args:matlab+ :noweb yes
#+PROPERTY : header-args:matlab+ :mkdirp yes
#+PROPERTY : header-args:matlab+ :output-dir figs
#+PROPERTY : header-args:latex :headers '("\\usepackage{tikz}" "\\usepackage{import}" "\\import{$HOME/Cloud/tikz/org/}{config.tex}")
#+PROPERTY : header-args:latex+ :imagemagick t :fit yes
#+PROPERTY : header-args:latex+ :iminoptions -scale 100% -density 150
#+PROPERTY : header-args:latex+ :imoutoptions -quality 100
#+PROPERTY : header-args:latex+ :results file raw replace
#+PROPERTY : header-args:latex+ :buffer no
#+PROPERTY : header-args:latex+ :tangle no
#+PROPERTY : header-args:latex+ :eval no-export
#+PROPERTY : header-args:latex+ :exports results
#+PROPERTY : header-args:latex+ :mkdirp yes
#+PROPERTY : header-args:latex+ :output-dir figs
#+PROPERTY : header-args:latex+ :post pdf2svg(file=*this*, ext="png")
:END:
#+begin_export html
<hr >
<p >This report is also available as a <a href="./dcm_lookup_tables.pdf" >pdf</a >.</p >
<hr >
#+end_export
#+latex : \clearpage
* Introduction
* Stepper Motors Calibration
:PROPERTIES:
:header-args:matlab+: :tangle matlab/dcm_stepper_lut.m
:END:
<<sec:dcm_stepper_lut >>
** Introduction :ignore:
** Matlab Init :noexport:ignore:
#+begin_src matlab :tangle no :exports none :results silent :noweb yes :var current_dir=(file-name-directory buffer-file-name)
<<matlab-dir >>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init >>
#+end_src
#+begin_src matlab :tangle no :noweb yes
<<m-init-path >>
#+end_src
#+begin_src matlab :eval no :noweb yes
<<m-init-path-tangle >>
#+end_src
#+begin_src matlab :noweb yes
<<m-init-other >>
#+end_src
** Schematic
** Simulation
In this section, we suppose that we are in the frame of one fast jack (all transformations are already done), and we wish to create a LUT for one fast jack.
Let's say with make a Bragg angle scan between 10deg and 60deg during 100s.
#+begin_src matlab
Fs = 10e3; % Sample Frequency [Hz]
2021-12-06 17:11:28 +01:00
t = 0:1/Fs:10; % Time vector [s]
theta = linspace(10, 40, length(t)); % Bragg Angle [deg]
2021-12-06 11:58:41 +01:00
#+end_src
The IcePAP steps are following the theoretical formula:
\begin{equation}
d_z = \frac{d_ {\text{off}}}{2 \cos \theta}
\end{equation}
with $\theta$ the bragg angle and $d_{\text{off}} = 10\,mm$.
The motion to follow is then:
#+begin_src matlab
perfect_motion = 10e-3./(2*cos(theta*pi/180)); % Perfect motion [m]
#+end_src
And the IcePAP is generated those steps:
#+begin_src matlab
icepap_steps = perfect_motion; % IcePAP steps measured by Speedgoat [m]
#+end_src
#+begin_src matlab :exports none
%% Steps as a function of the bragg angle
figure;
plot(theta, icepap_steps);
xlabel('Bragg Angle [deg]'); ylabel('IcePAP Steps [m]');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/bragg_angle_icepap_steps_idealized.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name : fig:bragg_angle_icepap_steps_idealized
#+caption : IcePAP Steps as a function of the Bragg Angle
#+RESULTS :
[[file:figs/bragg_angle_icepap_steps_idealized.png ]]
Then, we are measuring the motion of the Fast Jack using the Interferometer.
The motion error is larger than in reality to be angle to see it more easily.
#+begin_src matlab
motion_error = 100e-6*sin(2*pi*perfect_motion/1e-3); % Error motion [m]
measured_motion = perfect_motion + motion_error; % Measured motion of the Fast Jack [m]
#+end_src
#+begin_src matlab :exports none
%% Measured Motion and Idealized Motion
figure;
hold on;
plot(icepap_steps, measured_motion, ...
'DisplayName', 'Measured Motion');
plot(icepap_steps, perfect_motion, 'k--', ...
'DisplayName', 'Ideal Motion');
hold off;
xlabel('IcePAP Steps [m]'); ylabel('Measured Motion [m]');
legend('location', 'southeast');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/measured_and_ideal_motion_fast_jacks.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name : fig:measured_and_ideal_motion_fast_jacks
#+caption : Measured motion as a function of the IcePAP Steps
#+RESULTS :
[[file:figs/measured_and_ideal_motion_fast_jacks.png ]]
Let's now compute the lookup table.
For each micrometer of the IcePAP step, another step is associated that correspond to a position closer to the wanted position.
#+begin_src matlab
%% Get range for the LUT
% We correct only in the range of tested/measured motion
lut_range = round(1e6*min(icepap_steps)):round(1e6*max(icepap_steps)); % IcePAP steps [um]
%% Initialize the LUT
lut = zeros(size(lut_range));
%% For each um in this range
for i = 1:length(lut_range)
% Get points indices where the measured motion is closed to the wanted one
close_points = measured_motion > 1e-6*lut_range(i) - 500e-9 & measured_motion < 1e-6*lut_range(i) + 500e-9;
% Get the corresponding closest IcePAP step
lut(i) = round(1e6*mean(icepap_steps(close_points))); % [um]
end
#+end_src
#+begin_src matlab :exports none
%% Generated Lookup Table
figure;
plot(lut_range, lut);
xlabel('IcePAP input step [um]'); ylabel('Lookup Table output [um]');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/generated_lut_icepap.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name : fig:generated_lut_icepap
#+caption : Generated Lookup Table
#+RESULTS :
[[file:figs/generated_lut_icepap.png ]]
2021-12-06 17:11:28 +01:00
The current LUT implementation is the following:
2021-12-06 11:58:41 +01:00
#+begin_src matlab
motion_error_lut = zeros(size(lut_range));
for i = 1:length(lut_range)
% Get points indices where the icepap step is close to the wanted one
close_points = icepap_steps > 1e-6*lut_range(i) - 500e-9 & icepap_steps < 1e-6*lut_range(i) + 500e-9;
% Get the corresponding motion error
2021-12-06 17:11:28 +01:00
motion_error_lut(i) = lut_range(i) + (lut_range(i) - round(1e6*mean(measured_motion(close_points)))); % [um]
2021-12-06 11:58:41 +01:00
end
#+end_src
2021-12-06 17:11:28 +01:00
Let's compare the two Lookup Table in Figure [[fig:lut_comparison_two_methods ]].
#+begin_src matlab :exports none
%% Comparison of the two Generated Lookup Table
figure;
hold on;
plot(lut_range, lut, ...
'DisplayName', 'New LUT');
plot(lut_range, motion_error_lut, ...
'DisplayName', 'Old LUT');
hold off;
xlabel('IcePAP input step [um]'); ylabel('Lookup Table output [um]');
legend('location', 'southeast');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/lut_comparison_two_methods.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name : fig:lut_comparison_two_methods
#+caption : Comparison of the two lookup tables
#+RESULTS :
[[file:figs/lut_comparison_two_methods.png ]]
If we plot the "corrected steps" for all steps for both methods, we clearly see the difference (Figure [[fig:lut_correct_and_motion_error ]]).
2021-12-06 11:58:41 +01:00
#+begin_src matlab :exports none
%% Corrected motion and motion error at each step position
figure;
hold on;
plot(lut_range, lut-lut_range, ...
2021-12-06 17:11:28 +01:00
'DisplayName', 'New LUT');
plot(lut_range, motion_error_lut-lut_range, ...
'DisplayName', 'Old LUT');
2021-12-06 11:58:41 +01:00
hold off;
xlabel('IcePAP Steps [um]'); ylabel('Corrected motion [um]');
ylim([-110, 110])
2021-12-06 17:11:28 +01:00
legend('location', 'southeast');
2021-12-06 11:58:41 +01:00
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/lut_correct_and_motion_error.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name : fig:lut_correct_and_motion_error
#+caption : LUT correction and motion error as a function of the IcePAP steps
#+RESULTS :
[[file:figs/lut_correct_and_motion_error.png ]]
2021-12-06 17:11:28 +01:00
Let's now implement both LUT to see which implementation is correct.
#+begin_src matlab :exports none
icepap_steps_output_new = lut(round(1e6*icepap_steps)-lut_range(1)+1);
i = round(1e6*icepap_steps)-motion_error_lut(1)+1;
i(i>length(motion_error_lut)) = length(motion_error_lut);
icepap_steps_output_old = motion_error_lut(i);
#+end_src
#+begin_src matlab
motion_new = zeros(size(icepap_steps_output_new));
motion_old = zeros(size(icepap_steps_output_old));
for i = 1:length(icepap_steps_output_new)
[~, i_step] = min(abs(icepap_steps_output_new(i) - 1e6*icepap_steps));
motion_new(i) = measured_motion(i_step);
[~, i_step] = min(abs(icepap_steps_output_old(i) - 1e6*icepap_steps));
motion_old(i) = measured_motion(i_step);
end
#+end_src
#+begin_src matlab :exports none
%% Measured Motion and Idealized Motion
% Use only middle motion where the LUT is working
i = round(0.1*length(icepap_steps)):round(0.9*length(icepap_steps));
figure;
hold on;
plot(icepap_steps(i), motion_new(i), ...
'DisplayName', 'Motion (new LUT)');
plot(icepap_steps(i), motion_old(i), ...
'DisplayName', 'Motion (old LUT)');
plot(icepap_steps(i), perfect_motion(i), 'k--', ...
'DisplayName', 'Ideal Motion');
hold off;
xlabel('IcePAP Steps [m]'); ylabel('Measured Motion [m]');
legend('location', 'southeast');
#+end_src
#+begin_src matlab :tangle no :exports results :results file replace
exportFig('figs/compare_old_new_lut_motion.pdf', 'width', 'wide', 'height', 'normal');
#+end_src
#+name : fig:compare_old_new_lut_motion
#+caption : Comparison of the obtained motion with new and old LUT
#+RESULTS :
[[file:figs/compare_old_new_lut_motion.png ]]
2021-12-06 11:58:41 +01:00
* Attocube Calibration :noexport:
* Helping Functions :noexport:
** Initialize Path
#+NAME : m-init-path
#+BEGIN_SRC matlab
%% Path for functions, data and scripts
addpath('./matlab/mat/ '); % Path for data
addpath('./matlab/ '); % Path for scripts
#+END_SRC
#+NAME : m-init-path-tangle
#+BEGIN_SRC matlab
%% Path for functions, data and scripts
addpath('./mat/ '); % Path for data
#+END_SRC
** Initialize Simscape Model
#+NAME : m-init-simscape
#+begin_src matlab
#+end_src
** Initialize other elements
#+NAME : m-init-other
#+BEGIN_SRC matlab
%% Colors for the figures
colors = colororder;
%% Frequency Vector
freqs = logspace(1, 3, 1000);
#+END_SRC
* Bibliography :ignore:
#+latex : \printbibliography