Split View: 신호처리 & 제어시스템 완전 가이드: 푸리에 변환부터 PID 제어까지
신호처리 & 제어시스템 완전 가이드: 푸리에 변환부터 PID 제어까지
- 1. 신호와 시스템 기초
- 2. 푸리에 급수 (Fourier Series)
- 3. 푸리에 변환 (Fourier Transform)
- 4. 이산 푸리에 변환 (DFT) & FFT
- 5. 라플라스 변환 (Laplace Transform)
- 6. Z-변환
- 7. 디지털 필터 설계
- 8. 제어시스템 기초
- 9. PID 제어기
- 10. 상태 공간 표현 (State Space)
- 11. AI/ML과 신호처리
- 12. 퀴즈
- 참고 문헌
1. 신호와 시스템 기초
1.1 신호의 분류
신호(Signal)는 정보를 전달하는 물리적 양의 변화입니다. 기본 분류는 다음과 같습니다.
연속시간 신호 vs 이산시간 신호
연속시간 신호(CT Signal)는 모든 시간 에서 정의됩니다. 예: 아날로그 음성 신호
이산시간 신호(DT Signal)는 정수 인덱스 에서만 정의됩니다. 예: 디지털 오디오 샘플
에너지 신호와 전력 신호
신호의 에너지 와 평균 전력 :
이면 에너지 신호, 이면 전력 신호입니다.
1.2 기본 신호
단위 임펄스(Unit Impulse)
체(Sifting) 성질:
단위 계단(Unit Step)
관계가 성립합니다.
1.3 선형 시불변(LTI) 시스템
LTI 시스템은 두 가지 핵심 성질을 만족합니다.
- 선형성(Linearity):
- 시불변성(Time Invariance):
1.4 컨볼루션
LTI 시스템의 출력은 입력과 임펄스 응답의 컨볼루션으로 표현됩니다.
이산시간의 경우:
컨볼루션은 교환법칙, 결합법칙, 분배법칙을 만족합니다.
2. 푸리에 급수 (Fourier Series)
2.1 주기 신호의 푸리에 급수
주기 를 갖는 신호 는 복소 지수 함수의 합으로 표현됩니다. 기본 주파수는 입니다.
푸리에 계수:
2.2 구형파(Square Wave) 예제
진폭 A, 주기 T, 듀티 사이클 50%인 구형파의 푸리에 계수:
홀수 고조파만 존재하며, 고차 고조파일수록 진폭이 감소합니다. 기브스 현상(Gibbs Phenomenon)이 불연속점 근방에서 나타납니다.
2.3 파셀발 정리
시간 영역의 평균 전력과 주파수 영역의 계수 제곱합이 같습니다.
3. 푸리에 변환 (Fourier Transform)
3.1 연속 푸리에 변환 (CTFT)
비주기 신호에 대한 푸리에 변환 쌍:
3.2 중요 변환 쌍
| 신호 | 푸리에 변환 |
|---|---|
| 구형파 |
3.3 푸리에 변환 성질
- 선형성:
- 시간 이동:
- 주파수 이동(변조):
- 컨볼루션 정리:
- 곱셈 정리:
- 미분:
- 파셀발:
3.4 Python으로 푸리에 변환 계산
import numpy as np
from scipy.fft import fft, ifft, fftfreq, fftshift
import matplotlib.pyplot as plt
# 구형파 신호 생성
fs = 1000 # 샘플링 주파수 (Hz)
T = 1.0 # 신호 길이 (초)
t = np.linspace(0, T, int(fs * T), endpoint=False)
# 구형파: 주기 0.1초 (10Hz)
from scipy.signal import square
x = square(2 * np.pi * 10 * t)
# FFT 계산
N = len(x)
X = fft(x)
freqs = fftfreq(N, 1/fs)
# 양측 스펙트럼 (정규화)
magnitude = np.abs(fftshift(X)) / N
freq_shifted = fftshift(freqs)
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(t[:100], x[:100])
plt.title('Square Wave (time domain)')
plt.xlabel('Time (s)')
plt.subplot(1, 2, 2)
plt.plot(freq_shifted, magnitude)
plt.xlim(-100, 100)
plt.title('Fourier Transform (frequency domain)')
plt.xlabel('Frequency (Hz)')
plt.tight_layout()
plt.show()
4. 이산 푸리에 변환 (DFT) & FFT
4.1 이산 시간 푸리에 변환 (DTFT)
이산 시간 신호 의 DTFT:
역변환:
DTFT는 주파수 가 연속적이며 주기를 갖습니다.
4.2 DFT 정의
점 DFT는 DTFT를 개 주파수에서 균등 샘플링한 것입니다.
역 DFT:
4.3 FFT 알고리즘
직접 DFT 계산 복잡도는 이지만, FFT(Cooley-Tukey 알고리즘)는 입니다. 일 때 분할 정복(Divide and Conquer)으로 구현합니다.
회전 인수(Twiddle Factor):
4.4 스펙트럼 분석 예제
import numpy as np
from scipy.fft import fft, fftfreq
import matplotlib.pyplot as plt
# 신호 생성: 50Hz + 120Hz 복합 신호
fs = 1000 # 샘플링 주파수 (Hz)
N = fs # 샘플 수 (1초)
t = np.linspace(0, 1, N, endpoint=False)
# 복합 신호 (노이즈 포함)
signal = (np.sin(2 * np.pi * 50 * t)
+ 0.5 * np.sin(2 * np.pi * 120 * t)
+ 0.2 * np.random.randn(N))
# FFT 계산
yf = fft(signal)
xf = fftfreq(N, 1/fs)
# 단측 스펙트럼 (양수 주파수만)
half = N // 2
amplitude = 2.0 / N * np.abs(yf[:half])
freq_pos = xf[:half]
plt.figure(figsize=(10, 4))
plt.plot(freq_pos, amplitude)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.title('Single-Sided Amplitude Spectrum')
plt.axvline(x=50, color='r', linestyle='--', label='50 Hz')
plt.axvline(x=120, color='g', linestyle='--', label='120 Hz')
plt.legend()
plt.grid(True)
plt.show()
# 주파수 해상도: delta_f = fs / N = 1 Hz
print(f"Frequency resolution: {fs/N} Hz")
print(f"Nyquist frequency: {fs/2} Hz")
4.5 샘플링 정리 (Nyquist-Shannon)
샘플링 주파수 가 신호의 최대 주파수 의 두 배 이상이어야 에일리어싱(Aliasing) 없이 복원 가능합니다.
5. 라플라스 변환 (Laplace Transform)
5.1 정의
양측(Bilateral) 라플라스 변환:
단측(Unilateral) 라플라스 변환:
5.2 중요 변환 쌍
| 신호 | 변환 | 수렴 영역 |
|---|---|---|
| 전체 s-평면 | ||
5.3 전달 함수 (Transfer Function)
LTI 시스템의 입출력 관계를 s-영역에서 표현:
극점(Poles): 가 되는 값 (분모 = 0)
영점(Zeros): 이 되는 값 (분자 = 0)
극점의 위치가 시스템 안정성을 결정합니다. 모든 극점이 좌반 s-평면(LHP)에 있으면 BIBO 안정합니다.
5.4 2차 시스템 표준형
- : 자연 주파수(Natural Frequency)
- : 감쇠비(Damping Ratio)
- : 부족 감쇠(Underdamped) — 진동 응답
- : 임계 감쇠(Critically Damped) — 가장 빠른 무진동
- : 과감쇠(Overdamped) — 느린 무진동
6. Z-변환
6.1 정의
이산시간 신호 의 Z-변환:
(단위 원 위)로 치환하면 DTFT와 동일합니다.
6.2 Z-변환과 라플라스 변환의 관계
연속시간 시스템을 샘플링 주기 로 이산화할 때:
이 관계로 s-평면과 z-평면이 대응됩니다.
- s-평면의 허수축 z-평면의 단위 원
- s-평면의 좌반면 z-평면의 단위 원 내부
6.3 안정성 분석
이산시간 시스템이 안정하려면 모든 극점이 단위 원 내부에 있어야 합니다.
6.4 중요 Z-변환 쌍
| 신호 | Z-변환 |
|---|---|
7. 디지털 필터 설계
7.1 FIR vs IIR 필터
FIR (Finite Impulse Response) 필터
- 임펄스 응답이 유한 길이
- 항상 안정 (피드백 없음)
- 선형 위상 구현 가능
- 급격한 차단 특성을 위해 높은 차수 필요
IIR (Infinite Impulse Response) 필터
- 피드백 포함, 임펄스 응답 무한
- 낮은 차수로 급격한 차단 특성
- 위상 비선형 (위상 왜곡 발생 가능)
- 설계 불량 시 불안정
7.2 필터 유형
- 저역통과 (LPF): 낮은 주파수 통과, 높은 주파수 차단
- 고역통과 (HPF): 높은 주파수 통과, 낮은 주파수 차단
- 대역통과 (BPF): 특정 주파수 대역만 통과
- 대역저지 (BEF/Notch): 특정 주파수 대역 차단
7.3 필터 설계 함수
버터워스(Butterworth): 통과대역에서 최대한 평탄한 응답
체비셰프(Chebyshev) I형: 통과대역에 리플 허용, 더 급격한 차단
타원(Elliptic): 통과대역과 저지대역 모두 리플, 최소 차수로 최대 감쇠
7.4 scipy.signal을 이용한 필터 설계
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
# 샘플링 주파수
fs = 1000 # Hz
# 버터워스 저역통과 필터 (4차, 차단 주파수 100Hz)
nyq = fs / 2
cutoff = 100 / nyq # 정규화된 주파수 (0~1)
b_butter, a_butter = signal.butter(N=4, Wn=cutoff, btype='low')
# 체비셰프 I형 (4차, 1dB 리플, 차단 주파수 100Hz)
b_cheby, a_cheby = signal.cheby1(N=4, rp=1, Wn=cutoff, btype='low')
# 주파수 응답 계산
w, h_butter = signal.freqz(b_butter, a_butter, fs=fs)
w, h_cheby = signal.freqz(b_cheby, a_cheby, fs=fs)
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(w, 20 * np.log10(np.abs(h_butter)), label='Butterworth')
plt.plot(w, 20 * np.log10(np.abs(h_cheby)), label='Chebyshev I')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude (dB)')
plt.title('Filter Frequency Response')
plt.legend()
plt.grid(True)
plt.ylim(-80, 5)
# 노이즈가 낀 신호 필터링
t = np.linspace(0, 1, fs, endpoint=False)
clean = np.sin(2 * np.pi * 50 * t)
noisy = clean + 0.5 * np.sin(2 * np.pi * 300 * t)
filtered = signal.filtfilt(b_butter, a_butter, noisy)
plt.subplot(1, 2, 2)
plt.plot(t[:200], noisy[:200], alpha=0.5, label='Noisy')
plt.plot(t[:200], filtered[:200], label='Filtered')
plt.xlabel('Time (s)')
plt.legend()
plt.title('Filtering Result')
plt.tight_layout()
plt.show()
7.5 FIR 필터 설계 (Window Method)
from scipy.signal import firwin, freqz
# Hamming 윈도우를 사용한 FIR LPF
# 탭 수 = 51, 차단 주파수 = 100Hz
numtaps = 51
cutoff_hz = 100
b_fir = firwin(numtaps, cutoff_hz / (fs/2), window='hamming')
# 주파수 응답
w_fir, h_fir = freqz(b_fir, [1.0], fs=fs)
print(f"FIR filter order: {numtaps - 1}")
print(f"Linear phase: True (symmetric coefficients)")
8. 제어시스템 기초
8.1 개루프 vs 폐루프 제어
개루프(Open-Loop) 제어: 출력이 제어 동작에 영향을 주지 않습니다. 단순하지만 외란이나 모델 오차에 취약합니다.
폐루프(Closed-Loop) 제어: 출력을 측정하여 기준 입력과 비교하고 오차를 최소화합니다. 피드백(Feedback)으로 강인성이 높습니다.
기본 피드백 루프:
여기서 는 플랜트(Plant), 는 센서 전달 함수입니다.
8.2 안정성: 루스-허비츠 기준
특성 방정식 의 근이 모두 좌반 s-평면에 있으면 안정합니다.
루스 배열(Routh Array)을 이용하여 계수만으로 극점 위치를 판별합니다. 첫 열의 부호 변화 횟수가 우반면 극점 수와 같습니다.
8.3 보데 선도 (Bode Plot)
주파수 응답 를 로그 스케일로 표현합니다.
- 이득 선도: [dB] vs
- 위상 선도: [도] vs
안정도 여유:
- 위상 여유(Phase Margin, PM): 이득이 0 dB일 때 위상이 -180도에서 얼마나 여유가 있는지
- 이득 여유(Gain Margin, GM): 위상이 -180도일 때 이득이 0 dB에서 얼마나 여유가 있는지
PM > 45도, GM > 6 dB이면 일반적으로 안정한 시스템으로 봅니다.
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
# 2차 시스템 전달 함수: H(s) = 10 / (s^2 + 2s + 10)
num = [10]
den = [1, 2, 10]
sys = signal.TransferFunction(num, den)
# 보데 선도
w, mag, phase = signal.bode(sys)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6))
ax1.semilogx(w, mag)
ax1.set_ylabel('Magnitude (dB)')
ax1.set_title('Bode Plot')
ax1.grid(True, which='both')
ax2.semilogx(w, phase)
ax2.set_ylabel('Phase (degrees)')
ax2.set_xlabel('Frequency (rad/s)')
ax2.grid(True, which='both')
plt.tight_layout()
plt.show()
9. PID 제어기
9.1 PID 제어 동작
PID 제어기는 세 가지 동작의 합입니다.
여기서 는 오차 신호입니다.
- 비례(P) 제어: 현재 오차에 비례한 제어 출력. 빠른 응답이지만 정상상태 오차 잔존.
- 적분(I) 제어: 누적 오차를 제거하여 정상상태 오차를 0으로. 응답 느려짐.
- 미분(D) 제어: 오차 변화율에 반응하여 오버슈트 억제. 노이즈에 민감.
전달 함수:
9.2 지글러-니콜스 튜닝
방법 1 (개루프 스텝 응답):
공정 응답 곡선에서 지연 시간 과 시정수 를 구한 후:
| 제어기 | |||
|---|---|---|---|
| P | - | - | |
| PI | - | ||
| PID |
방법 2 (폐루프 한계 감도):
으로 놓고 를 증가시켜 지속 진동이 일어나는 임계 이득 와 진동 주기 를 구합니다.
| 제어기 | |||
|---|---|---|---|
| PID |
9.3 Python으로 PID 시뮬레이션
import numpy as np
import matplotlib.pyplot as plt
class PIDController:
def __init__(self, kp, ki, kd, dt):
self.kp = kp
self.ki = ki
self.kd = kd
self.dt = dt
self.integral = 0.0
self.prev_error = 0.0
def update(self, setpoint, measured):
error = setpoint - measured
self.integral += error * self.dt
derivative = (error - self.prev_error) / self.dt
output = self.kp * error + self.ki * self.integral + self.kd * derivative
self.prev_error = error
return output
# 1차 플랜트: dy/dt = -y + u (시정수 1초)
def plant_step(y, u, dt):
return y + dt * (-y + u)
# 시뮬레이션 파라미터
dt = 0.01
t = np.arange(0, 10, dt)
setpoint = 1.0
# PID 게인 설정 (지글러-니콜스 기반 튜닝)
pid = PIDController(kp=2.0, ki=1.0, kd=0.5, dt=dt)
y = 0.0
y_list = []
for _ in t:
u = pid.update(setpoint, y)
u = np.clip(u, -10, 10) # 액추에이터 포화 제한
y = plant_step(y, u, dt)
y_list.append(y)
plt.figure(figsize=(10, 4))
plt.plot(t, y_list, label='Plant Output')
plt.axhline(setpoint, color='r', linestyle='--', label='Setpoint')
plt.xlabel('Time (s)')
plt.ylabel('Output')
plt.title('PID Control Simulation')
plt.legend()
plt.grid(True)
plt.show()
10. 상태 공간 표현 (State Space)
10.1 상태 방정식
연속시간 LTI 시스템의 상태 공간 표현:
- : 상태 벡터 ()
- : 입력 벡터 ()
- : 출력 벡터 ()
- : 시스템 행렬 ()
- : 입력 행렬 ()
- : 출력 행렬 ()
- : 직결 행렬 ()
전달 함수와의 관계:
10.2 가관측성과 가제어성
가제어성(Controllability): 임의의 초기 상태에서 유한 시간 내에 원하는 상태로 이동 가능한가?
가제어성 행렬 의 계수가 이면 완전 가제어.
가관측성(Observability): 출력만으로 초기 상태를 결정 가능한가?
가관측성 행렬 의 계수가 이면 완전 가관측.
10.3 선형 이차 조절기 (LQR)
비용 함수를 최소화하는 최적 상태 피드백 제어:
최적 제어 입력:
는 상태 오차 가중치, 은 제어 입력 에너지 가중치입니다.
import numpy as np
from scipy import linalg
# 이중 적분기 시스템 예제
# x'' = u (2차 시스템)
A = np.array([[0, 1], [0, 0]])
B = np.array([[0], [1]])
C = np.array([[1, 0]])
D = np.array([[0]])
# LQR 가중치
Q = np.diag([10, 1]) # 위치 오차를 더 중요시
R = np.array([[1]])
# 리카티 방정식 풀기
P = linalg.solve_continuous_are(A, B, Q, R)
K = np.linalg.inv(R) @ B.T @ P
print("LQR Gain K:", K)
print("Closed-loop poles:", np.linalg.eigvals(A - B @ K))
11. AI/ML과 신호처리
11.1 CNN for 1D Signal
1D 합성곱 신경망은 ECG, 지진 신호, 음성 등 시간 시리즈 신호의 패턴 인식에 뛰어납니다.
import torch
import torch.nn as nn
class Signal1DCNN(nn.Module):
def __init__(self, num_classes=5):
super().__init__()
self.conv_layers = nn.Sequential(
nn.Conv1d(1, 32, kernel_size=7, padding=3),
nn.BatchNorm1d(32),
nn.ReLU(),
nn.MaxPool1d(2),
nn.Conv1d(32, 64, kernel_size=5, padding=2),
nn.BatchNorm1d(64),
nn.ReLU(),
nn.MaxPool1d(2),
nn.Conv1d(64, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.AdaptiveAvgPool1d(8)
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(128 * 8, 256),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(256, num_classes)
)
def forward(self, x):
x = self.conv_layers(x)
return self.classifier(x)
# 사용 예시
model = Signal1DCNN(num_classes=5)
# 입력 형태: (batch_size, channels=1, sequence_length=1000)
x = torch.randn(8, 1, 1000)
output = model(x)
print("Output shape:", output.shape) # (8, 5)
11.2 STFT와 Mel-Spectrogram
음성 AI에서는 신호를 시간-주파수 표현으로 변환한 후 CNN으로 처리하는 방법이 널리 사용됩니다.
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
# 오디오 로드
# y, sr = librosa.load('audio.wav', sr=22050)
# STFT (Short-Time Fourier Transform)
# D = librosa.stft(y)
# S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)
# Mel-Spectrogram
# mel_spec = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128)
# mel_db = librosa.power_to_db(mel_spec, ref=np.max)
# MFCC (Mel-Frequency Cepstral Coefficients)
# mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
print("STFT window: Hann window, hop_length=512, n_fft=2048")
print("Mel-filterbank: 128 mel bands, 0Hz ~ Nyquist")
print("MFCC: 13 coefficients commonly used for speech recognition")
11.3 신호처리 + 딥러닝 응용 사례
- ECG 부정맥 분류: 1D CNN + LSTM으로 심장 리듬 이상 감지
- 이상 진동 감지: FFT 특징 추출 후 오토인코더로 이상 탐지
- 음성 인식: MFCC + Transformer (Whisper, wav2vec 2.0)
- 지진 감지: 지진계 신호의 P파/S파 자동 분류
- 뇌파(EEG) 분석: 주파수 대역별 파워 스펙트럼으로 집중도/수면 상태 분류
12. 퀴즈
Q1. 샘플링 주파수가 8000 Hz인 시스템에서 에일리어싱 없이 표현할 수 있는 최대 신호 주파수는?
정답: 4000 Hz
해설: 나이퀴스트-섀넌 샘플링 정리에 의해 샘플링 주파수의 절반인 나이퀴스트 주파수(4000 Hz)가 에일리어싱 없이 표현 가능한 최대 주파수입니다. 전화 음성 코덱(8 kHz 샘플링)이 최대 4 kHz 음성을 처리하는 이유가 이것입니다.
Q2. FIR 필터가 IIR 필터에 비해 갖는 가장 큰 장점은 무엇인가?
정답: 선형 위상 특성과 무조건적 안정성
해설: FIR 필터는 피드백이 없으므로 항상 BIBO 안정합니다. 또한 계수를 대칭으로 설계하면 선형 위상(linear phase)을 보장하여 모든 주파수 성분의 지연이 동일합니다. 이는 위상 왜곡이 허용되지 않는 데이터 통신 등에서 중요합니다. 반면 IIR 필터는 낮은 차수로 급격한 차단 특성을 얻을 수 있다는 장점이 있습니다.
Q3. PID 제어기에서 미분(D) 동작의 역할과 단점은?
정답: 오차의 변화율에 반응하여 오버슈트를 억제하지만, 측정 노이즈에 매우 민감합니다.
해설: D 동작은 오차가 빠르게 변화할 때 강한 제어 출력을 생성하여 시스템이 목표값을 지나치는 현상(오버슈트)을 억제합니다. 그러나 노이즈가 있는 측정값을 미분하면 노이즈가 증폭됩니다. 실용적 PID에서는 미분 필터(low-pass filter on derivative term)를 추가하거나, 출력을 직접 미분하는 Derivative on Measurement 방식을 사용합니다.
Q4. Z-변환에서 디지털 필터의 안정성 조건은?
정답: 모든 극점(poles)이 z-평면의 단위 원 내부에 위치해야 합니다.
해설: 이산시간 시스템의 극점 위치와 안정성의 관계: 단위 원 내부(절댓값 1 미만)이면 안정, 단위 원 위이면 임계 안정, 단위 원 외부이면 불안정합니다. 이는 연속시간에서 극점이 s-평면의 좌반면에 있어야 안정한 것과 대응됩니다. z = exp(sT) 변환에서 좌반면이 단위 원 내부로 매핑됩니다.
Q5. 보데 선도에서 위상 여유(Phase Margin)가 음수라면 시스템은?
정답: 불안정(Unstable)합니다.
해설: 위상 여유는 이득 교차 주파수(gain crossover frequency, 이득이 0 dB인 주파수)에서의 위상이 -180도에서 얼마나 떨어져 있는지를 나타냅니다. 위상 여유가 음수이면 이득이 0 dB일 때 위상이 이미 -180도를 지나쳤다는 의미로, 폐루프 시스템이 불안정합니다. 일반적으로 안정하고 좋은 응답 특성을 위해 PM은 45도 ~ 60도를 목표로 설계합니다.
참고 문헌
- Oppenheim, A. V. & Schafer, R. W. — Discrete-Time Signal Processing (3rd ed.), Prentice Hall, 2010
- Ogata, K. — Modern Control Engineering (5th ed.), Prentice Hall, 2010
- Proakis, J. G. & Manolakis, D. G. — Digital Signal Processing, Prentice Hall, 2007
- SciPy Signal Processing Documentation — https://docs.scipy.org/doc/scipy/reference/signal.html
- MIT OpenCourseWare 6.003 — Signals and Systems — https://ocw.mit.edu/courses/6-003-signals-and-systems-fall-2011/
- NumPy FFT 문서 — https://numpy.org/doc/stable/reference/routines.fft.html
Signal Processing & Control Systems Guide: From Fourier Transform to PID Control
- 1. Signals and Systems Fundamentals
- 2. Fourier Series
- 3. Fourier Transform
- 4. Discrete Fourier Transform (DFT) & FFT
- 5. Laplace Transform
- 6. Z-Transform
- 7. Digital Filter Design
- 8. Control Systems Fundamentals
- 9. PID Controller
- 10. State-Space Representation
- 11. AI/ML and Signal Processing
- 12. Quiz
- References
1. Signals and Systems Fundamentals
1.1 Signal Classification
A signal is a physical quantity that carries information. The primary classifications are:
Continuous-Time vs Discrete-Time Signals
Continuous-time (CT) signals are defined for all . Example: an analog audio signal
Discrete-time (DT) signals are defined only at integer indices . Example: a digital audio sample sequence
Energy and Power Signals
Signal energy and average power :
If , the signal is an energy signal. If , it is a power signal.
1.2 Elementary Signals
Unit Impulse
Sifting property:
Unit Step
The relationship holds.
1.3 Linear Time-Invariant (LTI) Systems
An LTI system satisfies two core properties:
- Linearity:
- Time Invariance:
1.4 Convolution
The output of an LTI system is the convolution of the input and the impulse response.
For discrete-time:
Convolution satisfies the commutative, associative, and distributive laws.
2. Fourier Series
2.1 Fourier Series of Periodic Signals
A periodic signal with period can be expressed as a sum of complex exponentials with fundamental frequency :
Fourier coefficients:
2.2 Square Wave Example
For a square wave with amplitude A, period T, and 50% duty cycle:
Only odd harmonics are present, and amplitude decreases with increasing harmonic order. The Gibbs phenomenon appears near discontinuities.
2.3 Parseval's Theorem
The average power in the time domain equals the sum of squared coefficients in the frequency domain.
3. Fourier Transform
3.1 Continuous-Time Fourier Transform (CTFT)
The Fourier transform pair for aperiodic signals:
3.2 Important Transform Pairs
| Signal | Fourier Transform |
|---|---|
3.3 Fourier Transform Properties
- Linearity:
- Time Shift:
- Frequency Shift (Modulation):
- Convolution Theorem:
- Multiplication Theorem:
- Differentiation:
- Parseval's:
3.4 Computing Fourier Transforms with Python
import numpy as np
from scipy.fft import fft, ifft, fftfreq, fftshift
import matplotlib.pyplot as plt
# Generate a square wave signal
fs = 1000 # Sampling frequency (Hz)
T = 1.0 # Signal duration (s)
t = np.linspace(0, T, int(fs * T), endpoint=False)
from scipy.signal import square
x = square(2 * np.pi * 10 * t) # 10 Hz square wave
# Compute FFT
N = len(x)
X = fft(x)
freqs = fftfreq(N, 1/fs)
# Two-sided spectrum (normalized)
magnitude = np.abs(fftshift(X)) / N
freq_shifted = fftshift(freqs)
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(t[:100], x[:100])
plt.title('Square Wave (time domain)')
plt.xlabel('Time (s)')
plt.subplot(1, 2, 2)
plt.plot(freq_shifted, magnitude)
plt.xlim(-100, 100)
plt.title('Fourier Transform (frequency domain)')
plt.xlabel('Frequency (Hz)')
plt.tight_layout()
plt.show()
4. Discrete Fourier Transform (DFT) & FFT
4.1 Discrete-Time Fourier Transform (DTFT)
The DTFT of a discrete-time signal :
Inverse transform:
The DTFT has continuous frequency and is periodic with period .
4.2 DFT Definition
The N-point DFT is a uniform sampling of the DTFT at N frequencies:
Inverse DFT:
4.3 The FFT Algorithm
Direct DFT computation has complexity , but the FFT (Cooley-Tukey algorithm) achieves using divide-and-conquer when .
Twiddle factor:
4.4 Spectrum Analysis Example
import numpy as np
from scipy.fft import fft, fftfreq
import matplotlib.pyplot as plt
# Generate a composite signal: 50 Hz + 120 Hz
fs = 1000 # Sampling frequency (Hz)
N = fs # Number of samples (1 second)
t = np.linspace(0, 1, N, endpoint=False)
# Composite signal with noise
signal = (np.sin(2 * np.pi * 50 * t)
+ 0.5 * np.sin(2 * np.pi * 120 * t)
+ 0.2 * np.random.randn(N))
# Compute FFT
yf = fft(signal)
xf = fftfreq(N, 1/fs)
# Single-sided spectrum (positive frequencies only)
half = N // 2
amplitude = 2.0 / N * np.abs(yf[:half])
freq_pos = xf[:half]
plt.figure(figsize=(10, 4))
plt.plot(freq_pos, amplitude)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.title('Single-Sided Amplitude Spectrum')
plt.axvline(x=50, color='r', linestyle='--', label='50 Hz')
plt.axvline(x=120, color='g', linestyle='--', label='120 Hz')
plt.legend()
plt.grid(True)
plt.show()
# Frequency resolution = fs / N = 1 Hz
print(f"Frequency resolution: {fs/N} Hz")
print(f"Nyquist frequency: {fs/2} Hz")
4.5 Nyquist-Shannon Sampling Theorem
To reconstruct a signal without aliasing, the sampling frequency must be at least twice the maximum signal frequency :
5. Laplace Transform
5.1 Definition
Bilateral Laplace transform:
Unilateral (one-sided) Laplace transform:
5.2 Important Transform Pairs
| Signal | Transform | ROC |
|---|---|---|
| Entire s-plane | ||
5.3 Transfer Function
The input-output relationship in the s-domain:
Poles: values of where (denominator = 0)
Zeros: values of where (numerator = 0)
Pole locations determine system stability. A system is BIBO stable if all poles lie in the left half of the s-plane (LHP).
5.4 Standard Second-Order System
- : Natural frequency
- : Damping ratio
- : Underdamped — oscillatory response
- : Critically damped — fastest non-oscillatory
- : Overdamped — slow non-oscillatory
6. Z-Transform
6.1 Definition
The Z-transform of a discrete-time signal :
Substituting (on the unit circle) reduces to the DTFT.
6.2 Relationship Between Z-Transform and Laplace Transform
When a continuous-time system is discretized with sampling period :
This maps the s-plane to the z-plane:
- Imaginary axis of s-plane unit circle in z-plane
- Left half of s-plane interior of unit circle in z-plane
6.3 Stability Analysis
A discrete-time system is stable if and only if all poles lie inside the unit circle:
6.4 Important Z-Transform Pairs
| Signal | Z-Transform |
|---|---|
7. Digital Filter Design
7.1 FIR vs IIR Filters
FIR (Finite Impulse Response) Filter
- Finite-length impulse response
- Always stable (no feedback)
- Can achieve linear phase
- Requires high order for sharp cutoff
IIR (Infinite Impulse Response) Filter
- Includes feedback, infinite impulse response
- Sharp cutoff at lower order
- Nonlinear phase (potential phase distortion)
- Can become unstable if poorly designed
7.2 Filter Types
- Low-Pass Filter (LPF): Passes low frequencies, attenuates high frequencies
- High-Pass Filter (HPF): Passes high frequencies, attenuates low frequencies
- Band-Pass Filter (BPF): Passes a specific frequency band
- Band-Stop Filter (BSF/Notch): Attenuates a specific frequency band
7.3 Classical Filter Designs
Butterworth: Maximally flat response in the passband
Chebyshev Type I: Ripple in passband, sharper rolloff
Elliptic: Ripple in both passband and stopband, minimum order for given attenuation
7.4 Filter Design with scipy.signal
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
fs = 1000 # Sampling frequency (Hz)
# Butterworth low-pass filter (order 4, cutoff 100 Hz)
nyq = fs / 2
cutoff = 100 / nyq # Normalized frequency (0 to 1)
b_butter, a_butter = signal.butter(N=4, Wn=cutoff, btype='low')
# Chebyshev Type I (order 4, 1 dB ripple, cutoff 100 Hz)
b_cheby, a_cheby = signal.cheby1(N=4, rp=1, Wn=cutoff, btype='low')
# Frequency response
w, h_butter = signal.freqz(b_butter, a_butter, fs=fs)
w, h_cheby = signal.freqz(b_cheby, a_cheby, fs=fs)
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(w, 20 * np.log10(np.abs(h_butter)), label='Butterworth')
plt.plot(w, 20 * np.log10(np.abs(h_cheby)), label='Chebyshev I')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude (dB)')
plt.title('Filter Frequency Response')
plt.legend()
plt.grid(True)
plt.ylim(-80, 5)
# Filter a noisy signal
t = np.linspace(0, 1, fs, endpoint=False)
clean = np.sin(2 * np.pi * 50 * t)
noisy = clean + 0.5 * np.sin(2 * np.pi * 300 * t)
filtered = signal.filtfilt(b_butter, a_butter, noisy)
plt.subplot(1, 2, 2)
plt.plot(t[:200], noisy[:200], alpha=0.5, label='Noisy')
plt.plot(t[:200], filtered[:200], label='Filtered')
plt.xlabel('Time (s)')
plt.legend()
plt.title('Filtering Result')
plt.tight_layout()
plt.show()
7.5 FIR Filter Design (Window Method)
from scipy.signal import firwin, freqz
# FIR LPF using Hamming window
# 51 taps, cutoff 100 Hz
numtaps = 51
cutoff_hz = 100
b_fir = firwin(numtaps, cutoff_hz / (fs / 2), window='hamming')
w_fir, h_fir = freqz(b_fir, [1.0], fs=fs)
print(f"FIR filter order: {numtaps - 1}")
print(f"Linear phase: True (symmetric coefficients)")
8. Control Systems Fundamentals
8.1 Open-Loop vs Closed-Loop Control
Open-Loop Control: The output does not feed back to affect the control action. Simple but sensitive to disturbances and model errors.
Closed-Loop Control: The output is measured and compared with the reference; the error drives the controller. Feedback provides robustness.
Basic feedback loop transfer function:
where is the plant and is the sensor transfer function.
8.2 Stability: Routh-Hurwitz Criterion
A system is stable if all roots of the characteristic equation lie in the left half s-plane (LHP).
The Routh array determines pole locations from coefficients alone. The number of sign changes in the first column equals the number of right-half-plane poles.
8.3 Bode Plot
The frequency response plotted on a logarithmic scale:
- Magnitude plot: [dB] vs
- Phase plot: [degrees] vs
Stability margins:
- Phase Margin (PM): How far the phase is from -180 degrees when the gain is 0 dB
- Gain Margin (GM): How far the gain is from 0 dB when the phase is -180 degrees
PM > 45 degrees and GM > 6 dB are generally considered acceptable stability margins.
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
# Second-order transfer function: H(s) = 10 / (s^2 + 2s + 10)
num = [10]
den = [1, 2, 10]
sys = signal.TransferFunction(num, den)
w, mag, phase = signal.bode(sys)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6))
ax1.semilogx(w, mag)
ax1.set_ylabel('Magnitude (dB)')
ax1.set_title('Bode Plot')
ax1.grid(True, which='both')
ax2.semilogx(w, phase)
ax2.set_ylabel('Phase (degrees)')
ax2.set_xlabel('Frequency (rad/s)')
ax2.grid(True, which='both')
plt.tight_layout()
plt.show()
9. PID Controller
9.1 PID Control Action
A PID controller combines three control actions:
where is the error signal.
- Proportional (P): Control output proportional to current error. Fast response but leaves steady-state error.
- Integral (I): Eliminates accumulated error to drive steady-state error to zero. Slows response.
- Derivative (D): Reacts to rate of change of error, suppressing overshoot. Sensitive to noise.
Transfer function:
9.2 Ziegler-Nichols Tuning
Method 1 (Open-loop step response):
Determine dead time and time constant from the process reaction curve:
| Controller | |||
|---|---|---|---|
| P | - | - | |
| PI | - | ||
| PID |
Method 2 (Closed-loop ultimate gain):
Set . Increase until sustained oscillation occurs. Record ultimate gain and period :
| Controller | |||
|---|---|---|---|
| PID |
9.3 PID Simulation in Python
import numpy as np
import matplotlib.pyplot as plt
class PIDController:
def __init__(self, kp, ki, kd, dt):
self.kp = kp
self.ki = ki
self.kd = kd
self.dt = dt
self.integral = 0.0
self.prev_error = 0.0
def update(self, setpoint, measured):
error = setpoint - measured
self.integral += error * self.dt
derivative = (error - self.prev_error) / self.dt
output = self.kp * error + self.ki * self.integral + self.kd * derivative
self.prev_error = error
return output
# First-order plant: dy/dt = -y + u (time constant = 1s)
def plant_step(y, u, dt):
return y + dt * (-y + u)
dt = 0.01
t = np.arange(0, 10, dt)
setpoint = 1.0
pid = PIDController(kp=2.0, ki=1.0, kd=0.5, dt=dt)
y = 0.0
y_list = []
for _ in t:
u = pid.update(setpoint, y)
u = np.clip(u, -10, 10) # actuator saturation
y = plant_step(y, u, dt)
y_list.append(y)
plt.figure(figsize=(10, 4))
plt.plot(t, y_list, label='Plant Output')
plt.axhline(setpoint, color='r', linestyle='--', label='Setpoint')
plt.xlabel('Time (s)')
plt.ylabel('Output')
plt.title('PID Control Simulation')
plt.legend()
plt.grid(True)
plt.show()
10. State-Space Representation
10.1 State Equations
State-space representation of a continuous-time LTI system:
- : state vector ()
- : input vector ()
- : output vector ()
- : system matrix ()
- : input matrix ()
- : output matrix ()
- : feedthrough matrix ()
Relationship to transfer function:
10.2 Controllability and Observability
Controllability: Can the state be driven from any initial condition to any desired state in finite time?
The controllability matrix must have rank for full controllability.
Observability: Can the initial state be determined from the output alone?
The observability matrix must have rank for full observability.
10.3 Linear Quadratic Regulator (LQR)
Optimal state feedback that minimizes a quadratic cost function:
Optimal control:
weights state error; weights control energy.
import numpy as np
from scipy import linalg
# Double integrator: x_ddot = u
A = np.array([[0, 1], [0, 0]])
B = np.array([[0], [1]])
# LQR weights: penalize position error more
Q = np.diag([10, 1])
R = np.array([[1]])
# Solve continuous algebraic Riccati equation
P = linalg.solve_continuous_are(A, B, Q, R)
K = np.linalg.inv(R) @ B.T @ P
print("LQR Gain K:", K)
print("Closed-loop poles:", np.linalg.eigvals(A - B @ K))
11. AI/ML and Signal Processing
11.1 CNN for 1D Signals
1D convolutional neural networks excel at pattern recognition in time-series signals such as ECG, seismic data, and audio.
import torch
import torch.nn as nn
class Signal1DCNN(nn.Module):
def __init__(self, num_classes=5):
super().__init__()
self.conv_layers = nn.Sequential(
nn.Conv1d(1, 32, kernel_size=7, padding=3),
nn.BatchNorm1d(32),
nn.ReLU(),
nn.MaxPool1d(2),
nn.Conv1d(32, 64, kernel_size=5, padding=2),
nn.BatchNorm1d(64),
nn.ReLU(),
nn.MaxPool1d(2),
nn.Conv1d(64, 128, kernel_size=3, padding=1),
nn.ReLU(),
nn.AdaptiveAvgPool1d(8)
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(128 * 8, 256),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(256, num_classes)
)
def forward(self, x):
x = self.conv_layers(x)
return self.classifier(x)
# Example usage
model = Signal1DCNN(num_classes=5)
# Input shape: (batch_size, channels=1, sequence_length=1000)
x = torch.randn(8, 1, 1000)
output = model(x)
print("Output shape:", output.shape) # (8, 5)
11.2 STFT and Mel-Spectrogram
Speech AI systems commonly convert signals to time-frequency representations and process them with CNNs.
import librosa
import numpy as np
# STFT (Short-Time Fourier Transform)
# D = librosa.stft(y)
# S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)
# Mel-Spectrogram
# mel_spec = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128)
# mel_db = librosa.power_to_db(mel_spec, ref=np.max)
# MFCC (Mel-Frequency Cepstral Coefficients)
# mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
print("STFT: Hann window, hop_length=512, n_fft=2048")
print("Mel-filterbank: 128 mel bands, 0 Hz to Nyquist")
print("MFCC: 13 coefficients commonly used for speech recognition")
11.3 Signal Processing + Deep Learning Applications
- ECG Arrhythmia Classification: 1D CNN + LSTM for detecting cardiac rhythm abnormalities
- Anomalous Vibration Detection: FFT feature extraction followed by autoencoder-based anomaly detection
- Speech Recognition: MFCC + Transformer architectures (Whisper, wav2vec 2.0)
- Seismic Event Detection: Automatic P-wave/S-wave classification from seismometer signals
- EEG Analysis: Frequency-band power spectrum for attention/sleep state classification
12. Quiz
Q1. Given a sampling frequency of 8000 Hz, what is the maximum signal frequency that can be represented without aliasing?
Answer: 4000 Hz
Explanation: By the Nyquist-Shannon sampling theorem, the maximum representable frequency is half the sampling frequency — the Nyquist frequency (4000 Hz). This is exactly why telephone voice codecs (8 kHz sampling) handle audio up to 4 kHz.
Q2. What is the most important advantage of FIR filters over IIR filters?
Answer: Linear phase response and unconditional stability.
Explanation: FIR filters have no feedback, so they are always BIBO stable. Symmetric coefficients guarantee linear phase, meaning all frequency components experience the same group delay. This is critical in data communications where phase distortion must be avoided. IIR filters, by contrast, achieve sharp cutoff at much lower filter orders.
Q3. What is the role of the derivative (D) action in a PID controller, and what is its main drawback?
Answer: The D term reacts to the rate of change of error to suppress overshoot, but it amplifies measurement noise.
Explanation: The D action generates a strong control output when the error changes rapidly, preventing the system from overshooting the setpoint. However, differentiating a noisy measurement amplifies high-frequency noise. Practical implementations add a low-pass filter on the derivative term, or use derivative-on-measurement (differentiating the output rather than the error) to mitigate this problem.
Q4. What is the stability condition for a digital filter stated in terms of the Z-transform?
Answer: All poles must lie strictly inside the unit circle in the z-plane.
Explanation: For a discrete-time system: poles inside the unit circle (magnitude less than 1) imply stability; poles on the unit circle imply marginal stability; poles outside the unit circle imply instability. This mirrors the continuous-time condition that all poles must be in the left half s-plane. Under the mapping z = exp(sT), the left half s-plane maps exactly to the interior of the unit circle.
Q5. If the phase margin of a closed-loop control system is negative, what can you conclude about the system?
Answer: The system is unstable.
Explanation: Phase margin is measured at the gain crossover frequency (where gain = 0 dB). A negative phase margin means the phase has already passed -180 degrees before the gain drops to 0 dB, causing the closed-loop system to be unstable. Well-designed systems typically target a phase margin of 45 to 60 degrees and a gain margin greater than 6 dB.
References
- Oppenheim, A. V. & Schafer, R. W. — Discrete-Time Signal Processing (3rd ed.), Prentice Hall, 2010
- Ogata, K. — Modern Control Engineering (5th ed.), Prentice Hall, 2010
- Proakis, J. G. & Manolakis, D. G. — Digital Signal Processing, Prentice Hall, 2007
- SciPy Signal Processing Documentation — https://docs.scipy.org/doc/scipy/reference/signal.html
- MIT OpenCourseWare 6.003 — Signals and Systems — https://ocw.mit.edu/courses/6-003-signals-and-systems-fall-2011/
- NumPy FFT Documentation — https://numpy.org/doc/stable/reference/routines.fft.html