Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

Arduino UNO EMI Near-Field Morse Code Transmitter

利用電磁干擾諧波實現摩斯密碼發射之實驗報告

日期: 2026年 作者:wanjay0337


1. Abstract(摘要)

本實驗利用 Arduino Uno 微控制器在正常運作時產生的電磁干擾(Electromagnetic Interference, EMI),透過 Timer1 硬體定時器產生精確的 4 MHz 方波訊號,並利用其第七次諧波(112 MHz)作為無線載波,搭配開關鍵控(On-Off Keying, OOK)調變方式,實現摩斯密碼(Morse Code)的近場無線傳輸。接收端使用 UV-K5 手持式無線電接收機,於 112.000 MHz AM 模式下進行接收。本實驗驗證了利用微控制器諧波輻射進行近場通訊的可行性,並成功建構一套可透過電腦串列埠(UART)輸入文字、自動轉換並發射摩斯密碼的完整系統。


2. Motivation & Background(動機與背景)

2.1 實驗動機

數位電路在高速切換時會不可避免地產生諧波輻射。一般情況下,工程師視之為需要抑制的電磁干擾問題;然而,若能善加利用,這些諧波輻射便可成為低功率近場通訊的訊號來源。

本實驗的核心問題為:能否在不使用任何額外 RF 元件的情況下,純粹利用 Arduino Uno 的諧波輻射傳送摩斯密碼?

2.2 摩斯密碼簡介

摩斯密碼(Morse Code)是一種以點(dot, .)與劃(dash, -)的組合來表示字母與數字的編碼系統。其時序規則如下:

元素 持續時間
點(Dot) 1 單位
劃(Dash) 3 單位
符號間隔 1 單位
字母間隔 3 單位
單字間隔 7 單位

2.3 OOK 調變原理

開關鍵控(On-Off Keying, OOK)是最簡單的數位調幅(AM)調變方式:載波開啟代表「1」,載波關閉代表「0」。本實驗利用此原理,以點與劃的時序控制 112 MHz 載波的開關,使接收端的 AM 解調電路能還原出摩斯密碼的包絡節奏。


3. Theoretical Analysis(理論分析)

3.1 諧波產生原理

方波訊號在頻域上可分解為基頻與奇次諧波的疊加(傅立葉級數):

f(t) = (4/π) × [sin(ωt) + (1/3)sin(3ωt) + (1/5)sin(5ωt) + ...]

Arduino Uno 使用 16 MHz 石英晶振,其諧波分佈為:

諧波次數 頻率
基頻(1st) 16 MHz
2次諧波 32 MHz
4次諧波 64 MHz
7次諧波 112 MHz ✓
8次諧波 128 MHz

選擇 112 MHz(7次諧波) 的原因:

  • UV-K5 原廠韌體的 AM 前端電路針對 108~135 MHz 航空波段優化,靈敏度最高
  • 64 MHz(4次諧波)雖在理論上可用,實測前端衰減超過 20 dB,無法穩定接收
  • 128 MHz(8次諧波)能量較弱,且諧波強度隨次數遞減約 1/n

3.2 Timer1 方波產生原理

Arduino Uno 的 Timer1 為 16 位元硬體定時器,支援 CTC(Clear Timer on Compare Match)模式。透過設定比較暫存器 OCR1A = 1 並啟用 COM1A0(比較匹配時翻轉 OC1A 輸出腳),即可在 Pin 9 產生精確的 4 MHz 方波:

f = F_CPU / (2 × (OCR1A + 1) × Prescaler)
  = 16,000,000 / (2 × (1+1) × 1)
  = 4,000,000 Hz = 4 MHz

4 MHz 方波的第七次諧波即為 28 MHz × 4 = 112 MHz(嚴格說為 4 MHz × 28 = 112 MHz)。

3.3 EMI 輻射機制

PCB 走線在高頻切換時充當非故意天線,將諧波能量以近場電磁輻射的形式向外發散。Pin 9 的 PCB 走線長度約 2~5 cm,在 112 MHz 下接近 λ/4(約 67 cm),配合 PCB 電源平面的耦合效應,使 112 MHz 諧波輻射效率相對較高。


4. System Design(系統設計)

4.1 系統架構

[電腦] ─USB/UART─→ [Arduino Uno]
                        │
                   Timer1 (4 MHz)
                   Pin 9 OC1A
                        │
                   EMI 諧波輻射
                   112 MHz OOK
                        │
                   (近場,< 5 cm)
                        │
                  [UV-K5 接收機]
                  112.000 MHz AM
                        │
                   [揚聲器輸出]
                   摩斯密碼音

4.2 硬體規格

項目 規格
微控制器 Arduino Uno (ATmega328P, 16 MHz)
發射頻率 112.000 MHz(4 MHz × 7次諧波)
調變方式 OOK(On-Off Keying)
輸出腳位 Pin 9(OC1A)
串列通訊 UART 9600 bps
接收機 Quansheng UV-K5
接收模式 AM,靜噪關閉(SQ=0)
有效距離 ≤ 5 cm(近場耦合)

4.3 UV-K5 接收設定

項目 設定值
頻率 112.000 MHz
模式 AM
靜噪(SQ) 0(關閉)
步進 1 kHz
天線位置 SMA 接頭對準 Pin 9,距離 ≤ 2 cm

5. Software Implementation(軟體實作)

5.1 程式架構

程式分為以下四個主要模組:

  1. Timer1 初始化模組 — 設定 4 MHz CTC 方波輸出
  2. 串列埠輸入模組 — 接收電腦輸入的文字指令
  3. 指令解析模組 — 處理 SOS、SPEED n、STOP 等控制指令
  4. 摩斯密碼轉換模組 — 將文字對應到點劃序列並控制載波開關

5.2 Timer1 暫存器設定解析

// CTC 模式:計數到 OCR1A 後清零並觸發比較匹配
TCCR1A = 0;
TCCR1B = 0;
OCR1A  = 1;                              // 比較值 = 1,產生 4 MHz

TCCR1A |= _BV(COM1A0);                   // 比較匹配時翻轉 OC1A (Pin 9)
TCCR1B |= _BV(WGM12) | _BV(CS10);       // CTC 模式 + 無預分頻(×1)
暫存器位元 功能
COM1A0 比較匹配時翻轉 OC1A 輸出
WGM12 啟用 CTC 模式(Mode 4)
CS10 時脈來源 = 系統時脈,無預分頻

5.3 OOK 載波控制

透過動態設定 COM1A0 位元,控制方波輸出的開啟與關閉:

// 載波開啟:恢復 Timer1 翻轉輸出
inline void carrierOn()  { TCCR1A |= _BV(COM1A0); }

// 載波關閉:停止翻轉並強制 Pin 9 為 LOW
inline void carrierOff() {
    TCCR1A &= ~_BV(COM1A0);
    digitalWrite(EMI_PIN, LOW);
}

5.4 時序參數設計

時序參數定義為可修改的全域變數(而非 #define 常數),以支援執行期動態調整:

int DOT_DURATION  = 100;   // 點 = 1 單位(ms)
int DASH_DURATION = 300;   // 劃 = 3 單位(ms)
int SYMBOL_SPACE  = 100;   // 符號間隔 = 1 單位(ms)
int LETTER_SPACE  = 300;   // 字母間隔 = 3 單位(ms)
int WORD_SPACE    = 700;   // 單字間隔 = 7 單位(ms)

關鍵修正: 原始版本使用 #define DOT_DURATION 100,導致 SPEED 指令執行 DOT_DURATION = newSpeed; 時出現編譯錯誤(#define 為預處理期文字替換,等效於 100 = newSpeed;,數字字面量不是 lvalue,無法被賦值)。改為 int 全域變數後問題解決。

5.5 摩斯密碼表

const char* morseTable[] = {
  ".-","-...","-.-.","-..",".","..-.","--.",
  "....","..","----",".-..","--","-.",
  "---",".--.","--.-",".-.","...","--.",
  "..-","...-",".--","-..-","-.--","--..",
  // 數字 0-9
  "-----",".----","..---","...--","....-",
  ".....","-....","--...","---.","----."
};

5.6 串列埠指令介面

指令 功能
SOS 發送國際求救訊號 ... --- ...
SPEED n 設定點持續時間為 n ms(範圍:50~200)
STOP 中斷目前發送
任意文字 轉換為摩斯密碼並發射(支援 A-Z、0-9、.,?)

6. Experimental Process(實驗過程)

6.1 開發歷程

本實驗經歷以下主要階段:

階段一:頻率選擇(64 MHz → 112 MHz)

最初嘗試使用 64 MHz(16 MHz 的 4 次諧波),因 UV-K5 原廠韌體 AM 接收模式最低僅支援約 50 MHz。然而實測結果只有高頻雜訊,無法辨識節奏。

分析原因:UV-K5 的 AM 前端電路針對 108~135 MHz 航空波段優化,64 MHz 接收靈敏度下降超過 10~15 dB,AGC 電路將訊號壓縮,包絡對比度消失,導致只聽到寬頻雜訊。

階段二:改用 Timer1 硬體方波(Busy-Loop → Timer1 CTC)

早期版本使用 CPU busy-loop 切換 GPIO,產生的方波頻率不穩定且寬頻噪聲過高,無法形成 AM 解調所需的窄帶載波。改用 Timer1 CTC 模式後,4 MHz 方波精確度大幅提升,諧波能量集中,OOK 包絡對比度提升約 5 倍。

階段三:編譯錯誤除錯(#define → int 全域變數)

加入 SPEED n 動態調速指令時,發現 #define 常數無法在執行期賦值,導致編譯錯誤。將所有時序參數改為 int 全域變數後,動態調速功能正常運作。

階段四:串列埠介面整合

加入 UART 串列埠輸入介面,實現從電腦端輸入文字、自動轉換摩斯密碼並即時發射的完整功能。

6.2 測試結果

測試項目 結果
112 MHz 載波接收 ✓ 成功,聽到清晰的脈衝節奏
SOS 指令發射 ✓ 成功辨識 ... --- ... 節奏
SPEED 150 調速 ✓ 節奏明顯放慢,辨識率提升
英文字串傳送 ✓ HELLO 等單字可辨識
最大有效距離 約 3~5 cm(UV-K5 天線貼近 Pin 9)

7. Discussion(討論)

7.1 諧波強度限制

諧波強度隨次數遞減,7次諧波(112 MHz)的輻射功率約為基頻的 1/49(理論值),加上 PCB 走線的非理想天線特性,實際有效距離僅約 3~5 cm。若需增加距離,可在 Pin 9 焊接一段 5~7 cm 的單芯銅線作為寄生天線,輻射效率可提升 3~5 倍。

7.2 供電干擾

電腦 USB 供電線路上存在 50/60 Hz 共模雜訊,會混入 EMI 輻射並干擾 OOK 包絡的清晰度。改用行動電源供電可有效降低底噪,提升節奏對比度。

7.3 法規說明

本實驗屬於 Class B 非故意輻射(Unintentional Radiator),有效輻射距離通常小於 5 cm,符合多數地區低功率實驗豁免規定。實驗過程中應避免干擾合法頻段用戶,建議於金屬屏蔽環境下操作。


8. Conclusion(結論)

本實驗成功驗證以下幾點:

  1. 諧波利用可行性:Arduino Uno 的 16 MHz 晶振諧波輻射可被 UV-K5 在 112 MHz 接收,無需任何額外 RF 元件。

  2. Timer1 CTC 方波的有效性:相比 CPU busy-loop,硬體定時器產生的穩定方波能使諧波能量集中,顯著提升 OOK 包絡對比度。

  3. 完整通訊系統:從電腦 UART 輸入文字,到摩斯密碼轉換、112 MHz OOK 發射、UV-K5 接收解調,整個通訊鏈路得以完整實現。

  4. 軟體設計教訓:#define 常數與執行期變數的本質差異是 C/C++ 的重要觀念。預處理器文字替換與編譯期型別系統是不同層次的機制,設計需要動態修改的參數時應使用變數而非巨集。

本實驗展示了電子電路中「非預期行為的再利用」這一工程思維——EMI 通常是需要被抑制的問題,但透過對其物理原理的深入理解,反而可以成為實用的功能。


** 9. Practical Video (實作影片)

zh-ver: https://youtu.be/YQSUlGtsHOU | en-ver: https://youtu.be/x7MMNjl5Rog


實驗平台:Arduino Uno R3 + Quansheng UV-K5

About

This is a fun project can use Arduino Uno to get morse code.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages