#+TITLE: Encoder Renishaw Vionic - Test Bench :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} #+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+ :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 * Introduction :ignore: #+begin_note You can find below the document of: - [[file:doc/L-9517-9678-05-A_Data_sheet_VIONiC_series_en.pdf][Vionic Encoder]] - [[file:doc/L-9517-9862-01-C_Data_sheet_RKLC_EN.pdf][Linear Scale]] #+end_note We would like to characterize the encoder measurement system. In particular, we would like to measure: - Power Spectral Density of the measurement noise - Bandwidth of the sensor - Linearity of the sensor #+name: fig:encoder_vionic #+caption: Picture of the Vionic Encoder #+attr_latex: :width 0.6\linewidth [[file:figs/encoder_vionic.png]] - 1: 2YA275 - 2: 2YA274 - 3: 2YA273 - 4: 2YA270 - 5: 2YA272 - 6: 2YA271 - 7: 2YJ313 * Encoder Model The Encoder is characterized by its dynamics $G_m(s)$ from the "true" displacement $y$ to measured displacement $y_m$. Ideally, this dynamics is constant over a wide frequency band with very small phase drop. It is also characterized by its measurement noise $n$ that can be described by its Power Spectral Density (PSD). The model of the encoder is shown in Figure [[fig:encoder-model-schematic]]. #+begin_src latex :file encoder-model-schematic.pdf \begin{tikzpicture} \node[block] (G) at (0,0){$G_m(s)$}; \node[addb, left=0.8 of G] (add){}; \draw[<-] (add.west) -- ++(-1.0, 0) node[above right]{$y$}; \draw[->] (add.east) -- (G.west); \draw[->] (G.east) -- ++(1.0, 0) node[above left]{$y_m$}; \draw[<-] (add.north) -- ++(0, 0.6) node[below right](n){$n$}; \begin{scope}[on background layer] \node[fit={(add.west|-G.south) (n.north-|G.east)}, inner sep=8pt, draw, dashed, fill=black!20!white] (P) {}; \node[below left] at (P.north east) {Encoder}; \end{scope} \end{tikzpicture} #+end_src #+name: fig:encoder-model-schematic #+caption: Model of the Encoder #+RESULTS: [[file:figs/encoder-model-schematic.png]] We can also use a transfer function $G_n(s)$ to shape a noise $\tilde{n}$ with unity ASD as shown in Figure [[fig:vionic_expected_noise]]. #+begin_src latex :file encoder-model-schematic-with-asd.pdf \begin{tikzpicture} \node[block] (G) at (0,0){$G_m(s)$}; \node[addb, left=0.8 of G] (add){}; \node[block, above=0.5 of add] (Gn) {$G_n(s)$}; \draw[<-] (add.west) -- ++(-1.0, 0) node[above right]{$y$}; \draw[->] (add.east) -- (G.west); \draw[->] (G.east) -- ++(1.0, 0) node[above left]{$y_m$}; \draw[->] (Gn.south) -- (add.north) node[above right]{$n$}; \draw[<-] (Gn.north) -- ++(0, 0.6) node[below right](n){$\tilde{n}$}; \begin{scope}[on background layer] \node[fit={(Gn.west|-G.south) (n.north-|G.east)}, inner sep=8pt, draw, dashed, fill=black!20!white] (P) {}; \node[below left] at (P.north east) {Encoder}; \end{scope} \end{tikzpicture} #+end_src #+RESULTS: [[file:figs/encoder-model-schematic-with-asd.png]] #+name: tab:vionic_characteristics_manual #+caption: Characteristics of the Vionic Encoder #+attr_latex: :environment tabularx :width \linewidth :align lXX #+attr_latex: :center t :booktabs t :float t | | | | | *Characteristics* | *Manual* | *Specifications* | |----------------------+----------------+------------------| | Range | Ruler length | > 200 [um] | | Resolution | 2.5 [nm] | < 50 [nm rms] | | Sub-Divisional Error | $< \pm 15\,nm$ | | | Bandwidth | To be checked | > 5 [kHz] | #+name: fig:vionic_expected_noise #+attr_latex: :width \linewidth #+caption: Expected interpolation errors for the Vionic Encoder [[file:./figs/vionic_expected_noise.png]] * Noise Measurement <> ** Test Bench To measure the noise $n$ of the encoder, one can rigidly fix the head and the ruler together such that no motion should be measured. Then, the measured signal $y_m$ corresponds to the noise $n$. ** 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 addpath('./matlab/mat/'); addpath('./matlab/'); #+end_src #+begin_src matlab :eval no addpath('./mat/'); #+end_src ** Results First we load the data. #+begin_src matlab %% Load Data enc1 = load('noise_meas_100s_20kHz_1.mat', 't', 'x'); enc2 = load('noise_meas_100s_20kHz_2.mat', 't', 'x'); enc3 = load('noise_meas_100s_20kHz_3.mat', 't', 'x'); enc4 = load('noise_meas_100s_20kHz_4.mat', 't', 'x'); enc6 = load('noise_meas_100s_20kHz_6.mat', 't', 'x'); enc7 = load('noise_meas_100s_20kHz_7.mat', 't', 'x'); #+end_src #+begin_src matlab :exports none %% Remove initial offset enc1.x = enc1.x - mean(enc1.x(1:1000)); enc2.x = enc2.x - mean(enc2.x(1:1000)); enc3.x = enc3.x - mean(enc3.x(1:1000)); enc4.x = enc4.x - mean(enc4.x(1:1000)); enc6.x = enc6.x - mean(enc6.x(1:1000)); enc7.x = enc7.x - mean(enc7.x(1:1000)); #+end_src The raw measured data as well as the low pass filtered data (using a first order low pass filter with a cut-off at 10Hz) are shown in Figure [[fig:vionic_noise_raw_lpf]]. #+begin_src matlab :exports none figure; hold on; plot(enc1.t, 1e9*enc1.x, '.', 'DisplayName', 'Enc 1 - Raw'); plot(enc1.t, 1e9*lsim(1/(1 + s/2/pi/10), enc1.x, enc1.t), '-', 'DisplayName', 'Enc 1 - LPF'); hold off; xlabel('Time [s]'); ylabel('Displacement [nm]'); legend('location', 'northwest'); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/vionic_noise_raw_lpf.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:vionic_noise_raw_lpf #+caption: Time domain measurement (raw data and low pass filtered data with first order 10Hz LPF) #+RESULTS: [[file:figs/vionic_noise_raw_lpf.png]] The time domain data for all the encoders are compared in Figure [[fig:vionic_noise_time]]. #+begin_src matlab :exports none figure; hold on; plot(enc1.t, 1e9*lsim(1/(1 + s/2/pi/10), enc1.x, enc1.t), '.', 'DisplayName', 'Enc 1'); plot(enc2.t, 1e9*lsim(1/(1 + s/2/pi/10), enc2.x, enc2.t), '.', 'DisplayName', 'Enc 2'); plot(enc3.t, 1e9*lsim(1/(1 + s/2/pi/10), enc3.x, enc3.t), '.', 'DisplayName', 'Enc 3'); plot(enc4.t, 1e9*lsim(1/(1 + s/2/pi/10), enc4.x, enc4.t), '.', 'DisplayName', 'Enc 4'); plot(enc6.t, 1e9*lsim(1/(1 + s/2/pi/10), enc6.x, enc6.t), '.', 'DisplayName', 'Enc 6'); plot(enc7.t, 1e9*lsim(1/(1 + s/2/pi/10), enc7.x, enc7.t), '.', 'DisplayName', 'Enc 7'); hold off; xlabel('Time [s]'); ylabel('Displacement [nm]'); legend('location', 'northwest'); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/vionic_noise_time.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:vionic_noise_time #+caption: Comparison of the time domain measurement #+RESULTS: [[file:figs/vionic_noise_time.png]] The amplitude spectral density is computed and shown in Figure [[fig:vionic_noise_asd]]. #+begin_src matlab :exports none % Compute sampling Frequency Ts = (enc1.t(end) - enc1.t(1))/(length(enc1.t)-1); Fs = 1/Ts; % Hannning Windows win = hanning(ceil(0.5/Ts)); [p1, f] = pwelch(enc1.x, win, [], [], Fs); [p2, ~] = pwelch(enc2.x, win, [], [], Fs); [p3, ~] = pwelch(enc3.x, win, [], [], Fs); [p4, ~] = pwelch(enc4.x, win, [], [], Fs); [p6, ~] = pwelch(enc6.x, win, [], [], Fs); [p7, ~] = pwelch(enc7.x, win, [], [], Fs); #+end_src #+begin_src matlab :exports none figure; hold on; plot(f, sqrt(p1), 'DisplayName', 'Enc 1'); plot(f, sqrt(p2), 'DisplayName', 'Enc 2'); plot(f, sqrt(p3), 'DisplayName', 'Enc 3'); plot(f, sqrt(p4), 'DisplayName', 'Enc 4'); plot(f, sqrt(p6), 'DisplayName', 'Enc 6'); plot(f, sqrt(p7), 'DisplayName', 'Enc 7'); set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xlabel('Frequency [Hz]'); ylabel('ASD [$m/\sqrt{Hz}$]'); xlim([10, Fs/2]); ylim([1e-11, 1e-10]); legend('location', 'northeast'); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/vionic_noise_asd.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:vionic_noise_asd #+caption: Amplitude Spectral Density of the measured signal #+RESULTS: [[file:figs/vionic_noise_asd.png]] Let's create a transfer function that approximate the measured noise of the encoder. #+begin_src matlab Gn_e = 1.8e-11/(1 + s/2/pi/1e4); #+end_src The amplitude of the transfer function and the measured ASD are shown in Figure [[fig:vionic_noise_asd_model]]. #+begin_src matlab :exports none figure; hold on; plot(f, sqrt(p1), 'color', [0, 0, 0, 0.5], 'DisplayName', '$\Gamma_n(\omega)$'); plot(f, sqrt(p2), 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(f, sqrt(p3), 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(f, sqrt(p4), 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(f, sqrt(p6), 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(f, sqrt(p7), 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off'); plot(f, abs(squeeze(freqresp(Gn_e, f, 'Hz'))), 'r-', 'DisplayName', '$|G_n(j\omega)|$'); hold off; set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log'); xlabel('Frequency [Hz]'); ylabel('ASD [$m/\sqrt{Hz}$]'); xlim([10, Fs/2]); ylim([1e-11, 1e-10]); legend('location', 'northeast'); #+end_src #+begin_src matlab :tangle no :exports results :results file replace exportFig('figs/vionic_noise_asd_model.pdf', 'width', 'wide', 'height', 'normal'); #+end_src #+name: fig:vionic_noise_asd_model #+caption: Measured ASD of the noise and modelled one #+RESULTS: [[file:figs/vionic_noise_asd_model.png]] * Linearity Measurement <> ** Test Bench In order to measure the linearity, we have to compare the measured displacement with a reference sensor with a known linearity. An interferometer or capacitive sensor should work fine. An actuator should also be there so impose a displacement. One idea is to use the test-bench shown in Figure [[fig:test_bench_encoder_calibration]]. The APA300ML is used to excite the mass in a broad bandwidth. The motion is measured at the same time by the Vionic Encoder and by an interferometer (most likely an Attocube). As the interferometer has a very large bandwidth, we should be able to estimate the bandwidth of the encoder if it is less than the Nyquist frequency that can be around 10kHz. #+name: fig:test_bench_encoder_calibration #+caption: Schematic of the test bench [[file:figs/test_bench_encoder_calibration.png]] ** 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 addpath('./matlab/mat/'); addpath('./matlab/'); #+end_src #+begin_src matlab :eval no addpath('./mat/'); #+end_src ** Results * Dynamical Measurement <> ** Test Bench ** 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 addpath('./matlab/mat/'); addpath('./matlab/'); #+end_src #+begin_src matlab :eval no addpath('./mat/'); #+end_src ** Results