# 2025 Microprocessor Final Project
contributed by Group7 (柯智幃, 陳睿謙, 鄭誌恩, 莊凱程)
## 一、系統功能與原理說明
我們的期末專案旨在建構一套自動化的防災原型系統,整合了紅外線(火焰)感測器、機電(伺服馬達、沉水幫浦)控制、微處理器邏輯與監控介面。系統運作流程分為四個主要階段:偵測警報、定位追蹤、瞄準滅火以及資料回傳。
### 自動偵測與警報
系統利用紅外線感測器結合 PIC18F4520 ADC 模組持續監測環境。當 ADC 數值低於設定閾值時,程式立即判定為火災狀態並觸發蜂鳴器示警,確保能在第一時間察覺災害發生。
### 火源定位與追蹤
透過 Timer0 中斷精確控制第一個伺服馬達 (Servo 1),使其在角度 -90° ~ +90° 間進行週期性掃描。此機制讓感測器能主動覆蓋前方半圓形區域,動態搜尋並鎖定潛在的熱源位置。
### 自動瞄準與滅火
一但偵測到火源,系統會立即暫停掃描 (Servo 1) 並鎖定當前方位,隨即啟動第二個伺服馬達轉向火源位置 (Servo 2) ,並啟動沉水幫浦 (Motor 3) 精準對準火源進行撲滅,直到感測數值回升至安全範圍才停止運作。
### 資料分析與輸出
微控制器將角度、火焰數值與狀態封裝為 JSON 格式,經 UART 介面傳送至電腦。PC 端執行 Python Streamlit 儀表板,即時解析數據並繪製溫度與角度圖表,實現遠端視覺化監控。

## 二、系統使用環境及對象
系統設計於居家、實驗室或小型倉儲等室內平坦環境。運作時需避免太陽直射或強光干擾,以確保紅外線感測準確度。同時需透過 USB 連接電腦進行供電與 UART 資料傳輸,維持監控連線。透過電腦端的圖形化儀表板 (Dashboard),即可直觀監控環境數值、掌握火源方位並接收即時警報。
## 三、系統完整架構圖、流程圖、電路圖、設計
### 系統完整架構圖
```graphviz
digraph system_architecture {
rankdir=LR;
label = "系統完整架構圖";
fontname="Sans-Serif";
node [shape=record, style="filled,rounded", fontname="Sans-Serif", fontsize=10, margin=0.2];
edge [fontname="Sans-Serif", fontsize=9];
subgraph cluster_inputs {
label = "Input Layer";
style = dashed;
color = "#82b366";
fontcolor = "#82b366";
node [fillcolor="#d5e8d4", color="#82b366"];
sensor [label="{ 火焰傳感器 }"];
btn [label="{ 按鈕 }"];
}
subgraph cluster_PC {
label = "PC Dashboard";
style = dashed;
color = "#6c8ebf";
fontcolor = "#6c8ebf";
node [fillcolor="#dae8fc", color="#6c8ebf"];
pc [label="{ <json> JSON \n Parser | <py> Python \n Streamlit }"];
}
subgraph cluster_MCU {
label = "PIC18F4520 ";
style = dashed;
color = "#d79b00";
fontcolor = "#d79b00";
node[fillcolor="#ffe6cc", color="#d79b00"]
mcu [label="{ { <ADC> ADC | <In> Input } | <uart> UART | { <PWM> PWM | <Out> Output } }"];
}
subgraph cluster_outputs {
label = "Output Layer";
style = dashed;
color = "#b85450";
fontcolor = "#b85450";
node [fillcolor="#f8cecc", color="#b85450"];
motor1 [label="{ 伺服馬達 (Servo 1) \n (掃描) }"];
motor2 [label="{ 伺服馬達 (Servo 2) \n (對準目標) }"];
motor3 [label="{ 沉水幫浦 (Motor 3) \n (抽水)}"];
alert [label="{ 蜂鳴器 \n (警報) }"];
leds [label="{ LED \n (方位判讀) }"];
}
sensor:e -> mcu:ADC:w [color="green"];
btn:e -> mcu:In:w [color="green"];
mcu:PWM:n -> motor1:w [color="orange"];
mcu:PWM:e -> motor2:w [color="orange"];
mcu:Out:e -> motor3:w [color="blue"];
mcu:Out:s -> alert:w [color="blue"];
mcu:Out:s -> leds:w [color="blue"];
pc:py:e -> mcu:uart:s [color="purple", dir="back"];
}
```
### 流程圖
```graphviz
digraph software_flowchart {
rankdir=TB;
nodesep=0.7;
label = "流程圖";
fontname="Sans-Serif";
node [fontname="Sans-Serif", fontsize=10];
node [shape=ellipse, style="filled", fillcolor="#e1d5e7", color="#9673a6"];
Start [label="系統啟動\n(Start)"];
node [shape=box, style="filled", fillcolor="#dae8fc", color="#6c8ebf"];
Init [label="系統初始化\n(System Initialize)\n UART, ADC, PWM, Timer0, IO"];
MainLoop [label="進入主迴圈(While)"];
ReadSensors [label="讀取感測器數據\n ADC (火焰), IO (按鈕)"];
Calc [label="資料處理\n 換算角度,判斷火災狀態"];
node [shape=diamond, style="filled", fillcolor="#ffe6cc", color="#d79b00"];
IsFire [label="是否偵測到火源?\n(ADC < 400)"];
IsSafe [label="是否安全?\n(ADC > 600)"];
CheckMsg [label="傳送資料?\n(per 0.25 sec)"];
node [shape=box, style="filled, rounded", fillcolor="#f8cecc", color="#b85450"];
FireAction [label="執行滅火程序\n- 停止掃描 (Run=0)\n- 鎖定目標\n- 啟動沉水幫浦/蜂鳴器"];
SafeAction [label="恢復監控模式\n- 啟動掃描 (Run=1)\n- 關閉沉水幫浦/蜂鳴器"];
SendUART [label="UART 資料傳輸\n- JSON 格式封包\n- 更新 PC Dashboard"];
subgraph cluster_isr {
label = "Timer0 中斷 (ISR)";
style = dashed;
color = "#82b366";
fontcolor = "#82b366";
node [fillcolor="#d5e8d4", color="#82b366"];
ISR_Start [shape=ellipse, label="TMR0 中斷發生"];
ISR_Count [label="計數器累加\n(Timing Control)"];
ISR_Scan [label="伺服馬達掃描\n(Update Servo Angle)"];
ISR_End [shape=ellipse, label="返回主程式"];
}
Start:s -> Init:n;
Init:s-> MainLoop:n;
MainLoop:s -> ReadSensors:n;
ReadSensors:w -> Calc:n [label="trigger", fontcolor="red"];
Calc:s -> IsFire:n;
IsFire:s -> FireAction:n [label="Yes (Fire!)", fontcolor="red"];
IsFire:w -> IsSafe:n [label="No"];
IsSafe:s -> SafeAction:n [label="Yes (Safe!)", fontcolor="green"];
IsSafe:w -> CheckMsg:w [label="No \n(Keep State!)"];
FireAction:s -> CheckMsg:n;
SafeAction:s -> CheckMsg:w;
CheckMsg:s -> SendUART:n [label="Yes"];
CheckMsg:e -> ReadSensors:s [label="No"];
SendUART:e -> ReadSensors:e;
ISR_Start:s -> ISR_Count:n;
ISR_Count:s -> ISR_Scan:n;
ISR_Scan:s -> ISR_End:n;
{ rank=same; MainLoop; ISR_Start }
}
```
### 電路圖
```graphviz
digraph hardware_wiring {
rankdir=LR;
nodesep=0.5;
ranksep=1.5;
bgcolor="white";
label = "PIC18F4520 + 外接硬體 電路圖";
fontname="Sans-Serif";
node [fontname="Sans-Serif", fontsize=10, style="filled"];
edge [fontname="Sans-Serif", fontsize=9];
subgraph cluster_MCU {
label = "PIC18F4520";
style = dashed;
color = "#d79b00";
fontcolor = "#d79b00";
node [shape=record, fillcolor="#fff2cc", color="#d6b656"];
pic [label="{ { <RA0> RA0 | <RB0> RB0 | <RC1> RC1 (CCP2) | <RC2> RC2 (CCP1) } | { <RD0> RD0 | <RD1> RD1 | <vcc> VDD (5V) | <gnd> VSS (GND) | <RC6> RC6 (TX) | <RC7> RC7 (RX) | <RD4to7> RD4~RD7 } }"];
}
node [shape=record, style="filled,rounded", fillcolor="#e1d5e7", color="#9673a6"];
sensor [label="{4pin\n火焰感測器 | { <AO> (Analog Out) | <DO> (Digital Out)} }", fillcolor="#d5e8d4"];
btn [label="2pin\n按鈕開關", fillcolor="#d5e8d4"];
servo1 [label="3pin\nServo 1\n(掃描馬達)", fillcolor="#dae8fc"];
servo2 [label="3pin\nServo 2\n(瞄準馬達)", fillcolor="#dae8fc"];
buzzer [label="2pin\n蜂鳴器", fillcolor="#f8cecc"];
TIP122 [label="{{ <B> B | <C> C | <E> E } | 3pin\nTIP122}", fillcolor="#f8cecc"];
leds [label="2pin\nLED (x4)", fillcolor="#dae8fc"];
pc_usb [label="USB-TTL\n轉接器", fillcolor="#bac8d3"];
sensor:AO:e -> pic:RA0:w [color="green"];
sensor:DO:e -> pic:RB0:w [color="green"];
btn:e -> pic:RB0:w [color="green"];
servo1:e -> pic:RC2:w [color="orange", dir="back"];
servo2:e -> pic:RC1:w [color="orange", dir="back"];
pic:RD0:e -> buzzer:w [color="blue"];
pic:RD1:e -> TIP122:B:w [color="blue"];
pic:vcc:e -> pc_usb:w [color="red", dir="back"];
pic:gnd:e -> pc_usb:w [color="black", dir="back"];
pic:RC6:e -> pc_usb:w [color="green"];
pc_usb:w -> pic:RC7:e [color="gray"];
pic:RD4to7:e -> leds:w [color="blue"];
}
```
```graphviz
digraph hardware_wiring {
rankdir=LR;
label = "TIP122 + Motor 3 + 6V Power Supply 電路圖";
fontname="Sans-Serif";
node [fontname="Sans-Serif", fontsize=10, style="filled"];
edge [fontname="Sans-Serif", fontsize=9];
node [shape=record, fillcolor="#fff2cc", color="#d6b656"];
pic [label="{ PIC18F4520 | {<RD1> RD1 | <gnd> VSS (GND)} }"];
node [shape=record, style="filled,rounded", fillcolor="#e1d5e7", color="#9673a6"];
pwr [label="6V Power\nSupply", shape=cylinder, fillcolor="#f8cecc"];
TIP122 [label="{{ <B> B | <C> C | <E> E } | 3pin\nTIP122}", fillcolor="#f8cecc"];
motor3 [label="2pin\nMotor 3\n(沉水幫浦)", fillcolor="#dae8fc"];
pic:RD1:e -> TIP122:B:w [color="blue"];
motor3:s -> pwr:w [color="red", dir="back"];
motor3:e -> TIP122:C:w [color="black", dir="back"];
pwr:e -> TIP122:E:w [color="black"]
TIP122:E:w -> pic:gnd:e [color="black"]
}
```
## 四、系統開發工具、材料及技術
### 系統開發工具
MPLAB X IDE、MPLAB® PICkit 4、Python Streamlit
### 材料
- PIC18F4520
- SG90伺服馬達 * 2
- 4Pin火焰傳感器模組
- 蜂鳴器
- TIP122達林頓電晶體
- 沉水幫浦+矽膠軟管
- 6V外接電池盒
- 打火機
- Button、LED、杜邦線、鱷魚夾、電阻...
### 技術
#### 單元項目舉例:
- [x] Interrupt
- [x] Timer
- [x] PWM
- [x] UART
- [x] ADC
- [ ] SPI
#### 進階單元項目舉例:
- [x] 使用更多外部周邊,電子硬體元件(火焰感測器、蜂鳴器、沉水幫浦、TIP122達林頓電晶體)
- [ ] 能減少耗電、增加效率之軟硬體應用及演算法
- [x] 整合性、專題完整性、創新性
## 五、實際組員之分工項目
| 組員 | 分工項目 |
|:------ |:----------- |
| 柯智幃 | 伺服馬達與時脈設置、材料採購 |
| 陳睿謙 | 前端介面設計、類比輸出設置 |
| 鄭誌恩 | UART設置、蜂鳴器驅動與LED顯示、系統測試 |
| 莊凱程 | 系統架構設計、電路硬體整合、材料採購、報告撰寫 |
## 六、遇到的困難及如何解決
### 電源供應不足問題
對於同一個電壓 (筆電接出) 供應至多個設備 (PIC18F4520、火焰感測器、伺服馬達、蜂鳴器) ,分散輸出導致引腳電流太小,容易有供電不穩的情形。因此將沉水幫浦外接6V電源,單獨供電,並使用TIP122電晶體來作為電子開關,以小電流控制大電流,保護微處理器安全。
### 驅動沉水幫浦的電流供應
一開始使用碳鋅電池時,發現沉水幫浦雖然有過電聲響但無法順利抽水,且系統運作不穩。因為沉水幫浦啟動時的瞬時電流需求極大,碳鋅電池的放電能力與續航力不足以支撐。我們將電源更換為高能量密度且低內阻的鹼性電池後,成功解決了瞬間壓降導致的啟動失敗問題。
### 沉水幫浦的運作問題
即使沉水幫浦馬達正常運轉,但若矽膠軟管或幫浦內存有空氣,葉片會因為在空氣中空轉而無法產生足夠的負壓,導致無法出水。我們將這種非自吸式的設計,在啟動前手動將矽膠管充滿水以排出空氣(預先灌水),讓幫浦葉片能順利推動水流。
## 七、程式碼與影片
[程式碼](https://github.com/KyntonKCC/NCKU_114-1_Microprocessor_Final_Project)
[影片](https://www.youtube.com/shorts/g-ZNsFBYXuA)