改造全解析:從硬件選型到固件開發(fā))
如果你家里有一臺(tái)半自動(dòng)意式濃縮咖啡機(jī)大概率有過這種體驗(yàn)開機(jī)之后只能干等預(yù)熱水溫到底穩(wěn)定不穩(wěn)定全憑感覺萃取過程中壓力是什么走勢(shì)根本看不到。這些問題其實(shí)都不是玄學(xué)而是缺少一個(gè)能實(shí)時(shí)檢測(cè)、閉環(huán)控制的控制器。我花了幾周時(shí)間用一塊ESP32 MCU把家里那臺(tái)老式震動(dòng)泵半自動(dòng)機(jī)做了全面改造——現(xiàn)在它不僅能通過Wi-Fi聯(lián)網(wǎng)還支持手機(jī)App遠(yuǎn)程開關(guān)機(jī)、預(yù)熱監(jiān)控、溫度PID閉環(huán)、壓力流量記錄甚至能OTA升級(jí)固件。今天就把這個(gè)“Wi-Fi Espresso Machine”項(xiàng)目的完整思路、硬件選型、固件開發(fā)、踩坑實(shí)錄全部翻出來給同樣想動(dòng)手折騰的朋友一個(gè)可以直接抄的參考。這個(gè)項(xiàng)目最適合兩類人一類是手頭有舊咖啡機(jī)、想提升萃取質(zhì)量的咖啡玩家另一類是玩ESP32/嵌入式開發(fā)、想找真實(shí)落地場(chǎng)景的工程師。整個(gè)項(xiàng)目不需要高深理論只要你能拿烙鐵焊板子、會(huì)裝Arduino IDE就能跟著做出一臺(tái)能聯(lián)網(wǎng)的半智能咖啡機(jī)。下文所有電路和控制邏輯我都按照常見方案做了補(bǔ)充說明參數(shù)可以按自己機(jī)器微調(diào)。1. 項(xiàng)目整體思路與方案選型1.1 為什么選擇ESP32作為主控MCU先回答一個(gè)最核心的問題為什么是ESP32市面上做控制的MCU太多了STC、STM32、樹莓派Pico都能跑控制器邏輯但咖啡機(jī)這個(gè)場(chǎng)景有幾個(gè)特殊要求讓我最終把票投給了ESP32。第一是通信能力。一臺(tái)“Wi-Fi Espresso Machine”必須自帶聯(lián)網(wǎng)能力。ESP32系列芯片原生集成2.4GHz Wi-Fi和藍(lán)牙這意味著我不用再外掛ESP8266模組或者NRF24L01這類無線模塊能省掉不少布線成本和麻煩。第二是模擬采集能力??Х葯C(jī)需要監(jiān)控水溫、鍋爐壓力、流量這些信號(hào)最終都要落到ADC和GPIO上。ESP32內(nèi)部有2個(gè)SAR ADC支持12位采樣而arduino生態(tài)下調(diào)用analogRead()就能讀門檻極低。第三是外設(shè)接口足夠豐富I2C接OLED屏幕、SPI接SD卡或者Flash、PWM驅(qū)動(dòng)可控硅加熱、UART外接藍(lán)牙或傳感器全部覆蓋。拿STM32F103這類傳統(tǒng)MCU對(duì)比它雖然實(shí)時(shí)性更穩(wěn)但要想聯(lián)網(wǎng)就得額外接轉(zhuǎn)接板開發(fā)復(fù)雜度直接上了一個(gè)臺(tái)階。拿樹莓派對(duì)比它運(yùn)行Linux、性能強(qiáng)但冷啟動(dòng)速度慢、實(shí)時(shí)響應(yīng)不夠穩(wěn)定而且咖啡機(jī)這種潮濕高溫震動(dòng)環(huán)境對(duì)SD卡和完整操作系統(tǒng)并不友好。所以ESP32是“夠用”和“好用”之間最平衡的選擇。方案Wi-Fi能力實(shí)時(shí)控制開發(fā)難度成本能耗ESP32原生Wi-Fi藍(lán)牙強(qiáng)雙核240MHz低Arduino/ESP-IDF15~35元低STM32Wi-Fi模組需外掛很強(qiáng)較高50元以上低樹莓派Zero W原生Wi-Fi一般受OS影響中等80元以上高1.2 系統(tǒng)架構(gòu)與功能拆解整個(gè)系統(tǒng)可以分成五個(gè)模塊電源、傳感、執(zhí)行、控制和通信。電源模塊負(fù)責(zé)把220V交流電降壓成24V給水泵、3.3V給ESP32供電傳感模塊負(fù)責(zé)采集溫度、壓力、流量信號(hào)執(zhí)行模塊負(fù)責(zé)驅(qū)動(dòng)加熱管和震動(dòng)泵控制模塊就是ESP32的固件邏輯通信模塊負(fù)責(zé)Wi-Fi連接和App交互。功能上我最初的目標(biāo)很簡(jiǎn)單能手機(jī)遠(yuǎn)程關(guān)機(jī)、能看到實(shí)時(shí)溫度。但真正動(dòng)手之后功能清單越寫越長(zhǎng)。目前這臺(tái)機(jī)器已經(jīng)實(shí)現(xiàn)水溫實(shí)時(shí)采集與PID閉環(huán)控制目標(biāo)溫度在88~96°C之間可調(diào)穩(wěn)態(tài)波動(dòng)約±0.5°C。鍋爐壓力監(jiān)控讀取壓力傳感器數(shù)值并繪制曲線。流量計(jì)統(tǒng)計(jì)單次萃取水量并能自動(dòng)停止萃取。OLED屏顯示當(dāng)前狀態(tài)配一個(gè)旋轉(zhuǎn)編碼器做本地操作。WiFi聯(lián)網(wǎng)后通過MQTT協(xié)議連接Home Assistant手機(jī)App我用的開源的MQTT客戶端能遠(yuǎn)程控制開關(guān)機(jī)、查看溫度曲線。固件支持OTA升級(jí)參數(shù)通過SPIFFS文件系統(tǒng)保存斷電不丟失。這里有個(gè)很關(guān)鍵的設(shè)計(jì)理念不要把控制邏輯全部交給云端??Х葯C(jī)是一款安全相關(guān)的家電就算Wi-Fi斷開、MQTT服務(wù)器掛掉本地的PID控制、過熱保護(hù)、無水檢測(cè)也必須正常工作。所以我的代碼里所有閉環(huán)控制都在ES32本地完成Wi-Fi和App只是“監(jiān)控和參數(shù)下發(fā)”的通道。這個(gè)思路做產(chǎn)品也適用網(wǎng)絡(luò)永遠(yuǎn)只是輔助穩(wěn)定性才是底線。1.3 被否決的替代方案和改進(jìn)方向方案論證過程中我其實(shí)還想過兩個(gè)方向一是直接用現(xiàn)成的商用Wi-Fi插座控制咖啡機(jī)電源但那個(gè)方案只能遠(yuǎn)程通斷電不能監(jiān)控溫度也不能做到PID穩(wěn)溫和自動(dòng)停水改造價(jià)值極低。二是在原有咖啡機(jī)模擬控制板上并聯(lián)一個(gè)“監(jiān)聽”電路只讀溫度不上控制這種方式改動(dòng)小但舊機(jī)器原本的機(jī)械溫控開關(guān)本身就存在回差大、溫度漂移的問題保留原控制等于白瞎了PID算法。最終的改造方案是完全繞過原機(jī)器的溫控開關(guān)和機(jī)械定時(shí)器由ESP32直接驅(qū)動(dòng)加熱管和震動(dòng)泵。原有保險(xiǎn)絲、過熱保護(hù)回路保留作為最后一道安全防線。如果你的機(jī)器比較舊我建議也遵循這個(gè)原則新增的智能控制和原有物理安全保護(hù)要并行絕對(duì)不要用軟件保護(hù)替代物理保護(hù)。2. 硬件設(shè)計(jì)與核心電路2.1 關(guān)鍵元器件選型明細(xì)硬件選型是整個(gè)項(xiàng)目的基石我把物料清單整理成了一個(gè)表格。這里列出的器件都是我在實(shí)際項(xiàng)目中驗(yàn)證過、容易買到的型號(hào)適合直接照抄。價(jià)格只是參考不同渠道浮動(dòng)很大。元器件型號(hào)/規(guī)格作用備注主控ESP32 DevKitC V4ESP32-WROOM-32系統(tǒng)控制與Wi-Fi也可以用ESP32-S3溫度傳感器NTC 100K B3950封裝防水探頭鍋爐溫度采集需分壓電阻壓力傳感器0~20Bar模擬輸出壓力變送器鍋爐/萃取壓力監(jiān)控需運(yùn)放或分壓適配流量計(jì)霍爾流量計(jì) YF-S201萃取水量統(tǒng)計(jì)中斷計(jì)數(shù)加熱驅(qū)動(dòng)BTA16可控硅MOC3021光耦220V加熱管通斷需過零檢測(cè)泵驅(qū)動(dòng)24V繼電器震動(dòng)泵啟停需續(xù)流二極管電源模塊HLK-PM24/HLK-PM03模塊220V轉(zhuǎn)24V和3.3V必須隔離電源顯示0.96寸OLED SSD1306本地狀態(tài)顯示I2C接口交互EC11旋轉(zhuǎn)編碼器菜單操作需硬件消抖Flash存儲(chǔ)主控自帶SPIFFS分區(qū)保存PID參數(shù)不需要外掛外接擴(kuò)展無保持簡(jiǎn)單遵循KISS原則2.2 溫度采集電路NTC還是PT100咖啡機(jī)溫度采集有兩個(gè)常見方案NTC熱敏電阻和PT100鉑電阻。PT100精度高配上MAX31865這類專用芯片可以做到±0.1°C但成本高、接線復(fù)雜還需要SPI接口。而NTC的方案就簡(jiǎn)單得多一個(gè)100K電阻和一個(gè)104電容做分壓濾波接到ESP32的ADC引腳就能讀。我在實(shí)際測(cè)試中發(fā)現(xiàn)對(duì)于水溫控制來說NTC的精度完全夠用。我用的NTC是100K B3950在25°C時(shí)阻值為100K在95°C時(shí)阻值約為6.8K。分壓電路我用的是上拉100K電阻到3.3VNTC接地中間抽頭接ADC。溫度換算用Steinhart-Hart方程熱力學(xué)溫度T 1 / (A B * ln(R) C * (ln(R))^3)其中R為NTC當(dāng)前阻值A(chǔ)、B、C由廠家給的B值反推得到更常用的工程寫法是簡(jiǎn)化公式float readNTC() { int raw analogRead(TEMP_PIN); float v raw / 4095.0 * 3.3; float r (3.3 - v) / v * 100000.0; // 100K上拉 float steinhart log(r / 100000.0) / 3950.0 1.0 / (25.0 273.15); float temp 1.0 / steinhart - 273.15; return temp; }實(shí)測(cè)下來在90~100°C區(qū)間NTC方案和工業(yè)PT100溫度表對(duì)比誤差在±0.5°C以內(nèi)對(duì)咖啡萃取完全夠用。注意ADC參考電壓不能直接用板載3.3V因?yàn)镋SP32的3.3V經(jīng)過穩(wěn)壓后還比較準(zhǔn)但如果你用的是一些雜牌開發(fā)板最好用實(shí)際電壓校準(zhǔn)一下否則溫度讀數(shù)會(huì)整體偏移。2.3 高壓與低壓隔離設(shè)計(jì)這里必須說一個(gè)重點(diǎn)咖啡機(jī)內(nèi)部是220V交流高壓而ESP32是3.3V的低壓系統(tǒng)。我強(qiáng)烈建議任何想復(fù)刻這個(gè)項(xiàng)目的朋友先做好心理建設(shè)——焊接和測(cè)試時(shí)一定要戴絕緣手套、用隔離變壓器或者漏電保護(hù)插排。生命安全比咖啡重要一萬(wàn)倍。加熱驅(qū)動(dòng)我用的是雙向可控硅BTA16加MOC3021光耦隔離。MOC3021內(nèi)部是LED加雙向可控硅輸出輸入側(cè)由ESP32 GPIO通過三極管驅(qū)動(dòng)輸出側(cè)串聯(lián)220V回路。這樣控制信號(hào)和強(qiáng)電之間是光隔離的不會(huì)把高壓引入控制板。如果不想用可控硅也可以用220V繼電器模塊但繼電器響應(yīng)慢、有機(jī)械壽命限制做PID調(diào)功時(shí)頻繁通斷噪音很大長(zhǎng)期用下來我覺得不太合適。下面是一段可控硅驅(qū)動(dòng)的示例代碼用來控制加熱功率void setHeaterPower(int percent) { // percent: 0~100控制AC過零后的輸出占空比 digitalWrite(HEATER_PIN, percent 0 ? HIGH : LOW); heaterPercent constrain(percent, 0, 100); }這只是最簡(jiǎn)單的開關(guān)控制。更精細(xì)的做法是配合過零檢測(cè)電路在每個(gè)過零周期內(nèi)按比例控制可控硅的導(dǎo)通角這樣能降低對(duì)電網(wǎng)的沖擊也能讓加熱功率更平滑。不過對(duì)于加熱管這種大熱慣性負(fù)載簡(jiǎn)單的開關(guān)PID比例調(diào)節(jié)已經(jīng)足夠不需要做斬波調(diào)壓。水泵控制更簡(jiǎn)單直接用24V繼電器控制震動(dòng)泵啟停就行繼電器觸點(diǎn)加RC吸收電路避免拉弧對(duì)控制板造成干擾。2.4 引腳分配與接線注意事項(xiàng)ESP32的引腳資源豐富但有幾個(gè)坑要注意。一是GPIO34~39是純輸入引腳不能作為輸出二是ADC2的某些通道在Wi-Fi開啟時(shí)會(huì)被占用所以如果既用Wi-Fi又要讀模擬量最好把所有模擬采集都放到ADC1通道上。三是GPIO0、GPIO2、GPIO15在啟動(dòng)時(shí)有特殊功能不能用作普通輸出否則會(huì)影響固件燒錄。我實(shí)際使用的引腳分配表如下功能引腳說明溫度傳感器ADC1GPIO34ADC1_CH6壓力傳感器ADC1GPIO35ADC1_CH7流量計(jì)中斷GPIO26霍爾脈沖輸入加熱可控硅驅(qū)動(dòng)GPIO25GPIO輸出泵繼電器GPIO33GPIO輸出OLED SCLGPIO22I2C時(shí)鐘OLED SDAGPIO21I2C數(shù)據(jù)旋轉(zhuǎn)編碼器A/BGPIO16/17外部中斷接線時(shí)需要注意所有傳感器信號(hào)線盡量遠(yuǎn)離220V強(qiáng)電走線尤其是NTC的引線如果和加熱線綁在一起電磁干擾會(huì)讓ADC讀數(shù)劇烈跳動(dòng)。我用的是屏蔽線屏蔽層單端接地效果不錯(cuò)。另外ESP32開發(fā)板上的3.3V穩(wěn)壓器電流能力有限OLED、編碼器都從3.3V取電沒問題但如果你想外接藍(lán)牙模塊或者大屏建議單獨(dú)加一路3.3V DC-DC不要全部依賴開發(fā)板的LDO。3. 固件開發(fā)從Arduino到生產(chǎn)級(jí)別3.1 開發(fā)環(huán)境搭建固件開發(fā)我選了Arduino IDE原因很簡(jiǎn)單上手快、庫(kù)里什么東西都有。你只需要在“開發(fā)板管理器”里添加espressif的ESP32開發(fā)板地址然后安裝esp32 core。國(guó)內(nèi)用戶經(jīng)常遇到下載失敗的情況我這里補(bǔ)充一下可以先從GitHub release頁(yè)找到對(duì)應(yīng)版本的離線包比如esp32-arduino-core-2.0.17放到Arduino的hardware/espressif目錄解壓之后打開IDE就能識(shí)別到ESP32 Dev Module。如果你是老手當(dāng)然也可以直接用ESP-IDF或PlatformIO。用ESP-IDF優(yōu)點(diǎn)是實(shí)時(shí)性更強(qiáng)、代碼結(jié)構(gòu)更工程化但學(xué)習(xí)曲線陡。用PlatformIO則是藏在VS Code里庫(kù)管理做得很好適合習(xí)慣看代碼的人。我建議首次嘗試的朋友直接走Arduino路線把精力放在調(diào)試上而不是環(huán)境上。搭好了環(huán)境第一件事就是測(cè)試串口打印“Hello Espresso”確認(rèn)連接和芯片型號(hào)都沒問題。這里有個(gè)細(xì)節(jié)如果開發(fā)板不識(shí)別通常是因?yàn)闆]有安裝CH340/CP2102的USB轉(zhuǎn)串口驅(qū)動(dòng)另外必須按住開發(fā)板上的BOOT按鈕再插入U(xiǎn)SB才能進(jìn)入燒錄模式。3.2 PID控制與溫度穩(wěn)定邏輯意式濃縮咖啡萃取溫度通常在90~96°C之間水溫穩(wěn)定度直接影響咖啡品質(zhì)。我最初用的簡(jiǎn)單雙位控制溫度低了就開加熱到了就關(guān)效果很差溫差能到5°C以上。后來我改成增量式PID穩(wěn)定度提升非常明顯。整個(gè)控制的思路是溫度傳感器每秒采樣一次用PID計(jì)算輸出占空比通過可控硅控制加熱管功率??Х葯C(jī)熱慣性比較大PID參數(shù)我通過試湊法調(diào)到了一組比較穩(wěn)定的值Kp 60Ki 1.8Kd 12采樣周期 1s輸出范圍 0~100%核心代碼大致如下double setpoint 93.0; double kp 60, ki 1.8, kd 12; double lastError 0, integral 0; double computePID(double current) { double error setpoint - current; integral error * 0.1; // 采樣周期1秒 integral constrain(integral, -10, 10); double derivative error - lastError; lastError error; return kp * error ki * integral kd * derivative; }我犯過一個(gè)典型錯(cuò)誤一開始把積分限幅設(shè)得太大導(dǎo)致溫度沖到97°C還降不下來后來把積分限幅和輸出限幅都調(diào)小系統(tǒng)才穩(wěn)定。還要注意咖啡機(jī)加水后溫度會(huì)驟降PID控制器會(huì)計(jì)算出接近100%的加熱功率所以升溫階段要防止積分飽和否則到目標(biāo)溫度后超調(diào)嚴(yán)重。我加了一個(gè)簡(jiǎn)單的抗積分飽和邏輯當(dāng)輸出超過100時(shí)暫停積分累加。更有效的做法是采用“分段控制”升溫初期用100%全功率溫度接近目標(biāo)值時(shí)切到PID控制。這樣既快又穩(wěn)。實(shí)際測(cè)試下來從室溫到93°C大約需要8分鐘到目標(biāo)溫度后10分鐘內(nèi)波動(dòng)不超過±0.5°C。3.3 Wi-Fi連接與斷線重連機(jī)制Wi-Fi這塊我首先用了WiFiManager庫(kù)做配網(wǎng)。用戶可以通過手機(jī)連上ESP32的AP熱點(diǎn)在網(wǎng)頁(yè)里填寫自家Wi-Fi名稱密碼參數(shù)保存到NVS里開機(jī)自動(dòng)連接。這個(gè)體驗(yàn)比寫死SSID友好太多了家里換路由器都不用重新編譯固件。連接Wi-Fi的代碼很常規(guī)#include WiFi.h #include WiFiManager.h void setup_wifi() { WiFiManager wm; if (!wm.autoConnect(Espresso-AP)) { delay(3000); ESP.restart(); } while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(WiFi connected: WiFi.localIP().toString()); }Wi-Fi斷線問題是我踩坑最深的。最初我用的是單次連接一旦路由器重啟或者Wi-Fi信號(hào)波動(dòng)ESP32就徹底連接不上只能重啟設(shè)備。后來我加了斷線重連機(jī)制在主循環(huán)里檢測(cè)WiFi.status()如果斷開就立刻重連如果連續(xù)重連30秒失敗就重啟系統(tǒng)。實(shí)測(cè)下來路由器重啟一次咖啡機(jī)也能在1分多鐘內(nèi)自動(dòng)恢復(fù)連接這里面還要配合看門狗定時(shí)器防止死循環(huán)卡死。關(guān)于熱點(diǎn)的問題我還遇到過一種情況當(dāng)我在咖啡機(jī)測(cè)試階段想把設(shè)備配成AP模式時(shí)系統(tǒng)提示“我們無法設(shè)置移動(dòng)熱點(diǎn)因?yàn)槟愕碾娔X未建立以太網(wǎng)、Wi-Fi或手機(jī)網(wǎng)絡(luò)數(shù)據(jù)連接”。這是因?yàn)殡娔X本身沒有聯(lián)網(wǎng)時(shí)Windows的熱點(diǎn)功能無法啟動(dòng)。所以如果不想被這個(gè)限制困擾本地調(diào)試時(shí)直接用串口查看日志比依賴熱點(diǎn)靠譜得多。3.4 OTA升級(jí)與SPIFFS參數(shù)存儲(chǔ)聯(lián)網(wǎng)設(shè)備不做OTA升級(jí)等于半殘。我做了一個(gè)簡(jiǎn)單的OTA Web升級(jí)頁(yè)面ESP32內(nèi)置一個(gè)Web Server監(jiān)聽/update路徑我只要在瀏覽器里訪問這個(gè)路徑就能上傳新的固件bin文件幾秒鐘后設(shè)備自動(dòng)重啟并運(yùn)行新固件。底層用的是ArduinoOTA庫(kù)配合WebOTA庫(kù)也可以做到上傳界面更友好。OTA升級(jí)的代碼基礎(chǔ)版#include ArduinoOTA.h void setup_ota() { ArduinoOTA.setHostname(esp32-espresso); ArduinoOTA.begin(); } void loop_ota() { ArduinoOTA.handle(); }OLED上會(huì)顯示正在升級(jí)的狀態(tài)升級(jí)期間我強(qiáng)制關(guān)閉了加熱輸出避免升級(jí)過程中本來要開的繼電器誤動(dòng)作這是安全設(shè)計(jì)里比較重要的一環(huán)。參數(shù)存儲(chǔ)用的是SPIFFS文件系統(tǒng)。我最初用Preferences庫(kù)保存PID參數(shù)后來參數(shù)越來越多目標(biāo)溫度、PID三個(gè)數(shù)、水量閾值、Wi-Fi配置就改用SPIFFS存一個(gè)JSON配置文件。使用前需要在Arduino IDE里安裝ArduinoJson庫(kù)并在分區(qū)方案里選擇“Huge APP (3MB No OTA/1MB SPIFFS)”或者在分區(qū)里預(yù)留SPIFFS區(qū)域。JSON格式的好處是結(jié)構(gòu)清晰手動(dòng)改也直觀適合把一組參數(shù)導(dǎo)出來備份。#include SPIFFS.h #include ArduinoJson.h void loadConfig() { if (!SPIFFS.begin(true)) { Serial.println(SPIFFS Mount Failed); return; } File configFile SPIFFS.open(/config.json, r); if (!configFile) { Serial.println(No config file); return; } DynamicJsonDocument doc(1024); deserializeJson(doc, configFile); setpoint doc[setpoint] | 93.0; Kp doc[kp] | 60.0; Ki doc[ki] | 1.8; Kd doc[kd] | 12.0; configFile.close(); }4. 手機(jī)App與云端聯(lián)動(dòng)4.1 通信協(xié)議選擇MQTT還是HTTP聯(lián)網(wǎng)咖啡機(jī)需要和手機(jī)/云端通信我對(duì)比過HTTP輪詢和MQTT推送兩種方案。HTTP最簡(jiǎn)單ESP32開一個(gè)Web Server手機(jī)定時(shí)GET請(qǐng)求就好但問題在于“輪詢間隔”尷尬間隔短了浪費(fèi)流量和電量間隔長(zhǎng)了狀態(tài)更新不及時(shí)。而且如果要做遠(yuǎn)程控制手機(jī)和ESP32之間還隔著路由器做端口映射麻煩又不安全。所以我選了MQTT。MQTT是物聯(lián)網(wǎng)場(chǎng)景最常見的長(zhǎng)連接消息協(xié)議ESP32作為客戶端連接一臺(tái)MQTT Broker手機(jī)App或Home Assistant也連同一個(gè)Broker所有消息通過主題主題訂閱分發(fā)。這種模式很自然ESP32發(fā)布狀態(tài)主題App訂閱狀態(tài)主題App發(fā)布控制主題ESP32訂閱控制主題。我用的Broker是本地的Home Assistant樹莓派上運(yùn)行的Mosquitto。局域網(wǎng)內(nèi)使用完全夠快延時(shí)在50ms以內(nèi)。如果你只想在局域網(wǎng)玩不用碰公網(wǎng)如果想跨網(wǎng)絡(luò)遠(yuǎn)程控制再做FRP內(nèi)網(wǎng)穿透或者連公網(wǎng)Broker但要注意配置密碼鑒權(quán)千萬(wàn)不能裸奔。4.2 本地Web控制臺(tái)除了MQTT我在ESP32里還跑了一個(gè)輕量Web Server這樣即使沒有App、沒有MQTT Broker只要手機(jī)連同一個(gè)Wi-Fi打開瀏覽器輸入IP就能看到咖啡機(jī)的當(dāng)前狀態(tài)。Web頁(yè)面是我用純HTMLJavaScript寫的一個(gè)單頁(yè)通過WebSocket實(shí)時(shí)推送溫度值。頁(yè)面啟動(dòng)后每隔100ms在頁(yè)面上更新一次溫度曲線順便放幾個(gè)按鈕控制開關(guān)機(jī)、設(shè)置目標(biāo)溫度。這樣做的好處是移動(dòng)端和桌面瀏覽器都能用不需要安裝App非常適合現(xiàn)場(chǎng)調(diào)試。Web頁(yè)面代碼很簡(jiǎn)單我放在ESP32的SPIFFS里用AsyncWebServer框架提供服務(wù)#include AsyncTCP.h #include ESPAsyncWebServer.h AsyncWebServer server(80); AsyncWebSocket ws(/ws); void notifyClients() { String json {\temp\: String(currentTemp) ,\setpoint\: String(setpoint) }; ws.textAll(json); }這個(gè)WebSocket通知機(jī)制讓頁(yè)面顯示非常流暢幾乎沒有閃爍感。Web控制臺(tái)的好處還在于它不依賴任何第三方服務(wù)這是整個(gè)系統(tǒng)最穩(wěn)定可靠的“底線界面”。4.3 手機(jī)App與智能家居聯(lián)動(dòng)手機(jī)App我并沒有另寫一個(gè)專用應(yīng)用而是直接用了現(xiàn)成的MQTT客戶端比如iOS上的MQTTool或者Android上的MQTT Dash。在App里添加Broker地址訂閱/device/espresso/state和/device/espresso/temp兩個(gè)主題就能實(shí)時(shí)看到溫度發(fā)布/device/espresso/set主題payload填{power:on}或者{target:94}就能控制設(shè)備。這種方式零開發(fā)成本而且不同品牌手機(jī)都能用。如果你想進(jìn)一步聯(lián)動(dòng)智能家居可以把ESP32接入Home Assistant。Home Assistant的MQTT集成會(huì)自動(dòng)發(fā)現(xiàn)實(shí)體然后我配置成溫度傳感器、開關(guān)和數(shù)顯控件。這樣我每天早上可以通過一個(gè)自動(dòng)化腳本檢測(cè)工作日、檢測(cè)當(dāng)前時(shí)間自動(dòng)觸發(fā)咖啡機(jī)預(yù)熱等我洗漱完過去正好是93°C。這就是整個(gè)項(xiàng)目最提升幸福感的地方。接入Home Assistant后實(shí)現(xiàn)語(yǔ)音控制也很簡(jiǎn)單。配合小度、小愛這類帶音箱只需要在Home Assistant里配置一個(gè)“打開咖啡機(jī)”的Script語(yǔ)音指令就能聯(lián)動(dòng)觸發(fā)。如果你玩過esp32的小智AI之類的本地離線語(yǔ)音框架其實(shí)也能讓咖啡機(jī)直接響應(yīng)語(yǔ)音命令不過那就是另外一個(gè)更大的坑了。5. 實(shí)操調(diào)試與踩坑記錄5.1 溫度曲線與PID調(diào)參實(shí)錄PID調(diào)參是我花時(shí)間最多的環(huán)節(jié)。一開始我把Kp調(diào)到150結(jié)果溫度在目標(biāo)值附近來回震蕩最高能沖到98°C萃取時(shí)加冷水又會(huì)拉低到85°C以下完全沒法用。后來改成“先P后I再D”的調(diào)法先讓Ki和Kd都為0只調(diào)Kp。從Kp30開始觀察溫度是否出現(xiàn)等幅振蕩。我在Kp80時(shí)開始出現(xiàn)輕微振蕩說明系統(tǒng)臨界增益在80附近。然后把Kp保守地設(shè)為60增加Ki來消除靜差。Ki從0.5開始往上加當(dāng)Ki加到2.0時(shí)系統(tǒng)出現(xiàn)低頻波動(dòng)我認(rèn)為積分作用稍強(qiáng)最終降到1.8。最后加KdKd從0開始試到8然后試了1515時(shí)超調(diào)變小但噪聲放大12是一個(gè)比較平衡的值。下面是各組參數(shù)的實(shí)際表現(xiàn)KpKiKd穩(wěn)態(tài)波動(dòng)升溫到93°C時(shí)間表現(xiàn)8000±1.2°C10分鐘有靜差502.00±0.8°C9分鐘輕微低頻波動(dòng)601.85±0.5°C8分鐘左右溫度平穩(wěn)601.812±0.4°C8分鐘最終方案調(diào)參過程中我用了串口繪圖器功能把目標(biāo)溫度和實(shí)測(cè)溫度畫成兩條曲線一眼就能看出超調(diào)量和振蕩頻率。如果你的固件沒有輸出串口曲線的邏輯我建議先加一個(gè)每隔1s打印溫度的日志再配一個(gè)網(wǎng)頁(yè)端曲線來觀察否則靠看OLED那個(gè)小屏幕上的數(shù)字調(diào)PID非常痛苦。5.2 ADC噪聲問題排查有個(gè)問題幾乎困擾了我一個(gè)周末溫度讀數(shù)在96°C附近來回跳了2°C但萬(wàn)用表量NTC兩端電壓卻非常穩(wěn)定。用示波器一看ADC引腳上疊加了一個(gè)100Hz左右的衰減振蕩噪聲。這個(gè)噪聲來源就是加熱管工作時(shí)的大電流回路通過空間耦合到NTC信號(hào)線上同時(shí)ADC采樣時(shí)Pin上的信號(hào)還沒有完全穩(wěn)定。解決方案有三個(gè)層面。第一是硬件在NTC輸出到ADC之間加一個(gè)100nF電容到地組成RC低通濾波截止頻率大約1.6kHz第二是軟件連續(xù)采樣10次去掉最大值最小值后取平均也就是滑動(dòng)中位數(shù)濾波第三是采樣時(shí)機(jī)在可控硅不導(dǎo)通的間歇窗口去采樣或者避開加熱管上升沿附近。三個(gè)方案疊加后溫度讀數(shù)穩(wěn)定度至少提升了10倍。如果你對(duì)精度還有更高要求可以改成PT100加MAX31865那就不需要擔(dān)心ADC噪聲問題了。5.3 Wi-Fi不穩(wěn)定問題Wi-Fi掉線是另一個(gè)高頻問題。咖啡機(jī)附近通常有微波爐、冰箱、金屬外殼2.4GHz頻段干擾嚴(yán)重。我實(shí)測(cè)在機(jī)器啟動(dòng)加熱時(shí)ESP32的射頻靈敏度會(huì)明顯下降尤其在加熱管全功率運(yùn)行時(shí)出現(xiàn)過MQTT斷連率飆升、甚至重啟后久久無法連上Wi-Fi的情況。我最后做了幾件有效的事情一是把ESP32的PCB天線豎起來不要貼著金屬鍋爐外殼二是給加熱管和泵的電機(jī)都加了X電容和共模電感減少傳導(dǎo)干擾三是把Wi-Fi功率設(shè)為WiFi.setTxPower(WIFI_POWER_11dBm)而不是默認(rèn)的最大功率實(shí)測(cè)反而更穩(wěn)定因?yàn)榘l(fā)熱減少了四是開Wi-Fi低功耗模式配合斷線重連避免頻繁掃描信道導(dǎo)致溫度控制卡頓。做完之后連續(xù)運(yùn)行48小時(shí)沒有再出現(xiàn)斷連。5.4 常見問題速查表最后整理一個(gè)速查表很多問題都是我在群里看別人做類似項(xiàng)目時(shí)高頻出現(xiàn)的放在這里方便你直接排查問題現(xiàn)象可能原因處理方法溫度讀數(shù)跳動(dòng)大NTC信號(hào)受干擾加濾波電容、軟件濾波、避開加熱時(shí)序采樣溫度一直上不去可控硅不導(dǎo)通或加熱管損壞用萬(wàn)用表測(cè)加熱管開斷檢查MOC3021驅(qū)動(dòng)是否正常Wi-Fi頻繁斷開天線位置差、電源干擾調(diào)整天線方向給電源加濾波降低TX功率OTA升級(jí)后無法啟動(dòng)分區(qū)地址錯(cuò)誤確認(rèn)分區(qū)表支持OTA升級(jí)時(shí)保持供電穩(wěn)定水泵不工作繼電器燒觸點(diǎn)更換繼電器并加續(xù)流二極管、RC吸收電路MQTT收不到數(shù)據(jù)主題或Broker地址錯(cuò)誤檢查訂閱主題、Broker端口、用戶名密碼手機(jī)Web打開白屏SPIFFS文件缺失把HTML文件正確上傳到SPIFFS分區(qū)按鍵旋鈕不靈敏缺少消抖改用中斷定時(shí)器消抖或者加RC去抖電路另外如果你在搭建Arduino開發(fā)環(huán)境時(shí)遇到esp32庫(kù)下載失敗這類情況優(yōu)先考慮離線安裝包。Arduino IDE第一次在線下載esp32 core往往會(huì)被網(wǎng)絡(luò)拖死離線包解壓到hardware目錄就能用省下大半天的折騰。還有一點(diǎn)提醒焊高壓部分之前先把低電壓控制部分全部調(diào)通再接220V。我第一次聯(lián)調(diào)時(shí)圖省事直接上電結(jié)果浪涌把主板的3.3V穩(wěn)壓器打得冒煙了。從此就長(zhǎng)記性了先USB供電調(diào)邏輯再隔離變壓器降壓測(cè)試最后才上高壓。寫在最后的一個(gè)小建議如果你動(dòng)手做了這個(gè)項(xiàng)目建議第一版不要追求功能多先把“遠(yuǎn)程開機(jī)溫度PID水箱保護(hù)”這三個(gè)基礎(chǔ)功能跑通。然后你會(huì)發(fā)現(xiàn)咖啡機(jī)從一臺(tái)機(jī)械電器變成了一臺(tái)能聯(lián)網(wǎng)、能收集數(shù)據(jù)的設(shè)備后續(xù)再加流量統(tǒng)計(jì)、壓力曲線、磨豆聯(lián)動(dòng)都只是加傳感器的功夫。我自己用下來最大的變化是出品越來越穩(wěn)定了。以前萃取時(shí)手忙腳亂現(xiàn)在只要在App里看好溫度曲線穩(wěn)定在93°C壓力在9Bar左右剩下的都交給控制器。這個(gè)項(xiàng)目最大的價(jià)值不是“多了一個(gè)Wi-Fi”而是讓咖啡機(jī)真正變成了一個(gè)閉環(huán)控制系統(tǒng)——這才是ESP32這類MCU最擅長(zhǎng)的事情。