議與反相電路詳解:從串口原理到飛控集成實(shí)戰(zhàn))
玩穿越機(jī)、固定翼航模的朋友說到接收機(jī)和飛控之間的連接SBUS這三個(gè)字基本繞不開。它是一套用串口承載遙控通道數(shù)據(jù)的協(xié)議最早由Futaba推出來后來被各家接收機(jī)廠商廣泛采用幾乎成了航模遙控接收機(jī)的標(biāo)配輸出方式。很多新手第一次接SBUS接收機(jī)十個(gè)有九個(gè)會(huì)栽在同一個(gè)地方——信號(hào)反相。明明看著線接對(duì)了飛控就是識(shí)別不到搖桿或者通道跳得像抽風(fēng)排查半天才發(fā)現(xiàn)是硬件反相電路的問題。這篇內(nèi)容把SBUS協(xié)議本身、硬件反相電路、飛控集成配置和常見坑一次講清楚不管是第一次接觸SBUS的玩家還是想自己畫一塊帶SBUS輸入的小板子的開發(fā)者都可以直接照著做。1. SBUS協(xié)議基礎(chǔ)別只看串口參數(shù)1.1 SBUS到底是怎么傳數(shù)據(jù)的傳統(tǒng)PWM接收機(jī)每個(gè)通道就需要一根信號(hào)線。一臺(tái)固定翼用6個(gè)舵機(jī)就要接6根PWM線穿越機(jī)動(dòng)輒8個(gè)通道以上線束會(huì)繞成一團(tuán)飛控的輸入引腳也不夠用。SBUS的思路是接收機(jī)把所有通道的脈寬值按位打包成一串?dāng)?shù)字幀通過一根信號(hào)線連續(xù)發(fā)給飛控飛控再解包還原出每個(gè)通道的值。再加上鋰電池電壓、遙控器開關(guān)量、失控保護(hù)狀態(tài)這些信息一根線就能傳16個(gè)通道這是PPM都無法比的優(yōu)勢(shì)。SBUS本質(zhì)上是串口UART協(xié)議波特率是100000bps8個(gè)數(shù)據(jù)位偶校驗(yàn)Even Parity2個(gè)停止位沒有硬件流控。注意這個(gè)波特率不是常用的9600、115200而是偏門的100000調(diào)試的時(shí)候如果選錯(cuò)讀出來的就是一團(tuán)亂碼。實(shí)際傳輸?shù)奈锢黼娖绞沁壿嬰娖浇邮諜C(jī)通常輸出3.3V或者5V信號(hào)所以F4、F7這類飛控的芯片引腳能夠直接兼容只是反相問題需要特別處理。1.2 25字節(jié)一幀16個(gè)通道怎么塞進(jìn)去的SBUS協(xié)議每一幀固定25個(gè)字節(jié)格式很規(guī)整字節(jié)位置內(nèi)容Byte 0幀頭 0x0FByte 1 ~ Byte 22通道數(shù)據(jù)共22字節(jié)Byte 23狀態(tài)字節(jié)內(nèi)含幀丟失、失控保護(hù)等標(biāo)志位Byte 24幀尾 0x0016個(gè)通道每個(gè)通道值是11bit16個(gè)通道一共占用176bit正好等于22字節(jié)×8bit。數(shù)據(jù)按位連續(xù)打包從通道1開始低比特在前、高比特在后。實(shí)際通道值范圍一般約為0~2047飛控拿到后會(huì)按照自己的邏輯映射到1000~2000甚至更多。所以在飛控配置頁面能看到搖桿量程而不是直接看到PWM脈寬。解碼的時(shí)候如果把22字節(jié)數(shù)據(jù)看成一個(gè)整數(shù)用小端模式拼接然后每11bit切一段就能得到16個(gè)通道的值。這個(gè)做法我在后面調(diào)試部分會(huì)給出一個(gè)能直接跑的Python函數(shù)。幀頭0x0F和幀尾0x00是鎖定幀邊界的關(guān)鍵。不過要注意狀態(tài)字節(jié)里面如果出現(xiàn)0x00也容易讓人誤判幀尾所以固定長(zhǎng)度掃描比單純找?guī)哺煽空业?x0F后直接往后取25字節(jié)再檢查最后一個(gè)字節(jié)是不是0x00。1.3 為什么會(huì)有“反相”這種反人類設(shè)計(jì)這是SBUS新手最不理解的地方。普通UART空閑時(shí)是高電平起始位是低電平停止位是高電平。而SBUS恰恰相反空閑時(shí)為低電平起始位是高電平停止位是低電平。也就是說SBUS信號(hào)是標(biāo)準(zhǔn)UART信號(hào)的反向。有人會(huì)問好好一個(gè)串口為什么非要反著來SBUS是從Futaba的遙控系統(tǒng)里出來的當(dāng)初設(shè)計(jì)時(shí)可能考慮到與某些射頻前端或光耦隔離電路配合更方便具體原因沒有官方文檔說得很清楚但結(jié)果就是你用普通UART直接收會(huì)一直收到break錯(cuò)誤、幀錯(cuò)誤飛控根本解析不出來。解決方式要么是接收機(jī)輸出非反相信號(hào)部分固件支持要么在外部加一個(gè)反相器這正是接下來要講的重點(diǎn)。2. 硬件反相電路設(shè)計(jì)選型、計(jì)算與實(shí)戰(zhàn)2.1 先判斷你的飛控到底需不需要反相器加不加外部反相器先看飛控。很多成品飛控上會(huì)留一個(gè)專門標(biāo)注“SBUS”的焊盤比如接在某個(gè)UART的RX腳旁邊板子上已經(jīng)集成了反相電路有些飛控則只給了普通UART接口如果你把SBUS反相信號(hào)直接接到普通RX上大概率通道完全不進(jìn)。怎么判斷最直接的方法看飛控原理圖或者產(chǎn)品說明。要是沒有資料就自己測(cè)把接收機(jī)單獨(dú)供電用萬用表測(cè)量SBUS輸出引腳對(duì)地電壓。接收機(jī)沒收到遙控信號(hào)時(shí)如果測(cè)到接近0V說明這是反相SBUS如果測(cè)到接近3.3V或5V說明輸出是非反相信號(hào)。還有一種土辦法把SBUS信號(hào)直接連到USB轉(zhuǎn)TTL模塊的RX用串口助手設(shè)好100000波特率、8E2如果出來的全是亂碼或根本無輸出大概率就是反相問題。大多數(shù)接收機(jī)默認(rèn)輸出反相SBUS所以“直接接普通UART就能用”反而是例外。保險(xiǎn)起見我施工時(shí)都會(huì)先測(cè)靜態(tài)電平再?zèng)Q定要不要加反相器而不是一上來就焊。2.2 三極管反相電路一個(gè)能直接抄的電路我推薦最常用的NPN三極管方案元件到處都能買到成本幾毛錢。電路非常經(jīng)典接收機(jī)SBUS ──┬── R1(10kΩ) ──┬── Q1(NPN) 基極 │ │ R3(100kΩ) Q1 發(fā)射極 ── GND │下拉 GND Q1 集電極 ──┬── 飛控UART RX └── R2(4.7kΩ) ── 3.3V電源原理一句話輸入為低電平時(shí)Q1截止集電極通過R2被拉到3.3V所以輸出高電平輸入為高電平時(shí)Q1飽和導(dǎo)通集電極被拉到接近0V所以輸出低電平。輸入輸出剛好反相同時(shí)把電平鉗在3.3V對(duì)飛控MCU安全。元件參數(shù)不是隨便選的。設(shè)接收機(jī)SBUS高電平為3.3VQ1選擇2N3904集電極電流Ic主要由R2決定R24.7kΩ時(shí)Ic≈3.3V/4.7kΩ≈0.7mA。要讓三極管深度飽和基極電流Ib至少取Ic/10約0.07mA。基極電阻R1如果取10kΩ基極電流約為(3.3V-0.7V)/10kΩ0.26mA余量足夠。R3的下拉電阻要盡量大取100kΩ避免和R1分壓把基極電壓拖低如果換成1kΩ輸入高電平時(shí)基極可能連0.7V都達(dá)不到三極管根本不開這也是很多自制反相器失敗的常見原因。為什么R2取4.7kΩ而不是100Ω集電極上拉電阻太小靜態(tài)電流會(huì)很大三極管導(dǎo)通時(shí)功耗也會(huì)增加上拉電阻取太大輸出上升沿被RC時(shí)間常數(shù)拖慢100kbps波特率下容易出誤碼。4.7kΩ到10kΩ是我實(shí)測(cè)比較穩(wěn)的范圍。2.3 用MOS管反相和邏輯門反相的區(qū)別除了NPN三極管還可以用增強(qiáng)型NMOS管比如2N7000。電路類似源極接地漏極輸出外部上拉R2到3.3V柵極接輸入柵極對(duì)地接一個(gè)100kΩ到1MΩ的下拉電阻。輸入低電平時(shí)Vgs0MOS截止輸出高輸入高電平時(shí)Vgs大于閾值MOS導(dǎo)通輸出低。2N7000的導(dǎo)通電阻很低輸出低電平很接近0V波形比三極管更干凈。不過使用MOS管要注意柵極閾值電壓。2N7000的Vgs(th)一般在1V到2V之間3.3V邏輯沒問題如果接收機(jī)輸出高電平只有2.8V這種低電壓建議選邏輯電平MOS管否則可能無法完全導(dǎo)通。更省心的方案是邏輯門反相器比如74HC04、74LVC1G04這類芯片。把輸入接到其中一個(gè)反相器輸入輸出接到飛控RX芯片電源接3.3V。邏輯門的優(yōu)勢(shì)是輸出波形上升下降沿很陡幾乎無失真抗干擾也強(qiáng)缺點(diǎn)是比單管多焊一個(gè)芯片還要加0.1μF電源去耦電容。如果你只是給一塊飛控改SBUS三極管方案就夠了如果要在強(qiáng)干擾環(huán)境下做信號(hào)整形邏輯門更穩(wěn)。2.4 焊接和布線階段的三個(gè)建議第一反相器要盡量靠近飛控RX焊盤焊接輸出線越短越好。SBUS波特率100k不算高但飛行環(huán)境里電調(diào)和電機(jī)是強(qiáng)干擾源輸入線如果和電源線平行長(zhǎng)距離走線可能把噪聲耦合進(jìn)來。第二接收機(jī)、反相器、飛控三者必須共地地線盡量粗不要靠信號(hào)線自己回流。第三如果接收機(jī)輸出的是5V信號(hào)輸入側(cè)經(jīng)過R1限流進(jìn)入三極管基極只要R1不是太小不會(huì)燒管子輸出側(cè)因?yàn)樯侠?.3V飛控RX不會(huì)承受5V比較安全。焊接完成后先別急著裝槳上電用萬用表量一下反相器輸出端靜態(tài)電壓。正常的SBUS信號(hào)在空閑時(shí)輸入是低電平所以反相器輸出應(yīng)為約3.3V高電平。如果輸出是0V說明電路沒工作可能是管子腳位焊錯(cuò)也可能R3取值太小把輸入高電平拉沒了。3. 飛控集成實(shí)操接線、配置與驗(yàn)證3.1 從接收機(jī)到飛控的完整接線流程在動(dòng)手之前先把鏈路理清接收機(jī)輸出SBUS信號(hào)反相器負(fù)責(zé)把反相信號(hào)變成普通UART信號(hào)飛控的UART RX接收固件解析出通道。整個(gè)鏈路里每個(gè)環(huán)節(jié)都必須對(duì)。以穿越機(jī)最常見的F4飛控為例接線步驟如下接收機(jī)的電源線接飛控5V和GND或者用獨(dú)立BEC供電但GND一定要和飛控共地。接收機(jī)SBUS輸出接反相器輸入。注意有些接收機(jī)有S.BUS和S.PORT兩個(gè)口S.PORT是傳感器總線不要接錯(cuò)。反相器輸出接飛控目標(biāo)UART的RX焊盤比如UART1 RX、UART2 RX。具體哪個(gè)看飛控手冊(cè)接錯(cuò)串口后面配置就亂了。上電后用萬用表測(cè)反相器輸出的靜態(tài)電平應(yīng)當(dāng)約為3.3V同時(shí)測(cè)一下接收機(jī)供電是否正常。再把飛控連接地面站進(jìn)入端口配置頁面。這個(gè)過程看似簡(jiǎn)單但我見過不少人把RX和TX焊反或者把SBUS信號(hào)接到了S.PORT焊盤上結(jié)果怎么配都沒有反應(yīng)。所以強(qiáng)烈建議第一步先看飛控絲印再拿萬用表蜂鳴檔對(duì)著原理圖找焊盤。3.2 Betaflight / INAV 里的固件配置硬件接好后需要在飛控固件里打開對(duì)應(yīng)串口并選擇SBUS協(xié)議。以Betaflight為例打開Betaflight Configurator連接飛控后進(jìn)入“端口Ports”頁面找到你接的那個(gè)UART。在對(duì)應(yīng)的“Serial RX”列打勾確保狀態(tài)變成“Enabled”。有些默認(rèn)固件里這個(gè)端口已經(jīng)被其他功能占用比如GPS或遙測(cè)需要先關(guān)掉。接著進(jìn)入“配置Configuration”頁面接收器Receiver Mode選擇“Serial (via UART)”接收器協(xié)議Receiver Provider選擇“SBUS”。保存并重啟飛控。INAV的流程類似也是在端口頁面把對(duì)應(yīng)UART設(shè)為串行RX然后在配置頁面選擇SBUS。如果找不到某個(gè)選項(xiàng)先檢查固件版本和刷寫時(shí)的目標(biāo)板別把F4的固件刷到F7上去。完成配置后在Betaflight的“接收器Receiver”頁面或者遙控器打桿的同時(shí)觀察對(duì)應(yīng)通道的進(jìn)度條。正常情況通道值應(yīng)該在1000~2000之間波動(dòng)中位接近1500。如果通道有反應(yīng)但數(shù)值不在正常范圍檢查遙控器端通道映射和端點(diǎn)的設(shè)置。3.3 關(guān)于serialrx_inverted這類隱藏參數(shù)的說明在Betaflight的CLI命令行里有一些和串行接收機(jī)有關(guān)的參數(shù)比如get serialrx_provider get serialrx_invertedserialrx_provider用來查看當(dāng)前選擇的協(xié)議正常會(huì)顯示SBUS。serialrx_inverted這個(gè)參數(shù)各個(gè)版本含義略有不同如果你的信號(hào)鏈路里已經(jīng)通過外置反相器或飛控板載反相器把SBUS轉(zhuǎn)成了普通UART通常保持OFF如果某個(gè)飛控板把反相邏輯又反轉(zhuǎn)了一次或者你接了非反相SBUS信號(hào)進(jìn)MCU導(dǎo)致最終到芯片的是反相UART可能需要把這個(gè)參數(shù)設(shè)為ON才能正常解析。我的建議是不要亂改這個(gè)參數(shù)。先確認(rèn)硬件鏈路里反相次數(shù)SBUS接收機(jī)出來是反相經(jīng)過外置反相器后變正常這算一次飛控板載反相器再反一次MCU看到的又變回反相那么該飛控設(shè)計(jì)時(shí)就應(yīng)該有對(duì)應(yīng)處理。你只需要按照飛控官方接線圖接除非你確認(rèn)信號(hào)極性不對(duì)才用CLI參數(shù)去“軟件反相”救命。3.4 ArduPilot或其他開源固件的參考ArduPilot通常不是用Betaflight那種“串口協(xié)議”的思路來配SBUS。很多飛控板有專門的RCIN接口SBUS接收機(jī)可以直接插RCIN排針固件自動(dòng)檢測(cè)協(xié)議當(dāng)然也包括SBUS。如果是通過普通串口接入一般需要在Mission Planner的完整參數(shù)列表里找到對(duì)應(yīng)的SERIALx_PROTOCOL把它設(shè)為23即RCIN同時(shí)確認(rèn)SERIALx_OPTIONS里有沒有需要打開的反相選項(xiàng)。不同版本的ArduPilot對(duì)SBUS的支持有一些差異而且飛控硬件五花八門我不建議完全照抄別人的參數(shù)。最可靠的方法是去查對(duì)應(yīng)飛控板和ArduPilot官方wiki確認(rèn)RCIN或串口輸入的具體引腳和默認(rèn)協(xié)議。飛控集成這種東西最怕的就是“我朋友說這樣配能用”結(jié)果板子根本不是同一個(gè)型號(hào)。4. 調(diào)試、故障排查與一些獨(dú)家避坑經(jīng)驗(yàn)4.1 常見問題速查表癥狀可能原因排查步驟完全沒通道數(shù)據(jù)接收機(jī)燈正常信號(hào)極性不對(duì)、串口選錯(cuò)、RX/TX接反萬用表測(cè)反相器輸出靜態(tài)電平確認(rèn)接到飛控RX腳重新檢查端口配置通道值跳變、偶爾抽風(fēng)共地不良、供電不足、虛焊加粗地線檢查接收機(jī)供電電壓重新補(bǔ)焊信號(hào)線地面站顯示RXLOSS接收機(jī)沒有輸出SBUS、接線斷路、協(xié)議沒選SBUS用示波器/邏輯分析儀看SBUS引腳有無幀波形檢查配置頁面通道值只有一半或無中位遙控器通道映射錯(cuò)誤、EndPoint設(shè)置不對(duì)在遙控器上校準(zhǔn)行程地面站里確認(rèn)通道映射表接上SBUS后其他串口設(shè)備異常占用同一個(gè)UART或者信號(hào)誤接換一個(gè)空閑UART重新配置端口上電后反相器發(fā)燙上拉電阻太小、三極管引腳接錯(cuò)檢查R2阻值用萬用表確認(rèn)集電極、發(fā)射極、基極是否和電路圖一致這些都是我實(shí)際見過的問題。尤其是共地不良在通電后電機(jī)轉(zhuǎn)動(dòng)時(shí)特別明顯通道值會(huì)跟著油門抖很多人還以為是接收機(jī)壞了。4.2 現(xiàn)場(chǎng)排除過的一個(gè)反相器故障有一次給一架固定翼改SBUS用的是2N3904三極管反相電路焊好以后萬用表測(cè)輸入靜態(tài)低電平0V輸出卻只有0.4V怎么看都不對(duì)。最后發(fā)現(xiàn)是集電極和發(fā)射極焊反了三極管EBC腳位沒對(duì)上輸入信號(hào)從集電極進(jìn)去輸出從發(fā)射極出來管子根本沒有工作在正確狀態(tài)。換過來以后輸出恢復(fù)到3.3V重上電立刻有通道值。后來我養(yǎng)成一個(gè)習(xí)慣焊完三極管先用萬用表二極管檔量一遍確認(rèn)B/E/C三腳和焊盤的對(duì)應(yīng)關(guān)系再上電。尤其是從元件盒里翻出來的散裝三極管絲印經(jīng)常模糊腳位不一定都是同一種排列。這類小元件問題排查起來最浪費(fèi)時(shí)間而且新手很容易忽略。還有一個(gè)案例是接收機(jī)輸出SBUS信號(hào)在電腦USB轉(zhuǎn)TTL上能看到正常幀但接上飛控后就是沒反應(yīng)。查了半天發(fā)現(xiàn)反相器輸出和飛控RX之間隔了一根20cm的杜邦線杜邦線內(nèi)部折斷萬用表量靜態(tài)電壓有3.3V但信號(hào)一到高頻就丟包。把杜邦線換成直接焊接的短跳線后解決。從這里得到的教訓(xùn)是信號(hào)線上的任何劣質(zhì)連接都對(duì)100kbps傳輸有影響。4.3 用邏輯分析儀定位SBUS信號(hào)異常如果沒有飛控日志或者日志里看太抽象邏輯分析儀是排查SBUS問題最好的工具。我習(xí)慣把邏輯分析儀的地接GND一個(gè)通道接到反相器輸出端也就是飛控RX這一側(cè)采樣率至少設(shè)到2MHz。在PulseView這類軟件里可以加一個(gè)UART協(xié)議解碼器波特率設(shè)100000數(shù)據(jù)位8校驗(yàn)Even停止位2然后重點(diǎn)看解碼器設(shè)置里有沒有“反相信號(hào)Invert Signal”選項(xiàng)。因?yàn)镾BUS的原始輸出是反相的如果邏輯分析儀直接夾在接收機(jī)SBUS輸出端必須勾選反相如果夾在反相器輸出端就可以當(dāng)成普通UART來解。正常情況下你能看到一幀接一幀的25字節(jié)數(shù)據(jù)幀頭是0x0F尾部有0x00。如果解碼出來全是0x00或0xFF這種規(guī)律數(shù)據(jù)八成是極性搞反了如果幀頭能找到但后面數(shù)據(jù)亂跳檢查停止位、校驗(yàn)位和波特率是否嚴(yán)格按照8E2、100000。定位問題之后再往回查接收機(jī)輸出、反相器、飛控RX很快就能鎖定故障點(diǎn)。4.4 一個(gè)能直接用的Python通道解析函數(shù)調(diào)試時(shí)如果手頭沒有飛控也可以把SBUS信號(hào)接到USB轉(zhuǎn)TTL模塊配一個(gè)反相電路在電腦上直接讀串口。但注意USB轉(zhuǎn)TTL的RX輸入也需要反相別把接收機(jī)SBUS直接懟進(jìn)去。下面這段Python代碼輸入一個(gè)25字節(jié)完整幀輸出16個(gè)通道值適合放在日志分析腳本里def parse_sbus_frame(frame): if len(frame) ! 25: return None if frame[0] ! 0x0F: return None payload int.from_bytes(frame[1:23], little) channels [] for i in range(16): value (payload (i * 11)) 0x7FF channels.append(value) flags frame[23] footer frame[24] return { channels: channels, ch1: channels[0], frame_lost: bool(flags 0x04), failsafe: bool(flags 0x08), footer_ok: footer 0x00, } # 用法示例從一段原始字節(jié)流中按0x0F固定長(zhǎng)度取幀 def extract_frames(raw_bytes): frames [] i 0 while i len(raw_bytes) - 24: if raw_bytes[i] 0x0F: candidate raw_bytes[i:i 25] if candidate[24] 0x00: frames.append(candidate) i 25 continue i 1 return frames兩個(gè)關(guān)鍵點(diǎn)一是用int.from_bytes把22字節(jié)按小端模式拼成一個(gè)整數(shù)比一個(gè)字節(jié)一個(gè)字節(jié)移位更簡(jiǎn)單二是幀頭0x0F可能出現(xiàn)在數(shù)據(jù)區(qū)所以一定要檢查第25字節(jié)是否為0x00。這段代碼不能替代示波器但用來批量回放日志、驗(yàn)證解包算法非常方便。最后再分享一個(gè)實(shí)用習(xí)慣我焊反相器焊了無數(shù)次最后養(yǎng)成一個(gè)習(xí)慣直接用一小塊萬用板做一個(gè)“SBUS反相轉(zhuǎn)接小板”輸入焊三根線輸出焊三根線中間放一個(gè)SOT-23封裝的NPN三極管和兩個(gè)電阻用熱縮管包起來尺寸不到指甲蓋大。以后不管是改飛控、接地面站、還是給DIY設(shè)備做遙控輸入拿出來就能用不用每次重新焊。反相電路本身不難難的是理解SBUS協(xié)議為什么要這樣設(shè)計(jì)以及在不同飛控、不同固件里怎么正確配置。希望這篇內(nèi)容能幫你少走點(diǎn)彎路。真到了現(xiàn)場(chǎng)記住一句話先測(cè)靜態(tài)電平再看地盤站配置最后才懷疑元件。按這個(gè)順序排查大部分SBUS問題都能在十分鐘內(nèi)解決。