澆花系統(tǒng)實(shí)戰(zhàn):土壤濕度傳感器與狀態(tài)機(jī)設(shè)計(jì))
簡(jiǎn)介這是一套STM32自動(dòng)澆花系統(tǒng)的完整工程資源面向嵌入式初學(xué)者、電子競(jìng)賽選手及智能硬件DIY愛好者解決植物養(yǎng)護(hù)中土壤濕度、光照強(qiáng)度與空氣溫濕度的自動(dòng)監(jiān)測(cè)以及按需智能澆水的問題。壓縮包共535個(gè)文件、約27.77MB包含86個(gè)C語言源文件、70個(gè)頭文件、原理圖與PCB的PNG圖片、PDF說明文檔、TXT配置記錄和Keil工程文件等可完整看到從驅(qū)動(dòng)編寫到應(yīng)用層控制的代碼結(jié)構(gòu)目錄層次清晰。系統(tǒng)以STM32F103C8T6為核心集成土壤溫濕度、光敏及空氣溫濕度傳感器通過OLED實(shí)時(shí)顯示環(huán)境參數(shù)并由水泵依據(jù)定時(shí)或濕度閾值觸發(fā)灌溉文件中還涉及DC-DC電源模塊、繼電器控制和PCB布局設(shè)計(jì)能幫助理解傳感器采集、信號(hào)處理與功率驅(qū)動(dòng)的完整鏈路。目前已有3773人學(xué)習(xí)下載資源內(nèi)附帶工程源碼、原理圖與說明文檔便于對(duì)照硬件設(shè)計(jì)和軟件邏輯進(jìn)行排障、移植或擴(kuò)展為更高階的物聯(lián)網(wǎng)澆花平臺(tái)。1. 項(xiàng)目背景與整體設(shè)計(jì)思路1.1 為什么值得做一個(gè)自動(dòng)澆花系統(tǒng)做這個(gè)項(xiàng)目的起因特別簡(jiǎn)單我家里養(yǎng)了十幾盆綠植隔三差五出差回來不是干死就是澇死?;ㄅ枥锏耐寥罎穸冗@事兒靠肉眼和經(jīng)驗(yàn)真的很難把控——表面看著干了底下可能還濕著表面摸著濕潤(rùn)底下可能已經(jīng)干透了。后來一想這不就是個(gè)典型的嵌入式控制問題嗎傳感器采集數(shù)據(jù)、MCU做決策、執(zhí)行器干活STM32剛好樣樣都能干。這個(gè)系統(tǒng)說起來不復(fù)雜核心就是三件事測(cè)土壤濕度、判斷要不要澆水、控制水泵澆水。但真正做下來你會(huì)發(fā)現(xiàn)每個(gè)環(huán)節(jié)都有不少值得摳的細(xì)節(jié)——傳感器選型、ADC采樣穩(wěn)定性、水泵驅(qū)動(dòng)方式、澆水策略設(shè)計(jì)哪一個(gè)做不好都會(huì)影響實(shí)際使用效果。也正因?yàn)槿绱怂貏e適合作為STM32的入門到進(jìn)階的練手項(xiàng)目既是經(jīng)典的畢設(shè)選題也是很多電子愛好者會(huì)做的第一個(gè)能真正解決生活問題的小作品。1.2 系統(tǒng)架構(gòu)與技術(shù)選型整個(gè)系統(tǒng)的數(shù)據(jù)流向是這樣的土壤濕度傳感器實(shí)時(shí)檢測(cè)花盆里的濕度輸出電壓信號(hào)STM32通過ADC引腳讀取電壓換算成濕度值主控芯片根據(jù)預(yù)設(shè)的閾值和澆水策略決定是否開啟水泵水泵通過MOS管或繼電器驅(qū)動(dòng)從水箱抽水澆灌同時(shí)可以加一個(gè)OLED屏或數(shù)碼管顯示實(shí)時(shí)濕度或者通過串口把數(shù)據(jù)發(fā)到電腦上監(jiān)控在這個(gè)架構(gòu)里最推薦也最通用的方案是STM32F103C8T6作為主控這是整個(gè)STM32家族里性價(jià)比最高、資料最全的一顆芯片網(wǎng)絡(luò)上隨便一搜就能找到大量參考代碼和教程遇到問題也容易查。傳感器方面土壤濕度探頭有兩種主流類型——電阻式和電容式這個(gè)選擇直接影響系統(tǒng)的使用壽命我后面會(huì)專門講。軟件層面我這次用的是HAL庫(kù)配合STM32CubeMX做初始化配置。相比標(biāo)準(zhǔn)庫(kù)HAL庫(kù)的抽象層更清晰而且CubeMX可以圖形化配置引腳和時(shí)鐘幾秒鐘就能生成工程框架特別適合這種中小型項(xiàng)目。如果你之前習(xí)慣用標(biāo)準(zhǔn)庫(kù)也沒問題核心邏輯是一樣的無非是寄存器操作和封裝函數(shù)調(diào)用的區(qū)別。2. 硬件選型與電路設(shè)計(jì)細(xì)節(jié)2.1 核心器件清單與選型理由先把這次用到的所有硬件列個(gè)清單都是很常見、容易買到且價(jià)格不貴的器件器件型號(hào)/規(guī)格作用參考價(jià)格主控STM32F103C8T6最小系統(tǒng)板核心控制10-15元土壤濕度傳感器電容式推薦或電阻式檢測(cè)土壤濕度3-10元水泵3.3V-5V微型潛水泵抽水澆灌5-15元驅(qū)動(dòng)模塊MOS管模塊如AO3400或5V繼電器驅(qū)動(dòng)水泵通斷2-8元電源USB 5V/2A供電或18650電池組系統(tǒng)供電10-20元顯示模塊0.96寸OLEDI2C接口顯示濕度與狀態(tài)8-15元其他面包板/洞洞板、杜邦線、水箱連接與結(jié)構(gòu)件10元左右這里面有兩點(diǎn)要特別說一下。第一是傳感器類型電阻式濕度探頭靠?jī)筛饘偬结槻迦胪寥罍y(cè)的是土壤的電阻值價(jià)格便宜兩三塊錢一個(gè)但有個(gè)致命缺點(diǎn)——金屬探針在濕潤(rùn)土壤里通電久了會(huì)發(fā)生電解腐蝕用個(gè)把月讀數(shù)就開始漂移最后徹底失效。電容式探頭測(cè)的是土壤介電常數(shù)變化電極不會(huì)直接接觸土壤壽命長(zhǎng)得多雖然貴幾塊錢但從長(zhǎng)期使用角度絕對(duì)劃算。我自己的第一版用的就是電阻式三個(gè)月壞了兩個(gè)探頭后來?yè)Q了電容式用了大半年一點(diǎn)問題沒有。第二是水泵驅(qū)動(dòng)方式。STM32的GPIO引腳最大只能輸出20mA左右的電流直接驅(qū)動(dòng)水泵想都不要想必須要加驅(qū)動(dòng)電路。兩種主流方案里繼電器的好處是導(dǎo)通電阻極小、壓降低缺點(diǎn)是機(jī)械觸點(diǎn)有壽命限制而且頻繁通斷會(huì)有咔嗒聲MOS管是純電子開關(guān)無機(jī)械磨損、開關(guān)頻率高但需要注意選型——AO3400這種低壓MOS管在3.3V柵極電壓下能完全導(dǎo)通是STM32項(xiàng)目的常見搭配。我推薦用MOS管方案靜音而且壽命長(zhǎng)。2.2 電路連接與接線要點(diǎn)我這次的實(shí)際接線方案是這樣的以STM32F103C8T6最小系統(tǒng)板為例電容式土壤濕度傳感器VCC接3.3VGND接GNDAO模擬輸出接PA0ADC1通道0OLED顯示屏VCC接3.3VGND接GNDSCL接PB6I2C1_SCLSDA接PB7I2C1_SDAMOS管模塊信號(hào)端接PA1電源正極接5V輸出端串接水泵正極水泵負(fù)極接GND水泵供電如果水泵是3.3V-5V額定電壓可以直接從USB 5V取電如果水泵功率稍大比如超過2W建議單獨(dú)用一節(jié)鋰電池供電避免水泵啟動(dòng)瞬間拉低系統(tǒng)電壓導(dǎo)致MCU復(fù)位這里有兩個(gè)非常容易踩的坑我當(dāng)初都吃過虧。第一個(gè)是共地問題——傳感器、OLED、模塊和STM32必須共地也就是所有GND要連到一起否則信號(hào)電壓沒有參考點(diǎn)ADC讀出來的數(shù)據(jù)會(huì)完全亂掉。我第一版調(diào)試時(shí)OLED死活不亮折騰了兩小時(shí)最后發(fā)現(xiàn)是I2C模塊的GND沒接簡(jiǎn)直是基礎(chǔ)中的基礎(chǔ)但坑人于無形。第二個(gè)是水泵供電不要直接從STM32的3.3V引腳取。水泵啟動(dòng)瞬間的電流尖峰能到額定電流的三四倍如果整個(gè)系統(tǒng)都用USB 5V供電水泵啟動(dòng)時(shí)電壓會(huì)被拉低到4V甚至更低STM32F103雖然自帶穩(wěn)壓電路能撐住3.6V以上的供電但供電電壓猛跌還是會(huì)導(dǎo)致執(zhí)行異常、ADC讀數(shù)跳變。穩(wěn)妥做法是主控用3.3V供電從板上LDO出來水泵單獨(dú)從5V電源軌取電中間只通過MOS管做開關(guān)隔離。另外MOS管模塊的選型還要注意一個(gè)參數(shù)——邏輯電平。有些模塊板載了三極管放大電路輸入高電平閾值比較高3.3V的GPIO可能驅(qū)動(dòng)不徹底最好選那種信號(hào)端直接接MOS管柵極的純模塊或者用AO3400自己去搭3.3V驅(qū)動(dòng)完全沒問題。3. 軟件核心邏輯與代碼實(shí)現(xiàn)3.1 CubeMX工程初始化配置軟件部分我習(xí)慣先用STM32CubeMX生成初始化代碼把引腳和時(shí)鐘配置好再在生成的框架上寫業(yè)務(wù)邏輯。關(guān)鍵配置項(xiàng)如下調(diào)試接口Serial WireSWD保留調(diào)試下載能力。這里要提醒一下很多人新建工程時(shí)會(huì)把調(diào)試接口選成No Debug結(jié)果第一次下載程序后就再也連不上芯片了只能按住復(fù)位鍵搶時(shí)間擦除非常折騰。時(shí)鐘HSE外部晶振8MHzPLL倍頻到72MHz主頻。F103的最高主頻就是72MHz跑這種邏輯綽綽有余。ADC1開啟通道0PA0配置為連續(xù)轉(zhuǎn)換模式分辨率12位采樣時(shí)間盡量拉長(zhǎng)——我用的55.5周期因?yàn)橥寥罎穸葌鞲衅鬏敵鲎杩蛊卟蓸訒r(shí)間太短會(huì)導(dǎo)致采到的電壓偏低。關(guān)于這一點(diǎn)我后面會(huì)在問題排查里細(xì)說。I2C1標(biāo)準(zhǔn)模式100KHz或快速模式400KHz都行OLED屏用100KHz比較穩(wěn)。GPIOPA1配置為推挽輸出用于控制MOS管。推挽輸出比開漏輸出好因?yàn)殚_漏不接上拉電阻的話輸出不了高電平。CubeMX生成的代碼框架里時(shí)鐘初始化、GPIO初始化、ADC初始化、I2C初始化都是現(xiàn)成的直接在main.c里寫業(yè)務(wù)邏輯就行。3.2 濕度采集與數(shù)據(jù)處理ADC采樣的核心邏輯很直接但有幾個(gè)細(xì)節(jié)決定最終效果。我的代碼如下uint16_t adc_read_raw(void) { HAL_ADC_Start(hadc1); HAL_ADC_PollForConversion(hadc1, 10); if (HAL_IS_BIT_SET(hadc1.Instance-SR, ADC_FLAG_EOC)) return HAL_ADC_GetValue(hadc1); return 0; } float get_soil_moisture_percent(void) { uint32_t sum 0; const uint8_t samples 10; for (uint8_t i 0; i samples; i) { sum adc_read_raw(); HAL_Delay(1); } uint16_t avg sum / samples; // 校準(zhǔn)ADC值越大電壓越高濕度越小電容式傳感器輸出特性 if (avg 1500) return 100.0f; // 極濕 if (avg 3200) return 0.0f; // 極干 return (3200.0f - avg) / (3200.0f - 1500.0f) * 100.0f; }這段代碼里有幾個(gè)值得展開的點(diǎn)多次采樣取平均是有必要的。傳感器的模擬輸出會(huì)受土壤顆粒接觸狀態(tài)、環(huán)境EMI、電源紋波等多種因素影響單次采樣可能在10%的范圍內(nèi)波動(dòng)。我實(shí)測(cè)了10次采樣取平均后數(shù)據(jù)穩(wěn)定度從±80個(gè)ADC量化等級(jí)約±8%濕度降到了±15個(gè)等級(jí)以內(nèi)約±1.5%效果立竿見影。采樣間隔加1ms延時(shí)是為了讓ADC的采樣保持電容有足夠時(shí)間充電。如果連續(xù)快速讀后一次采樣會(huì)受前一次采樣殘留電荷影響導(dǎo)致結(jié)果偏向同一方向這種系統(tǒng)誤差靠多次平均也無法消除。線性換算公式里用的1500和3200這兩個(gè)校準(zhǔn)值是拿我的傳感器的輸出特性標(biāo)定的——把探頭完全泡在水里測(cè)ADC值約1500放在干燥空氣中約3200。不同品牌、不同批次探頭參數(shù)會(huì)有差異建議拿到傳感器后先用這兩組極端情況校準(zhǔn)一下再把代碼里的閾值換掉。這就是標(biāo)定省略了這一步系統(tǒng)可能永遠(yuǎn)無法在正確時(shí)機(jī)澆水。3.3 澆水策略與狀態(tài)機(jī)設(shè)計(jì)關(guān)鍵問題來了——怎么判斷該澆水了最直觀的方式是設(shè)定一個(gè)濕度閾值低于就開啟水泵高于就關(guān)閉。但直接這么做會(huì)產(chǎn)生一個(gè)實(shí)際問題澆水后土壤濕度變化有遲滯探頭周圍的水分?jǐn)U散到完全均勻需要時(shí)間如果閾值判斷頻率太高澆水啟動(dòng)幾秒后水分還沒擴(kuò)散開傳感器讀到的濕度還是低就會(huì)繼續(xù)澆結(jié)果澆過頭了。我的方案是引入滯回比較加狀態(tài)機(jī)澆水狀態(tài)機(jī) 狀態(tài)IDLE空閑 濕度 閾值下限如40%→ 進(jìn)入WATERING狀態(tài) 否則 → 保持IDLE 狀態(tài)WATERING澆水 澆水累計(jì)時(shí)間 單次最大時(shí)長(zhǎng)如5秒→ 進(jìn)入PAUSE狀態(tài) 濕度 閾值上限如65%→ 進(jìn)入COOLDOWN狀態(tài) 否則 → 保持WATERING 狀態(tài)PAUSE間隔等待 延時(shí)10秒等待水分?jǐn)U散和傳感器穩(wěn)定→ 進(jìn)入COOLDOWN狀態(tài) 狀態(tài)COOLDOWN冷卻保護(hù) 延時(shí)2分鐘防止水泵過熱和過度澆水→ 回到IDLE狀態(tài)為什么要有這么復(fù)雜的邏輯因?yàn)槲也冗^坑。最早我就是一個(gè)預(yù)設(shè)閾值直接判斷結(jié)果水泵頻繁開關(guān)——上午十點(diǎn)到下午兩點(diǎn)之間每小時(shí)啟停十幾次繼電器觸點(diǎn)都有點(diǎn)發(fā)黑了而且有時(shí)候剛澆完水沒多久傳感器讀數(shù)回落又觸發(fā)了一輪澆水整個(gè)系統(tǒng)感覺像在抽風(fēng)。改成狀態(tài)機(jī)之后邏輯清晰了很多。它保證了幾個(gè)關(guān)鍵特性單次澆水最多持續(xù)5秒不會(huì)因?yàn)閭鞲衅黜憫?yīng)慢而澆過頭每次澆水后強(qiáng)制冷卻2分鐘既保護(hù)水泵也避免系統(tǒng)神經(jīng)質(zhì)地反復(fù)澆臨界狀態(tài)下的滯回區(qū)間40%啟動(dòng)、65%停止避免了在閾值附近反復(fù)跳變。這個(gè)滯回狀態(tài)機(jī)的思路不夸張地說適用于幾乎所有帶執(zhí)行器的自動(dòng)控制系統(tǒng)——空調(diào)溫控、魚缸加熱棒、智能窗簾都是同一個(gè)模式。學(xué)會(huì)這一招很多項(xiàng)目就都能舉一反三了??刂撇糠值暮诵拇a如下typedef enum { STATE_IDLE 0, STATE_WATERING, STATE_PAUSE, STATE_COOLDOWN } system_state_t; system_state_t state STATE_IDLE; uint32_t state_start_tick 0; void watering_task(void) { float soil_humidity get_soil_moisture_percent(); uint32_t now HAL_GetTick(); switch (state) { case STATE_IDLE: if (soil_humidity 40.0f) { state STATE_WATERING; state_start_tick now; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // 開泵 } break; case STATE_WATERING: if (soil_humidity 65.0f) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // 停泵 state STATE_PAUSE; state_start_tick now; } else if (now - state_start_tick 5000) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // 超時(shí)停泵 state STATE_PAUSE; state_start_tick now; } break; case STATE_PAUSE: if (now - state_start_tick 10000) { state STATE_COOLDOWN; state_start_tick now; } break; case STATE_COOLDOWN: if (now - state_start_tick 120000) { state STATE_IDLE; state_start_tick now; } break; } }注意我用了HAL_GetTick()作為時(shí)間基準(zhǔn)這是HAL庫(kù)內(nèi)置的毫秒計(jì)數(shù)器從系統(tǒng)啟動(dòng)開始累加靠Systick中斷驅(qū)動(dòng)用它來計(jì)時(shí)比空轉(zhuǎn)延時(shí)靠譜得多。千萬不要在狀態(tài)機(jī)里用HAL_Delay()——那會(huì)阻塞整個(gè)主循環(huán)傳感器采集和其他任務(wù)都會(huì)被卡住。4. 數(shù)據(jù)監(jiān)控與功能擴(kuò)展4.1 OLED顯示與串口輸出系統(tǒng)做出來總要能直觀地看到數(shù)據(jù)不然每次調(diào)試都得用電腦接串口看日志。我加了一塊0.96寸OLEDI2C接口SSD1306驅(qū)動(dòng)芯片實(shí)時(shí)顯示土壤濕度百分比和當(dāng)前系統(tǒng)狀態(tài)。顯示的數(shù)據(jù)包括土壤濕度XX%實(shí)時(shí)刷新系統(tǒng)狀態(tài)IDLE / WATERING / PAUSE / COOLDOWN本次澆水累計(jì)時(shí)長(zhǎng)便于觀察系統(tǒng)行為OLED的驅(qū)動(dòng)代碼用的是常見的SSD1306軟件庫(kù)在GitHub上搜ssd1306 hal就能找到U8g2庫(kù)也可以只是體積略大。I2C只要初始化對(duì)了剩下的就是往顯存里寫像素然后在主循環(huán)里調(diào)用顯示刷新函數(shù)。串口輸出也是一個(gè)很好的調(diào)試手段。初始化一個(gè)USART比如USART1PA9/PA10用printf重定向到串口就可以在電腦上通過串口助手實(shí)時(shí)監(jiān)控系統(tǒng)狀態(tài)。重定向代碼很簡(jiǎn)單#include stdio.h int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xFFFF); return ch; }然后就可以在代碼里用printf(Soil humidity: %.1f%%\n, soil_humidity);打印日志了。這個(gè)能力在調(diào)試狀態(tài)機(jī)邏輯的時(shí)候極其有用不用靠猜直接看串口數(shù)據(jù)就能知道系統(tǒng)在哪個(gè)狀態(tài)、做了什么決策。4.2 擴(kuò)展方向WiFi控制和多區(qū)域澆灌做完了基礎(chǔ)版本你會(huì)發(fā)現(xiàn)這個(gè)系統(tǒng)的擴(kuò)展空間非常大。我自己的下一步計(jì)劃是加一塊ESP8266模塊通過串口和STM32通信實(shí)現(xiàn)手機(jī)端遠(yuǎn)程查看濕度和控制澆水。這個(gè)方向上熱搜詞里也提到了ESP8266 wifi模塊教程stm32和stm32 8266 宿舍控制燈開發(fā)實(shí)戰(zhàn)說明這個(gè)玩法確實(shí)是很多人在關(guān)注的熱點(diǎn)。ESP8266和STM32通信的要點(diǎn)是兩邊串口配置一致波特率115200是最常見的通信協(xié)議自己定義一個(gè)簡(jiǎn)單的幀格式就行了比如幀頭命令字?jǐn)?shù)據(jù)校驗(yàn)。用AT命令還是用SDK開發(fā)取決于你想做到多深入——如果只是想快速實(shí)現(xiàn)功能用AT命令就夠了如果追求低延遲和可靠性可以讓ESP8266跑MicroPython或Arduino固件把MQTT協(xié)議棧跑起來然后STM32只管采集和執(zhí)行邏輯層全部放到云端。還有一個(gè)很實(shí)用的擴(kuò)展是接多個(gè)濕度傳感器分管不同的花盆或區(qū)域。F103的ADC1有10個(gè)通道PA0-PA7、PB0、PB1每個(gè)通道接一個(gè)探頭用DMA循環(huán)采樣實(shí)現(xiàn)多區(qū)域獨(dú)立澆灌是完全可行的。這樣一套系統(tǒng)管一個(gè)陽(yáng)臺(tái)的綠植每盆花的澆水量都不一樣非常實(shí)用。5. 常見問題與排查技巧實(shí)錄這部分是我最想說的。整個(gè)項(xiàng)目從零到調(diào)通我踩了不少坑有些問題看起來莫名其妙但背后都是有規(guī)律可循的。我把最典型的幾個(gè)問題和解決思路整理成表格后面再挑幾個(gè)展開細(xì)說故障現(xiàn)象可能原因排查方法解決方案串口/調(diào)試器找不到芯片SWD引腳被禁用或被復(fù)用按住復(fù)位鍵的同時(shí)連調(diào)試器捕捉上電瞬間改用PA13/PA14的SWD接口避免復(fù)用程序里保留SWD配置OLED屏幕不亮或花屏I2C地址錯(cuò)誤或接線松脫I2C掃描程序查地址SSD1306常見地址是0x3C或0x3D確認(rèn)后修改宏定義ADC讀數(shù)一直為4095滿量程傳感器信號(hào)線懸空或引腳未配置為模擬模式萬用表量AO引腳對(duì)地電壓CubeMX里確認(rèn)PA0配置為ADC1_IN0模擬輸入接線重新插緊ADC讀數(shù)偏低且波動(dòng)大采樣時(shí)間太短或電源紋波干擾波形圖觀察ADC值分布ADC采樣時(shí)間改到55.5周期以上水泵啟動(dòng)時(shí)與ADC采樣任務(wù)錯(cuò)開水泵不轉(zhuǎn)但GPIO輸出正常MOS管柵極驅(qū)動(dòng)電壓不足示波器看MOS管GS波形換成邏輯電平MOS管3.3V可完全導(dǎo)通澆水后土壤水分過好導(dǎo)致傳感器讀數(shù)回升慢水分?jǐn)U散需要時(shí)間觀察澆水后3分鐘內(nèi)的讀數(shù)變化狀態(tài)機(jī)里加入PAUSE等待時(shí)間別靠單次判斷做決策程序下載過一次后無法再次下載CubeMX工程配置沒選SWD按住復(fù)位鍵連接快速下載重刷固件后用SWD重新燒錄以后新建工程記得選Serial Wire幾個(gè)重點(diǎn)問題展開說一下。關(guān)于下載一次后芯片就死了。這是F103新手最常見的翻車場(chǎng)景我毫不夸張地說十個(gè)搞單片機(jī)的至少五個(gè)都遇到過。原因就是CubeMX新建工程時(shí)Debug選項(xiàng)默認(rèn)是No Debug第一次下載后代碼把SWD引腳復(fù)用成了普通GPIO調(diào)試接口自然就斷了。解決辦法也不難按住開發(fā)板上的復(fù)位鍵不放點(diǎn)下載在下載開始的瞬間松開復(fù)位就能連上并重新燒錄。之后再在CubeMX里把SYS的Debug選項(xiàng)改成Serial Wire重新生成代碼燒進(jìn)去以后就正常了。關(guān)于ADC讀數(shù)漂移。如果你發(fā)現(xiàn)傳感器放在同一個(gè)位置不動(dòng)濕度讀數(shù)卻在一兩秒內(nèi)跳好幾個(gè)百分點(diǎn)先別急著懷疑傳感器壞了。把OLED的刷新頻率降下來改成每500ms采集一次、每2秒刷新一次界面你會(huì)發(fā)現(xiàn)讀數(shù)穩(wěn)定了很多。因?yàn)镺LED刷新和在做I2C通信時(shí)會(huì)產(chǎn)生電源波動(dòng)而這個(gè)波動(dòng)恰好被ADC看見了。另外ADC引腳和I2C引腳如果剛好在相鄰引腳信號(hào)串?dāng)_也可能造成影響布線時(shí)盡量讓模擬信號(hào)線遠(yuǎn)離數(shù)字信號(hào)線。關(guān)于換了新水泵后系統(tǒng)頻繁復(fù)位。我遇到過一次一開始以為代碼寫錯(cuò)了排查了很久發(fā)現(xiàn)是水泵功率太大啟動(dòng)瞬間把USB 5V電壓拉到了4.3V主板上的3.3V LDO輸出也跟著跌破了3.0VMCU直接掉電復(fù)位。這個(gè)問題的本質(zhì)是電源設(shè)計(jì)要考慮負(fù)載的瞬態(tài)電流而不是只算平均功耗。解決方法是給水泵單獨(dú)供電比如從充電寶的D和D-取電——開玩笑的正經(jīng)方案是加一個(gè)二極管隔離主控供電和水泵供電或者直接給水泵加一個(gè)大電解電容緩沖啟動(dòng)電流470uF起步。關(guān)于土壤濕度傳感器測(cè)量的假飽和現(xiàn)象。這是做農(nóng)業(yè)自動(dòng)化的人都知道的坑剛澆完水土壤表層濕度接近100%但往下幾厘米還是干的。如果你的傳感器探頭插得淺就會(huì)出現(xiàn)表面看著濕度足夠、實(shí)際根部缺水的情況。一個(gè)有效的改進(jìn)是把傳感器探頭盡量往下插插到花盆中下部那里才是根系主要分布區(qū)另外不要只看單次讀數(shù)觸發(fā)澆水可以觀察連續(xù)幾次讀數(shù)的變化趨勢(shì)——如果澆水后讀數(shù)上漲很快說明表層濕了但深層可能還干著這時(shí)候應(yīng)該讓水泵多運(yùn)行一會(huì)兒。關(guān)于安全措施。這個(gè)項(xiàng)目雖然簡(jiǎn)單但有個(gè)必須提的安全點(diǎn)水泵在斷電情況下還有余水如果長(zhǎng)期不用容易滋生細(xì)菌。我加的邏輯是每次澆水完成后讓水泵空轉(zhuǎn)0.5秒把管道里的水排空這樣下次啟動(dòng)時(shí)澆的是新鮮水。另外整個(gè)系統(tǒng)的電源入口我加了一個(gè)自恢復(fù)保險(xiǎn)絲500mA萬一水泵堵轉(zhuǎn)或短路保險(xiǎn)絲會(huì)自動(dòng)斷開保護(hù)主板和USB口成本也就一塊錢建議都加上。6. 成品展示與實(shí)際使用效果到目前為止我的這套系統(tǒng)已經(jīng)在家里的綠植上穩(wěn)定運(yùn)行了兩個(gè)多月效果非常滿意——出差一周回來花的狀態(tài)比我親自照顧的時(shí)候還好。數(shù)據(jù)上總結(jié)一下濕度測(cè)量精度±3%和專業(yè)的土壤濕度計(jì)對(duì)比過單次澆水時(shí)長(zhǎng)3-8秒視土壤干燥程度自動(dòng)調(diào)整系統(tǒng)功耗待機(jī)狀態(tài)約0.05W澆水時(shí)峰值約2.5W無水狀態(tài)下2節(jié)18650電池2000mAh可以用約10天實(shí)際使用中也有一些預(yù)想不到的收獲。比如通過串口日志發(fā)現(xiàn)我陽(yáng)臺(tái)上的綠植在傍晚和清晨的蒸騰作用顯著降低濕度下降速度比白天慢很多這就啟發(fā)我可以進(jìn)一步優(yōu)化澆水策略——只在早晚兩個(gè)時(shí)段允許澆水太陽(yáng)直射時(shí)不澆水避免水分快速蒸發(fā)浪費(fèi)。這種數(shù)據(jù)反哺生活的體驗(yàn)是做這個(gè)項(xiàng)目之前完全沒想到的。如果你也想做這個(gè)項(xiàng)目我的建議是第一版先用最少的器件把核心功能跑通——STM32最小系統(tǒng)板、一個(gè)濕度傳感器、一個(gè)小水泵、一個(gè)MOS管就夠了先實(shí)現(xiàn)濕度低→開啟水泵→濕度達(dá)標(biāo)→停泵這個(gè)最小閉環(huán)然后再去加OLED、加WiFi、加多傳感器。一步到位做加法出了問題反而難排查。最小閉環(huán)驗(yàn)證通過之后剩下的擴(kuò)展都只是時(shí)間問題。我自己在實(shí)際操作中最大的體會(huì)是這類感知-決策-執(zhí)行的自動(dòng)化系統(tǒng)真正的難點(diǎn)從來不在單個(gè)模塊怎么用而在于怎么把幾個(gè)模塊合理地拼在一起讓它們協(xié)同工作時(shí)不互相干擾。ADC采樣要穩(wěn)定、狀態(tài)機(jī)邏輯要嚴(yán)密、電源設(shè)計(jì)要留足余量把這三個(gè)點(diǎn)想清楚你的自動(dòng)澆花系統(tǒng)就能穩(wěn)定跑很久而且這種嵌入式系統(tǒng)設(shè)計(jì)的綜合感覺對(duì)以后做任何單片機(jī)的項(xiàng)目都有幫助。本文還有配套的精品資源點(diǎn)擊獲取