lti-freq-domain-toolbox
1 Representing a dynamical system
1.1 Introduction
1.2 Elements
block
tf
adder
1.3 Connecting elements
connect
2 Plot functions
2.1 Frequency domain
bode
compare
evolve
tune
nyquist
2.2 Time domain
step
impulse
trajectory
3 Predefined circuits
3.1 Basic components
integrator
sine
phase-delay-circuit
3.2 Controllers
pi-controller
pd-controller
pid-controller
3.3 Filters
chebyshev-type1
3.4 Delay components
pade-delay
4 Circuit simplifications
4.1 Display modes
set-logger-mode!
8.12

lti-freq-domain-toolbox🔗ℹ

Ioannis Stefanis <iastefan@outlook.com>

 (require lti-freq-domain-toolbox)
  package: lti-freq-domain-toolbox

The lti-freq-domain-toolbox is a collection of functions written in Racket, which lets Control Systems engineers study LTI (linear time-invariant) dynamical systems - from PID controllers to more complex systems.

It can perform tasks such as:

Known issues & limitations: check the package’s README.md file.

    1 Representing a dynamical system

      1.1 Introduction

      1.2 Elements

      1.3 Connecting elements

    2 Plot functions

      2.1 Frequency domain

      2.2 Time domain

    3 Predefined circuits

      3.1 Basic components

      3.2 Controllers

      3.3 Filters

      3.4 Delay components

    4 Circuit simplifications

      4.1 Display modes

1 Representing a dynamical system🔗ℹ

1.1 Introduction🔗ℹ

A linear time-invariant (LTI) dynamical system is represented as a circuit of interconnected elements: transfer functions (tfs), adders and blocks.

A block of elements is a means for achieving abstraction. Circuit elements such as transfer functions (tfs), adders and even other blocks can be "stored" inside a block, and form a whole that can be handled as an element itself.

1.2 Elements🔗ℹ

procedure

(block)  block?

(block parent-block)  block?
  parent-block : block?

Implementation assumption:

Each block of elements has only one input (another tf, adder or block) and multiple outputs.

Multiple inputs can be achieved by adding in front of it an adder.

A new block is defined using the block procedure. A parent block inside which the block is stored can be optionally specified.

(define new-block1 (block))
(define new-block-inside-block-a (block a))

Notes:
  • The four blocks a, b, c, d are predefined for speed

  • Build new blocks only when needed and if there are elements to be stored inside

  • If all the elements inside a block are not connected, the value of the block’s overall tf is that of the latest tf stored

  • Re-run the program before defining new circuits in already used blocks

procedure

(tf nom-coeffs denom-coeffs b1)  tf?

  nom-coeffs : (listof real?)
  denom-coeffs : (listof real?)
  b1 : block?

Implementation assumption:

Each tf has only one input (another tf, adder or block) and multiple outputs.

Multiple inputs can be achieved by adding in front of it an adder.

To define a transfer function, the lists of the coefficients of its nominator and denominator polynomials, as well as the block it belongs to must be specified, using the tf procedure.

(define new-tf1 (tf '(4 3 6) '(2 1) b))

procedure

(adder b1)  adder?

  b1 : block?

Implementation assumption:

Each adder has multiple inputs and multiple outputs

An adder is an element used to add multiple input signals, and provide one or multiple outputs. It can be placed in front of a block or tf, to provide them with multiple inputs. An adder is created and placed inside a block using the adder procedure.

(define tf1 (tf '(1 0) '(2 1 0) b))
(define tf2 (tf '(5 0) '(5 1 0) b))
(define new-adder1 (adder b))
(connect tf1 new-adder1)
(connect tf2 new-adder1)

1.3 Connecting elements🔗ℹ

Elements (tfs, adders and blocks) are connected serially using the connect procedure:

procedure

(connect e1 e2)  element?

  e1 : element?
  e2 : element?
(connect tf1 tf2)
(connect tf2 adder1)
(connect tf3 adder1)
(connect a b)

The connection of two elements has no effect if they are not elements of the same block.

Complex connection designs can be achieved by defining all serial connections between elements.

2 Plot functions🔗ℹ

All plot functions listed below take as inputs blocks, not transfer functions.

2.1 Frequency domain🔗ℹ

procedure

(bode b1)  void?

  b1 : block?
The bode function takes as input a block. It computes and prints its overall tf, Bode magnitude and phase plots, and characteristic numbers.

(bode (pd-controller 5 8 a))

This example works because the pd-controller function is defined so that it returns as result the block in which it is installed in.

procedure

(compare b1 b2)  void?

  b1 : block?
  b2 : block?
The compare function takes as inputs two different blocks. It computes and prints comparatively their overall tfs, Bode magnitude and phase plots.

(define c1 (block))
(define c2 (block))
(define tf1 (tf '(1) '(1 0 1) c1))
(define tf2 (tf '(5) '(1 0 1) c2))
(compare c1 c2)
(compare (pid-controller 6 7 3 a) (pi-controller 7 8 b))

The second example works because the pid-controller and pi-controller functions return as result the block they are installed in.

procedure

(evolve b1)  void?

  b1 : block?
The evolve function takes as input a block. It computes and prints its overall tf and its Bode magnitude and phase plots, storing the results. The next time it is called, it prints the current block’s Bode plot on top of the last one stored.

(evolve (pid-controller 6 7 3 a))
(evolve (pid-controller 5 20 4 a))

procedure

(tune b1 condition freq)  void?

  b1 : block?
  condition : list?
  freq : positive?
The tune function can be used in order to compute the value of a single system’s parameter, so that the system achieves a specific performance. It takes as inputs a block, an equality condition regarding the amplitude response AR or the phase shift ph, and the frequency at which this equality condition must be satisfied.

The function prints the value of the parameter computed, and the Bode magnitude and phase plots of the system.

(tune (pi-controller 5 'y a) '(= AR 140) 0.01)
(tune (pi-controller 5 'y a) '(= ph -50) 0.01)

procedure

(nyquist b1)  void?

  b1 : block?
The nyquist function takes as input a block. It computes and prints its overall tf, Nyquist plot, and characteristic numbers.

(define tf1 (tf '(1) '(1 1 1) a))
(nyquist a)

2.2 Time domain🔗ℹ

procedure

(step b1 gain)  void?

  b1 : block?
  gain : real?
The step function takes as inputs a block and a gain number. It computes and prints the block’s tf, the block’s tf with gain added, and the step time response of the system.

(step (sine a) 5)
(define tf2 (tf '(1) '(0.3 0.1 1) b))
(step b 5)

procedure

(impulse b1)  void?

  b1 : block?
The impulse function takes as input a block. It computes and prints the block’s tf, and its impulse time response.

(impulse (sine a))
(define tf2 (tf '(1) '(0.3 0.1 1) b))
(impulse b)

procedure

(trajectory b1)  void?

  b1 : block?
The trajectory function takes as input a block. It computes and prints the block’s tf, and its time domain df(t)/dt - f(t) trajectory plot.

(trajectory (sine a))
(define tf2 (tf '(1) '(0.3 0.1 1) b))
(trajectory b)

3 Predefined circuits🔗ℹ

Circuits can be defined so that they return as result the block they are stored in. Therefore, they can be used directly as inputs to functions:

All plot functions listed below take as inputs blocks, not transfer functions.

(bode (feedback-loop-test1 a))

instead of:

(feedback-loop-test1 a)
(bode a)

That isn’t the case when using tfs, because a tf does not return the block in which it is installed.

3.1 Basic components🔗ℹ

procedure

(integrator b1)  block?

  b1 : block?

(bode (integrator a))

procedure

(sine b1)  block?

  b1 : block?

(bode (sine a))

procedure

(phase-delay-circuit b1)  block?

  b1 : block?

(bode (phase-delay-circuit a))

3.2 Controllers🔗ℹ

The PI, PD and PID controllers are defined by specifying the proportional (Kp), integral (Ki) and/or derivative (Kd) gains respectively, as well as the block to be stored in.

procedure

(pi-controller Kp Ki b1)  block?

  Kp : real?
  Ki : real?
  b1 : block?

(bode (pi-controller 5 8 a))

procedure

(pd-controller Kp Kd b1)  block?

  Kp : real?
  Kd : real?
  b1 : block?

(bode (pd-controller 5 8 a))

procedure

(pid-controller Kp Ki Kd b1)  block?

  Kp : real?
  Ki : real?
  Kd : real?
  b1 : block?

(bode (pid-controller 5 8 4 a))

3.3 Filters🔗ℹ

A Chebyshev Type I filter is defined by specifying the polynomial order (n), ripple factor (e) and cutoff frequency (w0) parameters, along with the block to be stored in.

procedure

(chebyshev-type1 n e w0 b1)  block?

  n : exact-positive-integer?
  e : real?
  w0 : positive?
  b1 : block?

(bode (chebyshev-type1 6 1 1 a))

3.4 Delay components🔗ℹ

Delay can be modeled in two ways:
  • by approximating it using a Padé polynomial

  • by adding delay as a function f(w) of the frequency w in the overall block’s tf (only for the s-domain)

The pade-delay procedure adds a time delay component to a block, modeled by a Padé polynomial of order [6/6] approximating the function e^(-t).

procedure

(pade-delay t b1)  block?

  t : positive?
  b1 : block?

(step (pade-delay 5 (sine a)) 1)

4 Circuit simplifications🔗ℹ

In order to compute the overall transfer function (tf) of a system modeled by interconnected elements inside a block, a simplification of its structure must be performed.

This simplification is performed by running a set of algorithms inside the block. Each algorithm may run more than once. During each algorithm run, a simplification may or may not be performed.

To be able to test and review this whole process, logging checkpoints have been implemented, with respective messages available to be displayed.

4.1 Display modes🔗ℹ

procedure

(set-logger-mode! logger-mode)  void?

  logger-mode : symbol?

(set-logger-mode! 'checkpoints)

The set-logger-mode! procedure can adjust the volume of simplifications-related messages displayed, in terms of the four following levels: