## TCLab Block Diagram Analysis

**Objective**: Determine the closed loop response of a PI controller to a step change in setpoint. Compare the analytical solution to the closed loop response to a setpoint change.

A TCLab block diagram shows the flow of information in a feedback control system that consists of a sensor, actuator, and controller. Block diagrams are different than a process diagram in that it is a diagram of the flow of information, not necessarily how the pieces of equipment are physically placed as reviewed in the TCLab Controller Assignment. The block diagram is a collection of signals and transfer functions that transform one signal into another. Transfer functions transform an input signal into an output signal. The PI controller (`K_c=2`, `\tau_I=180`) is a transfer function `G_c = K_c \frac{\tau_I s+1}{\tau_I s}` that tranforms an error signal (input) into a heater value (*Q _{1}*) (controller output). The process transfer function `(G_p = \frac{0.9}{180s+1} e^{-15s})` receives the heater value (

*Q*) as an input and produces a change in temperature 1 (

_{1}*T*) process variable output. The disturbance transfer function `(G_d=\frac{0.3}{180s+1} e^{-15s})` has an input of temperature 2 (

_{A1}*T*) and produces a predicted change in temperature 1 (

_{2}*T*) process variable output. The two temperature outputs are added together as

_{B1}*T*. The loop is created with the sensor providing information to the controller as an error (

_{1}= T_{A1}+ T_{B1}*E=T*) between the setpoint and measured value. The P-only controller changes the controller output

_{SP}-T_{1}*Q*to change the temperature

_{1}*T*and the cycle starts again.

_{1}**Block Diagram Algebra**

The overall transfer function between the disturbance *T _{2}* and

*T*is derived by algebraically combining the following expressions to eliminate all other signals besides the input and output of interest.

_{1}$$E(s) = T_{SP}(s)-T_1(s)$$

$$Q_1(s) = G_c(s) \, E(s) = G_c(s) \, (T_{SP}(s)-T_1(s))$$

$$T_{A1}(s) = G_p(s) \, Q_1(s) = G_c(s) \, G_p(s) \, (T_{SP}(s)-T_1(s))$$

$$T_{B1}(s) = G_d(s) \, T_2(s)$$

$$T_1(s) = T_{A1}(s)+T_{B1}(s) = G_c(s) \, G_p(s) \, (T_{SP}(s)-T_1(s)) + G_d \, T_2(s)$$

In this case, *T _{SP}(s)*=0 because it is assumed that there is no change in the setpoint as the disturbance transfer function is derived.

$$T_1(s) = - G_c(s) \, G_p(s) \, T_1(s) + G_d(s) \, T_2(s)$$

The transfer function is further simplified by collecting all *T _{1}(s)* terms to one side and

*T*terms to the other.

_{2}(s)$$T_1(s) + G_c(s) \, G_p(s) , T_1(s) = G_d \, T_2(s)$$

This simplifies to the overall closed loop transfer function for disturbance changes.

$$\frac{T_1(s)}{T_2(s)} = \frac{G_d(s)}{1+G_c(s)\,G_p(s)} = \frac{\frac{0.3}{180s+1} e^{-15s}}{1+K_c \frac{\tau_I s+1}{\tau_I s} \frac{0.9}{180s+1} e^{-15s}}$$

**Time-Delay to Polynomial Form**

An inverse Laplace transform is not possible with this transfer function because of the exponential terms. To compute an analytical solution to a step input, a Taylor series approximation or PadÃ© approximation of *exp(-15s)* with the first 2 or 3 terms are typically used to return to polynomial form.

*PadÃ© Approximation for exp*

$$\exp(x) \approx \frac{1+\frac{1}{2}x+\frac{1}{9}x^2}{1-\frac{1}{2}x+\frac{1}{9}x^2}$$

Two terms are selected to approximate the dead-time. Additional terms improve the accuracy of the approximation but also increase the order of the polynomial.

$$\exp(-15s) \approx \frac{1-7.5 s}{1+7.5 s}$$

*Taylor Series Approximation for exp*

$$\exp(x) \approx \sum_{n=0}^{\infty}\frac{x^n}{n!} = 1+x+\frac{x^2}{2!}+\frac{x^3}{3!}+\dots$$

The exponential is first place in the denominator and two terms are selected to approximate the dead-time.

$$e^{-15s} = \frac{1}{e^{15s}} \approx \frac{1}{15s+1}$$

The Taylor series approximation is used for this example. The polynomial form of the transfer function is used for the analytical solution. The PI controller rejects the disturbance

**Analytic Solution to PI Controller Response to +20 ^{o}C T_{2} Disturbance**

$$T(t) = \left(1.14 e^{0.0178t} - 7.97 e^{0.0600t} + 6.83 e^{0.067t}\right) e^{-0.072t} S(t-1)$$

from sympy.abc import s,t,x,y,z

import numpy as np

from sympy.integrals import inverse_laplace_transform

import matplotlib.pyplot as plt

# Define inputs

T2 = 20/s*sym.exp(-s)

# Transfer functions

Kc = 2.0

tauI = 180.0

Gc = Kc * (tauI*s+1)/(tauI*s)

delay = 1/(15*s+1) # Taylor series approx

Gd = delay * 0.3/(180*s+1)

Gp = delay * 0.9/(180*s+1)

# Closed loop response

Gc = Gd/(1+Gc*Gp)

# Calculate response

T1 = Gc * T2

# Inverse Laplace Transform

t2 = inverse_laplace_transform(T2,s,t)

t1 = inverse_laplace_transform(T1,s,t)

print('Temperature Solution')

print(t1)

# generate data for plot

tm = np.linspace(0,600,100)

T2plot = np.zeros(len(tm))

T1plot = np.zeros(len(tm))

# substitute numeric values

for i in range(len(tm)):

T2plot[i] = t2.subs(t,tm[i])

T1plot[i] = t1.subs(t,tm[i])

# plot results

plt.figure()

plt.plot([0,10],[0,0],'k:',label='T1 Setpoint')

plt.plot(tm/60,T2plot,label='T2 Disturbance')

plt.plot(tm/60,T1plot,label='T1 Predicted')

plt.legend()

plt.xlabel('Time (min)')

plt.ylabel(r'Temperature Change $(\Delta T \, ^oC)$')

plt.show()

**Compute T _{1} Analytic Solution to +20^{o}C Setpoint Change**

Using the above as an example, calculate the closed loop transfer function for a PI controller between the other input (setpoint *T _{SP}*) and the output (

*T*). Compute the analytical solution for

_{1}*T*and show predicted and measured values for a PI controller setpoint change from 23

_{1}^{o}C to 43

^{o}C. Use the PI Test Script to show the analytical and measured values for the closed loop control, modifying the line for the predicted temperature.

import matplotlib.pyplot as plt

import tclab

import time

n = 600 # Number of second time points (10 min)

tm = np.linspace(0,n-1,n) # Time values

T1Pred = # fill in analytic solution

# Kc,tauI,tauD

Kc = 2.0

tauI = 180.0

tauD = 0

# PID Controller Function

def pid(sp,pv,pv_last,ierr,dt):

# Parameters in terms of PID coefficients

KP = Kc

KI = Kc/tauI

KD = Kc*tauD

# ubias for controller (initial heater)

op0 = 0

# upper and lower bounds on heater level

ophi = 100

oplo = 0

# calculate the error

error = sp-pv

# calculate the integral error

ierr = ierr + KI * error * dt

# calculate the measurement derivative

dpv = (pv - pv_last) / dt

# calculate the PID output

P = KP * error

I = ierr

D = -KD * dpv

op = op0 + P + I + D

# implement anti-reset windup

if op < oplo or op > ophi:

I = I - KI * error * dt

# clip output

op = max(oplo,min(ophi,op))

# return the controller output and PID terms

return [op,P,I,D]

lab = tclab.TCLab()

T1 = np.zeros(n)

Q1 = np.zeros(n)

# step setpoint from 23.0 to 43.0 degC

SP1 = np.ones(n)*23.0

SP1[1:] = 43.0

Q1_bias = 0.0

ierr = 0.0

for i in range(n):

T1[i] = lab.T1

[Q1[i],P,ierr,D] = pid(SP1[i],T1[i],T1[max(0,i-1)],ierr,1.0)

lab.Q1(Q1[i])

if i%20==0:

print(' Heater, Temp, Setpoint')

print(f'{Q1[i]:7.2f},{T1[i]:7.2f},{SP1[i]:7.2f}')

time.sleep(1)

lab.close()

# Save data file

data = np.vstack((tm,Q1,T1,SP1)).T

np.savetxt('PI_control.csv',data,delimiter=',',\

header='Time,Q1,T1,SP1',comments='')

# Create Figure

plt.figure(figsize=(10,7))

ax = plt.subplot(2,1,1)

ax.grid()

plt.plot(tm/60.0,SP1,'k-',label=r'$T_1$ SP')

plt.plot(tm/60.0,T1,'r.',label=r'$T_1$ PV')

plt.plot(tm/60.0,T1Pred,'b-',label=r'$T_1$ Predicted')

plt.ylabel(r'Temp ($^oC$)')

plt.legend(loc=2)

ax = plt.subplot(2,1,2)

ax.grid()

plt.plot(tm/60.0,Q1,'b-',label=r'$Q_1$')

plt.ylabel(r'Heater (%)')

plt.xlabel('Time (min)')

plt.legend(loc=1)

plt.savefig('PI_Control.png')

plt.show()

**Solution**

The overall transfer function between the disturbance *T _{SP}* and

*T*is derived by algebraically combining the same expressions to eliminate all other signals besides the input and output of interest.

_{1}$$E(s) = T_{SP}(s)-T_1(s)$$

$$Q_1(s) = G_c(s) \, E(s) = G_c(s) \, (T_{SP}(s)-T_1(s))$$

$$T_{A1}(s) = G_p(s) \, Q_1(s) = G_c(s) \, G_p(s) \, (T_{SP}(s)-T_1(s))$$

$$T_{B1}(s) = G_d(s) \, T_2(s)$$

$$T_1(s) = T_{A1}(s)+T_{B1}(s) = G_c(s) \, G_p(s) \, (T_{SP}(s)-T_1(s)) + G_d \, T_2(s)$$

In this case, *T _{2}(s)*=0 because it is assumed that there is no change in the disturbance as the setpoint transfer function is derived.

$$T_1(s) = G_c(s) \, G_p(s) \, (T_{SP}(s)-T_1(s))$$

The transfer function is further simplified by collecting all *T _{1}(s)* terms to one side and

*T*terms to the other.

_{SP}(s)$$T_1(s) + G_c \, G_p(s) \, T_1(s) = G_c \, G_p(s) \, T_{SP}(s)$$

The closed loop transfer function is the ratio of the output to input.

$$\frac{T_1(s)}{T_{SP}(s)} = \frac{G_c \, G_p(s)}{1+G_c \, G_p(s)}$$

**Analytic Solution to +20 ^{o}C Setpoint Change**

$$T(t) = \left( 20.0 + 6.14 e^{-0.054\,t} - 26.13 e^{-0.012\,t} \right) S(t-1)$$

from sympy.abc import s,t,x,y,z

import numpy as np

from sympy.integrals import inverse_laplace_transform

import matplotlib.pyplot as plt

# Define inputs

# Setpoint step (up) starts at 1 sec

TSP = 20/s*sym.exp(-s)

# Transfer functions

Kc = 2.0

tauI = 180.0

Gc = Kc * (tauI*s+1)/(tauI*s)

delay = 1/(15*s+1) # Taylor series approx

Gp = delay * 0.9/(180*s+1)

# Closed loop response

Gc = Gc*Gp/(1+Gc*Gp)

# Calculate response

T1 = Gc * TSP

# Inverse Laplace Transform

tsp = inverse_laplace_transform(TSP,s,t)

t1 = inverse_laplace_transform(T1,s,t)

print('Temperature Solution')

print(t1)

# generate data for plot

tm = np.linspace(0,600,100)

TSPplot = np.zeros(len(tm))

T1plot = np.zeros(len(tm))

# substitute numeric values

for i in range(len(tm)):

TSPplot[i] = tsp.subs(t,tm[i]) + 23.0

T1plot[i] = t1.subs(t,tm[i]) + 23.0

# plot results

plt.figure()

plt.plot(tm/60,TSPplot,'k:',label='T1 Setpoint')

plt.plot(tm/60,T1plot,'b-',label='T1 Predicted')

plt.legend()

plt.xlabel('Time (min)')

plt.ylabel(r'Temperature Change $(\Delta T \, ^oC)$')

plt.show()

The PI Control test script is modified with the analytic solution.

The plot shows a comparison of the predicted and measured temperature values. The ambient temperature is less than the 23^{o}C simulated value and can be adjusted to achieve a better match to the analytic solution. However, despite the offset, the measured dynamic response of the closed-loop response is similar to the analytic solution.