166 lines
8.1 KiB
Matlab
166 lines
8.1 KiB
Matlab
%% Clear Workspace and Close figures
|
|
clear; close all; clc;
|
|
|
|
%% Intialize Laplace variable
|
|
s = zpk('s');
|
|
|
|
%% Path for functions, data and scripts
|
|
addpath('./src/'); % Path for scripts
|
|
addpath('./mat/'); % Path for data
|
|
addpath('./STEPS/'); % Path for Simscape Model
|
|
addpath('./subsystems/'); % Path for Subsystems Simulink files
|
|
|
|
%% Linearization options
|
|
opts = linearizeOptions;
|
|
opts.SampleTime = 0;
|
|
|
|
%% Open Simscape Model
|
|
mdl = 'detail_instrumentation_nass'; % Name of the Simulink File
|
|
open(mdl); % Open Simscape Model
|
|
|
|
%% Colors for the figures
|
|
colors = colororder;
|
|
freqs = logspace(1,4,1000); % Frequency vector [Hz]
|
|
|
|
% Closed-Loop Sensitivity to Instrumentation Disturbances
|
|
% <<ssec:detail_instrumentation_cl_sensitivity>>
|
|
|
|
% Several key noise sources are considered in the analysis (Figure ref:fig:detail_instrumentation_plant).
|
|
% These include the output voltage noise of the DAC ($n_{da}$), the output voltage noise of the voltage amplifier ($n_{amp}$), and the voltage noise of the ADC measuring the force sensor stacks ($n_{ad}$).
|
|
|
|
% Encoder noise, which is only used to estimate $R_z$, has been found to have minimal impact on the vertical sample error and is therefore omitted from this analysis for clarity.
|
|
|
|
% The transfer functions from these three noise sources (for one strut) to the vertical error of the sample are estimated from the multi-body model, which includes the APA300ML and the designed flexible joints (Figure ref:fig:detail_instrumentation_noise_sensitivities).
|
|
|
|
|
|
%% Identify the transfer functions from disturbance sources to vertical position error
|
|
% Let's initialize all the stages with default parameters.
|
|
initializeGround();
|
|
initializeGranite();
|
|
initializeTy();
|
|
initializeRy();
|
|
initializeRz();
|
|
initializeMicroHexapod();
|
|
initializeSample('m', 1);
|
|
initializeSimplifiedNanoHexapod();
|
|
|
|
initializeSimscapeConfiguration();
|
|
initializeDisturbances('enable', false);
|
|
initializeLoggingConfiguration('log', 'none');
|
|
initializeController('type', 'hac-iff');
|
|
initializeReferences();
|
|
|
|
% Decentralized IFF controller
|
|
wz = 2*pi*2;
|
|
xiz = 0.7;
|
|
Ghpf = (s^2/wz^2)/(s^2/wz^2 + 2*xiz*s/wz + 1);
|
|
|
|
Kiff = -200 * ... % Gain
|
|
1/(0.01*2*pi + s) * ... % LPF: provides integral action
|
|
Ghpf * ... % 2nd order HPF (limit low frequency gain)
|
|
eye(6); % Diagonal 6x6 controller (i.e. decentralized)
|
|
|
|
% Centralized HAC
|
|
wc = 2*pi*10; % Wanted crossover [rad/s]
|
|
H_int = wc/s; % Integrator
|
|
a = 2; % Amount of phase lead / width of the phase lead / high frequency gain
|
|
H_lead = 1/sqrt(a)*(1 + s/(wc/sqrt(a)))/(1 + s/(wc*sqrt(a))); % Lead to increase phase margin
|
|
H_lpf = 1/(1 + s/2/pi/80); % Low Pass filter to increase robustness
|
|
|
|
Khac = -5e4 * ... % Gain
|
|
H_int * ... % Integrator
|
|
H_lead * ... % Low Pass filter
|
|
H_lpf * ... % Low Pass filter
|
|
eye(6); % 6x6 Diagonal
|
|
|
|
% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/dac_noise'], 1, 'input'); io_i = io_i + 1; % DAC noise [V]
|
|
io(io_i) = linio([mdl, '/amp_noise'], 1, 'input'); io_i = io_i + 1; % Voltage Amplifier noise [V]
|
|
io(io_i) = linio([mdl, '/NASS/adc_noise'], 1, 'input'); io_i = io_i + 1; % ADC noise [V]
|
|
io(io_i) = linio([mdl, '/NASS/enc_noise'], 1, 'input'); io_i = io_i + 1; % Encoder noise [m]
|
|
io(io_i) = linio([mdl, '/NASS'], 2, 'output', [], 'z'); io_i = io_i + 1; % Vertical error [m]
|
|
io(io_i) = linio([mdl, '/NASS'], 2, 'output', [], 'y'); io_i = io_i + 1; % Lateral error [m]
|
|
|
|
Gd = linearize(mdl, io);
|
|
Gd.InputName = {...
|
|
'nda1', 'nda2', 'nda3', 'nda4', 'nda5', 'nda6', ... % DAC and Voltage amplifier noise
|
|
'namp1', 'namp2', 'namp3', 'namp4', 'namp5', 'namp6', ... % DAC and Voltage amplifier noise
|
|
'nad1', 'nad2', 'nad3', 'nad4', 'nad5', 'nad6', ... % ADC noise
|
|
'ddL1', 'ddL2', 'ddL3', 'ddL4', 'ddL5', 'ddL6' ... % Encoder noise
|
|
};
|
|
Gd.OutputName = {'y', 'z'}; % Vertical error of the sample
|
|
|
|
%% Save Requirements
|
|
save('./mat/instrumentation_sensitivity.mat', 'Gd');
|
|
|
|
%% Transfer function from noise sources to vertical motion errors
|
|
freqs = logspace(0, 3, 1000);
|
|
|
|
figure;
|
|
tiledlayout(1, 1, 'TileSpacing', 'compact', 'Padding', 'None');
|
|
nexttile();
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gd('z', 'nda1' ), freqs, 'Hz'))), 'DisplayName', '$\epsilon_z/n_{da}$');
|
|
plot(freqs, abs(squeeze(freqresp(Gd('z', 'namp1'), freqs, 'Hz'))), 'DisplayName', '$\epsilon_z/n_{amp}$');
|
|
plot(freqs, abs(squeeze(freqresp(Gd('z', 'nad1' ), freqs, 'Hz'))), 'DisplayName', '$\epsilon_z/n_{ad}$');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Sensitivity [m/V]');
|
|
ylim([1e-9, 1e-4]);
|
|
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
|
|
leg.ItemTokenSize(1) = 15;
|
|
xlim([1, 1e3]);
|
|
|
|
% Estimation of maximum instrumentation noise
|
|
% <<ssec:detail_instrumentation_max_noise_specs>>
|
|
|
|
% The most stringent requirement for the system is maintaining vertical vibrations below the smallest expected beam size of $100\,\text{nm}$, which corresponds to a maximum allowed vibration of $15\,\text{nm RMS}$.
|
|
|
|
% Several assumptions regarding the noise characteristics have been made.
|
|
% The DAC, ADC, and amplifier noise are considered uncorrelated, which is a reasonable assumption.
|
|
% Similarly, the noise sources corresponding to each strut are also assumed to be uncorrelated.
|
|
% This means that the power spectral densities (PSD) of the different noise sources are summed.
|
|
|
|
% The system symmetry has been utilized to further simplify the analysis.
|
|
% The effect of all struts on the vertical errors is identical, as verified from the extracted sensitivity curves.
|
|
% Therefore, only one strut is considered for this analysis, and the total effect of the six struts is calculated as six times the effect of one strut in terms of power, which translates to a factor of $\sqrt{6} \approx 2.5$ for RMS values.
|
|
|
|
% In order to derive specifications in terms of noise spectral density for each instrumentation component, a white noise profile is assumed, which is typical for these components.
|
|
|
|
% The noise specification is computed such that if all components operate at their maximum allowable noise levels, the specification for vertical error will still be met.
|
|
% While this represents a pessimistic approach, it provides a reasonable estimate of the required specifications.
|
|
|
|
% Based on this analysis, the obtained maximum noise levels are as follows: DAC maximum output noise ASD is established at $14\,\mu V/\sqrt{\text{Hz}}$, voltage amplifier maximum output voltage noise ASD at $280\,\mu V/\sqrt{\text{Hz}}$, and ADC maximum measurement noise ASD at $11\,\mu V/\sqrt{\text{Hz}}$.
|
|
% In terms of RMS noise, these translate to less than $1\,\text{mV RMS}$ for the DAC, less than $20\,\text{mV RMS}$ for the voltage amplifier, and less than $0.8\,\text{mV RMS}$ for the ADC.
|
|
|
|
% If the Amplitude Spectral Density of the noise of the ADC, DAC, and voltage amplifiers all remain below these specified maximum levels, then the induced vertical error will be maintained below 15nm RMS.
|
|
|
|
|
|
% Maximum wanted effect of each noise source on the vertical error
|
|
% Specifications: 15nm RMS
|
|
% divide by sqrt(6) because 6 struts
|
|
% divide by sqrt(3) because 3 considered noise sources
|
|
max_asd_z = 15e-9 / sqrt(6) / sqrt(3); % [m/sqrt(Hz)]
|
|
|
|
% Suppose unitary flat noise ASD => compute the effect on vertical noise
|
|
unit_asd = ones(1, length(freqs));
|
|
rms_unit_asd_dac = sqrt(sum((unit_asd.*abs(squeeze(freqresp(Gd('z', 'nda1' ), freqs, 'Hz'))).').^2));
|
|
rms_unit_asd_amp = sqrt(sum((unit_asd.*abs(squeeze(freqresp(Gd('z', 'namp1'), freqs, 'Hz'))).').^2));
|
|
rms_unit_asd_adc = sqrt(sum((unit_asd.*abs(squeeze(freqresp(Gd('z', 'nad1' ), freqs, 'Hz'))).').^2));
|
|
|
|
% Obtained maximum ASD for different instruments
|
|
max_dac_asd = max_asd_z./rms_unit_asd_dac; % [V/sqrt(Hz)]
|
|
max_amp_asd = max_asd_z./rms_unit_asd_amp; % [V/sqrt(Hz)]
|
|
max_adc_asd = max_asd_z./rms_unit_asd_adc; % [V/sqrt(Hz)]
|
|
|
|
% Estimation of the equivalent RMS noise
|
|
max_dac_rms = 1e3*max_dac_asd*sqrt(5e3) % [mV RMS]
|
|
max_amp_rms = 1e3*max_amp_asd*sqrt(5e3) % [mV RMS]
|
|
max_adc_rms = 1e3*max_adc_asd*sqrt(5e3) % [mV RMS]
|
|
|
|
%% Save Requirements
|
|
save('./mat/instrumentation_requirements.mat', ...
|
|
'max_dac_asd', 'max_amp_asd', 'max_adc_asd', ...
|
|
'max_dac_rms', 'max_amp_rms', 'max_adc_rms');
|