Mengolah sinyal di firmware: memahami sampling dan batas Nyquist, filter FIR dan IIR untuk membersihkan noise sensor, FFT untuk analisis frekuensi, matematika fixed-point, serta praktik DSP real-time dengan CMSIS-DSP.

Setelah di episode 21 firmware kita bisa berpikir (TinyML), pada episode ini ia belajar mendengar dan melihat dengan tajam. Dunia fisik menghasilkan sinyal — suara, getaran, arus, denyut nadi — dan hampir selalu terkontaminasi noise. DSP (Digital Signal Processing) adalah senjata firmware untuk membersihkan, menganalisis, dan mengambil keputusan dari sinyal tersebut.
Mengapa DSP penting? Karena sensor mentah hampir tidak pernah siap dipakai. Pembacaan ADC ber-getar, sinyal audio bercampur noise listrik, getaran motor punya frekuensi khas yang harus diekstrak. Firmware engineer yang paham DSP bisa membuat sensor murah bekerja seperti sensor mahal — dengan software.
Digitalisasi adalah pencuplikan sinyal kontinu menjadi deret angka. Aturan paling mendasar: teorema Nyquist — untuk menangkap frekuensi f, kalian harus sample minimal 2f.
Sinyal maks 1 kHz -> minimal 2 kHz sampling
Sampling 1 kHz -> frekuensi > 500 Hz jadi alias (salah baca)
Praktik: sample 4-10x frekuensi tertinggi + low-pass anti-aliasingAliasing adalah biang kesalahan yang "terlihat masuk akal": frekuensi tinggi muncul sebagai frekuensi rendah palsu. Selalu tanyakan: berapa bandwidth sinyal, berapa sampling rate?
Filter menghilangkan frekuensi yang tidak diinginkan. Dua keluarga utama:
| Aspek | FIR | IIR |
|---|---|---|
| Respons impuls | Terbatas (finite) | Tak terbatas (feedback) |
| Stabilitas | Selalu stabil | Bisa tak stabil |
| Fase | Linear (bagus untuk timing) | Non-linear |
| Order | Lebih tinggi (butuh banyak tap) | Lebih rendah (hemat) |
| Cocok untuk | Precision, audio | Sensor real-time, hemat resource |
Filter paling sederhana untuk sensor: rata-rata N sampel terakhir.
#define WINDOW 8
static uint16_t buf[WINDOW];
static uint32_t sum = 0;
static uint8_t idx = 0;
uint16_t filter(uint16_t sample) {
sum -= buf[idx]; // buang sampel tertua
buf[idx] = sample;
sum += sample;
idx = (idx + 1) % WINDOW;
return (uint16_t)(sum / WINDOW);
}Makin besar WINDOW, makin halus hasilnya — tapi makin lambat merespons perubahan (lag). Trade-off antara smoothness dan responsiveness ini keputusan desain, bukan angka ajaib.
Lebih hemat dan responsif daripada moving average:
static float y = 0.0f;
#define ALPHA 0.1f // 0..1: kecil = lebih halus
float lowpass(float x) {
y += ALPHA * (x - y); // y = y + a*(x-y)
return y;
}IIR makin halus dengan ALPHA kecil, tapi tambah lag. Untuk MCU tanpa FPU, konversi ke fixed-point (di bawah) sering diperlukan.
FFT (Fast Fourier Transform) mengubah sinyal domain waktu menjadi domain frekuensi — untuk mendeteksi getaran khas, frekuensi mains (50 Hz), atau komponen harmonik. Implementasi embedded paling umum: CMSIS-DSP (ARM) — optimal untuk Cortex-M:
#include "arm_math.h"
static float32_t input[256]; // window sampel
static float32_t fft_out[256]; // kompleks: real+imag berselang
static float32_t mag[128];
arm_rfft_fast_instance_f32 fft;
arm_rfft_fast_init_f32(&fft, 256);
void analyze(void) {
arm_rfft_fast_f32(&fft, input, fft_out, 0); // forward FFT
arm_cmplx_mag_f32(fft_out, mag, 128); // magnitudo
// mag[k] mewakili bin frekuensi k * (Fs/N)
}Fs = 1000 Hz, N = 256 -> resolusi = 1000/256 ≈ 3.9 Hz/bin
Puncak di bin 13 -> frekuensi dominan ≈ 50 HzBanyak MCU kecil tidak punya FPU — operasi float lambat. Solusinya fixed-point: representasikan nilai sebagai integer dengan skala tetap.
1.0 -> 32767
0.5 -> 16384
skala dikenal semua orang: konversi di awal, kalkulasi integer, skala kembali
CMSIS-DSP menyediakan versi q15/q31 dari semua filter & FFTAturan: kalau arsitektur target punya FPU (Cortex-M4F/M7) dan budget timing cukup, float32 lebih sederhana. Kalau tidak, fixed-point adalah jawabannya — CMSIS-DSP sudah menyediakannya.
Tip
Sebelum menulis filter sendiri, cek CMSIS-DSP: arm_biquad_cascade_df1_f32, arm_fir_f32, arm_rfft_fast_f32, arm_max_f32 — pustaka ARM sudah teruji dan dioptimalkan assembly. Menulis ulang yang sudah ada adalah sumber bug klasik DSP. Gunakan pustaka, fokus pada masalah sinyal kalian.
Alur khas firmware DSP — filter + FFT untuk deteksi getaran:
while (1) {
for (i = 0; i < 256; i++) {
input[i] = lowpass(adc_read()); // 1. IIR bersihkan noise
wait_sample_period(); // sampling konsisten
}
analyze(); // 2. FFT lihat frekuensi
if (detect_peak(&mag, 128)) // 3. deteksi puncak khas
raise_alarm(); // aksi di perangkat
}Perhatikan sampling konsisten — timer (episode 5), bukan delay() — karena FFT mengasumsikan interval tetap. Satu sampel "telat" merusak seluruh spektrum.
N sesuai.Inti yang harus dibawa pulang:
bin = k * Fs/N.Di episode 23 selanjutnya kita masuk industri otomotif: Automotive & CAN — protokol CAN bus, CAN-FD, AUTOSAR, dan praktik firmware komunikasi kendaraan. Perangkat kalian siap masuk mobil!