
如果你玩ESP32有一陣子了很難不碰到舵機控制這道坎。做智能小車要轉(zhuǎn)方向做機械臂要抬關(guān)節(jié)做云臺要偏航俯仰背后都是同一個東西在干活舵機。而我見過太多人卡在“代碼能編譯、舵機就是不聽話”這個階段要么抖動、要么轉(zhuǎn)不到位、要么接上就重啟。這篇ESP32舵機控制全攻略就是要把這些坑一次性填平從PWM信號原理、舵機選型、供電設(shè)計到ESP32驅(qū)動代碼、多舵機管理、平滑運動、串口指令控制一路講到高級玩法。新手上手能照著接線跑通第一個例子有基礎(chǔ)的人也能從高級部分找到優(yōu)化思路。1. 項目整體拆解為什么偏偏用ESP32玩舵機先說方案選型。單片機世界里能做舵機控制的板子很多但ESP32有幾個特性讓它特別適合干這活一是PWM資源多內(nèi)置LEDCLED Control控制器最多支持16路PWM輸出不需要外掛擴展芯片就能驅(qū)動十來個舵機二是引腳數(shù)量足夠多給每個舵機分配獨立信號線很寬松三是主頻高240MHz跑復(fù)雜控制邏輯、多舵機插值運算都不吃力四是自帶Wi-Fi和藍(lán)牙做完本地控制還能接上位機、接手機這個后面講高級應(yīng)用會用到。我最初做舵機控制其實用的是普通開發(fā)板引腳少、PWM通道也少接兩個舵機就得精打細(xì)算頻率稍微不對整個程序就亂了。換成ESP32之后最大的感受是“從省著用變成隨便用”16個PWM通道、4組定時器、微秒級脈寬精度這些參數(shù)放在舵機控制場景里非常寬裕。這套方案要解決的核心問題其實可以歸納成三類。第一類是“轉(zhuǎn)不起來”舵機不動作、角度偏、或者上電就卡死這多半是硬件接線和供電的問題。第二類是“轉(zhuǎn)不準(zhǔn)”角度誤差、回中偏差、兩路舵機動作不同步這是PWM信號和控制邏輯的問題。第三類是“轉(zhuǎn)不漂亮”舵機像開關(guān)一樣啪地彈過去而不是平滑運動這是運動規(guī)劃的問題。大部分人做到第一類就放棄了實際上后兩類才是讓項目看起來“專業(yè)”的分水嶺。這篇攻略采用的思路是從底層原理講起再做最小系統(tǒng)驗證最后往上疊加功能。我不會一上來就丟一堆代碼而是先把“為什么舵機要50Hz PWM”“為什么脈寬是0.5ms到2.5ms”“為什么必須共地”這些底層邏輯講清楚這樣后面排查問題才有依據(jù)。2. 舵機控制的核心PWM信號、選型與供電2.1 角度是靠“脈寬”而不是“占空比”決定的先聊最容易被忽略的基礎(chǔ)。標(biāo)準(zhǔn)模擬舵機的控制信號是一路周期為20ms的PWM方波也就是50Hz。舵機真正關(guān)心的是高電平持續(xù)多久這個“高電平持續(xù)時間”叫脈寬單位是微秒。絕大多數(shù)標(biāo)準(zhǔn)舵機的脈寬映射關(guān)系是這樣的0.5ms脈寬對應(yīng)0°1.5ms對應(yīng)90°2.5ms對應(yīng)180°。換算成角度就是脈寬(μs) 500 (角度 / 180.0) * 2000反過來說如果要讓舵機停在45°那脈寬就是500 45 / 180 * 2000 1000μs也就是1ms。這里有個很多人踩過的坑一聽到PWM就只關(guān)心占空比。比如你用50Hz頻率、50%占空比去驅(qū)動舵機得到的高電平是10ms遠(yuǎn)超過2.5ms舵機要么直接打死要么狂抖。占空比是比值而舵機讀的是絕對值。所以一定要記住頻率固定50Hz、脈寬才是控制量。有些數(shù)字舵機支持更高頻率比如333Hz甚至部分總線舵機完全不走PWM協(xié)議。選舵機前先確認(rèn)類型標(biāo)準(zhǔn)模擬舵機就老老實實按50Hz來。2.2 常見舵機型號怎么選不是扭矩越大越好我常用的是常見的SG90小舵機和MG996R金屬齒輪大舵機這兩個型號足夠說明選型邏輯。SG90是塑料齒輪重量9g左右扭矩大約1.8kg·cm適合做小車轉(zhuǎn)向、云臺俯仰、小型機械臂的末端關(guān)節(jié)。MG996R是金屬齒輪重量55g左右扭矩能達(dá)到11kg·cm左右適合做機械臂大臂、底盤轉(zhuǎn)向這類需要承受較大負(fù)載的關(guān)節(jié)。選型核心看三點。第一是扭矩余量。舵機的峰值扭矩要大于關(guān)節(jié)實際負(fù)載的2到3倍。如果關(guān)節(jié)需要1kg·cm的力用SG90的1.8kg·cm勉強夠但長時間接近滿負(fù)荷運轉(zhuǎn)會發(fā)熱嚴(yán)重、壽命驟降。這時候就該上MG996R或者更高一級的舵機。第二是工作電壓。SG90標(biāo)稱4.8VMG996R可以支持4.8V到6.8V。電壓越高扭矩越大但同時電流也上去。很多人直接把舵機接到ESP32的3.3V引腳上結(jié)果連空載都轉(zhuǎn)不動道理就在這。常規(guī)做法是給舵機一個5V的獨立電源電壓不足時再考慮升壓或換更高電壓舵機。第三是齒輪材質(zhì)。金屬齒輪抗沖擊、壽命長但價格高、重量大、電流需求也高塑料齒輪便宜、輕巧適合低速輕載場景。高速碰撞場景比如機器狗、機械臂快速擺動別用塑料齒輪容易掃齒。2.3 供電設(shè)計最容易翻車的環(huán)節(jié)沒有之一我調(diào)試舵機項目時踩過最狠的坑就是供電。一個SG90空載電流大概100mA到200mA堵轉(zhuǎn)時能飆到650mA甚至更高M(jìn)G996R堵轉(zhuǎn)電流可以超過2A。而大部分ESP32開發(fā)板的板載穩(wěn)壓器能穩(wěn)定輸出的電流也就500mA左右還要分給主控和Wi-Fi。結(jié)果就是舵機一啟動電壓瞬間被拉低ESP32直接重啟或者舵機在原地嗡嗡發(fā)抖。正確接法分兩路走ESP32用USB供電或獨立的3.3V/5V供電舵機用獨立的5V電源供電兩者之間必須共地。所謂共地就是把外部電源的負(fù)極和ESP32的GND引腳連在一起。如果不共地PWM信號的電平參考點不一致舵機收到的信號可能完全亂掉。如果你只是測試一個SG90用5V 1A的適配器就夠如果是兩個MG996R建議上5V 3A以上的電源或者直接用2S鋰電池加5V穩(wěn)壓模塊/UBEC。總之舵機電源寧大勿小尤其不要圖省事直接從ESP32開發(fā)板的Vin引腳甚至3.3V引腳取電。3. 硬件連接與最小系統(tǒng)搭建3.1 三根線的正確接法標(biāo)準(zhǔn)舵機引出來三根線顏色約定一般是棕色或黑色是地線GND紅色是電源線VCC橙色或黃色是信號線Signal。信號線接ESP32的GPIO引腳電源線接外部5V正極地線接外部電源負(fù)極同時和ESP32的GND相連。注意信號線絕對不要接到5V上ESP32的GPIO是3.3V邏輯直接接5V輕則IO口損壞重則燒芯片。某些舵機尤其是工業(yè)舵機需要5V邏輯信號那就要加電平轉(zhuǎn)換電路不能用3.3V直驅(qū)。推薦優(yōu)先使用的信號引腳有GPIO13、GPIO12、GPIO14、GPIO27、GPIO26、GPIO25。這幾個引腳沒有上電時序限制也沒有板載外設(shè)占用是舵機控制的“安全區(qū)”。需要避開的是GPIO0BOOT引腳、GPIO1和GPIO3串口、GPIO6到GPIO11連接板載Flash等。3.2 布線實踐信號線要短地線要粗常見場景里舵機裝在機械臂末端信號線要走一兩米這時就容易出問題。舵機信號線最好控制在20cm以內(nèi)越短越穩(wěn)。如果必須長距離走線用屏蔽線或者雙絞線并且GPIO上可以加一個1kΩ串聯(lián)電阻降低信號反射和干擾。電源線路也要注意。舵機啟動瞬間電流很大如果電源線太細(xì)線路壓降會把5V拉到4V以下舵機自然沒勁。我習(xí)慣用18AWG以上的線做舵機電源線或者直接焊線到舵機端而不是用杜邦線。實測過用普通杜邦線帶兩個MG996R同時動作線會發(fā)熱電壓跌落很明顯。最后說一句多舵機項目里建議給每個舵機電源端加一個100μF到470μF的電解電容靠近舵機電源輸入位置。這個電容能在啟動瞬間補充電流能明顯減少電壓跌落導(dǎo)致的抖動。4. 開發(fā)環(huán)境配置與舵機庫選型4.1 安裝Arduino Core for ESP32與ESP32Servo庫軟件側(cè)我用的是Arduino IDE加Espressif官方Arduino Core。安裝好核心之后還需要裝一個關(guān)鍵庫ESP32Servo。這個庫是專門為ESP32適配的舵機控制庫底層封裝了LEDC的PWM設(shè)置并把控制接口抽象成類似普通開發(fā)板Servo庫的寫法。在Arduino庫管理器里搜索“ESP32Servo”直接安裝作者是某個社區(qū)開發(fā)者這已經(jīng)是ESP32舵機控制事實上最常用的庫。它能同時管理十幾路舵機支持微秒級脈寬寫入還內(nèi)置了平滑移動方法后面的高級應(yīng)用會用到。如果不用這個庫直接用ESP32自帶的LEDC API寫PWM也行但手寫的代碼要多處理定時器分組、通道分配這些細(xì)節(jié)對新手不友好。我的建議是標(biāo)準(zhǔn)舵機控制場景一律用ESP32Servo只有需要非常規(guī)頻率或自定義波形的特殊需求才直接用LEDC API。4.2 ESP32Servo庫與LEDC API的關(guān)系理解一下底層邏輯。ESP32的LEDC模塊有16個通道分成4組定時器每組定時器最多帶8個通道。同組定時器的通道必須共用相同的頻率和分辨率。ESP32Servo庫會把舵機請求的50Hz設(shè)置到某個定時器組然后把通道分配給舵機。這里有個容易踩雷的地方同一組定時器里所有通道頻率必須相同如果你在一個項目里又用LEDC做LED呼吸燈頻率比如5kHz又用ESP32Servo驅(qū)動舵機50Hz兩者如果落在同一組定時器上會互相干擾表現(xiàn)為舵機亂抖、燈頻閃。解決辦法是手動指定servo庫使用不同的定時器或者干脆舵機和LED呼吸燈用不同的LEDC定時器組。我一般在多任務(wù)項目里習(xí)慣拆成兩組一組定時器專門給舵機另一組定時器給其它PWM設(shè)備這樣互不干擾。5. 基礎(chǔ)驅(qū)動代碼從write到自定義脈寬5.1 最小驅(qū)動代碼裝好庫之后跑通第一個舵機最簡單#include ESP32Servo.h Servo myServo; const int servoPin 13; void setup() { myServo.attach(servoPin, 500, 2400); // 引腳, 最小脈寬μs, 最大脈寬μs myServo.write(90); // 回到中位 } void loop() { for (int angle 0; angle 180; angle 1) { myServo.write(angle); delay(15); } for (int angle 180; angle 0; angle - 1) { myServo.write(angle); delay(15); } }attach函數(shù)的三個參數(shù)分別是信號引腳、最小脈寬和最大脈寬。默認(rèn)值是544到2400μs對應(yīng)0°和180°。為什么我寫500到2400因為SG90的實際行程范圍通常到不了2.5ms用2400作為180°端點在接近兩端時更不容易頂死。實測中我發(fā)現(xiàn)用默認(rèn)值直接write(0)和write(180)時有些舵機會發(fā)出“咔咔”的頂齒聲那是舵機機械限位已經(jīng)到了但信號還在驅(qū)動它繼續(xù)往死里頂。把脈寬范圍縮小一點反而更安全代價只是犧牲一點點角度范圍換來的是齒輪和保護(hù)。5.2 用writeMicroseconds精確控制如果你需要非常精確地控制某一個中間角度或者想讓舵機停在5°、10°這種位置的精細(xì)點上靠write(angle)可能不夠細(xì)因為庫內(nèi)部還要做一次浮點到脈寬的轉(zhuǎn)換。更直接的方法是writeMicrosecondsmyServo.writeMicroseconds(1500); // 90°位置 myServo.writeMicroseconds(1000); // 45°位置 myServo.writeMicroseconds(2000); // 135°位置這里有個好處你可以繞過角度整數(shù)直接給任意脈寬實現(xiàn)亞度級的位置控制。還有一個實際用途校準(zhǔn)舵機的中位。不同品牌舵機的90°位置對應(yīng)的脈寬可能略有偏差有的在1480μs有的在1520μs。用一個可以微調(diào)脈寬的程序?qū)崪y找出舵機真正回中的脈寬再把這個值作為基準(zhǔn)能顯著提升多舵機項目的精度。5.3 多舵機同步控制多舵機控制有兩種思路一種是每個舵機獨立attach然后逐個write另一種是所有舵機循環(huán)一個時間片讓它們在視覺上“同步”運動。第一種寫法的參考代碼#include ESP32Servo.h Servo servo[6]; int pins[6] {13, 12, 14, 27, 26, 25}; void setup() { for (int i 0; i 6; i) { servo[i].attach(pins[i], 500, 2400); servo[i].write(90); } } void loop() { for (int a 0; a 180; a 2) { for (int i 0; i 6; i) { servo[i].write(a); } delay(20); } }注意我在loop里不是把一個舵機從0轉(zhuǎn)到180再轉(zhuǎn)下一個而是所有舵機同時逐步變化。舵機物理響應(yīng)有一個時間過程多個舵機同時收到位置更新指令時它們在視覺上是同步開始運動的這就是“偽同步”。如果真要讓多個舵機精確到同一時刻到達(dá)某個角度單靠write是不夠的需要計算每個舵機的速度和加速度讓它們在同一時間窗內(nèi)到達(dá)目標(biāo)這就引出下一步的平滑運動。6. 高級應(yīng)用平滑運動、串口控制與多路擴展6.1 用插值實現(xiàn)平滑運動直接write會讓舵機以最大速度“彈”到目標(biāo)位置在機械臂上看起來非常生硬而且還容易因為慣性造成末端抖動。解決思路是中間插值把一段行程切成很多小步每步之間加延時讓舵機看起來是“勻速滑過去”。void smoothMove(Servo s, int startAngle, int endAngle, int durationMs) { int steps 30; int delta endAngle - startAngle; for (int i 0; i steps; i) { int angle startAngle delta * i / steps; s.write(angle); delay(durationMs / steps); } }這個接口看起來簡單但實際使用有幾個細(xì)節(jié)。第一是steps太少會有頓挫感太多則舵機追不上指令動作反而出現(xiàn)滯后。我實踐經(jīng)驗是30步左右對大多數(shù)模擬舵機剛剛好。第二是durationMs的最小值有物理限制普通模擬舵機從0°轉(zhuǎn)到180°大約需要0.3到0.5秒如果你強行把durationMs設(shè)成200ms舵機追不上最后還是全速沖過去。第三是這種簡單線性插值沒有加減速機械臂高速啟動、急停時依然會有沖擊感真正的順滑要在起始和結(jié)束段做S曲線加減速即速度先慢、中間快、末尾再慢。S曲線實現(xiàn)也不復(fù)雜就是在插值時不再等比例分配角度而是按一個正弦或多項式曲線分配比例。比如用正弦函數(shù)float t (float)i / steps; float eased (1.0 - cos(t * PI)) / 2.0; int angle startAngle (int)(delta * eased);這個公式的好處是起步和收尾速度都是0中間自然加速機械動作明顯柔和很多。6.2 串口指令控制把舵機交給上位機項目做大了之后舵機不可能總在固定的循環(huán)里跑你需要在上位機或者另一塊主控上隨時指定某個舵機轉(zhuǎn)到某個角度。最簡單的實現(xiàn)就是串口協(xié)議。#include ESP32Servo.h Servo myServo; String input ; void setup() { Serial.begin(115200); myServo.attach(13, 500, 2400); } void loop() { while (Serial.available()) { char c Serial.read(); if (c \n) { int angle input.toInt(); if (angle 0 angle 180) { myServo.write(angle); Serial.println(OK: String(angle)); } else { Serial.println(ERR); } input ; } else { input c; } } }協(xié)議格式定義為直接發(fā)整數(shù)如90換行確認(rèn)。回讀OK或ERR方便上位機確認(rèn)指令到達(dá)。這個協(xié)議很短但擴展性很好如果要控制多個舵機可以約定成1:90表示1號舵機到90°解析時用split處理冒號即可。再往上走可以用ESP32的Wi-Fi功能把舵機控制做成一個HTTP接口或者WebSocket服務(wù)。上位機不需要連串口線直接在瀏覽器里拖動滑塊遠(yuǎn)程控制機械臂。這部分本質(zhì)上是把串口字符換成了網(wǎng)絡(luò)請求控制邏輯完全一樣但應(yīng)用場景一下子就打開了。6.3 多舵機數(shù)量擴展PCA9685還是繼續(xù)用ESP32引腳如果舵機數(shù)量超過10個直接占用GPIO就不太劃算了因為還要留引腳給傳感器、編碼器、顯示屏。這種時候我傾向于用PCA9685舵機驅(qū)動板。它通過I2C接口控制16路PWM整個板子只占ESP32的兩個引腳SDA和SCL卻能接16個舵機擴展多塊板子還能繼續(xù)堆通道數(shù)。PCA9685的接線也很簡單VCC接5VGND共地SDA接GPIO21SCL接GPIO22ESP32的默認(rèn)I2C引腳。軟件上裝Adafruit PWM Servo Driver庫初始化時設(shè)置頻率為50Hz然后通過setPWM(channel, 0, pulseWidth)控制對應(yīng)舵機。這里有個關(guān)鍵參數(shù)PCA9685內(nèi)部是12位分辨率占空比數(shù)值范圍0到4095。50Hz周期20ms那么1ms脈寬對應(yīng)的計數(shù)是4095 * 1 / 20 ≈ 2051.5ms對應(yīng)307。換算公式pulseCount 脈寬(ms) * 4095 / 20用這個庫驅(qū)動舵機時記得給PCA9685單獨供電它板載的穩(wěn)壓器一般是給邏輯部分用的舵機電流還是從外部5V走。6.4 定時器分組與自定義PWM突破庫的邊界ESP32Servo庫很好用但它隱藏了定時器分配細(xì)節(jié)。如果你需要完全掌控PWM輸出或者是想在同一塊板上同時輸出多種頻率可以直接使用LEDC APIconst int freq 50; const int resolution 16; const int channel 0; const int pin 13; ledcSetup(channel, freq, resolution); ledcAttachPin(pin, channel); // 0°對應(yīng)脈寬0.5ms20ms周期duty 2^16 * 0.5 / 20 1638 ledcWrite(channel, 1638); // 90°對應(yīng)1.5ms脈寬duty 65535 * 1.5 / 20 4915 ledcWrite(channel, 4915);用16位分辨率時計數(shù)范圍0到6553550Hz下每個計數(shù)單位約0.3μs的脈寬精度足夠精細(xì)。但要注意16位分辨率下LEDC的實際分頻系數(shù)是有限制的某些頻率組合可能導(dǎo)致實際輸出頻率偏離設(shè)定值。我實測下來50Hz配16位在ESP32上工作正常如果你需要高速PWM把分辨率降到12位或更低反而更穩(wěn)定。這個方案適合的場景舵機需要非標(biāo)準(zhǔn)脈寬范圍、需要和別的PWM設(shè)備并行、或者需要在中斷里動態(tài)改脈寬的情況。普通控制還是用ESP32Servo更省心。7. 常見問題與排查技巧實錄7.1 舵機抖動或嗡嗡響怎么查舵機抖動永遠(yuǎn)是供電問題排在第一位信號問題排在第二位。先看電源舵機供電電壓是否穩(wěn)定有沒有用獨立電源地線有沒有共地電源線是否太細(xì)。用萬用表實時量一下舵機電源端的電壓如果動作瞬間電壓掉到4.5V以下基本就是供電不足。排除供電后再看信號線線是否太長、是否靠近電機或電感元件、有沒有和電源線綁在一起走線。我遇到過一次舵機在某個特定角度狂抖查了很久發(fā)現(xiàn)是控制線和大電流導(dǎo)線平行走了40cm干擾信號了。把導(dǎo)線分開、加上屏蔽后解決。還有一個容易忽略的點PWM頻率。如果你用ESP32Servo庫頻率被固定在50Hz不需要管但如果你手寫了LEDC配置頻率設(shè)錯比如設(shè)成500Hz舵機就會瘋狂抖動并尖銳鳴叫。檢查ledcSetup里的freq參數(shù)。7.2 舵機不動但發(fā)燙先聽聲音。如果舵機通電后內(nèi)部馬達(dá)在較勁發(fā)出悶悶的嗡聲說明舵機在努力往某個方向轉(zhuǎn)但被卡住了。常見原因是齒輪卡死、連桿過緊、或者電源電壓不夠?qū)е买?qū)動不了。這時候立即斷電手動轉(zhuǎn)動舵機搖臂看是否順暢排除機械卡頓。另一種情況是信號根本沒進(jìn)去。用示波器或邏輯分析儀看GPIO有沒有方波輸出沒有示波器的話先用Serial.print打印一下程序運行狀態(tài)確認(rèn)程序確實跑到了attach和write那幾行。我吃過一次虧初始化代碼寫在setup里然后loop里有個死循環(huán)跳不出來舵機當(dāng)然紋絲不動。7.3 接上舵機ESP32就重啟這是最經(jīng)典的電源坑。舵機啟動瞬間的電流沖擊拉低了整個系統(tǒng)的電壓ESP32的穩(wěn)壓器檢測到欠壓直接復(fù)位。排查方法把舵機的電源線和ESP32分開用獨立5V電源給舵機共地后如果問題消失那就確認(rèn)了是供電不足。如果臨時沒有獨立電源有一個應(yīng)急辦法在舵機電源引腳旁邊加一個大電容比如1000μF電解電容能緩解瞬間浪涌。但這只是緩兵之計長期跑項目一定要獨立供電。7.4 多個舵機動作互相干擾現(xiàn)象是動A舵機時B舵機也跟著抖或者兩個舵機位置錯亂。這大概率是定時器組沖突。前面講過ESP32的LEDC分4組定時器同組共享頻率。如果兩個舵機恰好被分配到同組定時器而且你在程序里又手動去改了這個組里某一個通道的頻率就會把整組通道帶偏。解決辦法ESP32Servo庫里有setTimerHz相關(guān)配置或者在attach前查清楚通道和定時器分配。更省事的方法是把所有用到不同頻率的PWM設(shè)備用同一組頻率驅(qū)動比如LED呼吸燈直接舍棄或者單獨用另一個LEDC定時器組、讓舵機全部走某一個組。7.5 實測排查順序表根據(jù)我大量排查經(jīng)驗列一張速查表按順序檢查能省下大量時間現(xiàn)象第一排查項第二排查項第三排查項舵機完全不動信號線是否接對GPIO供電是否到位代碼是否執(zhí)行到write舵機抖動供電電壓是否穩(wěn)定信號線是否受干擾頻率是否50Hz舵機角度不準(zhǔn)脈寬范圍是否匹配機械安裝是否松動舵機是否磨損接舵機即重啟供電是否獨立電容是否缺失電源功率是否夠多舵機互相影響定時器組是否沖突共地是否可靠電源線是否過細(xì)這張表不一定覆蓋所有情況但能解決日常八成問題。我后來做舵機項目都是先按表格過一遍再決定要不要深入排查程序邏輯。8. 一些親測好用的工程習(xí)慣最后聊點代碼之外的東西。第一個習(xí)慣是所有舵機項目先把電源做成“可斷”的舵機電源獨立開關(guān)方便程序燒錄時斷開舵機電源。否則每次燒錄時舵機突然回中機械臂會猛甩一下危險不說還容易撞壞結(jié)構(gòu)件。第二個習(xí)慣是給每路舵機定義一個邏輯編號結(jié)構(gòu)體統(tǒng)一管理角度范圍、當(dāng)前角度、目標(biāo)角度。項目變大以后你會發(fā)現(xiàn)所有舵機直接寫死在代碼里根本維護(hù)不了用結(jié)構(gòu)體數(shù)組加上統(tǒng)一的MoveTo接口上層邏輯會清晰很多。第三個習(xí)慣是API設(shè)計上盡量保留writeMicroseconds而不是只用write。角度write確實直觀但當(dāng)你需要做舵機校準(zhǔn)時脈寬是更底層的真實控制量。我習(xí)慣在配置里保存每路舵機的脈寬零點和范圍運行時全部用脈寬控制需要角度時再臨時換算。這樣換了舵機型號后只需改配置不改代碼。ESP32加舵機這個組合還有個擴展空間很大的方向接上MPU6050陀螺儀做閉環(huán)把舵機當(dāng)成云臺的執(zhí)行器姿態(tài)數(shù)據(jù)作為反饋做一個真正意義上的穩(wěn)定云臺。這已經(jīng)不是單純PWM控制的問題了而是控制算法的范疇。不過只要PWM這條線走得穩(wěn)到那個階段也只是水到渠成的事。