Signals & Systems
Fourier series, Laplace transforms, and system stability.
Signals & Systems
Signals and systems form the theoretical foundation for understanding how information is processed, transmitted, and analyzed in engineering applications. This mathematical framework is essential for analyzing everything from audio and telecommunications to control systems and biomedical devices.
Signals
Continuous-Time and Discrete-Time Signals
Continuous-Time Signals
Discrete-Time Signals
Signal Classification
Energy and Power Signals
Periodic and Aperiodic Signals
- Continuous: for all
- Discrete: for all
Basic Signals
Unit Step Function
Dirac Delta Function
Complex Exponential Signals
Where is a complex frequency.
Systems
System Properties
Linearity
Time-Invariance
Causality
Stability (BIBO)
Convolution
Continuous-Time
Discrete-Time
Properties
- Commutativity:
- Associativity:
- Distributivity:
Fourier Analysis
Fourier Series
Continuous-Time (CTFS)
For periodic signals with period :
Discrete-Time (DTFS)
For periodic discrete-time signals with period :
Fourier Transform
Continuous-Time Fourier Transform (CTFT)
Discrete-Time Fourier Transform (DTFT)
Properties of Fourier Transform
- Linearity:
- Time Shifting:
- Frequency Shifting:
- Time Scaling:
- Differentiation:
- Convolution:
Laplace Transform
Definition
For bilateral transform, integration is from to .
Common Transform Pairs
Properties
- Linearity:
- Time Shifting:
- Frequency Shifting:
- Time Differentiation:
- Time Integration:
Region of Convergence (ROC)
z-Transform
Definition
Common Transform Pairs
ROC Properties
For causal sequences: (outside circle of radius ) For anti-causal sequences: (inside circle of radius )
System Analysis
LTI Systems
Impulse Response
Frequency Response
System Functions
- Continuous:
- Discrete:
Transfer Function
Rational Function Form
Pole-Zero Representation
Where are zeros and are poles.
Stability Analysis
Continuous-Time Systems
For BIBO stability: All poles must lie in the left-half of s-plane ().
Discrete-Time Systems
For BIBO stability: All poles must lie inside the unit circle ().
Routh-Hurwitz Criterion
For polynomial :
Form Routh array and check for sign changes in first column.
System Response
Transient and Steady-State
First-Order Systems
Step response:
Second-Order Systems
Where is damping ratio and is natural frequency.
Filter Design
Ideal Filters
Lowpass Filter
Highpass Filter
Practical Filters
Butterworth Filter
Maximally flat in passband, monotonic response.
Chebyshev Filter
Where is Chebyshev polynomial, equiripple in passband.
Elliptic Filter
Equiripple in both passband and stopband, steepest roll-off.
Sampling Theory
Nyquist-Shannon Sampling Theorem
Where is sampling frequency and is highest frequency component.
Reconstruction
Where and .
Modulation and Communication
Amplitude Modulation
Where is message signal and is carrier frequency.
Frequency Modulation
Where is frequency deviation constant.
Applications in Signal Processing
Digital Filters
FIR Filter Design
Linear phase possible, always stable.
IIR Filter Design
More efficient but potentially unstable.
Spectral Analysis
Where is the Fourier transform of the truncated signal .
Real-World Application: Audio Filter Design
Digital filtering is essential in audio applications for noise reduction, equalization, and signal enhancement.
Audio Filter Analysis
# Design an audio equalizer filter bank
audio_params = {
'sample_rate': 44100, # Hz (CD quality)
'frequency_bands': [60, 250, 1000, 4000, 10000], # Hz (bass, low-mid, mid, high-mid, treble)
'bandwidth': 1.41, # Octave bandwidth (Q-factor related)
'gain_range': [-12, 12], # dB (gain adjustment range)
'filter_type': 'IIR', # IIR or FIR
'filter_order': 4, # Filter order
'buffer_size': 1024 # Samples for real-time processing
}
# Calculate filter parameters for peaking EQ
center_frequencies = audio_params['frequency_bands']
Q_factors = [f / (audio_params['bandwidth'] * f) for f in center_frequencies] # Simplified Q calculation
# For each frequency band, design a second-order peaking filter
# Using biquad filter coefficients
# H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) for peaking EQ
filter_coefficients = []
for i, fc in enumerate(center_frequencies):
# Normalize frequency to [0, 1] (Nyquist frequency = 0.5)
w0 = 2 * math.pi * fc / audio_params['sample_rate']
# Calculate Q parameter
Q = Q_factors[i]
# For now, assuming unity gain (flat response)
A = 1.0 # Linear gain factor
# Calculate biquad coefficients (for peaking filter)
alpha = math.sin(w0) / (2 * Q)
# Biquad coefficients: b0, b1, b2, a0, a1, a2
b0 = 1 + alpha*A
b1 = -2 * math.cos(w0)
b2 = 1 - alpha*A
a0 = 1 + alpha/A
a1 = -2 * math.cos(w0)
a2 = 1 - alpha/A
coeffs = {
'b0': b0,
'b1': b1,
'b2': b2,
'a0': a0,
'a1': a1,
'a2': a2,
'center_freq': fc,
'Q': Q
}
filter_coefficients.append(coeffs)
# Calculate total system frequency response
# Using the transfer function for IIR filters
# H(z) = (b0 + b1*z^-1 + b2*z^-2) / (a0 + a1*z^-1 + a2*z^-2)
# Frequency response calculation for each band
frequencies = [20, 100, 250, 500, 1000, 2000, 4000, 8000, 16000] # Standard frequencies
responses = []
for freq in frequencies:
z = math.exp(-1j * 2 * math.pi * freq / audio_params['sample_rate']) # z = e^(-j*2*pi*f/fs)
# Calculate overall response by multiplying all filter responses
total_response = 1.0
for coeffs in filter_coefficients:
numerator = coeffs['b0'] + coeffs['b1']*(1/z) + coeffs['b2']*(1/z)**2
denominator = coeffs['a0'] + coeffs['a1']*(1/z) + coeffs['a2']*(1/z)**2
band_response = numerator / denominator
total_response *= band_response
# Convert to dB
magnitude_db = 20 * math.log10(abs(total_response))
responses.append(magnitude_db)
print(f"Audio equalizer analysis at {audio_params['sample_rate']} Hz sample rate:")
print(f" Center frequencies: {center_frequencies} Hz")
print(f" Q factors: {[f'{q:.2f}' for q in Q_factors]}")
print(f" Buffer size: {audio_params['buffer_size']} samples")
print(f" Filter order: {audio_params['filter_order']}")
print(f" Gain range: {audio_params['gain_range'][0]} to {audio_params['gain_range'][1]} dB")
# Evaluate frequency response
print(f"\nFrequency Response at selected frequencies:")
for i, freq in enumerate(frequencies):
print(f" {freq} Hz: {responses[i]:.2f} dB")
# Calculate filter delay (group delay)
# For IIR biquads, delay varies with frequency
group_delays = []
for freq in frequencies:
w = 2 * math.pi * freq / audio_params['sample_rate']
# Group delay = -d(phase)/dw
# For phase calculation of a single biquad
z = math.exp(-1j * w)
total_phase = 0
for coeffs in filter_coefficients:
numerator = complex(coeffs['b0'] + coeffs['b1']*(1/z) + coeffs['b2']*(1/z)**2)
denominator = complex(coeffs['a0'] + coeffs['a1']*(1/z) + coeffs['a2']*(1/z)**2)
transfer_func = numerator / denominator
total_phase += math.atan2(transfer_func.imag, transfer_func.real) # Phase in radians
# Approximate group delay
group_delay = -total_phase / w if w != 0 else 0 # Samples
group_delays.append(group_delay)
print(f"\nGroup delay at selected frequencies:")
for i, freq in enumerate(frequencies):
print(f" {freq} Hz: {group_delays[i]:.2f} samples ({group_delays[i]/audio_params['sample_rate']*1000:.2f} ms)")
# Performance assessment
if all(abs(response) < 3 for response in responses): # Within 3dB tolerance
performance_quality = "Flat response - well-designed"
elif all(abs(response) < 10 for response in responses):
performance_quality = "Modest ripple - acceptable performance"
else:
performance_quality = "High ripple - may cause audible artifacts"
print(f"\nPerformance assessment: {performance_quality}")
# Processing latency considerations
processing_latency_samples = audio_params['buffer_size'] / 2 # Typical for FIR or IIR
processing_latency_ms = processing_latency_samples / audio_params['sample_rate'] * 1000
print(f"Processing latency: {processing_latency_ms:.2f} ms")
print(f"Real-time capability: {'Yes' if processing_latency_ms < 10 else 'Maybe' if processing_latency_ms < 30 else 'No (too high)'}")
Real-Time Processing Requirements
Meeting constraints for audio applications.
Your Challenge: Control System Stability Analysis
Analyze the stability of a feedback control system and determine the range of controller gains that ensure stable operation.
Goal: Apply system analysis techniques to determine controller parameters for stable closed-loop operation.
Control System Parameters
import math
# Feedback control system for DC motor speed control
control_system = {
'plant_transfer_function': 'K / (s(s+a)(s+b))', # DC motor: 2 poles + integrator
'controller_type': 'PID', # P, PI, PD, or PID
'plant_gain': 50, # Motor gain constant
'time_constants': [0.1, 0.05], # Time constants for poles (a=1/0.1=10, b=1/0.05=20)
'sampling_rate': 1000, # Hz (digital control)
'desired_bandwidth': 20, # Hz (closed-loop bandwidth requirement)
'phase_margin': 45, # degrees (stability requirement)
'gain_margin': 6, # dB (stability requirement)
'disturbance_rejection': True # Requirement for disturbance rejection
}
# Calculate plant parameters
K_motor = control_system['plant_gain']
a = 1 / control_system['time_constants'][0] # s⁻¹
b = 1 / control_system['time_constants'][1] # s⁻¹
# Plant transfer function: G(s) = K / [s(s+a)(s+b)]
# = K / [s³ + (a+b)s² + ab*s]
# For PID controller: C(s) = Kp + Ki/s + Kd*s = (Kd*s² + Kp*s + Ki) / s
# Overall open-loop: L(s) = C(s)*G(s) = K*(Kd*s² + Kp*s + Ki) / [s²(s+a)(s+b)]
# Calculate desired closed-loop characteristics
desired_nat_freq = control_system['desired_bandwidth'] * 2 * math.pi # Convert to rad/s
desired_damping = math.cos(math.radians(90 - control_system['phase_margin'])) # For phase margin
# For second-order approximation with PID control
# We want characteristic equation to have desired poles
# s² + 2*zeta*wn*s + wn² = 0
# Use Routh-Hurwitz criterion for stability
# Characteristic equation: 1 + L(s) = 0
# 1 + [K_motor * (Kd*s² + Kp*s + Ki)] / [s²(s+a)(s+b)] = 0
# s²(s+a)(s+b) + K_motor*(Kd*s² + Kp*s + Ki) = 0
# s⁴ + (a+b)s³ + ab*s² + K_motor*Kd*s² + K_motor*Kp*s + K_motor*Ki = 0
# s⁴ + (a+b)s³ + (ab + K_motor*Kd)s² + K_motor*Kp*s + K_motor*Ki = 0
# Routh array for 4th order system:
# s⁴: 1 | (ab + K*Kd) | K*Ki
# s³: (a+b) | K*Kp | 0
# s²: b1 | K*Ki | 0
# s¹: c1 | 0 | 0
# s⁰: K*Ki | 0 | 0
# Where b1 = [(a+b)(ab + K*Kd) - K*Kp] / (a+b)
# c1 = [b1*K*Kp - (a+b)*K*Ki] / b1
# For stability: All elements in first column must be positive
# Calculate stability conditions
R1 = 1 # Always positive
R2 = a + b # Always positive
R3 = ((a + b) * (a*b + K_motor * 1 * 0) - K_motor * 1 * 0) / (a + b) # Using placeholder values for now
# Using root locus approach to determine stable gain ranges
# For the open loop transfer function with PI controller (Kd = 0):
# L(s) = K_motor * (Kp + Ki/s) / [s(s+a)(s+b)] = K_motor * (Kp*s + Ki) / [s²(s+a)(s+b)]
# To find gain margin and phase margin, we need frequency response
# Calculate gain crossover frequency where |L(jw)| = 1
# Calculate phase at gain crossover frequency - should be > -180° + phase_margin for stability
# For now, let's focus on calculating required gains for desired performance
# Using pole placement for a simplified second-order system equivalent:
# Desired characteristic equation: s² + 2*zeta*wn*s + wn²
# For the third-order system we need to place poles appropriately
# One approach: dominant second-order with additional pole at higher frequency
# Place poles at: -ζωn ± jωn√(1-ζ²), -ωn*k (where k > 1 for separation)
dominant_poles_real_part = -desired_damping * desired_nat_freq
dominant_poles_imag_part = desired_nat_freq * math.sqrt(1 - desired_damping**2)
third_pole_location = -desired_nat_freq * 3 # 3x separation
print(f"Control system analysis:")
print(f" Plant gain: {K_motor}")
print(f" Pole locations: -{a}, -{b}, 0 (integrator)")
print(f" Desired natural frequency: {desired_nat_freq:.2f} rad/s ({desired_nat_freq/(2*math.pi):.2f} Hz)")
print(f" Desired damping ratio: {desired_damping:.3f}")
print(f" Desired closed-loop poles: {dominant_poles_real_part:.2f}±{dominant_poles_imag_part:.2f}j, {third_pole_location:.2f}")
print(f" Phase margin target: {control_system['phase_margin']}°")
print(f" Gain margin target: {control_system['gain_margin']} dB")
# Calculate approximate PID gains using pole placement (simplified approach)
# For a DC motor with PI control, good starting point:
# Kp = (2*zeta*wn*a*b) / K - 1 # Proportional gain
# Ki = wn² * a * b / K # Integral gain
Kp_calculated = (2 * desired_damping * desired_nat_freq * a * b) / K_motor - a - b
Ki_calculated = (desired_nat_freq**2 * a * b) / K_motor
Kd_calculated = 0 # For initial PI design
if Kp_calculated < 0:
# Adjust for practical values
Kp_calculated = desired_nat_freq / 10 # Empirical adjustment
Ki_calculated = (desired_nat_freq**2) / 10
# For PID with derivative action to improve stability margins:
# Add derivative term to improve phase margin
Kd_calculated = 0.1 * Kp_calculated # Empirical, typically 0.1-0.2 * Kp
ELI10 Explanation
Simple analogy for better understanding
Self-Examination
How do Fourier series and transforms convert time-domain signals to frequency-domain representations?
What is the significance of poles and zeros in system stability analysis?
How do convolution and correlation operations relate to system response?