#+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: #+HTML_HEAD: #+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

This report is also available as a pdf.


#+end_export #+latex: \clearpage * Introduction Several Lookup Tables (LUT) are used for the DCM in order to compensate for *repeatable* errors. - Section [[sec:dcm_stepper_lut]]: the stepper motors are calibrated using interferometers. - Section [[sec:dcm_attocube_lut]]: the Attocube periodic non-linearities are calibrated using piezoelectric actuators. * Stepper Motors Calibration :PROPERTIES: :header-args:matlab+: :tangle matlab/dcm_stepper_lut.m :END: <> ** 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) <> #+end_src #+begin_src matlab :exports none :results silent :noweb yes <> #+end_src #+begin_src matlab :tangle no :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+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] t = 0:1/Fs:10; % Time vector [s] theta = linspace(10, 40, length(t)); % Bragg Angle [deg] #+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]] The current LUT implementation is the following: #+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 motion_error_lut(i) = lut_range(i) + (lut_range(i) - round(1e6*mean(measured_motion(close_points)))); % [um] end #+end_src 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]]). #+begin_src matlab :exports none %% Corrected motion and motion error at each step position figure; hold on; plot(lut_range, lut-lut_range, ... 'DisplayName', 'New LUT'); plot(lut_range, motion_error_lut-lut_range, ... 'DisplayName', 'Old LUT'); hold off; xlabel('IcePAP Steps [um]'); ylabel('Corrected motion [um]'); ylim([-110, 110]) legend('location', 'southeast'); #+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]] 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 The output motion with both LUT are shown in Figure [[fig:compare_old_new_lut_motion]]. It is confirmed that the new LUT is the correct one. Also, it is interesting to note that the old LUT gives an output motion that is above the ideal one, as was seen during the experiments. #+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]] * Attocube Calibration :PROPERTIES: :header-args:matlab+: :tangle matlab/dcm_attocube_lut.m :END: <> ** 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) <> #+end_src #+begin_src matlab :exports none :results silent :noweb yes <> #+end_src #+begin_src matlab :tangle no :noweb yes <> #+end_src #+begin_src matlab :eval no :noweb yes <> #+end_src #+begin_src matlab :noweb yes <> #+end_src * 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