# 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 儀表板,即時解析數據並繪製溫度與角度圖表,實現遠端視覺化監控。 ![Dashboard](https://hackmd.io/_uploads/r1nq3wGmWl.png) ## 二、系統使用環境及對象 系統設計於居家、實驗室或小型倉儲等室內平坦環境。運作時需避免太陽直射或強光干擾,以確保紅外線感測準確度。同時需透過 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)