1e905703a38084a10e6508f39daaa0d88fea87e2
[thesis.git] / src / pyafm / auxiliary.tex
1 \section{Auxiliary packages}
2 \label{sec:pyafm:auxiliary}
3
4 The previous section covered the core of the experiment stack
5 (\cref{sec:pyafm:stack}), but skipped over some of the more peripheral
6 packages.
7
8 \subsection{h5config}
9 \label{sec:pyafm:h5config}
10
11 The \hFconfig\ package makes it easy to save and load configuration
12 classes from disk.  After populating base configuration classes with
13 parameters (\cref{fig:h5config}), \hFconfig\ automatically generates
14 \citetalias{hdf5} and \citetalias{yaml} backends for saving and
15 loading that class.
16
17 \begin{figure}
18   \begin{center}
19 \begin{minted}[mathescape]{python}
20 import h5config.config as _config
21
22 class AxisConfig (_config.Config):
23     "Configure a single piezo axis"
24     settings = [
25         _config.FloatSetting(
26             name='gain',
27             help=(
28                 'Volts applied at piezo per volt output from the DAQ card '
29                 '(e.g. if your DAQ output is amplified before driving the '
30                 'piezo),')),
31         _config.FloatSetting(
32             name='sensitivity',
33             help='Meters of piezo deflection per volt applied to the piezo.'),
34         # $\ldots$
35         _config.ConfigSetting(
36             name='channel',
37             help='Configure the underlying DAC channel.',
38             config_class=OutputChannelConfig,
39             default=None),
40         # $\ldots$
41         ]
42 \end{minted}
43     \caption{Portions of the configuration class for a single piezo
44       axis (from \pypiezo, \cref{sec:pyafm:pypiezo}).  The more
45       generic analog output channel configuration is nested under the
46       \imint{python}|channel| setting.\label{fig:h5config}}
47   \end{center}
48 \end{figure}
49
50 Basic configuration types include booleans, integers, floating point
51 numbers, enumerated choices, and freeform text.  There is also support
52 for lists of these basic types (e.g.~lists of integers).  The key
53 feature is nesting configuration classes.  This means that your higher
54 level tools can have their own configuration settings and also include
55 the configuration settings for their lower level components.  For
56 example, the piezo axis configuration given in \cref{fig:h5config}
57 contains configuration settings specific to piezo axes, and it also
58 contains a reference to the configuration settings for a generic
59 analog output channel.  The piezo axis code doesn't need to know what
60 the analog output channel configuration settings are, those are
61 defined somewhere else.
62
63 The nesting continues all the way up the stack, to the
64 \unfoldprotein\ configuration.  This means that a single file
65 (\imint{console}|~/.config/unfold_protein.yaml|) contains every
66 configurable setting required for the whole experiment in an
67 easy-to-edit text format.  Adding additional configuration settings at
68 any level of the experiment stack is just a matter of adjusting a
69 single \imint{python}|h5config.config.Config| subclass the
70 corresponding entry in the configuration file.  There is no need to
71 adjust the higher level code, the new setting is passed down the stack
72 to its point of use automatically.
73
74 Besides making it easy to configure your experiment, \hFconfig\ also
75 makes it easy to save the configuration alongside your data.  The
76 section of \unfoldprotein\ that writes the whole configuration stack
77 into the per-pull HDF5 file is only four lines long.  This makes
78 post-processing much easier, because almost every setting needed to
79 analyze the data is already stored in the data file (the only missing
80 values are those that you did not need during the experiment control
81 phase).
82
83 \subsection{stepper}
84 \label{sec:pyafm:stepper}
85
86 Because of thermal drift and mechanical instability, the distance
87 between the tip and the surface changes significantly over time.  When
88 the distance change exceeds the range of the piezo scanner, the
89 stepper motor must be engaged to reposition the AFM tip relative to
90 the sample.  The earlier LabVIEW software (\cref{sec:labview}) lacked
91 the ability to control the motor on its own, so it would pause roughly
92 every half hour and prompt the operator to make the necessary manual
93 adjustments.  Automatic motor control allows the system to run longer
94 without interrupts, facilitating the collection of large data sets.
95
96 The \stepper\ package provides Python control of stepper
97 motors\cite{jones95}.  The package is mostly concerned with the
98 maintenance of internal motor state:
99
100 \begin{description}
101   \item[position] is a half-step counter that records the current
102     motor position.
103   \item[full step] selects full or half stepping.
104   \item[logic] selects active high or active low operation.
105   \item[delay] sets the time delay between steps in seconds, in case
106     the motor response is slower than the digital output driver.
107   \item[step size] approximates the step size in meters.
108   \item[backlash] estimates the drive chain backlash in half-steps.
109 \end{description}
110
111 Actualizing the motor control signal is left up to the caller, in this
112 case \pyafm.
113
114 We verified the stability and reproducibility of the microscopic
115 movement of the motor by making several approach-retreat cycles from
116 the surface of $\sim$70 steps which resulted in the data displayed in
117 \cref{fig.stepper:backlash}.  We also measured the distance the
118 surface moved with every step by determining the change in deflection
119 voltage as a function of peizo position as we stepped the AFM tip
120 closer the the surface.  Our stepsize data is displayed in
121 \cref{fig:stepper:step-size}.
122
123 The motor is very consistent when approaching the surface, which
124 indicates that our control software is operating correctly.  However,
125 the motor exhibits some hysteretic behavior on a scale of $\sim$46
126 steps, which is almost certainly due to \emph{backlash}, or slack in
127 the motor--surface coupling machinery.  The first 46 steps in a new
128 direction take the slack out of the coupling, and further steps move
129 the tip relative to the surface.  The problem can be avoided entirely
130 by simply replacing ``backwards motion by one step'' with ``backwards
131 motion by 60 steps and forward motion by 59 steps''.
132
133 One issue raised by backlash is that it might be the source of some of
134 our surface drift, as the drive-chain relaxes towards some central
135 value and pulls the surface with it.  By oscillating into our eventual
136 position, we could perhaps settle the system at the beginning,
137 reducing the need for adjustments later on.  While this is not a
138 problem for the current unfolding experiments, it could be an issue
139 for longer unfolding-refolding experiments.
140
141 \begin{figure}
142   \begin{center}
143     \subfloat[][]{\label{fig:stepper:backlash}
144       \asyinclude{figures/stepper/backlash}}
145     \hspace{\stretch{1}}
146     \subfloat[][]{\label{fig:stepper:step-size}
147       \asyinclude{figures/stepper/step-size}}
148     \caption{\protect\subref{fig:stepper:backlash} Stepper motor
149       reproducibility, stability, and backlash.  The data are from a
150       single continuous counterclockwise trace of 14 approach-retreat
151       cycles.  The jump from about $(18, -6)$ to $(17, -0.4)$ is the
152       snap-off effect, where short-range attractive interactions
153       between the tip and the sample---due to surface wetting in
154       air---require the tip to be actively pulled off surface.  Signal
155       noise is comparable to that expected by drift.
156       \protect\subref{fig:stepper:step-size} Motor step size
157       calibration.  The stepper gradually stepped closer to the
158       surface, feeling forward with the piezo after each step.
159       Successive motor positions yield traces $a$, $b$, $c$, $d$, and
160       $e$.  As the motor moves the sample closer, less piezo movement
161       is required to approach to same deflection level.  The average
162       spacing between the traces is roughly $170\U{nm}$.  Traces $c$
163       and $d$ have regions of negative deflection because the tip no
164       longer retracts far enough from the surface to break free of the
165       snap-off effect.  There is no backlash because the data were
166       taken during a single approach.\label{fig:stepper}}
167   \end{center}
168 \end{figure}
169
170 \subsection{pypid}
171 \label{sec:pyafm:pypid}
172
173 The final component of the experiment control stack is \pypid, which
174 uses \citetalias{pymodbus} to communicate with a Melcor Series MTCA
175 Thermoelectric Cooler Controller\citep{melcor} over a serial line.
176 The controller monitors the fluid cell temperature with a
177 thermocouple, and reading temperatures from the controller is fairly
178 straightforward (\cref{fig:unfold-protein:unfolder}).  Temperature
179 control is via a Peltier device mounted underneath the sample surface
180 (\cref{fig:peltier}).
181
182 \begin{figure}
183   \begin{center}
184     \asyinclude{figures/schematic/peltier}
185     \caption{A Peltier functions by applying a voltage to regions of
186       p- and n-type semiconductor in series.  Conduction in n-type
187       semiconductors is mainly through thermally excited electrons and
188       in p-type semiconductors is mainly through thermally excited
189       holes.  Applying a positive voltage as shown in this figure
190       cools the sample by constantly pumping hot conductors in both
191       semiconductors towards heat sink, which radiates the heat into
192       the environment.  Reversing the applied voltage heats the
193       surface.\label{fig:peltier}}
194   \end{center}
195 \end{figure}
196
197 The controller tries to keep the measured temperature at the setpoint
198 temperature via a modified proportional-integral-derivative (PID)
199 feedback algorithm.  PID systems have been around for a
200 while\citep{ziegler42}, but finding appropriate feedback terms for
201 sensitive systems is not trivial.  There are a number of tuning
202 procedures which characterize the system by evaluating its response
203 under simpler driving conditions.  The \pypid\ package implements
204 Ziegler--Nichols' step response\citep{ziegler42}, bang-bang response,
205 ultimate cycle response\citep{ziegler42} tuning rules, as well as
206 Cohen--Coon's\citep{cohen53} and Wang--Juang--Chan's\citep{wang95}
207 step response tuning rules\citep{astrom93}.
208
209 \nomenclature{PID}{Proportional-integral-derivative feedback.  For a
210   process value $p$, setpoint $p_0$, and manipulated variable $m$, the
211   standard PID algorithm is
212   \begin{align}
213     m(t) &= K_p e(t) + K_i \integral{0}{t}{\tau}{e(\tau)}
214             + K_d \deriv{t}{e(t)} \\
215     e(t) &= p_0 - p \;,
216   \end{align}
217   where $e$ is the error function, $K_p$ is the proportional gain,
218   $K_i$ is the integral gain, and $K_d$ is the derivative gain.}