2000 lines
67 KiB
Org Mode
2000 lines
67 KiB
Org Mode
#+TITLE: Finite Element Model with Simscape
|
|
:DRAWER:
|
|
#+STARTUP: overview
|
|
|
|
#+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="./css/htmlize.css"/>
|
|
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="./css/readtheorg.css"/>
|
|
#+HTML_HEAD: <script src="./js/jquery.min.js"></script>
|
|
#+HTML_HEAD: <script src="./js/bootstrap.min.js"></script>
|
|
#+HTML_HEAD: <script src="./js/jquery.stickytableheaders.min.js"></script>
|
|
#+HTML_HEAD: <script src="./js/readtheorg.js"></script>
|
|
|
|
#+PROPERTY: header-args:matlab :session *MATLAB*
|
|
#+PROPERTY: header-args:matlab+ :comments org
|
|
#+PROPERTY: header-args:matlab+ :results none
|
|
#+PROPERTY: header-args:matlab+ :exports both
|
|
#+PROPERTY: header-args:matlab+ :eval no-export
|
|
#+PROPERTY: header-args:matlab+ :output-dir figs
|
|
#+PROPERTY: header-args:matlab+ :tangle no
|
|
#+PROPERTY: header-args:matlab+ :mkdirp yes
|
|
|
|
#+PROPERTY: header-args:shell :eval no-export
|
|
|
|
#+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 raw replace :buffer 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
|
|
:END:
|
|
|
|
* Amplified Piezoelectric Actuator - 3D elements
|
|
** Introduction :ignore:
|
|
The idea here is to:
|
|
- export a FEM of an amplified piezoelectric actuator from Ansys to Matlab
|
|
- import it into a Simscape model
|
|
- compare the obtained dynamics
|
|
- add 10kg mass on top of the actuator and identify the dynamics
|
|
- compare with results from Ansys where 10kg are directly added to the FEM
|
|
|
|
** 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
|
|
addpath('./src/');
|
|
addpath('./data/piezo_amplified_3d/');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
open('piezo_amplified_3d');
|
|
#+end_src
|
|
|
|
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
|
|
We first extract the stiffness and mass matrices.
|
|
#+begin_src matlab
|
|
K = extractMatrix('piezo_amplified_3d_K.txt');
|
|
M = extractMatrix('piezo_amplified_3d_M.txt');
|
|
#+end_src
|
|
|
|
Then, we extract the coordinates of the interface nodes.
|
|
#+begin_src matlab
|
|
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('piezo_amplified_3d.txt');
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
save('./mat/piezo_amplified_3d.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
|
|
#+end_src
|
|
|
|
** Output parameters
|
|
#+begin_src matlab
|
|
load('./mat/piezo_amplified_3d.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable([length(n_i); length(int_i); size(M,1) - 6*length(int_i); size(M,1)], {'Total number of Nodes', 'Number of interface Nodes', 'Number of Modes', 'Size of M and K matrices'}, {}, ' %.0f ');
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
| Total number of Nodes | 168959 |
|
|
| Number of interface Nodes | 13 |
|
|
| Number of Modes | 30 |
|
|
| Size of M and K matrices | 108 |
|
|
|
|
#+name: fig:amplified_piezo_interface_nodes
|
|
#+caption: Interface Nodes for the Amplified Piezo Actuator
|
|
[[file:figs/amplified_piezo_interface_nodes.png]]
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable([[1:length(int_i)]', int_i, int_xyz], {}, {'Node i', 'Node Number', 'x [m]', 'y [m]', 'z [m]'}, ' %f ');
|
|
#+end_src
|
|
|
|
#+caption: Coordinates of the interface nodes
|
|
#+RESULTS:
|
|
| Node i | Node Number | x [m] | y [m] | z [m] |
|
|
|--------+-------------+--------+-------+-------|
|
|
| 1.0 | 168947.0 | 0.0 | 0.03 | 0.0 |
|
|
| 2.0 | 168949.0 | 0.0 | -0.03 | 0.0 |
|
|
| 3.0 | 168950.0 | -0.035 | 0.0 | 0.0 |
|
|
| 4.0 | 168951.0 | -0.028 | 0.0 | 0.0 |
|
|
| 5.0 | 168952.0 | -0.021 | 0.0 | 0.0 |
|
|
| 6.0 | 168953.0 | -0.014 | 0.0 | 0.0 |
|
|
| 7.0 | 168954.0 | -0.007 | 0.0 | 0.0 |
|
|
| 8.0 | 168955.0 | 0.0 | 0.0 | 0.0 |
|
|
| 9.0 | 168956.0 | 0.007 | 0.0 | 0.0 |
|
|
| 10.0 | 168957.0 | 0.014 | 0.0 | 0.0 |
|
|
| 11.0 | 168958.0 | 0.021 | 0.0 | 0.0 |
|
|
| 12.0 | 168959.0 | 0.035 | 0.0 | 0.0 |
|
|
| 13.0 | 168960.0 | 0.028 | 0.0 | 0.0 |
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable(K(1:10, 1:10), {}, {}, ' %.1g ');
|
|
#+end_src
|
|
|
|
#+caption: First 10x10 elements of the Stiffness matrix
|
|
#+RESULTS:
|
|
| 300000000.0 | -30000.0 | 8000.0 | -200.0 | -30.0 | -60000.0 | 20000000.0 | -4000.0 | 500.0 | 8 |
|
|
| -30000.0 | 100000000.0 | 400.0 | 30.0 | 200.0 | -1 | 4000.0 | -8000000.0 | 800.0 | 7 |
|
|
| 8000.0 | 400.0 | 50000000.0 | -800000.0 | -300.0 | -40.0 | 300.0 | 100.0 | 5000000.0 | 40000.0 |
|
|
| -200.0 | 30.0 | -800000.0 | 20000.0 | 5 | 1 | -10.0 | -2 | -40000.0 | -300.0 |
|
|
| -30.0 | 200.0 | -300.0 | 5 | 40000.0 | 0.3 | -4 | -10.0 | 40.0 | 0.4 |
|
|
| -60000.0 | -1 | -40.0 | 1 | 0.3 | 3000.0 | 7000.0 | 0.8 | -1 | 0.0003 |
|
|
| 20000000.0 | 4000.0 | 300.0 | -10.0 | -4 | 7000.0 | 300000000.0 | 20000.0 | 3000.0 | 80.0 |
|
|
| -4000.0 | -8000000.0 | 100.0 | -2 | -10.0 | 0.8 | 20000.0 | 100000000.0 | -4000.0 | -100.0 |
|
|
| 500.0 | 800.0 | 5000000.0 | -40000.0 | 40.0 | -1 | 3000.0 | -4000.0 | 50000000.0 | 800000.0 |
|
|
| 8 | 7 | 40000.0 | -300.0 | 0.4 | 0.0003 | 80.0 | -100.0 | 800000.0 | 20000.0 |
|
|
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable(M(1:10, 1:10), {}, {}, ' %.1g ');
|
|
#+end_src
|
|
|
|
#+caption: First 10x10 elements of the Mass matrix
|
|
#+RESULTS:
|
|
| 0.03 | 2e-06 | -2e-07 | 1e-08 | 2e-08 | 0.0002 | -0.001 | 2e-07 | -8e-08 | -9e-10 |
|
|
| 2e-06 | 0.02 | -5e-07 | 7e-09 | 3e-08 | 2e-08 | -3e-07 | 0.0003 | -1e-08 | 1e-10 |
|
|
| -2e-07 | -5e-07 | 0.02 | -9e-05 | 4e-09 | -1e-08 | 2e-07 | -2e-08 | -0.0006 | -5e-06 |
|
|
| 1e-08 | 7e-09 | -9e-05 | 1e-06 | 6e-11 | 4e-10 | -1e-09 | 3e-11 | 5e-06 | 3e-08 |
|
|
| 2e-08 | 3e-08 | 4e-09 | 6e-11 | 1e-06 | 2e-10 | -2e-09 | 2e-10 | -7e-09 | -4e-11 |
|
|
| 0.0002 | 2e-08 | -1e-08 | 4e-10 | 2e-10 | 2e-06 | -2e-06 | -1e-09 | -7e-10 | -9e-12 |
|
|
| -0.001 | -3e-07 | 2e-07 | -1e-09 | -2e-09 | -2e-06 | 0.03 | -2e-06 | -1e-07 | -5e-09 |
|
|
| 2e-07 | 0.0003 | -2e-08 | 3e-11 | 2e-10 | -1e-09 | -2e-06 | 0.02 | -8e-07 | -1e-08 |
|
|
| -8e-08 | -1e-08 | -0.0006 | 5e-06 | -7e-09 | -7e-10 | -1e-07 | -8e-07 | 0.02 | 9e-05 |
|
|
| -9e-10 | 1e-10 | -5e-06 | 3e-08 | -4e-11 | -9e-12 | -5e-09 | -1e-08 | 9e-05 | 1e-06 |
|
|
|
|
Using =K=, =M= and =int_xyz=, we can use the =Reduced Order Flexible Solid= simscape block.
|
|
|
|
|
|
** Piezoelectric parameters
|
|
Parameters for the APA95ML:
|
|
|
|
#+begin_src matlab
|
|
d33 = 3e-10; % Strain constant [m/V]
|
|
n = 80; % Number of layers per stack
|
|
eT = 1.6e-7; % Permittivity under constant stress [F/m]
|
|
sD = 2e-11; % Elastic compliance under constant electric displacement [m2/N]
|
|
ka = 235e6; % Stack stiffness [N/m]
|
|
C = 5e-6; % Stack capactiance [F]
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
na = 2; % Number of stacks used as actuator
|
|
ns = 1; % Number of stacks used as force sensor
|
|
#+end_src
|
|
|
|
The ratio of the developed force to applied voltage is $d_{33} n k_a$ in [N/V].
|
|
We denote this constant by $g_a$ and:
|
|
\[ F_a = g_a V_a, \quad g_a = d_{33} n k_a \]
|
|
#+begin_src matlab :results replace value
|
|
d33*(na*n)*(ka/(na + ns)) % [N/V]
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 3.76
|
|
|
|
From cite:fleming14_desig_model_contr_nanop_system (page 123), the relation between relative displacement and generated voltage is:
|
|
\[ V_s = \frac{d_{33}}{\epsilon^T s^D n} \Delta h \]
|
|
where:
|
|
- $V_s$: measured voltage [V]
|
|
- $d_{33}$: strain constant [m/V]
|
|
- $\epsilon^T$: permittivity under constant stress [F/m]
|
|
- $s^D$: elastic compliance under constant electric displacement [m^2/N]
|
|
- $n$: number of layers
|
|
- $\Delta h$: relative displacement [m]
|
|
#+begin_src matlab :results replace value
|
|
1e-6*d33/(eT*sD*ns*n) % [V/um]
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 1.1719
|
|
|
|
** Identification of the Dynamics
|
|
The flexible element is imported using the =Reduced Order Flexible Solid= simscape block.
|
|
|
|
To model the actuator, an =Internal Force= block is added between the nodes 3 and 12.
|
|
A =Relative Motion Sensor= block is added between the nodes 1 and 2 to measure the displacement and the amplified piezo.
|
|
|
|
One mass is fixed at one end of the piezo-electric stack actuator, the other end is fixed to the world frame.
|
|
|
|
We first set the mass to be zero.
|
|
#+begin_src matlab
|
|
m = 0.01;
|
|
#+end_src
|
|
|
|
The dynamics is identified from the applied force to the measured relative displacement.
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gh = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
Then, we add 10Kg of mass:
|
|
#+begin_src matlab
|
|
m = 5;
|
|
#+end_src
|
|
|
|
And the dynamics is identified.
|
|
|
|
The two identified dynamics are compared in Figure [[fig:dynamics_act_disp_comp_mass]].
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Ghm = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(0, 4, 5000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gh, freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(Ghm, freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gh, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Ghm, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-360 0]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/dynamics_act_disp_comp_mass.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:dynamics_act_disp_comp_mass
|
|
#+caption: Dynamics from $F$ to $d$ without a payload and with a 10kg payload
|
|
#+RESULTS:
|
|
[[file:figs/dynamics_act_disp_comp_mass.png]]
|
|
|
|
** Comparison with Ansys
|
|
Let's import the results from an Harmonic response analysis in Ansys.
|
|
#+begin_src matlab
|
|
Gresp0 = readtable('FEA_HarmResponse_00kg.txt');
|
|
Gresp10 = readtable('FEA_HarmResponse_10kg.txt');
|
|
#+end_src
|
|
|
|
The obtained dynamics from the Simscape model and from the Ansys analysis are compare in Figure [[fig:dynamics_force_disp_comp_anasys]].
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(freqs, abs(squeeze(freqresp(Gh, freqs, 'Hz'))), '-');
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(Gresp0{:, 2}, 1e-3*Gresp0{:, 3}, '--');
|
|
|
|
set(gca,'ColorOrderIndex',2)
|
|
plot(freqs, abs(squeeze(freqresp(Ghm, freqs, 'Hz'))), '-');
|
|
set(gca,'ColorOrderIndex',2)
|
|
plot(Gresp0{:, 2}, 1e-3*Gresp10{:, 3}, '--');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gh, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$, Simscape');
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(Gresp0{:, 2}, 180/pi*unwrap(pi/180*Gresp0{:, 4}), '--', ...
|
|
'DisplayName', '$m = 0kg$, Ansys');
|
|
set(gca,'ColorOrderIndex',2)
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Ghm, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$, Simscape');
|
|
set(gca,'ColorOrderIndex',2)
|
|
plot(Gresp0{:, 2}, 180/pi*unwrap(pi/180*Gresp10{:, 4}), '--', ...
|
|
'DisplayName', '$m = 10kg$, Ansys');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-390 30]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
legend('location', 'southwest');
|
|
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/dynamics_force_disp_comp_anasys.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:dynamics_force_disp_comp_anasys
|
|
#+caption: Comparison of the obtained dynamics using Simscape with the harmonic response analysis using Ansys
|
|
#+RESULTS:
|
|
[[file:figs/dynamics_force_disp_comp_anasys.png]]
|
|
|
|
** Force Sensor
|
|
The dynamics is identified from internal forces applied between nodes 3 and 11 to the relative displacement of nodes 11 and 13.
|
|
|
|
The obtained dynamics is shown in Figure [[fig:dynamics_force_force_sensor_comp_mass]].
|
|
|
|
#+begin_src matlab
|
|
m = 0;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Fa'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Fs'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gf = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Fa'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Fs'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gfm = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gf, freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(Gfm, freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gf, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gfm, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-390 30]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/dynamics_force_force_sensor_comp_mass.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:dynamics_force_force_sensor_comp_mass
|
|
#+caption: Dynamics from $F$ to $F_m$ for $m=0$ and $m = 10kg$
|
|
#+RESULTS:
|
|
[[file:figs/dynamics_force_force_sensor_comp_mass.png]]
|
|
|
|
** Distributed Actuator
|
|
#+begin_src matlab
|
|
m = 0;
|
|
#+end_src
|
|
|
|
The dynamics is identified from the applied force to the measured relative displacement.
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d_distri';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gd = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
Then, we add 10Kg of mass:
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
And the dynamics is identified.
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d_distri';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gdm = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 5000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gh, freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(Ghm, freqs, 'Hz'))), '-');
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(freqs, abs(squeeze(freqresp(Gd, freqs, 'Hz'))), '--');
|
|
plot(freqs, abs(squeeze(freqresp(Gdm, freqs, 'Hz'))), '--');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gh, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Ghm, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$');
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gd, freqs, 'Hz')))), '--', ...
|
|
'DisplayName', '$m = 0kg$, distri');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gdm, freqs, 'Hz')))), '--', ...
|
|
'DisplayName', '$m = 10kg$, distri');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-360 0]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
** Distributed Actuator and Force Sensor
|
|
#+begin_src matlab
|
|
m = 0;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d_distri_act_sens';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Fm'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gfd = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d_distri_act_sens';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Fm'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gfdm = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gf, freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(Gfm, freqs, 'Hz'))), '-');
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(freqs, abs(squeeze(freqresp(Gfd, freqs, 'Hz'))), '--');
|
|
plot(freqs, abs(squeeze(freqresp(Gfdm, freqs, 'Hz'))), '--');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gf, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gfm, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$');
|
|
set(gca,'ColorOrderIndex',1)
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gfd, freqs, 'Hz')))), '--', ...
|
|
'DisplayName', '$m = 0kg$, distri');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gfdm, freqs, 'Hz')))), '--', ...
|
|
'DisplayName', '$m = 10kg$, distri');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-390 30]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
** Dynamics from input voltage to displacement
|
|
#+begin_src matlab
|
|
m = 5;
|
|
#+end_src
|
|
|
|
And the dynamics is identified.
|
|
|
|
The two identified dynamics are compared in Figure [[fig:dynamics_act_disp_comp_mass]].
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/V'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
G = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 4, 5000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G, freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G, freqs, 'Hz')))));
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-360 0]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
% xlim([10, 5e3]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
save('../test-bench-apa/mat/fem_model_5kg.mat', 'G')
|
|
#+end_src
|
|
|
|
** Dynamics from input voltage to output voltage
|
|
#+begin_src matlab
|
|
m = 5;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_3d';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Va'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Vs'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
G = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 4, 5000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G, freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G, freqs, 'Hz')))));
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([10, 5e3]);
|
|
#+end_src
|
|
|
|
* APA300ML
|
|
** Introduction :ignore:
|
|
|
|
#+name: fig:apa300ml_ansys
|
|
#+caption: Ansys FEM of the APA300ML
|
|
[[file:figs/apa300ml_ansys.jpg]]
|
|
|
|
** 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
|
|
addpath('./src/');
|
|
addpath('./data/APA300ML/');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
open('APA300ML_test_bench');
|
|
#+end_src
|
|
|
|
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
|
|
We first extract the stiffness and mass matrices.
|
|
#+begin_src matlab
|
|
K = extractMatrix('mat_K-48modes-7MDoF.matrix');
|
|
M = extractMatrix('mat_M-48modes-7MDoF.matrix');
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
K = extractMatrix('mat_K-80modes-7MDoF.matrix');
|
|
M = extractMatrix('mat_M-80modes-7MDoF.matrix');
|
|
#+end_src
|
|
|
|
Then, we extract the coordinates of the interface nodes.
|
|
#+begin_src matlab
|
|
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('Nodes_MDoF_NLIST_MLIST.txt');
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
save('./mat/APA300ML.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
|
|
#+end_src
|
|
|
|
** Output parameters
|
|
#+begin_src matlab
|
|
load('./mat/APA300ML.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable([length(n_i); length(int_i); size(M,1) - 6*length(int_i); size(M,1)], {'Total number of Nodes', 'Number of interface Nodes', 'Number of Modes', 'Size of M and K matrices'}, {}, ' %.0f ');
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
| Total number of Nodes | 7 |
|
|
| Number of interface Nodes | 7 |
|
|
| Number of Modes | 6 |
|
|
| Size of M and K matrices | 48 |
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable([[1:length(int_i)]', int_i, int_xyz], {}, {'Node i', 'Node Number', 'x [m]', 'y [m]', 'z [m]'}, ' %f ');
|
|
#+end_src
|
|
|
|
#+caption: Coordinates of the interface nodes
|
|
#+RESULTS:
|
|
| Node i | Node Number | x [m] | y [m] | z [m] |
|
|
|--------+-------------+---------+--------+-------|
|
|
| 1.0 | 53917.0 | 0.0 | -0.015 | 0.0 |
|
|
| 2.0 | 53918.0 | 0.0 | 0.015 | 0.0 |
|
|
| 3.0 | 53919.0 | -0.0325 | 0.0 | 0.0 |
|
|
| 4.0 | 53920.0 | -0.0125 | 0.0 | 0.0 |
|
|
| 5.0 | 53921.0 | -0.0075 | 0.0 | 0.0 |
|
|
| 6.0 | 53922.0 | 0.0125 | 0.0 | 0.0 |
|
|
| 7.0 | 53923.0 | 0.0325 | 0.0 | 0.0 |
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable(K(1:10, 1:10), {}, {}, ' %.1g ');
|
|
#+end_src
|
|
|
|
#+caption: First 10x10 elements of the Stiffness matrix
|
|
#+RESULTS:
|
|
| 200000000.0 | 30000.0 | 50000.0 | 200.0 | -100.0 | -300000.0 | 10000000.0 | -6000.0 | 20000.0 | -60.0 |
|
|
| 30000.0 | 7000000.0 | 10000.0 | 30.0 | -30.0 | -70.0 | 7000.0 | -500000.0 | 3000.0 | -10.0 |
|
|
| 50000.0 | 10000.0 | 30000000.0 | 200000.0 | -200.0 | -100.0 | 20000.0 | -2000.0 | 2000000.0 | -9000.0 |
|
|
| 200.0 | 30.0 | 200000.0 | 1000.0 | -0.8 | -0.4 | 50.0 | -6 | 9000.0 | -30.0 |
|
|
| -100.0 | -30.0 | -200.0 | -0.8 | 10000.0 | 0.2 | -40.0 | 10.0 | 20.0 | -0.05 |
|
|
| -300000.0 | -70.0 | -100.0 | -0.4 | 0.2 | 900.0 | -30000.0 | 10.0 | -40.0 | 0.1 |
|
|
| 10000000.0 | 7000.0 | 20000.0 | 50.0 | -40.0 | -30000.0 | 200000000.0 | -50000.0 | 30000.0 | -50.0 |
|
|
| -6000.0 | -500000.0 | -2000.0 | -6 | 10.0 | 10.0 | -50000.0 | 7000000.0 | -4000.0 | 8 |
|
|
| 20000.0 | 3000.0 | 2000000.0 | 9000.0 | 20.0 | -40.0 | 30000.0 | -4000.0 | 30000000.0 | -200000.0 |
|
|
| -60.0 | -10.0 | -9000.0 | -30.0 | -0.05 | 0.1 | -50.0 | 8 | -200000.0 | 1000.0 |
|
|
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable(M(1:10, 1:10), {}, {}, ' %.1g ');
|
|
#+end_src
|
|
|
|
#+caption: First 10x10 elements of the Mass matrix
|
|
#+RESULTS:
|
|
| 0.01 | 7e-06 | -5e-06 | -6e-08 | 3e-09 | -5e-05 | -0.0005 | -2e-07 | -3e-06 | 1e-08 |
|
|
| 7e-06 | 0.009 | 4e-07 | 6e-09 | -4e-09 | -3e-08 | -2e-07 | 6e-05 | 5e-07 | -1e-09 |
|
|
| -5e-06 | 4e-07 | 0.01 | 2e-05 | 2e-08 | 3e-08 | -2e-06 | -1e-07 | -0.0002 | 9e-07 |
|
|
| -6e-08 | 6e-09 | 2e-05 | 3e-07 | 1e-10 | 3e-10 | -7e-09 | 2e-10 | -9e-07 | 3e-09 |
|
|
| 3e-09 | -4e-09 | 2e-08 | 1e-10 | 1e-07 | -3e-12 | 6e-09 | -2e-10 | -3e-09 | 9e-12 |
|
|
| -5e-05 | -3e-08 | 3e-08 | 3e-10 | -3e-12 | 6e-07 | 1e-06 | -3e-09 | 2e-08 | -7e-11 |
|
|
| -0.0005 | -2e-07 | -2e-06 | -7e-09 | 6e-09 | 1e-06 | 0.01 | -8e-06 | -2e-06 | 9e-09 |
|
|
| -2e-07 | 6e-05 | -1e-07 | 2e-10 | -2e-10 | -3e-09 | -8e-06 | 0.009 | 1e-07 | 2e-09 |
|
|
| -3e-06 | 5e-07 | -0.0002 | -9e-07 | -3e-09 | 2e-08 | -2e-06 | 1e-07 | 0.01 | -2e-05 |
|
|
| 1e-08 | -1e-09 | 9e-07 | 3e-09 | 9e-12 | -7e-11 | 9e-09 | 2e-09 | -2e-05 | 3e-07 |
|
|
|
|
Using =K=, =M= and =int_xyz=, we can use the =Reduced Order Flexible Solid= simscape block.
|
|
|
|
** Piezoelectric parameters
|
|
Parameters for the APA300ML:
|
|
|
|
#+begin_src matlab
|
|
d33 = 3e-10; % Strain constant [m/V]
|
|
n = 80; % Number of layers per stack
|
|
eT = 1.6e-8; % Permittivity under constant stress [F/m]
|
|
sD = 2e-11; % Elastic compliance under constant electric displacement [m2/N]
|
|
ka = 235e6; % Stack stiffness [N/m]
|
|
C = 5e-6; % Stack capactiance [F]
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
na = 2; % Number of stacks used as actuator
|
|
ns = 1; % Number of stacks used as force sensor
|
|
#+end_src
|
|
|
|
The ratio of the developed force to applied voltage is $d_{33} n k_a$ in [N/V].
|
|
We denote this constant by $g_a$ and:
|
|
\[ F_a = g_a V_a, \quad g_a = d_{33} n k_a \]
|
|
#+begin_src matlab :results replace value
|
|
d33*(na*n)*(ka/(na + ns)) % [N/V]
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 0.42941
|
|
|
|
From cite:fleming14_desig_model_contr_nanop_system (page 123), the relation between relative displacement and generated voltage is:
|
|
\[ V_s = \frac{d_{33}}{\epsilon^T s^D n} \Delta h \]
|
|
where:
|
|
- $V_s$: measured voltage [V]
|
|
- $d_{33}$: strain constant [m/V]
|
|
- $\epsilon^T$: permittivity under constant stress [F/m]
|
|
- $s^D$: elastic compliance under constant electric displacement [m^2/N]
|
|
- $n$: number of layers
|
|
- $\Delta h$: relative displacement [m]
|
|
#+begin_src matlab :results replace value
|
|
1e-6*d33/(eT*sD*ns*n) % [V/um]
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 5.8594
|
|
|
|
** Identification of the APA Characteristics
|
|
*** Stiffness
|
|
#+begin_src matlab :exports none
|
|
m = 0.001;
|
|
#+end_src
|
|
|
|
The transfer function from vertical external force to the relative vertical displacement is identified.
|
|
|
|
#+begin_src matlab :exports none
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
G = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
The inverse of its DC gain is the axial stiffness of the APA:
|
|
#+begin_src matlab :results replace value
|
|
1e-6/dcgain(G) % [N/um]
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 1.8634
|
|
|
|
The specified stiffness in the datasheet is $k = 1.8\, [N/\mu m]$.
|
|
|
|
*** Resonance Frequency
|
|
The resonance frequency is specified to be between 650Hz and 840Hz.
|
|
This is also the case for the FEM model (Figure [[fig:apa300ml_resonance]]).
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(2, 4, 5000);
|
|
|
|
figure;
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G, freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
xlabel('Frequency [Hz]'); ylabel('Amplitude');
|
|
hold off;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/apa300ml_resonance.pdf', 'width', 'wide', 'height', 'normal');
|
|
#+end_src
|
|
|
|
#+name: fig:apa300ml_resonance
|
|
#+caption: First resonance is around 800Hz
|
|
#+RESULTS:
|
|
[[file:figs/apa300ml_resonance.png]]
|
|
|
|
*** Amplification factor
|
|
The amplification factor is the ratio of the axial displacement to the stack displacement.
|
|
|
|
#+begin_src matlab :exports none
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/d'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
G = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
The ratio of the two displacement is computed from the FEM model.
|
|
#+begin_src matlab :results replace value
|
|
-dcgain(G(1,1))./dcgain(G(2,1))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 4.936
|
|
|
|
If we take the ratio of the piezo height and length (approximation of the amplification factor):
|
|
#+begin_src matlab :results replace value
|
|
75/15
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 5
|
|
|
|
*** Stroke
|
|
|
|
Estimation of the actuator stroke:
|
|
\[ \Delta H = A n \Delta L \]
|
|
with:
|
|
- $\Delta H$ Axial Stroke of the APA
|
|
- $A$ Amplification factor (5 for the APA300ML)
|
|
- $n$ Number of stack used
|
|
- $\Delta L$ Stroke of the stack (0.1% of its length)
|
|
|
|
#+begin_src matlab :results replace value
|
|
1e6 * 5 * 3 * 20e-3 * 0.1e-2
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 300
|
|
|
|
This is exactly the specified stroke in the data-sheet.
|
|
|
|
** Identification of the Dynamics
|
|
The flexible element is imported using the =Reduced Order Flexible Solid= simscape block.
|
|
|
|
To model the actuator, an =Internal Force= block is added between the nodes 3 and 12.
|
|
A =Relative Motion Sensor= block is added between the nodes 1 and 2 to measure the displacement and the amplified piezo.
|
|
|
|
One mass is fixed at one end of the piezo-electric stack actuator, the other end is fixed to the world frame.
|
|
|
|
We first set the mass to be zero.
|
|
#+begin_src matlab :exports none
|
|
m = 0.01;
|
|
#+end_src
|
|
|
|
The dynamics is identified from the applied force to the measured relative displacement.
|
|
#+begin_src matlab :exports none
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gh = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
The same dynamics is identified for a payload mass of 10Kg.
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Ghm = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(0, 4, 5000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gh, freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(Ghm, freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gh, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Ghm, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-360 0]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/apa300ml_plant_dynamics.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:apa300ml_plant_dynamics
|
|
#+caption: Transfer function from forces applied by the stack to the axial displacement of the APA
|
|
#+RESULTS:
|
|
[[file:figs/apa300ml_plant_dynamics.png]]
|
|
|
|
** IFF
|
|
Let's use 2 stacks as actuators and 1 stack as force sensor.
|
|
|
|
The transfer function from actuator to sensors is identified and shown in Figure [[fig:apa300ml_iff_plant]].
|
|
#+begin_src matlab :exports none
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Va'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Vs'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Giff = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(0, 4, 5000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Giff, freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Giff, freqs, 'Hz')))), '-');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-180 180]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/apa300ml_iff_plant.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:apa300ml_iff_plant
|
|
#+caption: Transfer function from actuator to force sensor
|
|
#+RESULTS:
|
|
[[file:figs/apa300ml_iff_plant.png]]
|
|
|
|
For root locus corresponding to IFF is shown in Figure [[fig:apa300ml_iff_root_locus]].
|
|
|
|
#+begin_src matlab :exports none
|
|
figure;
|
|
|
|
gains = logspace(0, 5, 500);
|
|
|
|
hold on;
|
|
plot(real(pole(Giff)), imag(pole(Giff)), 'kx');
|
|
plot(real(tzero(Giff)), imag(tzero(Giff)), 'ko');
|
|
for k = 1:length(gains)
|
|
cl_poles = pole(feedback(Giff, gains(k)/s));
|
|
plot(real(cl_poles), imag(cl_poles), 'k.');
|
|
end
|
|
hold off;
|
|
axis square;
|
|
xlim([-500, 10]); ylim([0, 510]);
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/apa300ml_iff_root_locus.pdf', 'width', 'wide', 'height', 'tall');
|
|
#+end_src
|
|
|
|
#+name: fig:apa300ml_iff_root_locus
|
|
#+caption: Root Locus for IFF
|
|
#+RESULTS:
|
|
[[file:figs/apa300ml_iff_root_locus.png]]
|
|
|
|
** DVF
|
|
Now the dynamics from the stack actuator to the relative motion sensor is identified and shown in Figure [[fig:apa300ml_dvf_plant]].
|
|
#+begin_src matlab :exports none
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
G = -linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(0, 4, 5000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G, freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(G, freqs, 'Hz')))), '-');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-360 0]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/apa300ml_dvf_plant.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:apa300ml_dvf_plant
|
|
#+caption: Transfer function from stack actuator to relative motion sensor
|
|
#+RESULTS:
|
|
[[file:figs/apa300ml_dvf_plant.png]]
|
|
|
|
The root locus for DVF is shown in Figure [[fig:apa300ml_dvf_root_locus]].
|
|
|
|
#+begin_src matlab :exports none
|
|
figure;
|
|
|
|
gains = logspace(0, 5, 500);
|
|
|
|
hold on;
|
|
plot(real(pole(G)), imag(pole(G)), 'kx');
|
|
plot(real(tzero(G)), imag(tzero(G)), 'ko');
|
|
for k = 1:length(gains)
|
|
cl_poles = pole(feedback(G, gains(k)*s));
|
|
plot(real(cl_poles), imag(cl_poles), 'k.');
|
|
end
|
|
hold off;
|
|
axis square;
|
|
xlim([-500, 10]); ylim([0, 510]);
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/apa300ml_dvf_root_locus.pdf', 'width', 'wide', 'height', 'tall');
|
|
#+end_src
|
|
|
|
#+name: fig:apa300ml_dvf_root_locus
|
|
#+caption: Root Locus for Direct Velocity Feedback
|
|
#+RESULTS:
|
|
[[file:figs/apa300ml_dvf_root_locus.png]]
|
|
|
|
** TODO Sensor Fusion :noexport:
|
|
- [ ] What is the goal of that? Special control properties, lower the sensor noise?
|
|
|
|
Use the relative motion sensor at low frequency and the force sensor at high frequency.
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Va'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Vs'], 1, 'openoutput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
G = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
Gresp = squeeze(freqresp(G, freqs, 'Hz'));
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(Gresp(1, :)), '-');
|
|
plot(freqs, abs(Gresp(2, :)), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(Gresp(1, :))), '-', ...
|
|
'DisplayName', 'Force');
|
|
plot(freqs, 180/pi*unwrap(angle(Gresp(2, :))), '-', ...
|
|
'DisplayName', 'Displacement');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-390 30]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
Merge around 1kHz
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(Gresp(1, :).*squeeze(freqresp(0.0065/s^2, freqs, 'Hz'))'), '-');
|
|
plot(freqs, abs(Gresp(2, :)), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(Gresp(1, :).*squeeze(freqresp(1/s^2, freqs, 'Hz'))')), '-', ...
|
|
'DisplayName', 'Force');
|
|
plot(freqs, 180/pi*unwrap(angle(Gresp(2, :))), '-', ...
|
|
'DisplayName', 'Displacement');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
LPF and HPF
|
|
#+begin_src matlab
|
|
n = 3; w0 = 2*pi*1e3; G0 = 1/10; G1 = 1e5; Gc = 1/2;
|
|
W1 = (((1/w0)*sqrt((1-(G0/Gc)^(2/n))/(1-(Gc/G1)^(2/n)))*s + (G0/Gc)^(1/n))/((1/G1)^(1/n)*(1/w0)*sqrt((1-(G0/Gc)^(2/n))/(1-(Gc/G1)^(2/n)))*s + (1/Gc)^(1/n)))^n;
|
|
|
|
n = 3; w0 = 2*pi*1e3; G0 = 1e5; G1 = 0.1; Gc = 1/2;
|
|
W2 = (((1/w0)*sqrt((1-(G0/Gc)^(2/n))/(1-(Gc/G1)^(2/n)))*s + (G0/Gc)^(1/n))/((1/G1)^(1/n)*(1/w0)*sqrt((1-(G0/Gc)^(2/n))/(1-(Gc/G1)^(2/n)))*s + (1/Gc)^(1/n)))^n;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
P = [W1 -W1;
|
|
0 W2;
|
|
1 0];
|
|
|
|
[H2, ~, gamma, ~] = hinfsyn(P, 1, 1,'TOLGAM', 0.001, 'METHOD', 'ric', 'DISPLAY', 'on');
|
|
H1 = 1 - H2;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
Gresp = squeeze(freqresp(G, freqs, 'Hz'));
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(Gresp(1, :).*squeeze(freqresp(0.0065/s^2*H2, freqs, 'Hz'))'), '-');
|
|
plot(freqs, abs(Gresp(2, :).*squeeze(freqresp(H1, freqs, 'Hz'))'), '-');
|
|
plot(freqs, abs(Gresp(2, :).*squeeze(freqresp(H1, freqs, 'Hz'))' + Gresp(1, :).*squeeze(freqresp(0.0065/s^2*H2, freqs, 'Hz'))'), 'k--');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(Gresp(1, :).*squeeze(freqresp(0.0065/s^2*H2, freqs, 'Hz'))')), '-', ...
|
|
'DisplayName', 'Force');
|
|
plot(freqs, 180/pi*unwrap(angle(Gresp(2, :).*squeeze(freqresp(H1, freqs, 'Hz'))')), '-', ...
|
|
'DisplayName', 'Displacement');
|
|
plot(freqs, 180/pi*unwrap(angle(Gresp(2, :).*squeeze(freqresp(H1, freqs, 'Hz'))' + Gresp(1, :).*squeeze(freqresp(0.0065/s^2*H2, freqs, 'Hz'))')), 'k--', ...
|
|
'DisplayName', 'Super Sensor');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
Gss = -zpk(G(1)*0.0065/s^2*H2 + G(2)*H1);
|
|
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gss, freqs, 'Hz'))'), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*(angle(squeeze(freqresp(Gss, freqs, 'Hz'))')), '-', ...
|
|
'DisplayName', 'Force');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
Root locus
|
|
#+begin_src matlab
|
|
figure;
|
|
|
|
gains = logspace(4, 7, 100);
|
|
|
|
hold on;
|
|
plot(real(pole(Gss)), imag(pole(Gss)), 'kx');
|
|
plot(real(tzero(Gss)), imag(tzero(Gss)), 'ko');
|
|
for k = 1:length(gains)
|
|
cl_poles = pole(feedback(Gss, gains(k)*s));
|
|
plot(real(cl_poles), imag(cl_poles), 'k.');
|
|
end
|
|
hold off;
|
|
axis square;
|
|
xlim([-500, 10]); ylim([0, 510]);
|
|
|
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
|
#+end_src
|
|
|
|
** Identification for a simpler model
|
|
The goal in this section is to identify the parameters of a simple APA model from the FEM.
|
|
This can be useful is a lower order model is to be used for simulations.
|
|
|
|
The presented model is based on cite:souleille18_concep_activ_mount_space_applic.
|
|
|
|
The model represents the Amplified Piezo Actuator (APA) from Cedrat-Technologies (Figure [[fig:souleille18_model_piezo]]).
|
|
The parameters are shown in the table below.
|
|
|
|
#+name: fig:souleille18_model_piezo
|
|
#+caption: Picture of an APA100M from Cedrat Technologies. Simplified model of a one DoF payload mounted on such isolator
|
|
[[file:./figs/souleille18_model_piezo.png]]
|
|
|
|
#+caption: Parameters used for the model of the APA 100M
|
|
| | Meaning |
|
|
|-------+----------------------------------------------------------------|
|
|
| $k_e$ | Stiffness used to adjust the pole of the isolator |
|
|
| $k_1$ | Stiffness of the metallic suspension when the stack is removed |
|
|
| $k_a$ | Stiffness of the actuator |
|
|
| $c_1$ | Added viscous damping |
|
|
|
|
The goal is to determine $k_e$, $k_a$ and $k_1$ so that the simplified model fits the FEM model.
|
|
|
|
\[ \alpha = \frac{x_1}{f}(\omega=0) = \frac{\frac{k_e}{k_e + k_a}}{k_1 + \frac{k_e k_a}{k_e + k_a}} \]
|
|
\[ \beta = \frac{x_1}{F}(\omega=0) = \frac{1}{k_1 + \frac{k_e k_a}{k_e + k_a}} \]
|
|
|
|
If we can fix $k_a$, we can determine $k_e$ and $k_1$ with:
|
|
\[ k_e = \frac{k_a}{\frac{\beta}{\alpha} - 1} \]
|
|
\[ k_1 = \frac{1}{\beta} - \frac{k_e k_a}{k_e + k_a} \]
|
|
|
|
#+begin_src matlab :exports none
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
%% Name of the Simulink File
|
|
mdl = 'APA300ML_test_bench';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1; % External Vertical Force [N]
|
|
io(io_i) = linio([mdl, '/w'], 1, 'openinput'); io_i = io_i + 1; % Base Motion [m]
|
|
io(io_i) = linio([mdl, '/Fa'], 1, 'openinput'); io_i = io_i + 1; % Actuator Force [N]
|
|
io(io_i) = linio([mdl, '/y'], 1, 'openoutput'); io_i = io_i + 1; % Vertical Displacement [m]
|
|
io(io_i) = linio([mdl, '/Vs'], 1, 'openoutput'); io_i = io_i + 1; % Force Sensor [V]
|
|
io(io_i) = linio([mdl, '/d'], 1, 'openoutput'); io_i = io_i + 1; % Stack Displacement [m]
|
|
|
|
G = linearize(mdl, io);
|
|
|
|
G.InputName = {'Fd', 'w', 'Fa'};
|
|
G.OutputName = {'y', 'Fs', 'd'};
|
|
#+end_src
|
|
|
|
From the identified dynamics, compute $\alpha$ and $\beta$
|
|
#+begin_src matlab
|
|
alpha = abs(dcgain(G('y', 'Fa')));
|
|
beta = abs(dcgain(G('y', 'Fd')));
|
|
#+end_src
|
|
|
|
$k_a$ is estimated using the following formula:
|
|
#+begin_src matlab
|
|
ka = 0.8/abs(dcgain(G('y', 'Fa')));
|
|
#+end_src
|
|
The factor can be adjusted to better match the curves.
|
|
|
|
Then $k_e$ and $k_1$ are computed.
|
|
#+begin_src matlab
|
|
ke = ka/(beta/alpha - 1);
|
|
k1 = 1/beta - ke*ka/(ke + ka);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable(1e-6*[ka; ke; k1], {'ka', 'ke', 'k1'}, {'Value [N/um]'}, ' %.1f ');
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
| | Value [N/um] |
|
|
|----+--------------|
|
|
| ka | 42.9 |
|
|
| ke | 1.5 |
|
|
| k1 | 0.4 |
|
|
|
|
The damping in the system is adjusted to match the FEM model if necessary.
|
|
#+begin_src matlab
|
|
c1 = 1e2;
|
|
#+end_src
|
|
|
|
Analytical model of the simpler system:
|
|
#+begin_src matlab
|
|
Ga = 1/(m*s^2 + k1 + c1*s + ke*ka/(ke + ka)) * ...
|
|
[ 1 , k1 + c1*s + ke*ka/(ke + ka) , ke/(ke + ka) ;
|
|
-ke*ka/(ke + ka), ke*ka/(ke + ka)*m*s^2 , -ke/(ke + ka)*(m*s^2 + c1*s + k1)];
|
|
|
|
Ga.InputName = {'Fd', 'w', 'Fa'};
|
|
Ga.OutputName = {'y', 'Fs'};
|
|
#+end_src
|
|
|
|
Adjust the DC gain for the force sensor:
|
|
#+begin_src matlab
|
|
lambda = dcgain(Ga('Fs', 'Fd'))/dcgain(G('Fs', 'Fd'));
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(0, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ay = subplot(2, 3, 1);
|
|
title('$\displaystyle \frac{x_1}{w}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G( 'y', 'w'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Ga('y', 'w'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/m]');xlabel('Frequency [Hz]');
|
|
|
|
ax2 = subplot(2, 3, 2);
|
|
title('$\displaystyle \frac{x_1}{f}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G( 'y', 'Fa'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Ga('y', 'Fa'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]');xlabel('Frequency [Hz]');
|
|
|
|
ax3 = subplot(2, 3, 3);
|
|
title('$\displaystyle \frac{x_1}{F}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G( 'y', 'Fd'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Ga('y', 'Fd'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]');xlabel('Frequency [Hz]');
|
|
|
|
ax4 = subplot(2, 3, 4);
|
|
title('$\displaystyle \frac{F_s}{w}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(lambda*G( 'Fs', 'w'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Ga('Fs', 'w'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/m]');xlabel('Frequency [Hz]');
|
|
|
|
ax5 = subplot(2, 3, 5);
|
|
title('$\displaystyle \frac{F_s}{f}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(lambda*G( 'Fs', 'Fa'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Ga('Fs', 'Fa'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]');xlabel('Frequency [Hz]');
|
|
|
|
ax6 = subplot(2, 3, 6);
|
|
title('$\displaystyle \frac{F_s}{F}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(lambda*G( 'Fs', 'Fd'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Ga('Fs', 'Fd'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
|
|
|
|
linkaxes([ax1,ax2,ax3,ax4,ax5,ax6],'x');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/apa300ml_comp_simpler_model.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:apa300ml_comp_simpler_model
|
|
#+caption: Comparison of the Dynamics between the FEM model and the simplified one
|
|
#+RESULTS:
|
|
[[file:figs/apa300ml_comp_simpler_model.png]]
|
|
|
|
* Flexible Joint
|
|
** Introduction :ignore:
|
|
|
|
#+name: fig:flexor_id16_screenshot
|
|
#+caption: Flexor studied
|
|
[[file:figs/flexor_id16_screenshot.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
|
|
addpath('./src/');
|
|
addpath('./data/flexor_ID16/');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
open('flexor_ID16.slx');
|
|
#+end_src
|
|
|
|
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
|
|
We first extract the stiffness and mass matrices.
|
|
#+begin_src matlab
|
|
K = extractMatrix('mat_K_6modes_2MDoF.matrix');
|
|
M = extractMatrix('mat_M_6modes_2MDoF.matrix');
|
|
#+end_src
|
|
|
|
Then, we extract the coordinates of the interface nodes.
|
|
#+begin_src matlab
|
|
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('out_nodes_3D.txt');
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
save('./mat/flexor_ID16.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
|
|
#+end_src
|
|
|
|
** Output parameters
|
|
#+begin_src matlab
|
|
load('./mat/flexor_ID16.mat', 'int_xyz', 'int_i', 'n_xyz', 'n_i', 'nodes', 'M', 'K');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable([length(n_i); length(int_i); size(M,1) - 6*length(int_i); size(M,1)], {'Total number of Nodes', 'Number of interface Nodes', 'Number of Modes', 'Size of M and K matrices'}, {}, ' %.0f ');
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
| Total number of Nodes | 2 |
|
|
| Number of interface Nodes | 2 |
|
|
| Number of Modes | 6 |
|
|
| Size of M and K matrices | 18 |
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable([[1:length(int_i)]', int_i, int_xyz], {}, {'Node i', 'Node Number', 'x [m]', 'y [m]', 'z [m]'}, ' %f ');
|
|
#+end_src
|
|
|
|
#+caption: Coordinates of the interface nodes
|
|
#+RESULTS:
|
|
| Node i | Node Number | x [m] | y [m] | z [m] |
|
|
|--------+-------------+-------+-------+-------|
|
|
| 1.0 | 181278.0 | 0.0 | 0.0 | 0.0 |
|
|
| 2.0 | 181279.0 | 0.0 | 0.0 | -0.0 |
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable(K(1:10, 1:10), {}, {}, ' %.2e ');
|
|
#+end_src
|
|
|
|
#+caption: First 10x10 elements of the Stiffness matrix
|
|
#+RESULTS:
|
|
| 11200000.0 | 195.0 | 2220.0 | -0.719 | -265.0 | 1.59 | -11200000.0 | -213.0 | -2220.0 | 0.147 |
|
|
| 195.0 | 11400000.0 | 1290.0 | -148.0 | -0.188 | 2.41 | -212.0 | -11400000.0 | -1290.0 | 148.0 |
|
|
| 2220.0 | 1290.0 | 119000000.0 | 1.31 | 1.49 | 1.79 | -2220.0 | -1290.0 | -119000000.0 | -1.31 |
|
|
| -0.719 | -148.0 | 1.31 | 33.0 | 0.000488 | -0.000977 | 0.141 | 148.0 | -1.31 | -33.0 |
|
|
| -265.0 | -0.188 | 1.49 | 0.000488 | 33.0 | 0.00293 | 266.0 | 0.154 | -1.49 | 0.00026 |
|
|
| 1.59 | 2.41 | 1.79 | -0.000977 | 0.00293 | 236.0 | -1.32 | -2.55 | -1.79 | 0.000379 |
|
|
| -11200000.0 | -212.0 | -2220.0 | 0.141 | 266.0 | -1.32 | 11400000.0 | 24600.0 | 1640.0 | 120.0 |
|
|
| -213.0 | -11400000.0 | -1290.0 | 148.0 | 0.154 | -2.55 | 24600.0 | 11400000.0 | 1290.0 | -72.0 |
|
|
| -2220.0 | -1290.0 | -119000000.0 | -1.31 | -1.49 | -1.79 | 1640.0 | 1290.0 | 119000000.0 | 1.32 |
|
|
| 0.147 | 148.0 | -1.31 | -33.0 | 0.00026 | 0.000379 | 120.0 | -72.0 | 1.32 | 34.7 |
|
|
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no
|
|
data2orgtable(M(1:10, 1:10), {}, {}, ' %.1g ');
|
|
#+end_src
|
|
|
|
#+caption: First 10x10 elements of the Mass matrix
|
|
#+RESULTS:
|
|
| 0.02 | 1e-09 | -4e-08 | -1e-10 | 0.0002 | -3e-11 | 0.004 | 5e-08 | 7e-08 | 1e-10 |
|
|
| 1e-09 | 0.02 | -3e-07 | -0.0002 | -1e-10 | -2e-09 | 2e-08 | 0.004 | 3e-07 | 1e-05 |
|
|
| -4e-08 | -3e-07 | 0.02 | 7e-10 | -2e-09 | 1e-09 | 3e-07 | 7e-08 | 0.003 | 1e-09 |
|
|
| -1e-10 | -0.0002 | 7e-10 | 4e-06 | -1e-12 | -6e-13 | 2e-10 | -7e-06 | -8e-10 | -1e-09 |
|
|
| 0.0002 | -1e-10 | -2e-09 | -1e-12 | 3e-06 | 2e-13 | 9e-06 | 4e-11 | 2e-09 | -3e-13 |
|
|
| -3e-11 | -2e-09 | 1e-09 | -6e-13 | 2e-13 | 4e-07 | 8e-11 | 9e-10 | -1e-09 | 2e-12 |
|
|
| 0.004 | 2e-08 | 3e-07 | 2e-10 | 9e-06 | 8e-11 | 0.02 | -7e-08 | -3e-07 | -2e-10 |
|
|
| 5e-08 | 0.004 | 7e-08 | -7e-06 | 4e-11 | 9e-10 | -7e-08 | 0.01 | -4e-08 | 0.0002 |
|
|
| 7e-08 | 3e-07 | 0.003 | -8e-10 | 2e-09 | -1e-09 | -3e-07 | -4e-08 | 0.02 | -1e-09 |
|
|
| 1e-10 | 1e-05 | 1e-09 | -1e-09 | -3e-13 | 2e-12 | -2e-10 | 0.0002 | -1e-09 | 2e-06 |
|
|
|
|
Using =K=, =M= and =int_xyz=, we can use the =Reduced Order Flexible Solid= simscape block.
|
|
|
|
** Flexible Joint Characteristics
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable([1e-6*K(3,3), K(4,4), K(5,5), K(6,6); 60, 15, 15, 20]', {'Axial Stiffness [N/um]', 'Bending Stiffness [Nm/rad]', 'Bending Stiffness [Nm/rad]', 'Torsion Stiffness [Nm/rad]'}, {'*Caracteristic*', '*Value*', '*Estimation by Francois*'}, ' %0.f ');
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
| *Caracteristic* | *Value* | *Estimation by Francois* |
|
|
|----------------------------+---------+--------------------------|
|
|
| Axial Stiffness [N/um] | 119 | 60 |
|
|
| Bending Stiffness [Nm/rad] | 33 | 15 |
|
|
| Bending Stiffness [Nm/rad] | 33 | 15 |
|
|
| Torsion Stiffness [Nm/rad] | 236 | 20 |
|
|
|
|
** Identification
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
The dynamics is identified from the applied force to the measured relative displacement.
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'flexor_ID16';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/T'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/D'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
G = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports results :results value table replace :tangle no :post addhdr(*this*)
|
|
data2orgtable([1e-6*K(3,3), K(4,4), K(5,5), K(6,6) ; 1e-6./dcgain(G(3,3)), 1./dcgain(G(4,4)), 1./dcgain(G(5,5)), 1./dcgain(G(6,6))]', {'Axial Stiffness Dz [N/um]', 'Bending Stiffness Rx [Nm/rad]', 'Bending Stiffness Ry [Nm/rad]', 'Torsion Stiffness Rz [Nm/rad]'}, {'*Caracteristic*', '*Value*', '*Identification*'}, ' %0.f ');
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
| *Caracteristic* | *Value* | *Identification* |
|
|
|-------------------------------+---------+------------------|
|
|
| Axial Stiffness Dz [N/um] | 119 | 119 |
|
|
| Bending Stiffness Rx [Nm/rad] | 33 | 34 |
|
|
| Bending Stiffness Ry [Nm/rad] | 33 | 126 |
|
|
| Torsion Stiffness Rz [Nm/rad] | 236 | 238 |
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(0, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G(1,1), freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(G(2,2), freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(G(3,3), freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on
|
|
plot(freqs, 180/pi*(angle(squeeze(freqresp(G(1,1), freqs, 'Hz')))), '-');
|
|
plot(freqs, 180/pi*(angle(squeeze(freqresp(G(2,2), freqs, 'Hz')))), '-');
|
|
plot(freqs, 180/pi*(angle(squeeze(freqresp(G(3,3), freqs, 'Hz')))), '-');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(0, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G(4,4), freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(G(5,5), freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(G(6,6), freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on
|
|
plot(freqs, 180/pi*(angle(squeeze(freqresp(G(4,4), freqs, 'Hz')))), '-');
|
|
plot(freqs, 180/pi*(angle(squeeze(freqresp(G(5,5), freqs, 'Hz')))), '-');
|
|
plot(freqs, 180/pi*(angle(squeeze(freqresp(G(6,6), freqs, 'Hz')))), '-');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
#+end_src
|
|
|
|
* Integral Force Feedback with Amplified Piezo
|
|
** Introduction :ignore:
|
|
In this section, we try to replicate the results obtained in cite:souleille18_concep_activ_mount_space_applic.
|
|
|
|
** 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
|
|
addpath('./src/');
|
|
addpath('./data/piezo_amplified_IFF/');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
open('piezo_amplified_IFF');
|
|
#+end_src
|
|
|
|
** Import Mass Matrix, Stiffness Matrix, and Interface Nodes Coordinates
|
|
We first extract the stiffness and mass matrices.
|
|
#+begin_src matlab
|
|
K = extractMatrix('piezo_amplified_IFF_K.txt');
|
|
M = extractMatrix('piezo_amplified_IFF_M.txt');
|
|
#+end_src
|
|
|
|
Then, we extract the coordinates of the interface nodes.
|
|
#+begin_src matlab
|
|
[int_xyz, int_i, n_xyz, n_i, nodes] = extractNodes('piezo_amplified_IFF.txt');
|
|
#+end_src
|
|
|
|
** IFF Plant
|
|
The transfer function from the force actuator to the force sensor is identified and shown in Figure [[fig:piezo_amplified_iff_plant]].
|
|
|
|
#+begin_src matlab
|
|
Kiff = tf(0);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
m = 0;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_IFF';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Kiff'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/G'], 1, 'openoutput'); io_i = io_i + 1;
|
|
|
|
Gf = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
Gfm = linearize(mdl, io);
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gf, freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(Gfm, freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gf, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gfm, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-390 30]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/piezo_amplified_iff_plant.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:piezo_amplified_iff_plant
|
|
#+caption: IFF Plant
|
|
#+RESULTS:
|
|
[[file:figs/piezo_amplified_iff_plant.png]]
|
|
|
|
** IFF controller
|
|
The controller is defined and the loop gain is shown in Figure [[fig:piezo_amplified_iff_loop_gain]].
|
|
#+begin_src matlab
|
|
Kiff = -1e12/s;
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 5, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2,1,1);
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(Gf*Kiff, freqs, 'Hz'))), '-');
|
|
plot(freqs, abs(squeeze(freqresp(Gfm*Kiff, freqs, 'Hz'))), '-');
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude'); set(gca, 'XTickLabel',[]);
|
|
hold off;
|
|
|
|
ax2 = subplot(2,1,2);
|
|
hold on;
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gf*Kiff, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 0kg$');
|
|
plot(freqs, 180/pi*unwrap(angle(squeeze(freqresp(Gfm*Kiff, freqs, 'Hz')))), '-', ...
|
|
'DisplayName', '$m = 10kg$');
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
|
yticks(-360:90:360);
|
|
ylim([-180 180]);
|
|
xlabel('Frequency [Hz]'); ylabel('Phase [deg]');
|
|
hold off;
|
|
linkaxes([ax1,ax2],'x');
|
|
xlim([freqs(1), freqs(end)]);
|
|
legend('location', 'southwest');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/piezo_amplified_iff_loop_gain.pdf', 'width', 'full', 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:piezo_amplified_iff_loop_gain
|
|
#+caption: IFF Loop Gain
|
|
#+RESULTS:
|
|
[[file:figs/piezo_amplified_iff_loop_gain.png]]
|
|
|
|
** Closed Loop System
|
|
#+begin_src matlab
|
|
m = 10;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
Kiff = -1e12/s;
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
%% Name of the Simulink File
|
|
mdl = 'piezo_amplified_IFF';
|
|
|
|
%% Input/Output definition
|
|
clear io; io_i = 1;
|
|
io(io_i) = linio([mdl, '/Dw'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/F'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/Fd'], 1, 'openinput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/d'], 1, 'openoutput'); io_i = io_i + 1;
|
|
io(io_i) = linio([mdl, '/G'], 1, 'output'); io_i = io_i + 1;
|
|
|
|
Giff = linearize(mdl, io);
|
|
Giff.InputName = {'w', 'f', 'F'};
|
|
Giff.OutputName = {'x1', 'Fs'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
Kiff = tf(0);
|
|
#+end_src
|
|
|
|
#+begin_src matlab
|
|
G = linearize(mdl, io);
|
|
G.InputName = {'w', 'f', 'F'};
|
|
G.OutputName = {'x1', 'Fs'};
|
|
#+end_src
|
|
|
|
#+begin_src matlab :exports none
|
|
freqs = logspace(1, 3, 1000);
|
|
|
|
figure;
|
|
|
|
ax1 = subplot(2, 3, 1);
|
|
title('$\displaystyle \frac{x_1}{w}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G('x1', 'w'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Giff('x1', 'w'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/m]');xlabel('Frequency [Hz]');
|
|
|
|
ax2 = subplot(2, 3, 2);
|
|
title('$\displaystyle \frac{x_1}{f}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G('x1', 'f'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Giff('x1', 'f'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]');xlabel('Frequency [Hz]');
|
|
|
|
ax3 = subplot(2, 3, 3);
|
|
title('$\displaystyle \frac{x_1}{F}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G('x1', 'F'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Giff('x1', 'F'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]');xlabel('Frequency [Hz]');
|
|
|
|
ax4 = subplot(2, 3, 4);
|
|
title('$\displaystyle \frac{F_s}{w}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G('Fs', 'w'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Giff('Fs', 'w'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/m]');xlabel('Frequency [Hz]');
|
|
|
|
ax5 = subplot(2, 3, 5);
|
|
title('$\displaystyle \frac{F_s}{f}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G('Fs', 'f'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Giff('Fs', 'f'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]');xlabel('Frequency [Hz]');
|
|
|
|
ax6 = subplot(2, 3, 6);
|
|
title('$\displaystyle \frac{F_s}{F}$')
|
|
hold on;
|
|
plot(freqs, abs(squeeze(freqresp(G('Fs', 'F'), freqs, 'Hz'))));
|
|
plot(freqs, abs(squeeze(freqresp(Giff('Fs', 'F'), freqs, 'Hz'))));
|
|
hold off;
|
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
|
ylabel('Amplitude [m/N]'); xlabel('Frequency [Hz]');
|
|
|
|
linkaxes([ax1,ax2,ax3,ax4,ax5,ax6],'x');
|
|
#+end_src
|
|
|
|
#+begin_src matlab :tangle no :exports results :results file replace
|
|
exportFig('figs/piezo_amplified_iff_comp.pdf', 'width', 1500, 'height', 'full');
|
|
#+end_src
|
|
|
|
#+name: fig:piezo_amplified_iff_comp
|
|
#+caption: OL and CL transfer functions
|
|
#+RESULTS:
|
|
[[file:figs/piezo_amplified_iff_comp.png]]
|
|
|
|
|
|
#+name: fig:souleille18_results
|
|
#+caption: Results obtained in cite:souleille18_concep_activ_mount_space_applic
|
|
[[file:figs/souleille18_results.png]]
|
|
|
|
* Bibliography :ignore:
|
|
bibliographystyle:unsrt
|
|
bibliography:ref.bib
|