Dynamics characterization for a MEMS electrostatic inchworm motor and its gap closing actuators
Publication
- Rauf, Ahad M., Contreras, Daniel S., Shih, Ryan M., Schindler, Craig B., Pister, Kristofer S. J., "Nonlinear Dynamics of Lateral Electrostatic Gap Closing Actuators for Applications in Inchworm Motors", Journal of Microelectromechanical Systems (JMEMS), 2021, https://doi.org/10.1109/JMEMS.2021.3130957.
Note for Running This Code in Command Line/CodeOcean
This code was written in PyCharm, which runs files in their native locations and includes all files in the
overall directory in its system path. This doesn't happen when running this code in command line, so some script
files may require you to (a) navigate to the scripts/
directory before running your code, and
(b) fiddle with the import paths. See the FAQ below for code snippets that you can
try appending to the top of your file to help out with (b).
This code just requires numpy
, scipy
, and matplotlib
, although some scripts also involve the
scikit-learn.metrics
module. A good script to run first after setup
is python sim_gca_transient.py
to get a sense for what's going on.
You install the requirements all in one go by calling pip install -r requirements.txt
.
This simulation model is meant to be modular, so you can easily swap between different layouts and/or processes without changing too much of the actual simulation code.
-
process.py
: the process parameters for a 2-layer SOI process, or any other processes that you might come up with. You can import your respective process withfrom process import SOI
-
layouts/fawn.csv
,layouts/gamma.csv
, etc.: the layout files (named after the layouts of their respective runs). These files store the drawn dimensions of your model. The code written so far is robust to anything after the second comma (so you can write comments there). -
gca.py
: A simulation model for a gap closing actuator. The input is a drawn dimensions filename and the initial position. The default initial positions for pull-in and release can be found via the functionsGCA.x0_pullin()
andGCA.x0_release()
.- The simulation input is an input array
u = [V, F_external]
. The state is[x_spine, v_spine]
.
- The simulation input is an input array
-
assembly.py
: Used to package multiple GCA's or other components together. Each component's state can affect each other, so this modularity can help simulate larger components.from assembly import AssemblyGCA
: A basic GCA, with no other components
-
scripts/
: All the script files. There are generally 4 types of scripts in this folder:scripts/calculate_*.py
: These are just helper files for calculating different numbers in the paper.scripts/plot_*.py
: These are plotting file, which I used to generate the figures in the paper.scripts/sim_*.py
: These are the core simulation files. Run one of these to simulate a GCA's dynamics.scripts/test_*.py
: These are another type of helper file, which I used to test different evaluation metrics and the like.
-
scripts/sim_gca_V_Fext_pullin.py
, etc.: Your simulation files. Because of the structure above, you can swap process nodes by changing an import statement or layouts by just swapping which.csv
file you're reading from. The basic structure of the code is to:- Initialize a model with its drawn dimensions file and specify whether its initial state (e.g. whether it's pulling in or releasing)
- Specify the input, e.g.
u = [V, Fext]
- Simulate the assembly with a differential equation solver, like in the code below. You can then
check whether or not your simulation terminated by checking whether
len(sol.t_events[0]) > 0
:
from scipy.integrate import solve_ivp
def sim_gca(model, u, t_span, verbose=False):
f = lambda t, x: model.dx_dt(t, x, u, verbose=verbose)
x0 = model.x0()
terminate_simulation = lambda t, x: model.terminate_simulation(t, x)
terminate_simulation.terminal = True
sol = solve_ivp(f, t_span, x0, events=[terminate_simulation], dense_output=True, max_step=0.5e-6)
return sol
Note that the max_step
parameter in solve_ivp()
is actually quite important - generally,
in Python's implementation of solve_ivp()
, for small time scales like what we're working with
the final time recorded by the terminate_simulation
condition will be some multiple of max_step
.
Thus, for production code it's generally good to have low values for max_step
(e.g. 0.1e-6), but for
quick prototyping it's sufficient to have larger values (e.g. 0.25e-6, 0.5e-6).
-
I get the error
gca.py:149: RuntimeWarning: invalid value encountered in sqrt
orgca.py:177: IntegrationWarning: The occurrence of roundoff error is detected, which prevents the requested tolerance from being achieved. The error may be underestimated.
when running my code and using Fes_calc2 (i.e. choosing calc_method=2 as an option for Fes() in gca.py).- This is likely because the time step of the integration is too large. You can change this in the max_step option in solve_ivp() (e.g. see the sim_gca() function in sim_gca_V_fingerL_pullin_release.py for reference. Note that not all integral solvers in Scipy accept the max_step argument - the default RK45 method has been found to work pretty well). The error is caused when the gap between fingers becomes negative (i.e. pull-in happens, but the integration routine jumps over the terminate_simulation boundary condition instead of converging to it).
-
I get the warning
mio.py:226: MatReadWarning: Duplicate variable name "None" in stream - replacing previous with new Consider mio5.varmats_from_mat to split file into single variable files matfile_dict = MR.get_variables(variable_names)
- Probably not an issue? This is caused by some file formatting issue in how I'm reading the data files (in the
/data
folder). I'm not sure exactly how to fix this, to be honest - fiddling with the import settings should be enough, but it reads the data correctly so who cares?
- Probably not an issue? This is caused by some file formatting issue in how I'm reading the data files (in the
-
I get
ModuleNotFoundError
errors when trying to run scripts in command line- See the note at the top about running this code in command line. Add the following code to the beginning of your script file, making sure to change the part in brackets to your specific installation
import os file_location = os.path.abspath(os.path.dirname( __file__)) dir_location = os.path.abspath(os.path.join(file_location, '..')) import sys sys.path.append(file_location) # or just the path to the script's folder, generally speaking sys.path.append(dir_location) # or just the path to the gca_dynamics folder, generally speaking
This library originated from work by Daniel Contreras (Ph.D.), Craig Schindler (Ph.D.), and Ryan Shih (M.S.) at UC Berkeley under Professor Kristofer Pister. Daniel's and Craig's Ph.D. dissertations can be found here and here, respectively. Many thanks to them for providing the preliminary MATLAB simulation scripts they used in their dissertations.