2020-12-16 11:51:26 +01:00
#+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 : <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}
#+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:
2021-02-02 18:46:58 +01:00
#+begin_export html
<hr >
<p >This report is also available as a <a href="./test-bench-vionic.pdf" >pdf</a >.</p >
<hr >
#+end_export
2020-12-16 11:51:26 +01:00
* Introduction :ignore:
2020-12-16 14:07:07 +01:00
#+begin_note
2020-12-16 11:51:26 +01:00
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 ]]
2020-12-16 14:07:07 +01:00
#+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
2020-12-17 14:54:16 +01:00
- Bandwidth of the sensor
- Linearity of the sensor
2020-12-16 11:51:26 +01:00
2021-01-04 11:44:11 +01:00
#+name : fig:encoder_vionic
#+caption : Picture of the Vionic Encoder
2021-02-02 18:46:58 +01:00
#+attr_latex : :width 0.6\linewidth
2021-01-04 11:44:11 +01:00
[[file:figs/encoder_vionic.png ]]
2021-02-03 10:16:49 +01:00
- 1: 2YA275
- 2: 2YA274
- 3: 2YA273
- 4: 2YA270
- 5: 2YA272
- 6: 2YA271
- 7: 2YJ313
2020-12-16 11:51:26 +01:00
* 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).
2020-12-16 14:07:07 +01:00
The model of the encoder is shown in Figure [[fig:encoder-model-schematic ]].
2020-12-16 11:51:26 +01:00
#+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 ]]
2021-02-02 18:46:58 +01:00
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 ]]
2020-12-17 14:54:16 +01:00
#+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
2021-02-02 18:25:28 +01:00
| <l> | <c> | <c> |
| *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] |
2020-12-17 14:54:16 +01:00
#+name : fig:vionic_expected_noise
2021-02-02 18:46:58 +01:00
#+attr_latex : :width \linewidth
2020-12-17 14:54:16 +01:00
#+caption : Expected interpolation errors for the Vionic Encoder
[[file:./figs/vionic_expected_noise.png ]]
2021-02-02 18:46:58 +01:00
* Noise Measurement
<<sec:noise_measurement >>
** Test Bench
2020-12-16 11:51:26 +01:00
2020-12-16 14:07:07 +01:00
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$.
2020-12-16 11:51:26 +01:00
2021-02-02 18:46:58 +01:00
** Matlab Init :noexport:ignore:
2021-02-02 18:25:28 +01:00
#+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
addpath('./matlab/mat/ ');
addpath('./matlab/ ');
#+end_src
#+begin_src matlab :eval no
addpath('./mat/ ');
#+end_src
2021-02-02 18:46:58 +01:00
** Results
First we load the data.
2021-02-02 18:25:28 +01:00
#+begin_src matlab
2021-02-03 11:20:22 +01:00
%% 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');
2021-02-02 18:25:28 +01:00
#+end_src
2021-02-03 11:20:22 +01:00
#+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 ]].
2021-02-02 18:46:58 +01:00
#+begin_src matlab :exports none
2021-02-02 18:25:28 +01:00
figure;
hold on;
2021-02-03 11:20:22 +01:00
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');
2021-02-02 18:25:28 +01:00
hold off;
xlabel('Time [s]');
ylabel('Displacement [nm]');
2021-02-03 11:20:22 +01:00
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');
2021-02-02 18:25:28 +01:00
#+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
2021-02-03 11:20:22 +01:00
#+caption : Comparison of the time domain measurement
2021-02-02 18:25:28 +01:00
#+RESULTS :
[[file:figs/vionic_noise_time.png ]]
2021-02-03 11:20:22 +01:00
The amplitude spectral density is computed and shown in Figure [[fig:vionic_noise_asd ]].
2021-02-02 18:25:28 +01:00
#+begin_src matlab :exports none
% Compute sampling Frequency
2021-02-03 11:20:22 +01:00
Ts = (enc1.t(end) - enc1.t(1))/(length(enc1.t)-1);
2021-02-02 18:25:28 +01:00
Fs = 1/Ts;
% Hannning Windows
2021-02-03 11:20:22 +01:00
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);
2021-02-02 18:25:28 +01:00
#+end_src
#+begin_src matlab :exports none
figure;
2021-02-03 11:20:22 +01:00
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');
2021-02-02 18:25:28 +01:00
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD [$m/\sqrt{Hz}$]');
2021-02-03 11:20:22 +01:00
xlim([10, Fs/2]);
ylim([1e-11, 1e-10]);
legend('location', 'northeast');
2021-02-02 18:25:28 +01:00
#+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
2021-02-03 11:20:22 +01:00
Gn_e = 1.8e-11/(1 + s/2/pi/1e4);
2021-02-02 18:25:28 +01:00
#+end_src
2021-02-02 18:46:58 +01:00
The amplitude of the transfer function and the measured ASD are shown in Figure [[fig:vionic_noise_asd_model ]].
2021-02-02 18:25:28 +01:00
#+begin_src matlab :exports none
figure;
hold on;
2021-02-03 11:20:22 +01:00
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)|$');
2021-02-02 18:25:28 +01:00
hold off;
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
xlabel('Frequency [Hz]'); ylabel('ASD [$m/\sqrt{Hz}$]');
2021-02-03 11:20:22 +01:00
xlim([10, Fs/2]);
ylim([1e-11, 1e-10]);
legend('location', 'northeast');
2021-02-02 18:25:28 +01:00
#+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 ]]
2021-02-03 11:20:22 +01:00
2021-02-02 18:46:58 +01:00
* Linearity Measurement
<<sec: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)
<<matlab-dir >>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init >>
#+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
<<sec: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)
<<matlab-dir >>
#+end_src
#+begin_src matlab :exports none :results silent :noweb yes
<<matlab-init >>
#+end_src
#+begin_src matlab :tangle no
addpath('./matlab/mat/ ');
addpath('./matlab/ ');
#+end_src
#+begin_src matlab :eval no
addpath('./mat/ ');
#+end_src
** Results