空氣力學
- 卡爾曼濾波器 (Kalman Filter) 白話文與實戰
- 自動化參數掃描 (Parameter Sweeping 迴圈)
- 牽引力控制核心:Pacejka 魔術公式 (Magic Formula) 解析
- 傅立葉轉換 (FFT) 白話文與頻譜分析實戰
- 無線電系統概述
- 經典頻率濾波器 (低通、高通、帶通) 實戰速查表
- Simulink 檔案格式轉換 (.mdl 轉 .slx)
卡爾曼濾波器 (Kalman Filter) 白話文與實戰
卡爾曼濾波器不是硬體,而是一套**「結合數學預測與感測器測量,找出最優解」**的演算法。
1. 白話情境:開車過隧道 (GPS 雜訊 vs. 時速表)
想像你正在開車,你想知道自己「精確的位置」。你手上有兩個資訊來源:
- 你的油門與時速表 (數學預測 / 物理模型): 你知道自己前一秒在哪,也知道現在時速 60 km/h,所以你可以「猜」出自己現在大概在哪。但如果剛好遇到逆風或上坡,這個預測就不太準。
- 車上的 GPS (感測器測量): GPS 會告訴你座標,但它有雜訊,可能會有 $\pm 5$ 公尺的誤差。
卡爾曼濾波器在做什麼? 當你開進隧道(GPS 訊號變弱,雜訊超大),它會選擇相信你的時速表預測多一點;當你開在空曠的高速公路(GPS 超準),它會選擇相信 GPS 多一點。 它透過一個叫做**「卡爾曼增益 (Kalman Gain)」**的比例,不斷在這兩者之間抓平衡,算出一個比單看 GPS 或單看時速表都還要準確的「真實位置」。
2. 核心運作邏輯:預測 (Predict) 與 更新 (Update)
卡爾曼濾波器永遠在做這兩件事的無限迴圈:
- 預測 (Predict)「看未來」: 根據上一秒的狀態和物理公式,猜測現在的狀態。同時也會估算這次「猜測的誤差有多大」。
- 更新 (Update)「面對現實」: 拿到感測器熱騰騰的數據後,把「猜測值」跟「測量值」做加權平均(權重就是卡爾曼增益)。
3. 卡爾曼濾波器的 5 條神聖方程式
雖然看起來很可怕,但只要知道它們對應的意義,寫程式時照抄即可。這裡使用的是矩陣形式(因為通常會同時計算位置、速度等多個變數)。
➡️ 步驟一:預測 (Predict)
- 狀態預測 (猜測現在位置): $$\hat{x}{k}^{-} = A \hat{x}{k-1} + B u_k$$
- 誤差協方差預測 (猜測的不確定性有多大): $$P_{k}^{-} = A P_{k-1} A^T + Q$$ (註:$Q$ 代表系統模型本身的雜訊,也就是你對物理公式的不信任程度)
➡️ 步驟二:更新 (Update)
- 計算卡爾曼增益 (決定要相信模型還是感測器): $$K_k = P_{k}^{-} H^T (H P_{k}^{-} H^T + R)^{-1}$$ (註:$R$ 代表感測器的測量雜訊,也就是你對儀器的不信任程度)
- 狀態更新 (算出最終的最優估計值): $$\hat{x}k = \hat{x}{k}^{-} + K_k (z_k - H \hat{x}_{k}^{-})$$
- 誤差協方差更新 (更新當前的不確定性,留給下一回合用): $$P_k = (I - K_k H) P_{k}^{-}$$
4. MATLAB 1D 實戰:過濾超晃的感測器雜訊
我們來寫一個最簡單的 1D 範例(純量,不用矩陣)。假設我們正在測量一個恆定電壓(真實值是 1.2V),但電壓表的雜訊非常大,看看卡爾曼濾波器怎麼把它壓平!
% 1. 基本設定
N = 100; % 模擬 100 個時間點
true_voltage = 1.2; % 真實電壓 (我們假裝不知道)
measured_v = true_voltage + 0.1 * randn(1, N); % 加入常態分佈雜訊的測量值
% 2. 初始化卡爾曼濾波器變數
x_est = 0; % 初始猜測的狀態 (隨便猜一個 0)
P = 1; % 初始的不確定性 (設 1 代表很不確定)
% 兩個魔法調音旋鈕:Q 和 R
Q = 1e-5; % 過程雜訊 (我們相信電壓是恆定的,所以設很小)
R = 0.01; % 測量雜訊 (我們知道電壓表很爛,雜訊大概是 0.1^2)
% 準備陣列來存畫圖用的資料
kalman_result = zeros(1, N);
% 3. 開始卡爾曼濾波器迴圈 (Predict -> Update)
for k = 1:N
% --- [預測階段 Predict] ---
% 因為是測量恆定電壓,沒有控制力輸入,也沒有物理移動,所以 A=1, B=0
x_pred = x_est; % 預測下一個狀態跟現在一樣
P_pred = P + Q; % 預測不確定性增加一點點
% --- [更新階段 Update] ---
% 拿到最新的測量值 z_k
z_k = measured_v(k);
% 計算卡爾曼增益 (H=1)
K = P_pred / (P_pred + R);
% 更新最優估計狀態
x_est = x_pred + K * (z_k - x_pred);
% 更新不確定性
P = (1 - K) * P_pred;
% 存起來準備畫圖
kalman_result(k) = x_est;
end
% 4. 畫圖比較
figure;
hold on;
plot(1:N, true_voltage * ones(1,N), 'g-', 'LineWidth', 2); % 真實值 (綠線)
plot(1:N, measured_v, 'r.', 'MarkerSize', 10); % 測量值 (紅點)
plot(1:N, kalman_result, 'b-', 'LineWidth', 2); % 卡爾曼濾波結果 (藍線)
hold off;
title('卡爾曼濾波器 1D 電壓測量實戰');
xlabel('時間步長');
ylabel('電壓 (V)');
legend('真實值', '感測器測量值 (含雜訊)', '卡爾曼濾波後的最優估計');
grid on;
自動化參數掃描 (Parameter Sweeping 迴圈)
自動化參數掃描 (Parameter Sweeping 迴圈)
當你需要測試同一組模型,但想觀察某個參數(例如 Kp)在不同數值下的變化時,使用 for 迴圈是最高效的作法。
% 1. 準備工作
Kp_values = [0.5, 1.0, 1.5, 2.0, 2.5]; % 設定你想測試的 5 組 Kp 數值
num_tests = length(Kp_values); % 計算總共要跑幾次 (這裡會是 5)
% 2. 開啟畫布並鎖定
figure;
hold on; % 鎖定畫布,讓接下來迴圈裡的每一條線都畫在同一張圖上
% 3. 準備一個空的陣列來裝圖例名稱 (進階美化技巧)
legend_labels = cell(1, num_tests);
% 4. 開始自動化迴圈
for i = 1:num_tests
% (A) 更新參數
Kp = Kp_values(i); % 把現在要測的數值丟給 Kp
% (B) 執行模擬 (限制步長確保畫圖平滑)
out = sim('my_model', 'MaxStep', '0.01');
% (C) 抓取資料
t = out.tout;
y = out.sim_result;
% (D) 畫上這一回合的線
plot(t, y, 'LineWidth', 1.5);
% (E) 記錄這條線的名字,等一下給圖例 (Legend) 使用
legend_labels{i} = ['Kp = ', num2str(Kp)];
end
% 5. 迴圈結束後,進行圖表美化
hold off; % 解除鎖定
title('不同 Kp 參數之系統響應掃描');
xlabel('時間 (s)');
ylabel('系統輸出');
legend(legend_labels); % 自動貼上我們剛剛在迴圈裡準備好的標籤名稱!
grid on;
% 6. 自動存檔 (可選)
exportgraphics(gcf, 'Kp_Sweep_Result.png', 'Resolution', 300);
💡 程式碼亮點解析: hold on 放外面:這非常重要!如果你把 hold on 寫在迴圈裡面,有時候 MATLAB 會傻掉。放在迴圈外面,就像是先在桌上釘好一張圖畫紙,然後迴圈裡的每次 plot 就是拿不同顏色的筆在上面畫畫。
num2str(Kp):這是一個超實用的函數。因為 Kp 是數字,但圖例 (legend) 只能吃「文字字串」。所以我們用 num2str 把數字變成文字,這樣圖標就會自動顯示 Kp = 0.5, Kp = 1.0 等等,非常聰明!
將模擬數據匯出至 Excel (Export to Excel)
跑完 Simulink 後,如果想把時間軸(Time)和數據(Data)存成 .xlsx 檔,最專業的做法是先將資料轉成「表格 (Table)」,再加上欄位名稱,最後匯出。
% 1. 確保你已經從 out 物件中抓出數據
t = out.tout; % 時間資料 (假設是 1000x1 的直行陣列)
y = out.sim_result; % 模擬數據 (假設是 1000x1 的直行陣列)
% 2. 將時間與數據合併成一個大的矩陣 (用中括號 [ ] 並排)
% 注意:t 和 y 必須都是「直行 (Column vector)」,長度要一樣!
data_matrix = [t, y];
% 3. 將矩陣轉換成 Table 格式,並設定 Excel 的欄位名稱 (標題)
% 假設第一欄叫 'Time_sec',第二欄叫 'Motor_Speed_RPM'
T = array2table(data_matrix, 'VariableNames', {'Time_sec', 'Motor_Speed_RPM'});
% 4. 寫入 Excel 檔案
% 第一個參數是剛建立的表格 T,第二個參數是你想要的檔名
writetable(T, 'My_Simulation_Data.xlsx');
disp('✅ 資料已成功存入 Excel!');
💡 進階技巧:把迴圈掃描的結果存到「不同的工作表 (Sheet)」裡
如果你結合了前面的 for 迴圈(參數掃描),你可以利用 Sheet 屬性,把不同參數的結果存在同一個 Excel 檔案的不同分頁裡!
% 假設這段寫在迴圈裡,i 是迴圈的計數器,Kp 是當前的參數
sheet_name = ['Kp_', num2str(Kp)]; % 自動生成分頁名稱,例如 'Kp_1.5'
% 將數據寫入指定的 Sheet
writetable(T, 'Kp_Sweep_Data.xlsx', 'Sheet', sheet_name);
牽引力控制核心:Pacejka 魔術公式 (Magic Formula) 解析
牽引力控制核心:Pacejka 魔術公式 (Magic Formula) 解析
這是一個非常核心且內行的問題!在 FSAE 或是任何高階車輛動態控制(ABS、TC、ESC)領域,Pacejka 輪胎模型(俗稱魔術公式 Magic Formula, MF)絕對是繞不開的「聖經級」模型。
既然你正在做牽引力控制(TC),理解輪胎如何把馬達的扭矩轉換成推動車身的力,是最基礎也最重要的一步。以下幫你把這個模型拆解成容易咀嚼的重點:
1. 什麼是 Pacejka 魔術公式?
由荷蘭學者 Hans B. Pacejka 提出,它是一個半經驗模型(Semi-empirical Model)。
意思是:它並不是從嚴格的物理摩擦學推導出來的,而是拿著大量在測試機台(例如 FSAE 常用的 TTC 輪胎測試數據)上跑出來的數據,用一組巧妙的三角函數去「硬配適(Curve Fitting)」出來的曲線。
因為這組公式不僅能極度精準地擬合出輪胎的真實反應,而且曲線十分平滑(有利於電腦計算與微分),所以業界驚呼這簡直是「魔術」,故得名 Magic Formula。
2. 魔術公式的核心數學式
無論是算縱向力(加速/煞車)、橫向力(轉向)還是回正力矩,魔術公式的基本原型都是同一條長相奇特的方程式:
$$ y(x) = D \sin(C \arctan(Bx - E(Bx - \arctan(Bx)))) $$
- 輸入值 $x$: 通常是縱向滑移率 $\lambda$(或稱 $\kappa$)或是側偏角 $\alpha$。
- 輸出值 $y$: 通常是縱向力 $F_x$ 或是橫向力 $F_y$。
3. 解碼神奇的四大參數(B, C, D, E)
這條公式之所以厲害,是因為它把複雜的曲線拆成四個具有「幾何意義」的常數。理解這四個常數,你就看懂了輪胎的靈魂:
- D (Peak Factor - 峰值因子):
- 意義: 代表曲線的最高點,也就是輪胎能提供的最大抓地力(對應 $\mu_{peak}$)。
- 物理影響: $D$ 越大,車子能承受的極限加速度或過彎 G 值就越高。
- C (Shape Factor - 形狀因子):
- 意義: 控制曲線兩端漸近線的高度,決定了過了極限打滑點之後,抓地力下降的幅度。
- 物理影響: 對於縱向力 $F_x$,$C$ 通常落在 1.65 左右;對於橫向力 $F_y$,$C$ 約為 1.3。
- B (Stiffness Factor - 剛性因子):
- 意義: 控制曲線在原點($x=0$)附近的斜率(Slope)。
- 物理影響: 代表輪胎的縱向剛性或側向剛性。$B$ 越大,曲線爬升越陡,車手會感覺這條輪胎反應非常直接、神經質;$B$ 越小,輪胎反應越遲鈍、漸進。 (註:原點斜率其實是 $B \times C \times D$ 三個乘起來的結果。)
- E (Curvature Factor - 曲率因子):
- 意義: 控制曲線在達到峰值($D$)附近的彎曲程度。
- 物理影響: 決定了輪胎在瀕臨極限時,是「瞬間失去抓地力」(Snap)還是「慢慢滑出去」(Progressive)。
4. 與 Simulink 模型的關聯
在我們上一篇筆記中,你用的 Simulink QuarterCar 模型裡面的 roadCoeffs,其實是 Pacejka 的極度簡化版:
$$ \mu_x = c \sin(b \arctan(a\lambda)) $$
如果你把這個簡化版跟完整的魔術公式對照:
- 你的 $c$ 就是 $D$(峰值 $\mu$)。
- 你的 $b$ 就是 $C$(形狀因子)。
- 你的 $a$ 就是 $B$(剛性因子)。
差異: 你的簡化版省略了 $E$(令 $E=0$)。這在一般控制演算法的初步驗證上已經很夠用了,但在精確的車輛動態模擬(如 CarSim 或圈速模擬器)中,通常會帶入包含 $E$ 以及考慮垂直荷重 $F_z$ 動態變化的完整版公式。
5. Pacejka 模型的優缺點
| 痛點 / 特性 | 說明 | 對應到你的 FSAE TC 專案 |
|---|---|---|
| 精準度極高 | 穩態(Steady-state)下,對實車輪胎行為的描述幾乎無懈可擊。 | 用來建構 Simulink 的 Plant(受控體)非常完美。 |
| 需要龐大測試數據 | 模型本身沒有物理意義,你無法用「胎寬、橡膠配方」來算出 $B, C, D, E$,只能上機台硬測。 | 必須依賴 FSAE TTC 提供的原始數據來擬合參數。 |
| 運算量大、難以解析推導 | 對微控制器來說,算 $\sin$ 和 $\arctan$ 很耗資源;且在數學上很難直接反推或做線性化。 | 這就是為什麼 Savaresi 的書在設計控制器時,喜歡改用數學更簡單的 Burckhardt 模型或直接局部線性化。 |
透過 MATLAB 擬合 TTC 數據(Curve Fitting)做出車隊這套輪胎的 Pacejka
在實務上,FSAE 車隊通常會花很多時間在處理 TTC(輪胎測試聯盟)給的龐大數據檔。 把 FSAE TTC 給的實測數據(CSV/MAT檔),透過 MATLAB 擬合(Curve Fitting)出專屬於你們車隊這套輪胎的 Pacejka $B,C,D,E$ 參數。
這支程式使用了 MATLAB 內建的非線性最小平方法(lsqcurvefit),並內建了防呆機制:如果你還沒準備好實際的 TTC CSV 檔案,它會自動生成一組帶有雜訊的模擬數據,讓你立刻就能執行並看到擬合效果與圖表。
% =========================================================================
% FSAE TTC 輪胎數據 Pacejka 魔術公式 (Magic Formula) 曲線擬合腳本
% 適用於提取縱向力 (Fx) 或 縱向摩擦係數 (Mu_x) 的 B, C, D, E 參數
% =========================================================================
clear; clc; close all;
%% 1. 讀取輪胎數據 (載入 TTC CSV 或產生模擬數據)
filename = 'TTC_tire_data.csv';
if isfile(filename)
% 如果你有真實的 TTC 數據,讀取 CSV
fprintf('讀取真實數據: %s\n', filename);
data = readtable(filename);
% 假設你的 CSV 欄位名稱為 SlipRatio 和 Mu_x (請依實際情況修改)
kappa = data.SlipRatio;
mu_x = data.Mu_x;
else
% 若無檔案,產生一組帶有雜訊的模擬實測數據供測試
fprintf('找不到 %s,產生模擬測試數據...\n', filename);
kappa = linspace(-0.3, 0.3, 200)'; % 滑移率從 -30% 到 +30%
% 設定一組虛擬的真實參數 [B=10, C=1.65, D=1.2, E=0.05]
true_B = 10; true_C = 1.65; true_D = 1.2; true_E = 0.05;
% 產生理想曲線並加入隨機雜訊 (模擬機台測試數據)
ideal_mu = true_D * sin(true_C * atan(true_B.*kappa - true_E.*(true_B.*kappa - atan(true_B.*kappa))));
noise = 0.05 * randn(size(kappa));
mu_x = ideal_mu + noise;
end
%% 2. 定義 Pacejka 魔術公式模型
% x(1) = B (Stiffness)
% x(2) = C (Shape)
% x(3) = D (Peak)
% x(4) = E (Curvature)
% xdata = kappa (滑移率)
magic_formula = @(x, xdata) x(3) .* sin(x(2) .* atan(x(1).*xdata - x(4).*(x(1).*xdata - atan(x(1).*xdata))));
%% 3. 設定初始猜測值與上下界
% 合理的初始猜測值能幫助演算法更快、更準確收斂
x0 = [12.0, 1.5, 1.0, 0.0]; % 初始猜測: [B, C, D, E]
% 設定參數的上下界 (Lower Bound & Upper Bound),避免擬合出沒有物理意義的負值或極端值
lb = [1.0, 1.0, 0.5, -1.0]; % 下界
ub = [20.0, 2.0, 2.0, 1.0]; % 上界
%% 4. 執行曲線擬合 (Curve Fitting)
% 使用 lsqcurvefit (需要 Optimization Toolbox)
options = optimoptions('lsqcurvefit', 'Display', 'iter', 'StepTolerance', 1e-6);
fprintf('\n開始進行 Pacejka 參數擬合...\n');
[x_opt, resnorm] = lsqcurvefit(magic_formula, x0, kappa, mu_x, lb, ub, options);
% 提取擬合結果
B_fit = x_opt(1);
C_fit = x_opt(2);
D_fit = x_opt(3);
E_fit = x_opt(4);
fprintf('\n=== 擬合結果 ===\n');
fprintf('B (剛性因子) = %.4f\n', B_fit);
fprintf('C (形狀因子) = %.4f\n', C_fit);
fprintf('D (峰值因子) = %.4f\n', D_fit);
fprintf('E (曲率因子) = %.4f\n', E_fit);
fprintf('殘差平方和 = %.4f\n', resnorm);
%% 5. 繪圖驗證擬合效果
kappa_dense = linspace(min(kappa), max(kappa), 500)'; % 產生高密度 X 軸以繪製平滑曲線
mu_x_fit = magic_formula(x_opt, kappa_dense); % 計算擬合出的曲線
figure('Name', 'Pacejka Magic Formula Fitting', 'Color', 'w');
plot(kappa, mu_x, 'k.', 'MarkerSize', 8, 'DisplayName', 'TTC 原始測試數據'); % 畫出散點圖
hold on;
plot(kappa_dense, mu_x_fit, 'r-', 'LineWidth', 2, 'DisplayName', 'Pacejka 擬合曲線'); % 畫出擬合線
hold off;
grid on;
title('FSAE TTC 輪胎數據: 縱向滑移率 vs 摩擦係數');
xlabel('縱向滑移率 \lambda (Slip Ratio)');
ylabel('縱向摩擦係數 \mu_x (F_x / F_z)');
legend('Location', 'southeast');
xlim([min(kappa) max(kappa)]);
% 在圖表上標示出計算出的參數
annotation_str = sprintf('B = %.2f\nC = %.2f\nD = %.2f\nE = %.2f', B_fit, C_fit, D_fit, E_fit);
text(min(kappa)*0.8, max(mu_x)*0.8, annotation_str, 'BackgroundColor', 'w', 'EdgeColor', 'k', 'FontSize', 10);
執行前的小提醒:
- Toolbox 需求: 這支腳本使用了
lsqcurvefit,你的 MATLAB 需要安裝Optimization Toolbox才能執行。 - 導入真實數據: 當你要換成真實 TTC 數據時,只需把你的檔名填入
filename = '你的檔名.csv';,並確保kappa和mu_x抓取的是正確的欄位(TTC 的原始檔通常欄位名是SL代表Slip Ratio,FX代表縱向力,記得要先把 $F_x$ 除以垂直荷重 $F_z$ 換算成 $\mu_x$ 再丟進來擬合會比較直觀)。
傅立葉轉換 (FFT) 白話文與頻譜分析實戰
傅立葉轉換 (FFT) 白話文與頻譜分析實戰
1. 白話解析:果汁機理論 🍓🍌
想像你面前有一杯打好的「綜合果汁」(這就是時域訊號,所有東西都混在一起了)。 你喝了一口,覺得很好喝,但你不知道裡面到底加了什麼。
傅立葉轉換 (FFT) 就像是一台「逆向果汁機」。你把果汁倒進去,它會瞬間幫你分離出:
- 3 顆草莓 🍓
- 1 根香蕉 🍌
- 0.5 顆蘋果 🍎
這份「食譜」就是頻譜圖 (Spectrum)! 在頻譜圖上,X 軸是水果種類 (頻率 Hz),Y 軸是水果的數量 (振幅 Amplitude)。透過 FFT,不管雜訊藏得再深,都會在頻譜圖上變成一根特別突出的長條,讓你一眼就看穿它!
2. MATLAB 頻譜分析標準 S.O.P. (超級重要 ⚠️)
在 MATLAB 中使用 fft() 函數非常簡單,但初學者 100% 會卡在「如何把 FFT 的結果轉成人類看得懂的頻譜圖」。
因為 fft() 算出來的結果是包含虛數的「雙邊對稱頻譜」,我們必須經過取絕對值、正規化、切一半這三個神聖步驟,才能畫出正確的圖。請直接把下面這段當成你的萬用模板!
% 1. 建立測試訊號 (我們延續前面濾波器的例子)
fs = 1000; % 取樣頻率 1000 Hz (一秒鐘抓 1000 個點)
t = 0 : 1/fs : 1-1/fs; % 建立 1 秒的時間軸
L = length(t); % 訊號總長度 (總共有幾個點)
% 混合訊號:振幅為 2 的 5Hz 正弦波 + 振幅為 0.5 的 100Hz 雜訊
sig_raw = 2 * sin(2 * pi * 5 * t) + 0.5 * sin(2 * pi * 100 * t);
% --- 開始進入 FFT 照妖鏡流程 ---
% 2. 執行快速傅立葉轉換
Y = fft(sig_raw);
% 3. 正規化與單邊頻譜轉換 (魔法步驟 🪄)
% (A) 取絕對值,並除以總長度 L 來還原真實振幅
P2 = abs(Y / L);
% (B) 因為頻譜是左右對稱的,我們只需要看正頻率 (前半段)
P1 = P2(1 : L/2+1);
% (C) 把被切掉的後半段能量補回前半段 (除了直流成分也就是第 1 個點以外,其餘乘 2)
P1(2:end-1) = 2 * P1(2:end-1);
% 4. 建立對應的頻率 X 軸 (從 0 Hz 到 奈奎斯特頻率 fs/2)
f = fs * (0:(L/2)) / L;
% 5. 畫出頻譜圖
figure;
% 上半部:人類看不懂的時域圖
subplot(2,1,1);
plot(t, sig_raw);
title('時域圖 (Time Domain) - 完全看不出裡面有什麼');
xlabel('時間 (秒)');
ylabel('振幅');
grid on;
% 下半部:一目瞭然的頻域圖
subplot(2,1,2);
plot(f, P1, 'LineWidth', 2, 'Color', 'r');
title('頻域圖 (Frequency Domain) - 照妖鏡現形!');
xlabel('頻率 (Hz)');
ylabel('振幅 (Amplitude)');
xlim([0 150]); % 為了看清楚,我們只顯示 0 到 150 Hz 的區間
grid on;
3. 圖表解讀與實戰意義
當你執行上面這段程式碼後,看著下半部的紅線圖,你會發現兩件非常神奇的事情:
- 精準定位: 在 X 軸的 5 Hz 和 100 Hz 的地方,直直地插著兩根像電線桿一樣的線。這就代表 FFT 成功抓出了這兩個隱藏的頻率!
- 還原振幅: 你去看這兩根電線桿的高度 (Y 軸),5 Hz 的高度剛好是 2,100 Hz 的高度剛好是 0.5。這完美對應了我們當初建立訊號時設定的倍數!
工程應用: 實務上,如果你測量一台馬達的震動,然後把訊號丟進這個 FFT 模板。如果你發現在 60 Hz 的地方有一根超高的長條,你立刻就能跟老闆報告:「老闆,我們的系統被台灣的市電 (60Hz) 干擾了!」;然後你就可以回去翻前面的筆記,用一個 60Hz 的帶阻濾波器 (Band-stop Filter) 把它精準幹掉!
無線電系統概述
本文件整理賽道通訊系統的硬體配置,包含 IMSA 專業參考方案 與 DIY 自行組裝平替版 的硬體組成。
🔝 參考方案:IMSA 專業套裝
針對專業賽事設計,具備高可靠性與標準 IMSA 介面,支援車手與技師長雙向對講。
- 官方連結:IMSA Driver and Crew Chief Racing Kit
- 核心設備:R1 數位/類比雙模無線電、IMSA 標準線組、降噪耳機。

🛠️ 平替版方案:DIY 配件組合
透過通用型配件達成通訊功能,適合入門或練習使用。
1. 核心轉接與控制
所有設備的中樞,用於連接無線電主機與音訊配件。
- 品名:K 頭手台通用手咪線 DIY
- 特點:相容寶鋒等 K 頭無線電,可擴展 PTT 按鈕。

2. 車手耳機
用勞保耳機替代,入耳式設計,提供物理隔音,價格便宜。
- 品名:線雙入耳式 工廠耳塞

3. 頭盔內收音麥克風
體積小巧,可固定於頭盔下巴處。

📊 方案快速對比
| 比較維度 | IMSA 專業方案 | DIY 平替方案 |
|---|---|---|
| 可靠性 | ⭐️⭐️⭐️⭐️⭐️ (賽事專用) | ⭐️⭐️⭐️ (接頭需自行補強) |
| 安裝便利性 | 插拔即用,標準接口 | 需確認接頭規格相容性 |
| 成本預算 | 高 (美金計價) | 低 (人民幣/台幣計價) |
:::success
💡 實戰小建議
在使用 DIY 平替方案 時,建議在 3.5mm 或 K 頭連接處使用電工膠布或熱縮套管進行二次固定,防止賽車行進間的高頻震動導致接頭鬆脫。 :::
經典頻率濾波器 (低通、高通、帶通) 實戰速查表
在處理感測器訊號、音訊或心電圖 (ECG) 時,我們的訊號通常會混雜著各種不同頻率的波。透過濾波器,我們可以精準地「切出」我們想要的頻段。
1. 三大濾波器白話解析
🐢 低通濾波器 (Low-pass Filter, LPF)
- 保鑣規則: 「低頻率 (變化慢的) 通過,高頻率 (變化快的) 擋下來!」
- 白話情境: 就像你隔著牆壁聽隔壁開趴的音樂,你只會聽到「咚、咚、咚」的低音貝斯,因為高音(人聲、鈸聲)被牆壁(低通濾波器)擋住了。
- 工程用途: 消除雜訊、平滑訊號。 感測器的雜訊通常是高頻的毛刺(上下劇烈跳動),用 LPF 切掉高頻,訊號就會變得非常平滑。
🐇 高通濾波器 (High-pass Filter, HPF)
- 保鑣規則: 「高頻率 (變化快的) 通過,低頻率 (變化慢的) 擋下來!」
- 白話情境: 就像照相機的「邊緣檢測」。一整面平滑的白牆(低頻)會變成黑色的,但牆壁邊緣的銳利輪廓(高頻/劇烈變化)會被保留下來凸顯。
- 工程用途: 消除基準線飄移 (Baseline Wander)、捕捉突發事件。 比如移除重力造成的長期固定偏差,只保留瞬間的撞擊震動。
🎯 帶通濾波器 (Band-pass Filter, BPF)
- 保鑣規則: 「只有某個『特定頻率範圍』的可以通過,太低或太高的通通擋掉!」
- 白話情境: 收音機調頻!空氣中充滿了幾千個頻道的電磁波,當你轉到 FM 91.7,你的收音機就是啟動了一個 BPF,只讓 91.7 MHz 附近的頻率進來。
- 工程用途: 提取特定特徵。 例如人聲大約落在 300 Hz 到 3400 Hz 之間,用 BPF 把這個區間切出來,就能消除超低頻的風聲和超高頻的電流嘶嘶聲。
2. MATLAB 濾波器實戰:巴特沃斯濾波器 (Butterworth)
在 MATLAB 裡,最經典、最平滑、最常用的就是巴特沃斯濾波器。 ⚠️ 核心觀念:奈奎斯特頻率 (Nyquist Frequency) 在設計數位濾波器時,MATLAB 需要的頻率參數通常是「正規化」的。你必須先算出你的取樣頻率 (Sampling Rate, $f_s$) 的一半,這就是奈奎斯特頻率。
% 1. 創造一個混合訊號 (低頻主訊號 + 高頻雜訊)
fs = 1000; % 取樣頻率 1000 Hz (每秒抓 1000 個點)
t = 0 : 1/fs : 1 - 1/fs; % 建立 1 秒的時間軸
f_low = 5; % 5 Hz 的緩慢波 (我們想要的訊號)
f_high = 100; % 100 Hz 的快速波 (我們討厭的雜訊)
% 混合在一起的原始訊號
sig_raw = sin(2 * pi * f_low * t) + 0.5 * sin(2 * pi * f_high * t);
% --- 準備濾波器參數 ---
nyquist = fs / 2; % 奈奎斯特頻率 (1000/2 = 500 Hz)
order = 4; % 濾波器階數 (數字越大,切得越乾淨,但運算越慢且可能變形)
% 2. 設計並應用【低通濾波器 LPF】(砍掉 50Hz 以上的)
cutoff_LPF = 50 / nyquist; % 設定截止頻率 $f_c$ 為 50 Hz,並正規化
[b_low, a_low] = butter(order, cutoff_LPF, 'low');
sig_lpf = filtfilt(b_low, a_low, sig_raw); % 使用 filtfilt 可以達成「零相位延遲」(訊號不會往後平移)
% 3. 設計並應用【高通濾波器 HPF】(砍掉 20Hz 以下的)
cutoff_HPF = 20 / nyquist; % 設定截止頻率為 20 Hz
[b_high, a_high] = butter(order, cutoff_HPF, 'high');
sig_hpf = filtfilt(b_high, a_high, sig_raw);
% 4. 設計並應用【帶通濾波器 BPF】(只保留 80Hz 到 120Hz 之間的)
cutoff_BPF = [80 120] / nyquist; % 帶通需要輸入兩個數字的陣列
[b_band, a_band] = butter(order, cutoff_BPF, 'bandpass');
sig_bpf = filtfilt(b_band, a_band, sig_raw);
% 5. 畫圖大車拚
figure;
subplot(4,1,1); plot(t, sig_raw); title('1. 原始混合訊號 (5Hz + 100Hz)'); grid on;
subplot(4,1,2); plot(t, sig_lpf, 'r'); title('2. 低通濾波結果 (只剩 5Hz)'); grid on;
subplot(4,1,3); plot(t, sig_hpf, 'g'); title('3. 高通濾波結果 (只剩 100Hz)'); grid on;
subplot(4,1,4); plot(t, sig_bpf, 'm'); title('4. 帶通濾波結果 (精準抓出 100Hz)'); grid on;
💡 實戰隱藏秘訣:filter vs filtfilt
如果你去查網路,很多人會教你用 filter(b, a, data)。但強烈建議在「非即時(已經錄好整段數據)」的情況下,一律改用 filtfilt(b, a, data)!
因為一般濾波器會造成訊號「時間延遲(相位偏移)」,導致濾完波的波峰跟原始波峰對不起來。filtfilt 會正向濾一次、反向再濾一次,完美消除延遲,讓你的波形前後完全對齊!
Simulink 檔案格式轉換 (.mdl 轉 .slx)
在處理比較舊的 Simulink 模型時,我們經常需要將舊版的 .mdl 升級成現代的 .slx 格式。這裡提供兩種最常用的轉換方式:
1. 滑鼠點擊法 (適合只有一兩個檔案時)
這是最直覺的方法,就像用 Word 把 .doc 存成 .docx 一樣:
- 在 MATLAB 裡直接對著
.mdl檔案點兩下,把它打開。 - 在 Simulink 視窗的左上角選單,點擊 File (檔案) -> Save As... (另存新檔)。 (如果是較新版的 MATLAB 介面,請點擊頂部工具列的 Simulation 標籤 -> Save 下拉選單 -> Save As)
- 在存檔視窗的「存檔類型 (Save as type)」下拉選單中,選擇 Simulink Model (*.slx)。
- 按下存檔,大功告成!
2. 程式碼一鍵轉換法 (適合用腳本自動化處理)
身為程式化控制的玩家,當然也可以直接在 Command Window (指令視窗) 下指令,連 Simulink 畫面都不用打開就能瞬間轉好!
這裡會用到我們前面在「程式化模擬」學過的 load_system 和 save_system 函數:
% 假設你的舊檔案叫做 old_robot.mdl
% 1. 將舊模型載入記憶體 (畫面不會跳出來)
load_system('old_robot.mdl');
% 2. 使用 save_system 另存新檔,只要副檔名打 .slx,MATLAB 就會自動幫你轉換格式!
save_system('old_robot.mdl', 'new_robot.slx');
% 3. 關閉記憶體中的舊模型
close_system('old_robot.mdl');
disp('格式轉換成功!現在你有一個乾淨的 .slx 檔案了。');
💡 為什麼強烈建議轉成 .slx?
- 檔案超小:
.slx底層其實是一個 ZIP 壓縮檔,檔案大小通常只有.mdl的 1/4 甚至更小。 - 讀寫更快: 載入大型模型時,
.slx的開啟速度明顯快很多。 - 支援現代功能: 很多 Simulink 的新特徵(例如國際字元編碼 UTF-8 支援、更好的版本控制整合)都只有在
.slx格式下才能完美運作。