ZCU216 · Ka-band FMCW · 37.5 GHz · weather mode

Ka-Band Signal Chain

อธิบายว่าสัญญาณที่เข้า RF-ADC หน้าตาเป็นอย่างไร ประกอบด้วยอะไรบ้าง แล้วแต่ละขั้นของ processing ทำอะไรกับมันด้วยสมการอะไร และให้ผลออกมาเป็นอะไร ตัวเลขและกราฟทั้งหมดมาจาก simulation จริงของโปรเจกต์นี้ (config/weather.yaml: B = 10 MHz, T = 200 µs, 64 chirps × 8 dwells, Pt 20 dBm, ฝนแบบ stratiform มองขึ้นฟ้าในแนวดิ่ง)

ภาพรวม

ข้อมูลในแต่ละขั้น

ขั้นสัญญาณชนิดอัตราต่อ 1 chirpหน่วย / ความหมาย
ADC\(x[n]\)real, int16 (14 บิต)2.5 GS/s500,000code ADC → mV ที่ขา ADC
P1 DDC\(z[m]\)complex I/Q62.5 MS/s12,500chirp ที่ย้ายลงมาอยู่ baseband
P2–P3 dechirp + LPF\(b[n]\)complex6.25 MS/s1,250ผลรวมของ tone: ความถี่ = ระยะ
P4 range FFT\(X_m[k]\)complex1 ค่า/bin/chirp401 bin (0–6 km)ค่าเชิงซ้อนของแต่ละระยะ 15 m
P6 Doppler\(S_k(v)\)power1 ชุด/dwell401 × 64กำลังตามระยะ × ความเร็ว
P6–P10 moments\(Z, v, \sigma_v, R\)real1 profile/0.1 s401dBZ, m/s, mm/h ต่อความสูง

จะเห็นว่าข้อมูลลดลงจาก 500,000 ตัวอย่างต่อ chirp เหลือ 401 ค่า โดยที่ข้อมูลเกี่ยวกับฝนยังอยู่ครบ เพราะแต่ละขั้นตัดเฉพาะแถบความถี่ที่ไม่มีสัญญาณที่เราสนใจทิ้งไป และสิ่งนี้เองที่เพิ่ม SNR ขึ้นทีละขั้น (A6)

Part A

สัญญาณที่เข้า ADC เกิดขึ้นอย่างไร และหน้าตาเป็นอย่างไร

ADC ไม่ได้เห็น beat signal แบบเรดาร์ FMCW ทั่วไป มันเห็น chirp ที่ IF เต็มแถบ ซึ่งเป็นผลรวมของสามส่วน คือ TX leakage, echo จากฝน และ noise

A1แผนความถี่และ chirp ที่ส่งออก

\[ f_{LO} = 4\,N f_{ref} = 4 \times 1119 \times 7.68\ \text{MHz} = 34.37568\ \text{GHz}, \qquad f_{RF}(t) = f_{LO} + f_{IF}(t) \] \[ s(t) = e^{\,j\varphi(t)},\qquad \varphi(t) = \pi S t^2 - \pi B t,\qquad S = \frac{B}{T} = \frac{10\ \text{MHz}}{200\ \mu\text{s}} = 5\times10^{10}\ \text{Hz/s} \] \[ u_{DAC}(t) = \cos\!\big(2\pi f_{IF}\,t + \varphi(t)\big),\qquad f_{IF} = 37.5\ \text{GHz} - f_{LO} = 3.12432\ \text{GHz} \]

\(s(t)\) คือ complex envelope ของ chirp (ความถี่ขณะหนึ่งกวาดจาก −B/2 ถึง +B/2) ทุกสมการด้านล่างเขียนในรูป envelope นี้ ส่วนความถี่พาหะจะแยกเขียนเป็น \(e^{j2\pi f t}\)

DAC waveform, instantaneous frequency and spectrogram of one chirp
ซ้าย: DAC ส่ง cosine ที่ 3.124 GHz กลาง: ความถี่ RF ขึ้นเป็นเส้นตรง 37.495 → 37.505 GHz ทุก 200 µs (sawtooth) ขวา: spectrogram ของ chirp หนึ่งตัวที่ IF

A2สิ่งที่ antenna RX ได้รับ

ส่วนที่ 1
TX leakage เป็น chirp ที่รั่วตรงจาก antenna TX ไป RX ด้วย delay เกือบศูนย์ กำลัง = Pt/isolation = 20 − 40 = −20 dBm
ส่วนที่ 2
Echo จากฝน คือ chirp เดียวกันแต่ delay ตามระยะ แต่ละเซลล์ของฝนมีแอมพลิจูดสุ่มและความเร็วของตัวเอง รวมทั้งหมดได้ประมาณ −89 dBm
ส่วนที่ 3
Noise เกิดในวงจรรับเอง (ดู A3)
\[ r(t) = \underbrace{a_L\, s(t-\tau_L)}_{\text{leakage}} \;+\; \sum_{c}\underbrace{a_c[m]\; e^{-j2\pi f_c \tau_c}\; s(t-\tau_c)\, e^{\,j2\pi f_{D,c} t}}_{\text{rain cell } c} ,\qquad \tau_c = \frac{2R_c}{c_0},\quad f_{D,c} = \frac{2v_c}{\lambda} \] \[ |a_L|^2 = \frac{P_t}{\mathrm{ISO}},\qquad \mathrm{E}\,|a_c|^2 = \frac{P_t G_t G_r\,\theta\phi\,\pi^3 |K|^2 Z(R_c)\,\delta r}{512\ln 2\;\lambda^2 R_c^2 L}\;10^{-\mathrm{PIA}(R_c)/10} \]

สูตรที่สองคือ weather radar equation (Probert-Jones): กำลังจากฝนแปรตาม \(Z/R^2\) ไม่ใช่ \(1/R^4\) เพราะปริมาตรที่ลำคลื่นกวาดโตตาม \(R^2\) ส่วน \(a_c[m]\) เปลี่ยนจาก chirp ถึง chirp ตาม Doppler spectrum แบบ Gaussian (mean \(v\), width \(\sigma_v\)) โดยใช้วิธีของ Zrnić ส่วน PIA คือ attenuation สองทางจากฝนระหว่างทาง

Leakage versus rain echo power in one chirp
Leakage (ส้ม) คงที่ −20 dBm ส่วน echo ฝน (น้ำเงิน) แกว่งอยู่แถว −90 dBm ห่างกัน 69 dB ทั้งที่ทั้งคู่เป็น chirp เดียวกัน ต่างกันแค่ delay กับแอมพลิจูด

A3Down-converter (ADMV1014), 90° hybrid และ noise

\[ z(t) = \sqrt{G}\; r(t)\, e^{\,j2\pi f_{IF} t} + n(t), \qquad z'(t) = \mu\, z(t) + \nu\, z^*(t), \qquad \mathrm{IRR} = \frac{|\mu|^2}{|\nu|^2} = 26.9\ \text{dB} \] \[ y(t) = \sqrt{2}\;\operatorname{Re}\{\mathcal{P}_+\, z'(t)\} \quad(\text{image-reject hybrid: upper sideband only}) \] \[ N_0 = k T_0\, F\, G + N_{0,ADC} \] \[ = (-144.0\ \text{dBm/Hz}) \oplus (-149.0\ \text{dBm/Hz}) = -142.8\ \text{dBm/Hz} \;\Rightarrow\; F_{eff} = 11.2\ \text{dB} \]

\(G\) = gain จาก antenna ถึง ADC (สมมติ 20 dB), \(F\) = NF ของ mixer (สมมติ 10 dB), \(\mu,\nu\) มาจาก IQ imbalance 0.5 dB / 4° และ \(\mathcal{P}_+\) หมายถึงเก็บเฉพาะความถี่บวก noise ของ ADC (NSD −150 dBFS/Hz) บวกเข้ามาอีกทำให้ NF รวมเพิ่มขึ้น 1.2 dB

Complex IF spectrum, image rejection test tones, real IF
ซ้าย: I/Q จาก mixer มีสัญญาณที่ +fIF (sideband ที่ต้องการ) และ noise ทั้งสองฝั่ง กลาง: ทดสอบด้วย tone สองตัว tone ใน image band เหลือ −26.9 dB ขวา: real IF ที่ออกจาก hybrid มี chirp แคบ 10 MHz ที่ 3.124 GHz และ LO leakage ที่ DC
Noise cascade and level diagram
Level diagram ที่ขา ADC: full scale +1 dBm, leakage 0 dBm (headroom แค่ 1 dB), echo รวม −68 dBm, noise ในแถบ 10 MHz −73 dBm และ noise ต่อ range bin หลัง FFT −104 dBm

A4หน้าตาของสัญญาณที่ขา ADC

รวม A1–A3 แล้วผ่าน BPF ที่เลือก Nyquist zone 3 (2.5–3.75 GHz) จะได้สัญญาณแอนะล็อกที่ ADC รับจริง:

\[ y(t) = \sqrt{2G}\;\operatorname{Re}\Big\{\Big[a_L\, s(t-\tau_L) + \sum_c a_c\, e^{-j2\pi f_c\tau_c}\, s(t-\tau_c)\Big]\, e^{\,j2\pi f_{IF} t}\Big\} + w(t) \]

กล่าวคือ ADC เห็นคลื่น cosine ที่ 3.124 GHz ความถี่เลื่อน ±5 MHz ตาม chirp แอมพลิจูดเกือบคงที่ 325 mV peak (มาจาก leakage) บนนั้นมี echo ฝนขนาดเล็กมากกับ noise ขี่อยู่ ใน time domain จึงแทบมองไม่เห็นฝนเลย

325 mV pkTX leakage (0.2 dBm) = 7,508 LSB
0.50 mV rmsnoise ทั้ง zone (−53 dBm) = 12 LSB
0.083 mV rmsecho ฝนทุกระดับรวมกัน (−68.6 dBm) = 1.9 LSB
4.2 µV rmsecho จาก bin 15 m ที่ 1 km (−94.6 dBm) = 0.1 LSB
Envelope of leakage, rain and noise; 4 ns zoom with ADC samples; samples tracing the alias
ซ้าย: envelope ตลอด chirp 200 µs แยกเป็นส่วน ๆ leakage อยู่ใกล้ full scale ส่วนฝนต่ำกว่า noise รวมทั้ง zone 1.25 GHz ประมาณ 15 dB กลาง: ซูม 4 ns เส้นส้มคือคลื่นแอนะล็อก 3.124 GHz และจุดดำคือ sample ของ ADC ทุก 0.4 ns ซึ่งคลื่นเดินไป 1.25 รอบระหว่างสอง sample (undersampling) ขวา: sample ชุดเดียวกันเรียงเป็นคลื่น 624 MHz ได้พอดี นี่คือ alias ใน zone 1
Power spectral density of each component at the ADC input
PSD แยกตามส่วนประกอบ: ในแถบ chirp 10 MHz leakage สูงกว่า noise ประมาณ 75 dB ส่วนฝนสูงกว่า noise เพียงไม่กี่ dB แต่ echo จากทุกความสูงใช้แถบ 10 MHz เดียวกัน (เป็น chirp ตัวเดียวกันที่ delay ต่างกันแค่ไม่กี่ µs) ที่ ADC จึงแยกไม่ได้ว่าฝนอยู่ที่ระยะไหน ต้องผ่าน dechirp + range FFT ก่อน echo ของแต่ละระยะถึงจะแยกออกมาได้

A5RF-ADC: sampling ใน zone 3 และ quantization 14 บิต

เข้า
\(y(t)\) แอนะล็อก ที่ 2.62–3.62 GHz (lab) หรือ 3.119–3.129 GHz (weather)
วิธี
sample ที่ \(f_s\) = 2.5 GS/s ซึ่งต่ำกว่า IF จงใจให้เกิด alias ลง zone 1 แล้ว quantize เป็น 14 บิต
ออก
int16 code ช่วง ±8192, 500,000 ตัวอย่างต่อ chirp (35 Gb/s ต่อช่อง) นี่คือ raw IF data ที่จะเก็บจาก ZCU216
\[ x[n] = \mathcal{Q}\{\,y(n/f_s)\,\},\qquad \Delta = \frac{2A_{FS}}{2^{14}} = 43.3\ \mu\text{V} \] \[ \text{SNR}_q = 6.02\times 14 + 1.76 = 86\ \text{dB} \] \[ f_{alias} = f_{IF} - (z-1)\frac{f_s}{2} = 3.12432 - 2.5 = 0.62432\ \text{GHz}\qquad(z = 3,\ \text{odd zone: not inverted}) \]

zone ที่ \(z = \lfloor f_{IF}/(f_s/2)\rfloor + 1 = 3\) เป็น zone คี่ สเปกตรัมจึงไม่กลับด้าน ถ้า chirp คร่อมขอบ zone (เช่นใช้ PLL 8.54 GHz ในโหมด 1 GHz) ส่วนที่ล้นเข้า zone 4 จะพับกลับด้านมาทับกัน

ADC spectrum folded into zone 1, zone map, code histogram
สเปกตรัมหลัง sampling ย้ายมาอยู่ที่ 624 MHz ± 5 MHz, zone map และ histogram ของ code (ใช้แค่ ±7,500 จาก ±8,192 เพราะ leakage)
First 80 ADC codes and LSB budget of each signal component
นี่คือข้อมูลดิบที่ได้จาก ADC: code เกือบทั้งหมดถูกใช้ไปกับ leakage ส่วน echo ฝนจาก 1 bin มีขนาดแค่ 0.1 LSB ที่ยังกู้คืนได้เพราะ noise (12 LSB rms) ทำหน้าที่เป็น dither และ processing ที่ตามมาเฉลี่ยตัวอย่างเป็นแสนตัว
ข้อสังเกตสำคัญ ถ้า leakage แรงกว่านี้อีก 1 dB ADC จะ clip ทันที และ clipping ของสัญญาณที่แรงที่สุดจะสร้าง harmonic ที่กลบฝนทั้งหมด การวัด TX–RX isolation จริงจึงเป็นงานแรกที่ต้องทำ

A6SNR ของฝน 1 bin ในแต่ละขั้น

ติดตาม echo จาก bin 15 m ที่ 1 km (−94.6 dBm ที่ ADC) ผ่านทุกขั้น ทุกขั้นที่แคบแถบลงช่วยตัด noise ออก สัญญาณจึงค่อย ๆ โผล่ขึ้นจาก noise

\[ \text{SNR}_i = \frac{P_{bin}}{N_0\, B_{n,i}},\qquad B_{n}:\ 1.25\ \text{GHz} \to 54\ \text{MHz} \to 4.6\ \text{MHz} \to \frac{\text{ENBW}}{T} = 7.5\ \text{kHz} \]
SNR of one range bin through the processing stages
จาก −42.8 dB ที่ ADC ขึ้นเป็น +9.5 dB หลัง range FFT (simulation วัดได้ +8.4 dB) และขึ้นเป็น +16.8 dB ที่ยอด Doppler spectrum เมื่อเฉลี่ย 8 dwell ส่วนที่เพิ่มมากที่สุด (+28 dB) มาจาก range FFT ซึ่งเป็น coherent integration ตลอด chirp 200 µs
Part B

Processing ทีละขั้น: วิธี สมการ และผลลัพธ์

โค้ดส่วนนี้ใช้ร่วมกันระหว่าง simulation กับข้อมูลจริง (radar_sim/processing/) ขั้น P1 อาจทำใน DDC ของ RFSoC หรือในซอฟต์แวร์ก็ได้ ขั้นอื่นทำใน FPGA หรือ PC

P1DDC: ย้าย chirp ลง baseband แล้วลดอัตรา

เข้า
\(x[n]\) real, 2.5 GS/s, 500,000 ตัว/chirp
วิธี
คูณด้วย NCO \(e^{-j2\pi f_{NCO} n/f_s}\) ที่ \(f_{NCO} = f_{IF}\) แล้วกรอง low-pass (FIR 961 tap) และ decimate ×40
ออก
\(z[m]\) complex I/Q, 62.5 MS/s, 12,500 ตัว/chirp มี chirp ที่กวาด −5 → +5 MHz รอบ DC
โค้ด
radar_sim/adc.py: ddc(), io/capture.py: ddc_stream()
\[ z[m] = \sqrt{2}\sum_{l} h[l]\; x[mD-l]\; e^{-j2\pi f_{NCO}(mD-l)/f_s},\qquad D = 40 \] \[ z(t) \approx \mu\sqrt{G}\,\Big[a_L\,s(t-\tau_L) + \sum_c a_c\, e^{-j2\pi f_c\tau_c}\, s(t-\tau_c)\Big]\,e^{\,j2\pi\Delta f\,t} + w(t),\qquad \Delta f = f_{IF}-f_{NCO} \]

ค่า \(\sqrt{2}\) ทำให้กำลังของ complex เท่ากับกำลังของ real (\(|z|^2 = P\)) หลัง DDC เราได้ complex envelope กลับคืนมาครบ ทั้ง phase และ amplitude ซึ่งเป็นสิ่งที่ Doppler ต้องใช้

DDC I and Q in the first 2 microseconds and the instantaneous frequency
ซ้าย: I กับ Q ห่างกัน 90° เป็น sinusoid ที่ −5 MHz ตอนเริ่ม chirp ขวา: ความถี่ที่คำนวณจาก phase slope กวาดเป็นเส้นตรง −5 → +5 MHz ใน 200 µs
DDC output spectrum and decimation filter
สเปกตรัมหลัง DDC (แถบเขียว = chirp 10 MHz) และ response ของ decimation filter อัตราข้อมูลลดจาก 35 Gb/s เหลือ 2 Gb/s
IF path versus baseband model after the DDC
การตรวจสอบ: ผลจาก IF path เต็มรูป (10 GS/s → ADC → DDC) ตรงกับ complex-baseband model ที่ NMSE −93 dB ดังนั้น chirp ส่วนใหญ่ใน simulation จึงใช้ baseband model ได้เลย

P2Digital dechirp: เปลี่ยน delay ให้เป็นความถี่

เข้า
\(z_m(t)\) ของ chirp ที่ \(m\) (12,500 ตัว) และ reference chirp \(s_{ref}(t)\) ที่สร้างในซอฟต์แวร์
วิธี
คูณ reference กับ conjugate ของสัญญาณรับทีละตัวอย่าง (ทำหน้าที่เหมือน mixer ของ FMCW แบบแอนะล็อก แต่ทำแบบดิจิทัล)
ออก
\(b_m(t)\) ผลรวมของ tone หนึ่ง tone ต่อหนึ่งระยะ ความถี่ \(f_b = S\tau\) เช่น 1 km → 334 kHz, 5 km → 1.67 MHz
โค้ด
processing/dechirp.py: dechirp()
\[ s_{ref}(t) = s(t)\,e^{\,j2\pi\Delta f\, t},\qquad b_m(t) = s_{ref}(t)\; z_m^*(t) \] \[ \varphi(t) - \varphi(t-\tau) = 2\pi S\tau\, t - \pi S\tau^2 - \pi B\tau \] \[ b_m(t) \approx \sum_c |a_c|\, \exp\!\Big(j\big[\,2\pi \underbrace{(S\tau_c - f_{D,c})}_{f_{b,c}}\, t + \underbrace{2\pi f_c \tau_c - \arg a_c}_{\phi_{c,m}}\big]\Big) \] \[ f_b = \frac{2SR}{c_0} - \frac{2v}{\lambda},\qquad \Delta\phi_{m\to m+1} = -\frac{4\pi v T}{\lambda} \]

ความถี่ของ tone บอกระยะ และ phase ที่เปลี่ยนจาก chirp ถึง chirp บอกความเร็ว (ใช้ใน P6) พจน์ \(-2v/\lambda\) คือ range–Doppler coupling ที่ 6 m/s ทำให้ระยะเพี้ยนประมาณ 4.5 m (0.3 bin) \(\Delta f\) ใน reference ต้องตรงกับ offset ของ NCO ไม่เช่นนั้นทุก tone จะเลื่อน

Time-frequency picture of TX and delayed echoes, and the resulting beat tones
ซ้าย: echo คือ chirp ที่เลื่อนไปทางขวาด้วย τ ในทุกขณะความถี่ห่างจาก reference เท่ากับ Sτ ขวา: หลัง dechirp แต่ละระยะกลายเป็น tone ความถี่คงที่ ช่วง τ แรกของแต่ละ chirp เป็นหางของ chirp ก่อนหน้าซึ่งไปอยู่นอกแถบ และจะถูกกรองทิ้งใน P3 (เสีย SNR เล็กน้อยที่ระยะไกล: 0.43 dB ที่ 6 km เมื่อใช้ Hann window)
Beat spectrogram of chirp 0 and beat frequency versus range
Spectrogram ของ beat จาก chirp แรกของฉากฝนจริง แถบพลังงานอยู่ที่ 0–1 MHz (ฝน 0–3 km) และ leakage อยู่ที่ ~0 Hz

P3Low-pass + decimate ×10

เข้า
\(b_m\) ที่ 62.5 MS/s
วิธี
FIR low-pass cutoff = 1.25 × fb,max = 2.5 MHz (fb,max ของ 6 km) แล้วเก็บทุกตัวที่ 10
ออก
\(b'_m[n]\) ที่ 6.25 MS/s, 1,250 ตัว/chirp ตัด noise นอกแถบ beat ทิ้ง (SNR +10.7 dB)
โค้ด
processing/dechirp.py: beat_decimate()
\[ b'_m[n] = \sum_l h_b[l]\; b_m[nD_2 - l],\qquad D_2 = 10,\qquad f_{s,beat} = 6.25\ \text{MS/s} \ge 2.5\,f_{b,max},\quad f_{b,max} = S\,\frac{2R_{max}}{c_0} = 2.0\ \text{MHz} \]
Beat spectrum before and after the low-pass filter
เทาคือก่อนกรอง (62.5 MS/s) น้ำเงินคือหลังกรองและลดอัตรา เส้นประคือ response ของ filter

P4Range FFT: แยก tone ออกเป็น range bin

เข้า
\(b'_m[n]\) 1,250 ตัวต่อ chirp
วิธี
คูณ Hann window แล้วทำ FFT โดย normalize ด้วย \(\sum w\) เพื่อให้ tone ที่มีกำลัง P ได้ \(|X|^2 = P\) พอดี
ออก
\(X_m[k]\) ค่าเชิงซ้อน 401 bin (0–6 km, bin ละ 15 m) ต่อ chirp เรียงเป็น range–chirp matrix 64 × 401 ต่อ dwell
โค้ด
processing/range_fft.py
\[ X_m[k] = \frac{1}{\sum_n w[n]}\sum_{n=0}^{N-1} w[n]\, b'_m[n]\, e^{-j2\pi kn/N},\qquad R_k = \frac{k\, f_{s,beat}}{N}\cdot\frac{c_0}{2S} = k\,\Delta R,\qquad \Delta R = \frac{c_0}{2B} = 15.0\ \text{m} \] \[ N_{bin} = N_0\,\frac{\text{ENBW}}{T},\qquad \text{ENBW}_{Hann} = 1.5 \;\Rightarrow\; N_{bin} = -142.8 + 10\log_{10}(7500) = -104.0\ \text{dBm} \]

tone ที่อยู่นิ่งตลอด chirp มีพลังงานรวมกันแบบ coherent ใน bin เดียว ขณะที่ noise กระจายไปทุก bin ขั้นนี้จึงให้ gain มากที่สุด (+28 dB)

Beat signal and range profile for three point targets
ตัวอย่างที่เห็นง่าย: เป้า 3 จุดที่ 1, 2.5, 4 km ใน time domain beat เป็นผลรวมของ 3 tone (ซ้าย) และ FFT แยกออกเป็น 3 peak ที่ระยะถูกต้อง (ขวา)
Range profile and range-chirp matrix of the rain scene
ฉากฝนจริง: range profile ของแต่ละ chirp และ range–chirp matrix ฝนเห็นชัดที่ 0–2.5 km แต่ leakage ที่ 0 m แรงกว่ามาก

P5ตัด TX leakage และ clutter ที่อยู่นิ่ง

เข้า
range–chirp matrix \(X_m[k]\)
วิธี
ลบค่าเฉลี่ยตามแกน chirp ออก (zero-Doppler notch) ทุกอย่างที่ไม่เปลี่ยนระหว่าง chirp จะหายไป ได้แก่ leakage, radome และ ground clutter
ออก
\(\tilde X_m[k]\) ขนาดเดิม เหลือแค่สิ่งที่เคลื่อนที่
\[ \tilde X_m[k] = X_m[k] - \frac{1}{M}\sum_{m'=0}^{M-1} X_{m'}[k] \]

ข้อจำกัด: เป้าที่ความเร็วใกล้ 0 (เช่น เมฆที่แทบไม่ตก) ถูกตัดไปด้วยบางส่วน และส่วนที่ leakage แกว่งระหว่าง chirp (สมมติ −60 dBc) จะเหลือค้างเป็น residual

Range profile before and after mean subtraction
ก่อนลบ (เทา) sidelobe ของ leakage ท่วมระยะใกล้ หลังลบ (น้ำเงิน) เหลือแต่ฝน

P6Doppler processing: FFT และ pulse-pair ต่อ range bin

เข้า
\(\tilde X_m[k]\) ของ bin \(k\) ใน 64 chirp (slow time, ห่างกัน T = 200 µs)
วิธี
(ก) FFT ตามแกน chirp ได้ Doppler spectrum แล้วเฉลี่ย 8 dwell (ข) pulse-pair: autocorrelation lag 0 และ lag 1
ออก
range–Doppler map 401 × 64 และต่อ bin ได้ \(R_0, R_1\) → กำลัง, \(v\), \(\sigma_v\)
โค้ด
processing/doppler.py
\[ S_k(f_i) = \frac{\big|\sum_m w_m \tilde X_m[k]\, e^{-j2\pi i m/M}\big|^2}{M\sum_m w_m^2},\qquad v_i = -\frac{\lambda f_i}{2},\qquad v_{max} = \frac{\lambda}{4T} = 9.99\ \text{m/s} \] \[ R_0 = \frac{1}{M}\sum_m |\tilde X_m|^2,\qquad R_1 = \frac{1}{M-1}\sum_m \tilde X_{m+1}\tilde X_m^* \] \[ \hat v = -\frac{\lambda}{4\pi T}\arg R_1,\qquad \hat\sigma_v = \frac{\lambda}{2\sqrt{2}\,\pi T}\sqrt{\ln\frac{\hat S}{|R_1|}},\qquad \hat S = R_0 - \hat N \]

phase ที่หมุนระหว่าง chirp บอกความเร็วเฉลี่ย และการที่ \(|R_1|\) น้อยกว่า \(S\) (สัญญาณ decorrelate) บอกความกว้างของ spectrum ถ้าความเร็วเกิน ±vmax phase จะหมุนเกิน ±180° และค่าที่ได้จะกลับฝั่ง (velocity aliasing)

Slow-time samples of the 1 km bin, phasor plot, and its Doppler spectrum
bin ที่ 1 km: ซ้าย ค่า I/Q ของ bin เดียวกันใน 64 chirp ดูเหมือนสุ่มเพราะเป็นผลรวมของเม็ดฝนจำนวนมาก (Rayleigh) ข้อมูลจึงอยู่ในสถิติ ไม่ได้อยู่ในค่าเดี่ยว ๆ กลาง phasor หมุนเฉลี่ย −119° ต่อ chirp (ลูกศร \(R_1\)) ขวา Doppler spectrum ยอดอยู่ที่ 6–7 m/s: pulse-pair ได้ 6.62 m/s เทียบกับค่าจริง 6.70 m/s
Range-Doppler map and velocity and width profiles
ทุก bin พร้อมกัน: range–Doppler map, ความเร็วเฉลี่ย และ spectrum width เทียบกับค่าจริง (เส้นดำ)

P7ประมาณ noise และคัด bin ที่เชื่อถือได้

เข้า
Doppler spectrum และ \(R_0\) ของทุก bin
วิธี
Hildebrand–Sekhon: เรียงจุดใน spectrum จากน้อยไปมาก แล้วหาส่วนที่ยังมีสถิติแบบ noise ขาว จากนั้นใช้ median ข้ามทุก bin
ออก
\(\hat N\) (−104.2 dBm เทียบกับทฤษฎี −104.0), SNR ต่อ bin และ mask ของ bin ที่ valid
\[ \hat N = \operatorname{mean}\{S_{(1..n^*)}\},\quad n^* = \max\big\{n : p\cdot\operatorname{var}\{S_{(1..n)}\} \le \operatorname{mean}\{S_{(1..n)}\}^2\big\} \] \[ \text{SNR}_k = \frac{R_0[k]-\hat N}{\hat N} \ge \gamma = -6\ \text{dB} \]

threshold −6 dB ใช้ได้เพราะเฉลี่ย 8 × 64 chirp ทำให้ค่า noise ที่ประมาณได้แกว่งน้อยกว่า −13 dB

SNR profile, threshold and noise estimates
SNR ต่อ bin (ซ้าย แถบเขียวคือ valid) และ noise ที่ประมาณได้เทียบกับทฤษฎี (ขวา)

P8Calibration: จากกำลังใน bin เป็น reflectivity (dBZ)

เข้า
\(\hat S\) กำลังฝนใน bin (W ที่ขา ADC)
วิธี
กลับสมการ radar แบบ weather (A2) โดยหาร gain ของสายรับ คูณ \(R^2\) และชดเชยความยาว bin ที่มีผลจริงของ window
ออก
\(Z\) (mm⁶/m³) และ dBZ ต่อ bin
โค้ด
processing/calibration.py: reflectivity()
\[ Z = C\;R^2\;\frac{\hat S}{G\,L_{ov}(R)}\;10^{\,\text{cal}/10},\qquad C = \frac{512\ln 2\;\lambda^2 L}{P_t G_t G_r\,\theta\phi\,\pi^3|K|^2\,\Delta R_{eff}} \] \[ \Delta R_{eff} = \text{ENBW}\cdot\frac{c_0}{2B} = 1.5\times 15 = 22.5\ \text{m},\qquad L_{ov}(R) = \Big(\frac{\sum_{n\ge n_\tau} w_n}{\sum_n w_n}\Big)^2,\quad n_\tau = \tau f_{s,beat} \]

\(\Delta R_{eff}\) ใหญ่กว่า 15 m เพราะ window ทำให้แต่ละ bin รับฝนจากช่วงที่กว้างกว่า bin ส่วน \(L_{ov}\) ชดเชยช่วง τ แรกที่ไม่มี beat (P2) ค่า cal ได้จากการ calibrate ด้วย corner reflector

Measured reflectivity versus truth and error versus SNR
Z ที่วัดได้ (จุด) เทียบกับค่าจริง (ดำ) และค่าที่คาดหวังหลัง attenuation (ประส้ม) เส้นจุดเทาคือ minimum detectable Z ขวามือคือ error: bias −0.14 dB, std 0.77 dB

P9แก้ attenuation ของ Ka-band (Hitschfeld–Bordan)

เข้า
\(Z_m(R)\) ที่ถูกฝนระหว่างทางดูดกลืนไปแล้ว
วิธี
สะสม attenuation จากระยะใกล้ออกไป โดยใช้ความสัมพันธ์ k–Z
ออก
\(Z_c(R)\) และ PIA (dB) ตามระยะ เช่น ที่ 1 km PIA = 2.5 dB
\[ k = \alpha Z^{\beta}\ \text{[dB/km]},\quad \alpha = a_k\, a^{-b_k/b},\ \beta = \frac{b_k}{b};\qquad Z_c(R) = \frac{Z_m(R)}{\big[1 - 0.46\,\beta\alpha\int_0^R Z_m^{\beta}(s)\,ds\big]^{1/\beta}} \]

\(k = 0.263 R^{0.979}\) ที่ ~37 GHz และ \(Z = 200R^{1.6}\) วิธีนี้ไม่เสถียรเมื่อ attenuation สูง จึงจำกัดการแก้ไว้ไม่เกิน 10 dB

Reflectivity before and after attenuation correction and path-integrated attenuation
Z ก่อนและหลังแก้ (ซ้าย) และ PIA ที่ประมาณได้เทียบกับค่าจริง (ขวา)

P10Rain rate

\[ R = \Big(\frac{Z}{a}\Big)^{1/b},\qquad a = 200,\ b = 1.6\ \ (\text{Marshall–Palmer}) \]
Estimated rain rate versus truth
ใช้ได้เฉพาะชั้นฝนที่เป็นน้ำ (ใต้ melting layer) ที่ 1 km ได้ 4.6 mm/h

P11ตีความ Doppler spectrogram

นำ Doppler spectrum ของทุก bin มาวางเรียงตามความสูงจะได้ภาพที่อ่านโครงสร้างของเมฆฝนได้โดยตรง: ฝนตก 6–7 m/s และ spectrum กว้าง, bright band คือจุดที่ความเร็วกระโดดจาก ~1.5 เป็น ~6 m/s และ Z มียอด, ส่วนหิมะตกช้าราว 1 m/s

Annotated Doppler spectrogram of the vertically pointing radar
ที่ Pt 20 dBm โดยไม่มี LNA ตรวจพบฝนและ bright band แต่หิมะและเมฆ altostratus ต่ำกว่า minimum detectable Z
Part C · Block 18

MIMO: angle FFT และสิ่งที่ทำต่อหลังจากนั้น

ในส่วน A–B ใช้ RX ช่องเดียว ส่วนนี้ใช้ครบทั้ง 4 TX × 4 RX เพื่อแยกทิศทาง (angle) ภายในลำคลื่น 20° ของแต่ละ sub-array ตัวเลขมาจาก config/weather_mimo.yaml (ฝนเดิม มีลมพัดตามแกน x 2 → 9 m/s) และ config/lab_mimo.yaml (corner reflector 2 ตัว)

C0ก่อนเริ่ม: ต้องแลกอะไรไปบ้าง

±2.5 m/svmax ถ้าใช้ TDM กับ chirp 200 µs (แต่ละ TX ส่งทุก 800 µs) ฝนที่ตก 6–7 m/s จะ alias
50 µschirp ที่ใช้ในโหมด MIMO ทำให้แต่ละ TX ส่งทุก 200 µs และได้ vmax ±10 m/s กลับมา แลกกับ rmax ที่ลดเหลือ 3 km
7–11°ความละเอียดเชิงมุมของ virtual array 16 ตัว (aperture 8λ) ภายใน beam 20° จึงได้ประมาณ 3 cell อิสระ
\[ v_{max}^{TDM} = \frac{\lambda}{4\,N_{tx}\,T},\qquad \Delta(\sin\theta) \approx \frac{\text{ENBW}}{N_v\, d/\lambda} = \frac{1.5}{16\times 0.5} \;\Rightarrow\; \Delta\theta \approx 11^\circ\ (\text{Hann}) \]

ประโยชน์หลักของ MIMO สำหรับเรดาร์ตรวจฝนแบบชี้ขึ้นจึงไม่ใช่ภาพที่คมขึ้น แต่คือการได้ radial velocity ที่หลายมุมพร้อมกัน ซึ่งเอาไปคำนวณลมแนวนอนได้ (C7)

C1Virtual array และลำดับ TDM

เข้า
ADC 4 ช่อง (RX0–RX3) ทุก chirp โดย chirp ที่ \(m\) ส่งจาก TX \(t = m \bmod 4\)
วิธี
ทำ P1–P4 (DDC, dechirp, LPF, range FFT) แยกทีละ RX แล้วจัดกลุ่ม chirp ตาม TX ที่ส่ง
ออก
\(X_v[q, v, k]\): 64 slow-time × 16 virtual element × 201 range bin ต่อ dwell
โค้ด
radar_sim/mimo.py, processing/mimo.py: mimo_profiles(), to_virtual()
\[ x_v = x_{t} + x_{r},\quad x_t = 2t\ [\lambda],\ x_r = 0.5r\ [\lambda] \;\Rightarrow\; x_v = 0.5\,(4t + r),\qquad v = 4t + r = 0,\dots,15 \] \[ \tau_{t,r}(\theta) = \frac{2R - (x_t + x_r)\lambda\sin\theta}{c_0} \;\Rightarrow\; X_m[r,k] \propto e^{-j2\pi (x_t + x_r)\sin\theta},\qquad X_v[q, v, k] = X_{qN_{tx}+t}[r, k] \]

เพราะ TX ห่างกัน 2λ = 4 × ระยะห่าง RX ผลรวมตำแหน่ง TX+RX จึงเรียงเป็น array 16 ตัวที่ห่างกัน λ/2 พอดี phase ที่ต่างกันระหว่าง element เป็นเส้นตรงตาม \(\sin\theta\) (หลัง dechirp เครื่องหมายกลับเป็นลบเพราะมี conjugate)

TX, RX and virtual element positions, and TDM timing
ซ้าย: TX 4 ตัว (□), RX 4 ตัว (○) และ virtual element 16 ตัว (◇) สีบอกว่ามาจาก TX ตัวไหน ขวา: TDM: TX ผลัดกันส่งทีละ chirp ขนาด 50 µs แต่ละตัวจึงส่งซ้ำทุก 200 µs

C2Channel calibration ด้วย corner reflector

เข้า
\(X_v\) จาก capture ที่มี corner reflector วางที่มุมที่รู้ค่า (เช่น 0°)
วิธี
หาร phase และ gain ที่ควรเป็นตามทฤษฎีออก ส่วนที่เหลือคือ mismatch ของแต่ละช่อง (สาย, mixer, ADC) จากนั้นหารค่านี้ออกจากทุก capture
ออก
\(c_v\) ค่าเชิงซ้อน 16 ค่า เก็บเป็น *_cal.npy หรือ mimo.calibration ใน config
โค้ด
scripts/calibrate_mimo.py, processing/mimo.py: estimate_calibration()
\[ c_v = \frac{\overline{X_v[k_0]}}{\overline{X_0[k_0]}\; a_v(\theta_0)},\qquad a_v(\theta) = e^{-j2\pi x_v \sin\theta},\qquad \tilde X_v = X_v / c_v \]

ถ้าไม่ calibrate ความผิดพลาดของ phase ±25° ต่อช่องจะทำให้เกิด sidelobe สูงถึง −7 dB และเกิดเป้าปลอม หลัง calibrate ค่าที่ประมาณได้ต่างจากค่าจริงไม่เกิน 3° ต้อง calibrate ใหม่เมื่อเปลี่ยนสาย อุณหภูมิเปลี่ยน หรือ reset PLL

Range-angle maps of two corner reflectors before and after calibration
Corner A (1.0 m, 0°) และ corner B (1.6 m, +20°) ซ้าย ก่อน calibrate มี lobe ปลอมกระจายเต็มแถว กลาง หลัง calibrate เหลือ 2 จุดที่ตำแหน่งถูกต้อง (0.0° และ 20.1°) ขวา angle cut ที่ 1.6 m

C3Doppler FFT และชดเชยการเคลื่อนที่ระหว่าง TX (TDM compensation)

เข้า
\(\tilde X_v[q, k]\) หลังลบค่าเฉลี่ย (ตัด leakage)
วิธี
FFT ตามแกน \(q\) แล้วหมุน phase ของ element ที่มาจาก TX \(t\) กลับด้วย Doppler ของ bin นั้น เพราะ TX \(t\) ส่งช้ากว่า TX0 อยู่ \(tT\) ซึ่งระหว่างนั้นเม็ดฝนเคลื่อนที่ไปแล้ว
ออก
\(D[f, v, k]\) ที่ phase ของทุก element อ้างอิงเวลาเดียวกัน
\[ D[f_i, v, k] = e^{-j2\pi f_i\, t_v T}\sum_{q} w_q\,\tilde X_v[q,k]\, e^{-j2\pi f_i q N_{tx} T},\qquad t_v = \lfloor v / N_{rx}\rfloor \]

ถ้าไม่ชดเชย phase error \(2\pi f_D t T\) จะทำให้มุมเพี้ยนตามความเร็ว ในการทดสอบ เป้าที่ 10° ความเร็ว ±7 m/s: ชดเชยแล้วได้ 10.8° (ความละเอียดของ grid 1.8°) ถ้าไม่ชดเชยได้ 12.6° / 7.2° ถ้า Doppler alias การชดเชยจะผิดไปด้วย จึงต้องเลือก chirp ให้ vmax พอ

C4Angle FFT

เข้า
\(D[f, v, k]\) 16 element
วิธี
คูณ Hann window ตามแกน element แล้วทำ FFT 64 จุด (zero-pad) แกนผลลัพธ์เป็น \(\sin\theta\)
ออก
\(P[f, \theta, k]\) กำลังตาม Doppler × มุม × ระยะ (64 Doppler × 64 angle bin ครอบคลุม −90° ถึง +76° × 201 range bin)
\[ A[f,\theta_n,k] = \frac{1}{\sum_v w_v}\sum_{v=0}^{15} w_v\, D[f,v,k]\; e^{+j2\pi v n / N_\theta},\qquad \sin\theta_n = \frac{n/N_\theta}{d/\lambda} = 2\,\frac{n}{N_\theta} \] \[ P[f,\theta,k] = \frac{|A[f,\theta,k]|^2}{Q\sum_q w_q^2} \]

C5Moments และ Z ในแต่ละ cell (ระยะ × มุม)

เข้า
\(P[f,\theta,k]\) เฉลี่ย 8 dwell
วิธี
ได้ autocorrelation จาก spectrum (Wiener–Khinchin) จากนั้นใช้สูตร pulse-pair ชุดเดิม และแก้ Z ด้วย element pattern กับความกว้างของ angle bin
ออก
SNR, dBZ, \(v_r\), \(\sigma_v\) ต่อ cell ในระนาบแนวดิ่ง: \(x = R\sin\theta\), \(h = R\cos\theta\)
\[ R_0 = \sum_f P,\qquad R_1 = \sum_f P\, e^{\,j2\pi f N_{tx}T},\qquad \hat v_r = -\frac{\lambda}{4\pi N_{tx}T}\arg R_1 \] \[ Z(\theta) = Z_{beam}\big(\hat S\big)\cdot \frac{\theta_b\sqrt{\pi/(8\ln 2)}}{f^4(\theta)\;\Delta\theta_{eff}},\qquad \Delta\theta_{eff} = \frac{\text{ENBW}}{N_v\,(d/\lambda)\cos\theta},\qquad f^4(\theta) = e^{-8\ln 2\,\theta^2/\theta_b^2} \]

\(Z_{beam}\) คือสูตร P8 เดิม (ที่ถือว่ากำลังมาจากทั้ง beam) พจน์ที่เพิ่มเข้ามาเปลี่ยนเป็นกำลังจาก angle bin เดียว และชดเชยการที่ขอบ beam มี gain ต่ำกว่า

SNR, reflectivity and radial-velocity anomaly in the vertical plane
ข้อมูลเป็นรูปพัดในระนาบแนวดิ่ง ซ้าย SNR (ขอบพัดต่ำเพราะ element pattern) กลาง dBZ หลังแก้ pattern (สม่ำเสมอข้ามมุม ตามที่ควร) ขวา \(v_r\) ลบค่าเฉลี่ยข้ามมุม: ฝั่งซ้ายเข้าหาเรดาร์เร็วกว่า ฝั่งขวาช้ากว่า นี่คือสัญญาณของลมที่พัดไปทาง +x

C6มุมที่มีผลจริง (effective angle)

angle bin ที่ขอบ beam (เช่น 18°) ไม่ได้รับกำลังจาก 18° จริง เพราะ element pattern ที่ 18° ต่ำกว่า boresight ถึง −24 dB และ sidelobe ของ array ดึงกำลังจากกลาง beam เข้ามา ความเร็วที่วัดได้ใน bin นั้นจึงเป็นของมุมที่ใกล้ 0° กว่า ถ้าใช้มุมของ bin ตรง ๆ ลมจะออกมาต่ำกว่าจริงประมาณ 30%

\[ \theta_{eff,n} = \frac{\int \theta\, f^4(\theta)\,|H_n(\theta)|^2\, d\theta}{\int f^4(\theta)\,|H_n(\theta)|^2\, d\theta},\qquad H_n(\theta) = \frac{1}{\sum w}\sum_v w_v\, e^{\,j2\pi x_v(\sin\theta - \sin\theta_n)} \]

ผลคือ bin ±18.2° มีมุมจริง ±12.3° และ bin ±9.0° มีมุมจริง ±6.1° (ถือว่า Z สม่ำเสมอข้าม beam ที่ระยะเดียวกัน) ทดสอบกับฝนที่ไม่มี noise แล้ว θeff ตรงกับค่าที่คำนวณจาก cell ของฝนจริงภายใน 0.7°

C7หาลมแนวนอนและความเร็วตก (Doppler beam swinging)

เข้า
\(v_r(\theta_{eff}, k)\) ของ cell ที่ valid
วิธี
fit least squares (ถ่วงน้ำหนักด้วย SNR) รวม 7 range gate (105 m) ต่อครั้ง
ออก
\(u(h)\) ลมแนวนอนตามแกน array และ \(V(h)\) ความเร็วตกรวมกับลมแนวดิ่ง
โค้ด
processing/mimo.py: retrieve_wind(), scripts/run_mimo.py
\[ v_r(\theta) = V\cos\theta - u\sin\theta \quad\Rightarrow\quad \begin{bmatrix}\hat V\\ \hat u\end{bmatrix} = \arg\min \sum_i \frac{\text{SNR}_i}{1+\text{SNR}_i}\Big(v_{r,i} - V\cos\theta_i + u\sin\theta_i\Big)^2 \]

\(V\) = ความเร็วตกของเม็ดฝน + ลมแนวดิ่ง (สองอย่างนี้แยกกันไม่ได้ด้วยเรดาร์ตัวเดียว) ความไวต่อ noise ของ \(u\) สูงเพราะ \(\sin\theta_{eff}\) มีค่าแค่ ≤ 0.2 จึงต้องเฉลี่ยข้ามหลาย gate และหลาย dwell เช่นเดียวกับ wind profiler ทั่วไป

Doppler spectrum per angle, power versus angle, and the DBS fit at 1 km
ที่ 1 km: ซ้าย Doppler spectrum ของแต่ละ angle bin (ยอดเลื่อนจาก 7.5 → 5.8 m/s ตามมุม) กลาง SNR ตามมุมเทียบกับ element pattern ขวา \(v_r\) ที่มุมของ bin (เทา) กับที่ θeff (น้ำเงิน) fit ได้ u = 5.01 m/s (ค่าจริง 5.0)
Retrieved wind and fall-speed profiles versus truth
Profile ทั้งหมด: u RMSE 0.67 m/s เมื่อ fit รวม 7 gate (1.28 m/s ถ้า fit gate เดียว) และ V RMSE 0.05 m/s ถ้าไม่ calibrate u RMSE เพิ่มเป็น 0.75 m/s (config นี้มี mismatch เพียง 0.5 dB / 10°)

C8ขั้นต่อไปหลังจากนี้

งานได้อะไรต้องมีอะไร
Calibrate กับฮาร์ดแวร์จริง\(c_v\) 16 ค่า และ element pattern \(f(\theta)\) จริงที่ใช้ใน C5–C6corner reflector บนแท่นหมุนหรือวางหลายมุม
เฉลี่ยนานขึ้น (30 s – 5 min)u RMSE ต่ำกว่า 0.3 m/s และตรวจจับหิมะได้เก็บ capture ต่อเนื่อง หรือทำ P1–P4 ใน FPGA
Array แกนที่สอง หรือหมุนเรดาร์ 90°ลมครบทั้ง u และ v (ทิศและความเร็วลม)array 2 มิติ หรือวัดสองรอบ
ชี้เอียงแล้วหมุน (VAD / PPI / RHI)ภาพฝนแบบ 3 มิติ และลมจาก VADแท่นหมุน (mechanical scan)
DDMA แทน TDMส่งทุก TX พร้อมกัน ได้ SNR เต็ม แต่ต้องแบ่งช่วง Dopplerphase code ต่อ chirp ที่ DAC
ใช้ \(\sigma_v\) ตามมุมturbulence และ wind shear ในลำคลื่นSNR สูงหรือเฉลี่ยนาน
สรุป

ตามตัวเลขของ bin ที่ 1.00 km ตลอดสาย

ขั้นปริมาณค่ามาจาก
A4echo ของ bin นี้ที่ขา ADC−94.6 dBm = 4.2 µV rms = 0.10 LSBweather radar equation
A6SNR ที่ ADC (ทั้ง zone)−42.8 dB\(P_{bin}/(N_0 \cdot 1.25\ \text{GHz})\)
P2beat frequency334 kHz\(2SR/c_0\)
P4\(R_0\) หลัง range FFT−95.2 dBmสัญญาณ + noise
P7noise \(\hat N\)−104.2 dBmHildebrand–Sekhon
P7\(\hat S = R_0 - \hat N\), SNR−95.7 dBm, +8.4 dB
P6\(\arg R_1\) → \(\hat v\)−119.3° → 6.62 m/s (จริง 6.70)\(-\lambda\arg R_1/(4\pi T)\)
P6\(|R_1|/\hat S\) → \(\hat\sigma_v\)0.90 → 1.43 m/s (จริง 1.32)
P8\(\hat S / G\) (ที่ antenna)−115.7 dBm\(G\) = 20 dB
P8\(10\log C + 10\log R^2\)116.8 + 60.0 dB\(\Delta R_{eff}\) = 22.5 m
P8Z ที่วัดได้31.1 dBZ (คาดหวัง 32.3)−145.7 + 116.8 + 60.0 dB
P9PIA และ Z หลังแก้2.5 dB → 33.6 dBZ (จริง 34.9)Hitschfeld–Bordan
P10rain rate4.6 mm/h\(Z = 200R^{1.6}\)

ค่าตัวเลขและกราฟทั้งหมดสร้างใหม่ได้ด้วย python scripts/signal_walkthrough.py และ python scripts/run_pipeline.py --config config/weather.yaml ค่า gain, NF, isolation และ ADC full scale ยังเป็นสมมติฐาน (ดู config/default.yaml) เมื่อมีข้อมูลจริง ตัวเลขในส่วน A จะเปลี่ยน แต่สมการทั้งหมดยังคงเหมือนเดิม