的智能風(fēng)扇控制系統(tǒng)設(shè)計(jì):溫度采集、PWM調(diào)速與人體感應(yīng)完整方案)
簡介這份資源是面向電子、自動(dòng)化及單片機(jī)課程學(xué)習(xí)者與硬件愛好者的智能風(fēng)扇控制系統(tǒng)完整設(shè)計(jì)文檔針對(duì)傳統(tǒng)電扇人走不停、檔位無法隨溫度自動(dòng)調(diào)節(jié)等不合理使用現(xiàn)狀給出了一套可實(shí)際焊接驗(yàn)證的改進(jìn)方案。壓縮包內(nèi)共1個(gè)doc文件約2.07MB內(nèi)容涵蓋系統(tǒng)整體設(shè)計(jì)、硬件電路與軟件設(shè)計(jì)三大板塊可直接編輯使用。硬件部分涉及STC89C52最小系統(tǒng)、DS18B20溫度采集、FM24C02掉電存儲(chǔ)、人體紅外感應(yīng)、L298N驅(qū)動(dòng)直流電機(jī)PWM調(diào)速、蜂鳴器報(bào)警及LCD1602風(fēng)速等級(jí)顯示軟件部分以C語言實(shí)現(xiàn)溫度采集、上下限設(shè)置、外部中斷與定時(shí)器配合、紅外開關(guān)電機(jī)等邏輯并附有中斷指令精簡、晶振選型等排錯(cuò)思路。目前已有732人學(xué)習(xí)下載適合課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)或硬件入門者參考便于二次開發(fā)與實(shí)物制作。1. 從“人走扇?!闭f起這份智能風(fēng)扇控制資料到底能干什么夏天教室里人走光了吊扇還在呼呼轉(zhuǎn)宿舍里溫度降下來了風(fēng)扇還卡在最高檔吹得人頭疼。這類場(chǎng)景幾乎每個(gè)做過校園硬件項(xiàng)目的人都見過也正是這份《基于單片機(jī)的智能風(fēng)扇控制系統(tǒng)設(shè)計(jì)完整資料》要解決的核心問題。它不是一篇純理論論文而是一套可以直接拿去用的完整設(shè)計(jì)資料包含硬件電路、軟件流程、模塊選型和調(diào)試思路適合正在做單片機(jī)課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)或者想拿一個(gè)成熟方案快速搭出實(shí)物的開發(fā)者。這套系統(tǒng)以 51 單片機(jī)STC89C52為主控圍繞溫度采集、人體感應(yīng)、PWM 調(diào)速、LCD 顯示和蜂鳴器報(bào)警五個(gè)模塊展開。它要回答的問題很具體怎么讓風(fēng)扇根據(jù)環(huán)境溫度自動(dòng)分檔調(diào)速怎么在人離開時(shí)自動(dòng)斷電怎么把溫度上下限存下來掉電不丟。如果你手頭正好有一個(gè)風(fēng)扇控制類的題目或者想找一個(gè)軟硬件都跑通的參考方案這份資料的完整度是夠用的。下面我按實(shí)際復(fù)現(xiàn)的順序把關(guān)鍵模塊和容易翻車的地方拆開講。2. 硬件架構(gòu)拆解最小系統(tǒng)、DS18B20 與 L298N 怎么接2.1 為什么選 11.0592MHz 晶振而不是 12MHz最小系統(tǒng)是整個(gè)板子能不能跑起來的地基。這份資料里明確用了 11.0592MHz 晶振而不是很多人隨手抓的 12MHz。原因在串口和定時(shí)器11.0592MHz 能被 9600、19200 等常用波特率整除定時(shí)器初值算出來是整數(shù)長時(shí)間運(yùn)行不會(huì)累積誤差。12MHz 雖然看起來“整”但在需要精確定時(shí)的 PWM 調(diào)速場(chǎng)景里初值往往帶小數(shù)跑幾個(gè)小時(shí)就可能出現(xiàn)檔位漂移。復(fù)位電路這邊資料要求滿足 tRC2us保證復(fù)位高電平維持兩個(gè)機(jī)器周期以上。STC89C52 的 9 腳RST需要高電平復(fù)位典型做法是 10uF 電容配 10K 電阻。這里有個(gè)血淚經(jīng)驗(yàn)電解電容極性接反上電瞬間復(fù)位正常但斷電再上電就可能復(fù)位失敗表現(xiàn)是“有時(shí)候能跑有時(shí)候不能跑”查半天查不出原因。# 最小系統(tǒng)上電自檢思路用萬用表逐點(diǎn)測(cè) # 1. 測(cè) VCC 對(duì) GND應(yīng)為 5V ± 0.2V # 2. 測(cè) RST 腳上電瞬間應(yīng)有短暫高電平穩(wěn)定后為 0V # 3. 測(cè) XTAL1/XTAL2示波器應(yīng)看到 11.0592MHz 正弦波 # 4. 測(cè) EA 腳接 VCC 表示使用內(nèi)部程序存儲(chǔ)器上面這幾步是我每次焊完板子必走的流程。EA 腳很多人會(huì)忘懸空時(shí)單片機(jī)從外部存儲(chǔ)器取指令程序根本跑不起來現(xiàn)象就是“燒錄成功但沒反應(yīng)”。2.2 DS18B20 的溫度采集與 FM24C02 掉電存儲(chǔ)溫度采集用 DS18B20單總線協(xié)議只需要一個(gè) I/O 口。資料里用 P0 口控制數(shù)碼管段選、P1 口控制位選DS18B20 單獨(dú)占一個(gè)引腳。這里要注意的是單總線的時(shí)序DS18B20 對(duì)延時(shí)非常敏感讀時(shí)隙和寫時(shí)隙的微秒級(jí)延時(shí)必須準(zhǔn)。常見做法是用定時(shí)器做微秒延時(shí)而不是靠for循環(huán)空轉(zhuǎn)否則晶振一換時(shí)序就全亂。溫度上下限存在 FM24C02 里I2C 接口掉電不丟。默認(rèn)上限 45 度、下限 20 度通過四個(gè)獨(dú)立按鍵設(shè)置、復(fù)位、加、減動(dòng)態(tài)調(diào)整。FM24C02 的寫周期比較慢寫完一字節(jié)后要留 5ms 左右的內(nèi)部寫時(shí)間連續(xù)寫多個(gè)字節(jié)時(shí)如果不等后面的數(shù)據(jù)會(huì)丟。我一般會(huì)在寫操作后加一個(gè)短延時(shí)或者用應(yīng)答輪詢確認(rèn)寫完成。模塊器件接口方式關(guān)鍵參數(shù)主控STC89C52—11.0592MHz 晶振溫度采集DS18B20單總線精度 0.5°C測(cè)溫范圍 -55~125°C存儲(chǔ)FM24C02I2C2Kbit擦寫次數(shù) 100 萬次電機(jī)驅(qū)動(dòng)L298NPWM驅(qū)動(dòng)電壓 5~35V峰值電流 2A顯示LCD1602并口16x2 字符顯示風(fēng)速等級(jí)人體感應(yīng)紅外傳感器I/O 電平有人輸出高電平2.3 L298N 驅(qū)動(dòng)直流電機(jī)與 PWM 調(diào)速原理PWM 調(diào)速的核心公式是 Ud (t/T) × Us ρ × Us其中 ρ 是占空比t 是高電平時(shí)間T 是周期。改變 ρ 就能改變電機(jī)兩端的平均電壓從而改變轉(zhuǎn)速。資料里通過定時(shí)器產(chǎn)生 PWM 波不同溫度區(qū)間對(duì)應(yīng)不同占空比實(shí)現(xiàn)風(fēng)速分檔。L298N 的使能腳接 PWM 輸出方向腳接普通 I/O。這里有個(gè)容易翻車的點(diǎn)L298N 的使能腳如果是高電平有效PWM 占空比為 0 時(shí)電機(jī)停轉(zhuǎn)但如果你把方向腳和使能腳接反了會(huì)出現(xiàn)“占空比越大電機(jī)越慢”的玄學(xué)現(xiàn)象。我一般會(huì)先用固定占空比 50% 測(cè)一下轉(zhuǎn)向和轉(zhuǎn)速確認(rèn)接線無誤再寫調(diào)速邏輯。// PWM 調(diào)速核心邏輯51 單片機(jī)定時(shí)器實(shí)現(xiàn) // 假設(shè)使用 Timer0 產(chǎn)生 PWM周期 1ms分 100 個(gè)等級(jí) void Timer0_ISR() interrupt 1 { static unsigned char pwm_count 0; TH0 (65536 - 100) / 256; // 100us 中斷一次 TL0 (65536 - 100) % 256; pwm_count; if (pwm_count 100) pwm_count 0; // duty_cycle 由溫度區(qū)間決定范圍 0~100 if (pwm_count duty_cycle) { MOTOR_EN 1; // 使能電機(jī) } else { MOTOR_EN 0; // 關(guān)閉電機(jī) } }這段代碼里duty_cycle是根據(jù)溫度查表得到的。比如溫度低于下限duty_cycle0電機(jī)停溫度在下限到 25 度之間duty_cycle3025 到 35 度之間duty_cycle60高于上限duty_cycle100 并觸發(fā)蜂鳴器報(bào)警。參數(shù)怎么改改中斷頻率和計(jì)數(shù)上限就行但要注意中斷太頻繁會(huì)占用 CPU100us 一次在 11.0592MHz 下大概執(zhí)行 100 多條指令留給主程序的時(shí)間還夠用。3. 軟件流程與中斷設(shè)計(jì)溫度采集、紅外感應(yīng)和按鍵怎么協(xié)同3.1 主循環(huán)與中斷的分工原則資料里特別強(qiáng)調(diào)了一點(diǎn)中斷程序里要執(zhí)行的指令盡可能少把耗時(shí)操作放在主函數(shù)中。這是 51 單片機(jī)編程的鐵律。中斷里如果做 DS18B20 的完整讀寫一次溫度轉(zhuǎn)換要 750ms下次中斷來了還沒執(zhí)行完程序必亂。正確的做法是中斷里只置標(biāo)志位主循環(huán)檢測(cè)到標(biāo)志位再執(zhí)行具體任務(wù)。// 主循環(huán)框架 volatile bit temp_flag 0; // 溫度采集標(biāo)志 volatile bit ir_flag 0; // 紅外檢測(cè)標(biāo)志 volatile bit key_flag 0; // 按鍵標(biāo)志 void main() { Init_System(); // 初始化定時(shí)器、LCD、DS18B20 while (1) { if (temp_flag) { temp_flag 0; Read_Temp(); // 讀 DS18B20耗時(shí)操作放主循環(huán) Update_Fan_Speed(); // 根據(jù)溫度調(diào)整 PWM Display_Temp(); // 數(shù)碼管顯示溫度 } if (ir_flag) { ir_flag 0; Check_Human(); // 檢測(cè)人體紅外控制電機(jī)開關(guān) } if (key_flag) { key_flag 0; Handle_Key(); // 處理按鍵修改溫度上下限 } } }這個(gè)框架的好處是中斷響應(yīng)快主循環(huán)任務(wù)清晰。volatile關(guān)鍵字不能省否則編譯器優(yōu)化后可能把標(biāo)志位讀到寄存器里主循環(huán)永遠(yuǎn)看不到中斷的修改。3.2 人體紅外模塊的“寫 1 讀入”陷阱51 單片機(jī)的 P1、P2、P3 口是準(zhǔn)雙向 I/O做輸入口使用時(shí)必須先寫 1。資料里明確寫了這一點(diǎn)人體紅外傳感器有人時(shí)輸出高電平單片機(jī)讀取前要先給該 I/O 口寫 1。如果不寫 1口線內(nèi)部的下拉會(huì)把它拉低讀回來永遠(yuǎn)是 0現(xiàn)象就是“人站在傳感器前面風(fēng)扇也不轉(zhuǎn)”。// 人體紅外檢測(cè)正確寫法 sbit IR_PIN P1^0; // 紅外傳感器接 P1.0 sbit MOTOR_EN P1^1; // 電機(jī)使能 void Check_Human() { IR_PIN 1; // 先寫 1準(zhǔn)雙向口做輸入的必要步驟 delay_us(10); // 等電平穩(wěn)定 if (IR_PIN 1) { MOTOR_EN 1; // 有人允許電機(jī)運(yùn)行 } else { MOTOR_EN 0; // 無人關(guān)閉電機(jī) } }紅外傳感器的靈敏度和安裝位置關(guān)系很大。資料里提到“應(yīng)盡量避免盲區(qū)”實(shí)際調(diào)試時(shí)我發(fā)現(xiàn)傳感器正對(duì)門口和斜對(duì)墻角的效果完全不同。常見做法是先固定傳感器人走一遍測(cè)試區(qū)域用串口打印檢測(cè)結(jié)果確認(rèn)覆蓋范圍后再寫邏輯。3.3 按鍵中斷與溫度上下限的動(dòng)態(tài)調(diào)整按鍵接 P3.2 口作為外部中斷 0 的輸入。程序跑到死循環(huán)處等待中斷檢測(cè)到按鍵按下并釋放后執(zhí)行中斷行為。四個(gè)按鍵分別對(duì)應(yīng)設(shè)置、復(fù)位、加、減。設(shè)置鍵進(jìn)入設(shè)置模式加/減鍵修改當(dāng)前選中的參數(shù)上限或下限復(fù)位鍵恢復(fù)默認(rèn)值 45/20。這里有個(gè)細(xì)節(jié)按鍵按下和釋放之間需要消抖。硬件消抖用 0.1uF 電容并聯(lián)按鍵軟件消抖在中斷里延時(shí) 10ms 再讀一次。如果只做硬件消抖按鍵質(zhì)量差的時(shí)候還是會(huì)有誤觸發(fā)只做軟件消抖中斷里延時(shí)太長又影響其他中斷響應(yīng)。我一般兩個(gè)都做硬件電容 軟件短延時(shí)穩(wěn)。溫度上下限修改后要立刻寫入 FM24C02否則掉電就丟。寫完之后 LCD1602 上要同步更新顯示讓用戶知道當(dāng)前設(shè)定值。LCD1602 的顯示刷新不要太頻繁否則屏幕會(huì)閃一般 200ms 刷一次就夠了。4. 避坑與排查從“能燒錄但不跑”到“風(fēng)速檔位亂跳”4.1 現(xiàn)象程序燒錄成功但數(shù)碼管不亮、電機(jī)不轉(zhuǎn)原因EA 腳懸空或接錯(cuò)。STC89C52 的 EA 腳必須接 VCC 才能從內(nèi)部程序存儲(chǔ)器執(zhí)行代碼。很多人焊最小系統(tǒng)時(shí)漏了這個(gè)腳或者誤以為它和普通 I/O 一樣可以懸空。解決用萬用表測(cè) EA 腳對(duì) GND 電壓正常應(yīng)該是 5V。如果為 0 或懸空飛線接到 VCC。4.2 現(xiàn)象DS18B20 讀回來永遠(yuǎn)是 85 度原因DS18B20 上電默認(rèn)溫度寄存器就是 85 度如果初始化時(shí)序不對(duì)讀到的就是默認(rèn)值。常見問題是延時(shí)不夠復(fù)位脈沖拉低時(shí)間不足 480us或者存在脈沖檢測(cè)超時(shí)。解決用示波器看單總線波形復(fù)位脈沖拉低至少 480us然后釋放等待 15~60us 后 DS18B20 會(huì)拉低總線 60~240us 作為存在脈沖。如果看不到存在脈沖檢查上拉電阻通常 4.7K是否接好。4.3 現(xiàn)象PWM 調(diào)速時(shí)電機(jī)發(fā)出嘯叫轉(zhuǎn)速不穩(wěn)原因PWM 頻率太低落在人耳可聽范圍內(nèi)。資料里沒有明確寫 PWM 頻率但常見做法是 1kHz 以上。如果定時(shí)器中斷設(shè)成 1ms 一次、100 級(jí)調(diào)速PWM 頻率只有 10Hz電機(jī)不嘯叫才怪。解決把中斷周期改小比如 100us 一次100 級(jí)調(diào)速對(duì)應(yīng) 100Hz還是偏低改成 50us 一次對(duì)應(yīng) 200Hz勉強(qiáng)可以最好做到 1kHz 以上即中斷周期 10us但 51 單片機(jī)在 11.0592MHz 下 10us 只能執(zhí)行 100 多條指令中斷里做不了太多事。折中方案是減少調(diào)速等級(jí)比如 20 級(jí)中斷 100us 一次PWM 頻率 500Hz嘯叫明顯減小。4.4 現(xiàn)象人走了風(fēng)扇還在轉(zhuǎn)或者人沒走風(fēng)扇停了原因紅外傳感器安裝位置有盲區(qū)或者檢測(cè)邏輯寫反了。有些紅外模塊有人輸出低電平無人輸出高電平和資料里寫的相反。解決先單獨(dú)測(cè)試紅外模塊用串口打印輸出電平確認(rèn)有人/無人對(duì)應(yīng)的電平狀態(tài)。然后檢查代碼里的判斷條件if (IR_PIN 1)還是if (IR_PIN 0)要和實(shí)際模塊匹配。安裝位置避免正對(duì)空調(diào)出風(fēng)口或陽光直射這些都會(huì)干擾紅外檢測(cè)。4.5 現(xiàn)象溫度上下限改了之后掉電再上電又變回默認(rèn)值原因FM24C02 寫入后沒有等待內(nèi)部寫周期完成或者 I2C 時(shí)序不對(duì)數(shù)據(jù)根本沒寫進(jìn)去。解決每次寫 FM24C02 后加 5ms 延時(shí)或者用應(yīng)答輪詢。讀的時(shí)候先寫器件地址寫模式再寫內(nèi)存地址然后重啟 I2C 寫器件地址讀模式再讀數(shù)據(jù)。這個(gè)流程一步都不能少少一步就讀出 0xFF。5. 進(jìn)階技巧把風(fēng)速檔位從“拍腦袋”變成“查表可調(diào)”這套資料給的是一個(gè)基礎(chǔ)可跑的版本但實(shí)際用起來風(fēng)速檔位的劃分往往需要根據(jù)場(chǎng)景微調(diào)。我一般會(huì)把溫度區(qū)間和占空比的對(duì)應(yīng)關(guān)系做成一張表放在代碼開頭改參數(shù)不用翻遍整個(gè)程序。溫度區(qū)間占空比風(fēng)速等級(jí)LCD 顯示蜂鳴器 20°C0%停OFF不響20~25°C30%1 檔FAN-1不響25~30°C50%2 檔FAN-2不響30~35°C70%3 檔FAN-3不響35~45°C90%4 檔FAN-4不響 45°C100%5 檔FAN-5響這張表可以直接用數(shù)組存在代碼里溫度采集后查表得到占空比。改的時(shí)候只動(dòng)數(shù)組邏輯不用碰。// 溫度-占空比查表法 unsigned char code duty_table[6] {0, 30, 50, 70, 90, 100}; unsigned char code level_table[6] {0, 1, 2, 3, 4, 5}; unsigned char Get_Duty_Cycle(unsigned char temp) { if (temp 20) return duty_table[0]; else if (temp 25) return duty_table[1]; else if (temp 30) return duty_table[2]; else if (temp 35) return duty_table[3]; else if (temp 45) return duty_table[4]; else return duty_table[5]; }驗(yàn)證方法很簡單用熱風(fēng)槍或吹風(fēng)機(jī)對(duì)著 DS18B20 加熱觀察 LCD 顯示的風(fēng)速等級(jí)是否逐級(jí)變化同時(shí)用示波器測(cè)電機(jī)使能腳的占空比是否和表格一致。如果等級(jí)跳變但占空比沒變查duty_table的索引是不是寫錯(cuò)了。還有一個(gè)進(jìn)階玩法把人體紅外和溫度控制做成“與”邏輯。有人且溫度高于下限才轉(zhuǎn)無人直接停。這樣比單獨(dú)用紅外或單獨(dú)用溫度更省電。代碼上就是把兩個(gè)條件串起來但要注意優(yōu)先級(jí)——人走了立刻停溫度再高也不轉(zhuǎn)。從那以后我每次做風(fēng)扇類項(xiàng)目都會(huì)先把這張溫度-占空比表填好再動(dòng)手寫代碼。表沒定下來就寫邏輯改起來就是災(zāi)難。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取