Smart.BodePlot displays magnitude and phase against a logarithmic frequency axis, reads the gain and phase margins off an open-loop response, and puts a measured response and a model on the same axes.

A response is given as measured points, or as a transfer function in s that the component evaluates across the frequency range. The stability margins are marked on both bands and written out: the phase margin at the frequency where the gain crosses 0 dB and the gain margin at the frequency where the phase crosses -180 degrees. Phase is unwrapped before the margins are found. A cursor reads every response at one frequency.

A servo speed loop: the open-loop response and its margins

The plant is a motor with an electrical and a mechanical time constant, a small transport delay and a resonance at 180 Hz; the controller is a PI. Raise the gain and watch the phase margin shrink; when it reaches zero the margins are marked as failing. The frequency response the component draws is evaluated from the transfer function, so a change of gain redraws at once. Click the plot or press the arrow keys to read the loop at a frequency.

margins() returns what the readout shows; cursorChange is listed here.

Filters, as measured on the bench

A second-order low-pass and a notch, from a swept-sine measurement with a few hundred points each. The phase of the notch wraps at the notch frequency in the measurement and is unwrapped by the component before it is drawn.

Keyboard: the plot is a tab stop. The left and right arrow keys move the cursor along the frequency axis, with Shift by ten steps; Home and End move it to the ends. The legend is one tab stop where Enter or Space hides and shows a response. The margins and the cursor readings are text under the plot.