You are on page 1of 79

Lecture 2: System Integration

(Feedback Control)
MAE490G/EE 442
Mechatronic Systems Design
CSULB

Topics
Feedback control
Open vs. closed-loop
Stability and performance specifications
System response
PID controller

Motor control and interface


Position sensor Optical encoder
PWM

Working with Arduino and MATLAB/Simulink

Open and closed loop control


Basic problem:
Make actual output = desired output

Designing a control system means


Defining input and output
Techniques for applying corrective action
Techniques for stability and performance

Open Loop System


Computer sends a command based on u, and you
hope the right thing x comes out

For most applications, this relies on a good model


of the plant

Open Loop System


Procedure for force-control system:
Computer calculates a force, F, to display at the
end effector
Computer controller determines the correct
voltage to send to the actuator at the joint
T

J F

1
KT

K Ai

Dynamics of the device will result in a change in


position
results in

fwd. kin.

x, x

Closed Loop System

The command is modified based on error


between the output and the reference (feedback
control)
Advantages of feedback control
Stabilization
Disturbance rejection
Reference tracking

Closed-loop Transfer Function


Assume negligible noise and disturbance, a
feedback control system can be represented as

E(s) = R(s) H(s)Y(s). Note that with an ideal


sensor, H(s) = 1. The general transfer function is
Y ( s)
R( s )

C ( s )G ( s )
1 C ( s )G ( s ) H ( s )

The reference signal can vary with time (tracking)


or constant (regulator).

With Disturbance
C(S)

H(S)

The general transfer function is


Y ( s)
D( s )

G( s)
1 C ( s )G ( s ) H ( s )

Note that the denominator of both TFs are the


same => same poles => apply the same stability
consideration

LTI Systems
LTI = Linear time-invariant system.
For y(t) = S[x(t)],
Linearity: For any two input signals x1(t) and x2(t)
and a real constant a,
S[x1(t)+x2(t)] = S[x1(t)] + S[x2(t)] and
S[ax1(t)] = aS[x1(t)]
Time invariance: For any real constant T, y(t-T) =
S(x(t-T)). This includes constant-gain system and
linear combinations of time-shifts of the input
signal, i.e. y(t) = x(t) 2x(t-5).

Stability of LTI systems


Given a transfer function of a LTI system in the form,
The root of the characteristic equation, called the poles, can
be found from setting
which can be written as a complex number: p = + j
The system is stable if all the poles of its transfer function
have negative real parts ( < 0, on left-half plane) and
unstable otherwise.
When = 0, the system is marginally stable if the complex
roots are non-repeated and unstable otherwise.
The roots of the numerator is called zeros, which are not
related to the stability, though it will affect the response of
the system.

Stability Criterion
Rouths Method: Developed for obtaining the
information about the pole locations without
solving the roots of the characteristic equation, P.
Two conditions:
A necessary (but not sufficient) condition for stability is
that all the coefficients of P are positive
A necessary and sufficient condition is that all elements
in the first column of the Routh array are positive (see LTI
control references for further details)

Related MATLAB functions


>> sys = tf(num,den)
>> pole(sys)

Performance Specifications (Time domain)


The performance requirements are usually given for
the step response.
Rise time, tr
Overshoot, Mp
Peak time, tp
Settling time, ts
Delay time, td

W. Palm, System Dynamics, 3rd Ed.

Performance specifications
Rise time (tr): The time for output to rise from 0 (or
10%) to 90% of the final value
Overshoot (Mp): Maximum deviation of the output
above its steady-state value. Mp increases with
decreasing . Mp can also be expressed in % of the final
value (Xmax Xss)*100/Xss.
Peak time (tp): Time at which the max overshoot occurs
Settling time (ts): Time required for the oscillation to
stay within specified small percentage (usually 2 or 5%).
For 2% settling time, ts = 4/( n) = 4*time constant.
Delay time (td): Time required for the response to reach
50% of its final value

Response of 1st Order System


+ = , > 0
Laplace transform: + =
=
Solve

L-1,

1
+

1
()
+1

= +

1
()
+1

With step input (F(s) = A/s)),


=

+ [1

Consider a RL circuit:
Rewrite,

+ = , 0 = 0

+ =

Time constant =

For unit step input, =

1
(1

Whats the steady state response?


What happen at 4?

Consider 2nd order m-b-k system

What happen to the response, x(t), of the


system when we adjust k and b?
F

mx

mx f kx bx
mx bx kx f

fk

fb

includes all forces


applied to the system
f

Natural Frequency & Damping Ratio


Rewriting the 2nd-order equation in another form

Divided by 1/m: x

Natural frequency:

Damping ratio:

Note that

b
x
m

k
x
m

1
f
m

k
rad / s
m

b
2m

b
2 mk

0
17

Total Response
Laplace transform:

Solve for X(s):

Inverse Laplace transform:

Response to
Initial conditions

Response to
Input
18

Step Response
Assume the forcing function, step input

Step Response

Responses for different damping


ratio

0 < < 1 (Underdamped)


decaying oscillation
= 1 (Critically damped)
> 1 (Overdamped)
no oscillation

= 0.4

0.5

= 1.0
= 2.0
=0

0.4

Amplitude

= 0 (Undamped)
pure oscillation

= 0.1

0.3

0.2

0.1

-0.1

5
Time (sec)

19

10

Step response specifications of underdamped


system with no numerator dynamics

W. Palm, System Dynamics, 3rd Ed.


In control design, one or more of these requirements will be given to determine
the allowable region of the poles in the s-plane.

Topics
Feedback control
Open vs. closed-loop
Stability and performance specifications
System response
PID controller

Motor control and interface


Position sensor Optical encoder
PWM

Working with Arduino and MATLAB/Simulink

PID Controller
Proportional-integral-derivative control provides
a widely-used generic feedback controller
The control signal is generated based on the
error, e(t), between the current system state
and the reference and involves 3 gains:
kp = proportional gain (apply to the error)
kD = derivative gain (apply to the derivative of
the error)
kI = integral gain (apply to the integral of the
error)

Block diagram of PID controller

The expression of the controller is given by


t
Time domain: u(t ) k e(t ) k e( )d k de(t )
p

Transfer fn:

U ( s)
E ( s)

kp

kI
s

kD s

dt

PD Controller Example
Consider

2nd-order

plant:

G( s)

C ( s)

PD controller:
Overall TF:
Y ( s)
R( s )

s2

kp

s2

b
a1s a2

kD s

b(k D s k p )
(a1 bkD ) s a2 bk p

Increasing kp increases natural frequency


increases and decreases damping ratio.
Increasing kD increases damping.

Proportional
Control signal = kp(ref-y) = kpe
Effect: big signal for large error, small signal
for small error
Results in steady-state error
Needs a nonzero error to generate a control
action
Essentially a spring at the desired position
(F=kx)
High gain makes a stiffer spring and
increases tendency to oscillate

Effect of kp

Derivative
Control signal = kDd(e)/dt
Effect: slows control action and damps
oscillations; increases system stability
Can also make response more sluggish
Based on first derivative: either noise or
filtering lag (for velocity estimate from position)
can actually introduce instability again

Effect of kD

Integral
Control signal = ki (e)dt
Effect: integrates error over time
Control signal builds up and eventually brings
error to zero
Eliminates steady-state error and improves system
responsiveness
Unpleasant side effects:
Reduced damping and larger overshoot
(decreased stability)
Integrator wind-up

Effect of kI

Tuning a PID controller


Iterative manual tuning process
Start with P: increase until unstable
Add D until stable
If SS error is a problem, add I
(add D until stable)
Add more P, adjust D, etc.
Compromise between responsiveness and stability
There are systematic tuning guidelines available such
as the Ziegler-Nichols method. The optimal gains are
selected based on the lag time and the reaction rate
of the open loop unit-step response.

Topics
Feedback control
Open vs. closed-loop
Stability and performance specifications
System response
PID controller

Motor control and interface


Position sensor Optical encoder
PWM

Working with Arduino and MATLAB/Simulink

Optical encoder
A digital optical encoder is a device that converts
motion into a sequence of digital pulses. The motion
may be either linear or rotational.
We focus on the more common rotary optical
encoder.

Incremental optical encoder

A disk (or codewheel) attached to a rotating shaft


spins between two photo-emitters and detectors .
The disk has a radial pattern of lines that alternately
pass and block the beam between a photo-emitter
detector pair.
The photo detector outputs are called channel A and
B.

Incremental optical encoder


By counting the number of pulses and knowing the
number of radial lines in the disk, the rotation of the
shaft can be measured.
The direction of rotation is determined by the phase
relationship between the A and B pulse trains.
If A leads B, then the shaft is rotating counter-clockwise
If B leads A, then the shaft is rotating clockwise

Quadrature signals

Channel A and B are 1/4 cycle out of phase


with each other (quadrature signals).
There are four distinct states (S1 S4). Thus, a
500 count encoder which has 500 physical slits
for each photodiode will give you 2000 counts
per revolution.

DC motor speed control


Motor speed depends on armature voltage (Va):

If Va is a digital signal (high and low only), use pulsewidth modulation (PWM) to change its average
value.
PWM : fix the frequency but vary duty cycle to
change average output voltage:

H-bridge driver
PWM is often use with a H-bridge:

The H-bridge allows the motor to change direction:


If S1 and S4 are ON, and S2 and S3 OFF, the motor turns in
one direction.
If S1 and S4 are OFF, and S2 and S3 ON, the motor turns in the
opposite direction.
If S2 and S4 are OFF or S1 and S3 are OFF, the motor slows down.
Use PWM to control the switches, and hence the motor speed.

L298 H-bridge driver


Includes 2 H-bridges:

Arduino Microcontroller
Low cost, open source microcontroller.
Based on Atmel Atmega chip.
Different versions: Uno, Duemilanove, Mega,
Nano.
Easy to extend its function using accessory
shield board. Ex: Motor shield, wireless shield.

Arduino architecture

ATmega328 on Uno

Both analog and digital

Arduino Uno

Arduino Uno
Pins A0-A5 are analog
inputs. Can be used
as digital input or
output as well.
Pins 0-13 are digital
inputs/outputs. Max
current is 40mA per
pin.
Pins 3, 5, 6, 9, 10, and
11 can be configured
as 8-bit PWM output.

Arduino Program
Download and install free
Arduino Integrated
Development Environment
(IDE) software and USB
drivers:
http://arduino.cc/en/Main/Software

Latest version is 1.0.5.


Available for Windows,
Mac, Linux.
An Arduino program is
called a sketch
Code syntax is similar to C.

Arduino IDE
Verify
syntax

Upload
sketch to
board

new

Open

save

Open serial monitor

Arduino IDE
Examples:
File > Examples -> ..

Choose board
Tools -> Board -> Arduino Uno

Select serial port


Tools -> Serial port -> COMxx

Example sketch blink


/* Blink
Turns on an LED on for one second, then off for one second, repeatedly. */

Declaration section

// Pin 13 has an LED connected to it.


// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000);
// wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000);
// wait for a second
}

Setup section. Use


for setting pin mode
and serial port etc.
Main code section

Notes:
Commands are case sensitive
Text after // are comments
Text between /* and */ are comments
Each line of code needs to end with a ;

Input and output functions


pinMode(pin, mode)
Configures a digital pin to behave either as an input or
an output.
mode: INPUT, OUTPUT

digitalWrite(pin, value)
Turns a digital pin either on or off.
value: HIGH or LOW

digitalRead(pin)
Reads the value from a specified digital pin, either
HIGH or LOW.
Usually use an int variable to store the value.

Input and output functions


analogRead(pin)
Reads the voltage applied to an analog input pin (0- 5)
and returns a number between 0 and 1023 that
represents the voltages between 0 and 5 V.

analogWrite(pin, value)
Changes the PWM rate on one the digital pins 3, 5, 6,
9, 10, and 11.
Value may be a number between 0 and 255. 0 means
OFF, 255 means 100% duty cycle.
Need to use pinMode to set pin as output before using.

Sketch boilerplate
Any Arduino sketch must have a setup and loop
section.
void setup() {
// code
}
void loop() {
//code
}

The void means that the function does not


return any values when called.

Serial monitor
To display information on screen.
Click on
to open the serial monitor window.
Example sketch:
// sketch 3-05
void setup()
{
Serial.begin(9600);
int degC = 20;
int degF;
degF = degC * 9 / 5 + 32;
Serial.println(degF);
}
void loop()
{}

Set the serial port speed to


9600baud
Print the value of degF to the
serial monitor window

Note that Serial.println can also be used inside loop()

If-else statement
Syntax:

if (condition)
{
// action A
}
else
{
// action B
}

Condition operator:

If-else statement example


// sketch 3-09
int ledPin = 13;
int delayPeriod = 100;
int count = 0;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
digitalWrite(ledPin, HIGH);
delay(delayPeriod);
digitalWrite(ledPin, LOW);
delay(delayPeriod);
count ++;
if (count == 20)
{
count = 0;
delay(3000);
}
}

This sketch blinks the LED 20 times at


0.1sec rate and then wait for 3 sec
before repeating again.

Note:
count++ is the same as
count=count+1

Compound operators
x++;
x- - ;
x += y;
x -= y;
x *= y;
x /= y;

// equivalent to the expression x = x + 1;


// equivalent to the expression x = x - 1;
// equivalent to the expression x = x + y;
// equivalent to the expression x = x - y;
// equivalent to the expression x = x * y;
// equivalent to the expression x = x / y;

Boolean operators

&&

-- logical and
True only if both operands are true, e.g.
if (digitalRead(2) == 1 && digitalRead(3) == 1)
{ // code
}

||

--- logical or
True if either operand is true, e.g.
if (x > 0 || y > 0) {
// ...
}
is true if either x or y is greater than 0.

-- not
True if the operand is false, e.g.
if (!x) {
// ...
}
is true if x is false (i.e. if x equals 0).

Math operations

Data types

For statement
Syntax:
Example:

for (initialization; condition; increment)


{
//statement(s);
}
// sketch 3-08
int ledPin = 13;
int delayPeriod = 100;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
for (int i = 0; i < 20; i ++)
{
digitalWrite(ledPin, HIGH);
delay(delayPeriod);
digitalWrite(ledPin, LOW);
delay(delayPeriod);
}
delay(3000);
}

while statement
Syntax:
Example:

while(expression)
{
// statement(s)
}
// sketch 3-08
int ledPin = 13;
int delayPeriod = 100;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
int i=0;
while (i < 20)
{
digitalWrite(ledPin, HIGH);
delay(delayPeriod);
digitalWrite(ledPin, LOW);
delay(delayPeriod);
i ++;
} delay(3000); }

#define directive
Can use #define to associate a value with a
variable provided the value does not change. This
saves memory.
For example, replace
int ledPin = 13;

by
#define ledPin 13

Note there is no semi-colon needed after #define.

Functions
A function is a like a program within a program.
Syntax: returntype functionName( arguments )
{
//function body
return returntype;
}

Example:

Use a
function call
flash

int ledPin = 13;


int delayPeriod = 250;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
for (int i = 0; i < 20; i ++)
{
flash();
}
delay(3000);
}

void flash()
{
digitalWrite(ledPin, HIGH);
delay(delayPeriod);
digitalWrite(ledPin, LOW);
delay(delayPeriod);
}

Passing parameter to a function


Example:

numFlashes and d are local


variables that can only be used in
the function flash

// sketch 4-02
int ledPin = 13;
int delayPeriod = 250;
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
flash(20, delayPeriod);
delay(3000);
}

void flash(int numFlashes, int d)


{
for (int i = 0; i < numFlashes; i ++)
{
digitalWrite(ledPin, HIGH);
delay(d);
digitalWrite(ledPin, LOW);
delay(d);
}
}

Pass 20 and delayPeriod to the function


flash. So numFlashes=20 and d=delayPeriod.

Function that returns value


Example:
int centToFaren(int c)
{
int f = c * 9 / 5 + 32;
return f;
}

This function takes a temperature in degrees centigrade


and returns the equivalent in degrees fahrenheit. You can
call it using:
int Temperature = centToFaren(20);

Here the result is declared as an integer. So the result will


be rounded off. To keep decimal values, use float instead
of int.

Function that returns value (floating


point)

Example:

float centToFaren(float c)
{
float f = c * 9.0 / 5.0 + 32.0;
return f;

You can call it using:

Note that we have use floats


throughout here. We have also added
.0 to the end of our constants. This
ensures that the compiler knows to
treat them as floats rather than ints.

float Temperature = centToFaren(20);

Arrays
An array contains a list of
values, rather than just one
value.
int durations[] = {200, 200, 200, 500, 500, 500,
200, 200, 200};

Arrays
Example:
// sketch Morse code
int ledPin = 13;
int durations[] = {200, 200, 200,
500, 500, 500, 200, 200, 200};
void setup()
{
pinMode(ledPin, OUTPUT);
}
void loop()
{
for (int i = 0; i < 9; i++)
{
flash(durations[i]);
}
delay(3000);
}

void flash(int delayPeriod)


{
digitalWrite(ledPin, HIGH);
delay(delayPeriod);
digitalWrite(ledPin, LOW);
delay(delayPeriod);
}

Strings
A string is an array of type char.
The type char is a number between 0 and 127 that
represents one character (ASCII).
Common ASCII code:

Ex:
char name[] = "Hello";

This defines an array of char called name and


initializes it to the word Hello. It also adds a final
null value (ASCII 0) to mark the end of the string.
name[0] holds H
name[1] holds e, etc

Strings
The following are equivalent:
char name[] = "Hello";
char *name = "Hello";

The * indicates a pointer. So the name points to the first char


element of the char array.
Example:
// sketch
char message[] = "Hello"; // or use: char *message = "Hello";
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.println(message);
delay(1000);
}

Array of strings
We can also form an array of strings (not just array of char)
char *letters[] = { abc, def,ghi);

This means:
letters[0] holds abc
letters[1] holds def, etc

Serial communication
Serial.begin(speed) - sets the data rate in bits per second,
where speed is one of these rates: 300, 600, 1200, 2400, 4800,
9600, 14400, 19200, 28800, 38400, 57600, or 115200
Serial.available() -- This function returns the number of bytes
of data in the buffer that are waiting for you to read.
Serial.flush() - Waits for the transmission of outgoing serial
data to complete.
Serial.read() reads in one byte (or -1 if no data available)
Serial.write(val) - write binary data to serial port, where val is a
value to send as a single byte.
Serial.write(str) write binary data to serial port, where str is a
string to send as a series of bytes
Serial.write(buf, len) - write binary data to serial port, where
buf is an array to send as a series of bytes and len is the length
of the buffer

Serial communication
Serial.print(data) - Prints data to the serial port as humanreadable ASCII text.
Ex:
Serial.print(78) gives "78"
Serial.print(1.23456) gives "1.23"
Serial.print('N') gives "N"
Serial.print("Hello world.") gives "Hello world."

Serial.println(data) - prints data to the serial port as humanreadable ASCII text followed by a carriage return character

Serial communication
Example: we can communicate with arduino using serial monitor
//sketch
int outPin = 4;
void setup()
{
pinMode(outPin, OUTPUT);
Serial.begin(9600);
Serial.println("Enter 1 or 0");
}
void loop()
{
if (Serial.available() > 0)
{
char ch = Serial.read();
if (ch == '1')
{ digitalWrite(outPin, HIGH); }
else if (ch == '0')
{ digitalWrite(outPin, LOW); }
}
}

Binary, Hex numbers


Binary number use leading B. Only works with 8
bit values.
Example: B11111011

Hexadecimal number - use leading 0x.


Example: 0x7B

Bitwise operations
& -- bitwise AND.
Example: B11111011 & B00001111 yields B00001011
| - bitwise OR
Example: B11111011 | B00001111 yields B11111111
~ - bitwise NOT
Example: ~ B11111011 yields B00000100

Interrupts
Arduino is single thread. So monitoring the
occurrence of an event uses up precious CPU
time.
Use interrupt instead.
CPU will perform its regular activities until
interrupt occurs. Then it will suspend
whatever it is doing and runs a function to
handle the interrupt.
Arduino Uno has 2 interrupt pins (Pin 2 and 3)
corresponding to interrupt 0 and 1 respectively.

Using interrupts
Attach a signal to an interrupt pin.
Associate a function, interrupt service routine (ISR), with the
interrupt:
attachInterrupt(interrupt, function, mode)

where
interrupt: the number of the interrupt (0 or 1)
function: the name of the ISR
mode:
defines when the interrupt should be triggered.
LOW to trigger the interrupt whenever the pin is low,
CHANGE to trigger the interrupt whenever the pin changes
value
RISING to trigger when the pin goes from low to high,
FALLING when the pin goes from high to low.

When the interrupt occurs, the arduino will run the ISR.
When the ISR is done, the arduino will resume its regular
activities before the interruption.

Using interrupts
Example:
//sketch 7-04
int interruptPin = 2;
int ledPin = 13;
int period = 500;
void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT);
attachInterrupt(0, goFast, FALLING);
}
void loop()
{
digitalWrite(ledPin, HIGH);
delay(period);
digitalWrite(ledPin, LOW);
delay(period);
}
void goFast()
{
period = 100;
}

Interfacing with MATLAB/Simulink


Use Real-time windows target (rtwintgt) toolbox
packet input block
packet output block
(make sure to set the correct COM port the arduino is connected to)

Data type: single in matlab (4 bytes) is the same as float in


Arduino
Use Serial.write in arduino to send data to packet input block in
simulink. The following sends the value stored in a float variable
xyz to simulink:
Serial.write(((unit8_t*)&xyz),4);
where,
uint8_t means size is 1 byte, i.e. 8 bits
* means pointer
&xyz means address of xyz
4 means there are 4 bytes altogether to send

Interfacing with simulink


Use Serial.read in arduino to read data sent from packet output
block in simulink. The following reads a 4-byte float data from
simulink into a variable def:
while (!Serial.available()) {}
(((int8_t*)(&def))[0]) = Serial.read();
while (!Serial.available()) {}
(((int8_t*)(&def))[1]) = Serial.read();
while (!Serial.available()) {}
(((int8_t*)(&def))[2]) = Serial.read();
while (!Serial.available()) {}
(((int8_t*)(&def))[3]) = Serial.read();

Note that there are 4 reads (one byte at a time). First into def[0],
then def[1], def[2], def[3], where each is one byte.