415 lines
15 KiB
Org Mode
415 lines
15 KiB
Org Mode
#+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:
|
|
|
|
#+begin_export html
|
|
<hr>
|
|
<p>This report is also available as a <a href="./test-bench-vionic.pdf">pdf</a>.</p>
|
|
<hr>
|
|
#+end_export
|
|
|
|
* Introduction :ignore:
|
|
|
|
#+begin_note
|
|
You can find below the documentation 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
|
|
|
|
In this document, we wish to characterize the performances of the encoder measurement system.
|
|
In particular, we would like to measure:
|
|
- the measurement noise
|
|
- the linearity of the sensor
|
|
- the bandwidth of the sensor
|
|
|
|
This document is structured as follow:
|
|
- Section [[sec:vionic_expected_performances]]: the expected performance of the Vionic encoder system are described
|
|
- Section [[sec:encoder_model]]: a simple model of the encoder is developed
|
|
- Section [[sec:noise_measurement]]: the noise of the encoder is measured and a model of the noise is identified
|
|
- Section [[sec:linearity_measurement]]: the linearity of the sensor is estimated
|
|
|
|
* Expected Performances
|
|
<<sec:vionic_expected_performances>>
|
|
|
|
The Vionic encoder is shown in Figure [[fig:encoder_vionic]].
|
|
|
|
#+name: fig:encoder_vionic
|
|
#+caption: Picture of the Vionic Encoder
|
|
#+attr_latex: :width 0.6\linewidth
|
|
[[file:figs/encoder_vionic.png]]
|
|
|
|
From the Renishaw [[https://www.renishaw.com/en/how-optical-encoders-work--36979][website]]:
|
|
#+begin_quote
|
|
The VIONiC encoder features the third generation of Renishaw's unique filtering optics that average the contributions from many scale periods and effectively filter out non-periodic features such as dirt.
|
|
The nominally square-wave scale pattern is also filtered to leave a pure sinusoidal fringe field at the detector.
|
|
Here, a multiple finger structure is employed, fine enough to produce photocurrents in the form of four symmetrically phased signals.
|
|
These are combined to remove DC components and produce sine and cosine signal outputs with high spectral purity and low offset while maintaining *bandwidth to beyond 500 kHz*.
|
|
|
|
Fully integrated advanced dynamic signal conditioning, Auto Gain , Auto Balance and Auto Offset Controls combine to ensure *ultra-low Sub-Divisional Error (SDE) of typically* $<\pm 15\, nm$.
|
|
|
|
This evolution of filtering optics, combined with carefully-selected electronics, provide incremental signals with wide bandwidth achieving a maximum speed of 12 m/s with the lowest positional jitter (noise) of any encoder in its class.
|
|
Interpolation is within the readhead, with fine resolution versions being further augmented by additional noise-reducing electronics to achieve *jitter of just 1.6 nm RMS*.
|
|
#+end_quote
|
|
|
|
The expected interpolation errors (non-linearity) is shown in Figure [[fig:vionic_expected_noise]].
|
|
|
|
#+name: fig:vionic_expected_noise
|
|
#+attr_latex: :width \linewidth
|
|
#+caption: Expected interpolation errors for the Vionic Encoder
|
|
[[file:./figs/vionic_expected_noise.png]]
|
|
|
|
The characteristics as advertise in the manual as well as our specifications are shown in Table [[tab:vionic_characteristics]].
|
|
|
|
#+name: tab:vionic_characteristics
|
|
#+caption: Characteristics of the Vionic compared with the specifications
|
|
#+attr_latex: :environment tabularx :width 0.6\linewidth :align lcc
|
|
#+attr_latex: :center t :booktabs t :float t
|
|
| <l> | <c> | <c> |
|
|
| *Characteristics* | *Manual* | *Specification* |
|
|
|-------------------+--------------+-----------------|
|
|
| Time Delay | | < 0.5 ms |
|
|
| Bandwidth | > 500 kHz | > 5 kHz |
|
|
| Noise | < 1.6 nm rms | < 50 nm rms |
|
|
| Linearity | < +/- 15 nm | |
|
|
| Range | Ruler length | > 200 um |
|
|
|
|
* Encoder Model
|
|
<<sec: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) $\Gamma_n(\omega)$.
|
|
|
|
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]]
|
|
|
|
* Noise Measurement
|
|
<<sec: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)
|
|
<<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
|
|
|
|
** TODO Thermal drifts
|
|
- [ ] picture of the setup
|
|
- [ ] long thermal drifts
|
|
- [ ] once stabilize, look at the noise
|
|
- [ ] compute low frequency ASD (may still be thermal drifts of the mechanics and not noise)
|
|
|
|
** Time Domain signals
|
|
First we load the data.
|
|
#+begin_src matlab :exports none
|
|
%% Load all the measurements
|
|
enc = {};
|
|
for i = 1:7
|
|
enc(i) = {load(['mat/noise_meas_100s_20kHz_' num2str(i) '.mat'], 't', 'x')};
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
%% Remove initial offset
|
|
for i = 1:7
|
|
enc{i}.x = enc{i}.x - mean(enc{i}.x(1:1000));
|
|
end
|
|
#+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(enc{1}.t, 1e9*enc{1}.x, '.', 'DisplayName', 'Enc 1 - Raw');
|
|
plot(enc{1}.t, 1e9*lsim(1/(1 + s/2/pi/10), enc{1}.x, enc{1}.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;
|
|
for i=1:7
|
|
plot(enc{i}.t, 1e9*lsim(1/(1 + s/2/pi/10), enc{i}.x, enc{i}.t), '.', ...
|
|
'DisplayName', sprintf('Enc %i', i));
|
|
end
|
|
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]]
|
|
|
|
** Noise Spectral Density
|
|
The amplitude spectral density is computed and shown in Figure [[fig:vionic_noise_asd]].
|
|
#+begin_src matlab :exports none
|
|
% Compute sampling Frequency
|
|
Ts = (enc{1}.t(end) - enc{1}.t(1))/(length(enc{1}.t)-1);
|
|
Fs = 1/Ts;
|
|
|
|
% Hannning Windows
|
|
win = hanning(ceil(0.5/Ts));
|
|
|
|
[pxx, f] = pwelch(enc{1}.x, win, [], [], Fs);
|
|
enc{1}.pxx = pxx;
|
|
|
|
for i=2:7
|
|
[pxx, ~] = pwelch(enc{i}.x, win, [], [], Fs);
|
|
enc{i}.pxx = pxx;
|
|
end
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
figure;
|
|
hold on;
|
|
for i=1:7
|
|
plot(f, sqrt(enc{i}.pxx), ...
|
|
'DisplayName', sprintf('Enc %i', i));
|
|
end
|
|
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]]
|
|
|
|
** Noise Model
|
|
|
|
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)$');
|
|
for i=2:7
|
|
plot(f, sqrt(enc{i}.pxx), 'color', [0, 0, 0, 0.5], ...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
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 modeled one
|
|
#+RESULTS:
|
|
[[file:figs/vionic_noise_asd_model.png]]
|
|
|
|
** Validity of the noise model
|
|
The cumulative amplitude spectrum is now computed and shown in Figure [[fig:vionic_noise_cas_model]].
|
|
|
|
We can see that the Root Mean Square value of the measurement noise is $\approx 1.6 \, nm$ as advertise in the datasheet.
|
|
|
|
#+begin_src matlab :exports none
|
|
for i = 1:7
|
|
enc{i}.CPS = flip(-cumtrapz(flip(f), flip(enc{i}.pxx)));
|
|
end
|
|
|
|
CAS_Gn = flip(-cumtrapz(flip(f), flip(abs(squeeze(freqresp(Gn_e, f, 'Hz'))).^2)));
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
figure;
|
|
hold on;
|
|
plot(f, sqrt(enc{1}.CPS), 'color', [0, 0, 0, 0.5], 'DisplayName', '$CAS_n(\omega)$');
|
|
for i=2:7
|
|
plot(f, sqrt(enc{i}.CPS), 'color', [0, 0, 0, 0.5], 'HandleVisibility', 'off');
|
|
end
|
|
plot(f, sqrt(CAS_Gn), 'r-', 'DisplayName', 'model');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('CPS [$m$]');
|
|
xlim([10, Fs/2]);
|
|
ylim([1e-10, 1e-8]);
|
|
legend('location', 'northeast');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/vionic_noise_cas_model.pdf', 'width', 'wide', 'height', 'normal');
|
|
#+end_src
|
|
|
|
#+name: fig:vionic_noise_cas_model
|
|
#+caption: Meassured CAS of the noise and modeled one
|
|
#+RESULTS:
|
|
[[file:figs/vionic_noise_cas_model.png]]
|
|
|
|
* 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
|
|
|