:從CAN通信到偶發(fā)停機的完整排查)
1. 先說清楚這批B2模塊到底要干什么1.1 設備場景與B2模塊的定位這次調試的B2模塊是給某臺三軸搬運設備用的電機驅動控制板。設備結構不復雜X、Y、Z三個軸每軸一臺步進電機配絲桿末端是一個真空吸盤負責把物料從A工位搬到B工位。運動邏輯也很常規(guī)原點復位、取料、直線插補、放料、回原點。B2模塊是供應商提供的現(xiàn)成驅動板板子上集成了24V電源輸入、步進電機四線輸出A/A-/B/B-、兩個限位開關輸入、一個CAN通信口還有幾個撥碼開關用來設置節(jié)點ID和終端電阻。按理說這種模塊屬于拿來就能用的器件接線圖也在手冊里寫得清清楚楚真正調起來不該太費勁。但實際從第一次上電開始我就連著踩了好幾個坑前后花了兩周才把系統(tǒng)穩(wěn)定下來。1.2 調試環(huán)境與接線調試用的東西很簡單都是普通設備24V開關電源一臺B2模塊三塊步進電機三臺主控板用某款ARM Cortex-M內核的開發(fā)板另加一個USB-CAN分析儀用來監(jiān)聽和發(fā)送總線報文。萬用表、示波器、電子負載各一臺這些是后面排查故障時反復用到的東西。接線原則上很清晰電機四根線對應接A/A-/B/B-電源接24V和GNDCAN接CANH和CANL。三塊模塊的ID通過撥碼分別設為1、2、3限位開關接模塊輸入口。但我在這一步犯了個錯誤后面付出很大代價為了省事CAN線沒有單獨布雙絞線而是順著電源線一起走緊挨著電機動力線。我當時覺得調試階段無所謂出問題再整理結果這個決定讓后面一個偶發(fā)停機問題多查了兩天。先埋個伏筆第五節(jié)專門講。1.3 調試日志從第一天就開始寫調試第一天我就建了一個文本日志每次改動、每次故障現(xiàn)象、每次測量數(shù)據(jù)都往里記。這個習慣幫了大忙。尤其到第三周設備出現(xiàn)偶發(fā)停機時如果當時沒有日志根本不可能把停機時間和電機換向時間關聯(lián)起來。很多做嵌入式調試的人不愿意記錄覺得浪費時間但我的經(jīng)驗是越是感覺不難的系統(tǒng)越容易在一個隱蔽問題上卡好幾天日志是唯一能讓你從反復試轉向按證據(jù)排查的工具。2. 第一次上電就冒煙供電端口的兩個低級錯誤2.1 冒煙經(jīng)過與直接原因接線檢查了兩遍電機線沒有接反電源極性也沒錯。我按下開關電源的按鈕第一塊B2模塊的電源指示燈都來不及亮一股焦味就飄了出來。斷電拆下來電源端口的保險管已經(jīng)熔斷板子上的DC-DC芯片附近有明顯燒痕。第一反應是模塊本身有問題但第二塊、第三塊都是好的說明大概率不是來料不良。冷靜下來仔細看手冊才發(fā)現(xiàn)問題B2模塊的使能引腳EN默認是懸空的而它的內部邏輯把懸空當成使能且全速運行。上電瞬間驅動器直接進入全輸出狀態(tài)而這時主控板還在初始化方向引腳和脈沖引腳都是高阻等于驅動器在沒有任何有效指令的情況下滿電流輸出電流失去控制功率部分直接燒掉。這類問題在電機驅動模塊上很常見。不少模塊為了讓客戶上電即用會把使能引腳默認拉高但如果負載端堵轉、線纜過長或者電機電感較小上電瞬間的沖擊電流可以達到正常工作電流的3到5倍非常容易出問題。所以不管用什么驅動模塊上電前的第一個動作都應該是確認使能引腳有一個確定的默認電平而不是賭它默認不工作。2.2 用示波器復現(xiàn)故障波形燒了一塊板子后我沒有急著換新的而是用第二塊B2做了個簡單的故障復現(xiàn)24V供電EN引腳懸空示波器探頭夾在電機線的A和A-之間。上電瞬間抓到的波形顯示A和A-之間出現(xiàn)了一個脈寬約1.2毫秒、幅值接近24V的窄脈沖電流被推到接近5A。驅動器額定電流2.8A這就是冒煙的直接原因。這個波形說明了兩件事一是EN懸空導致的默認使能確實存在二是直流側缺少軟啟動上電瞬間的沖擊電流幾乎全部灌進了功率級。后來翻到模塊手冊附注里的一行小字才確認上電默認狀態(tài)就是EN有效客戶必須在主控初始化前拉低EN或者在電源輸入端加軟啟動。這類手冊小字是最容易被忽略的但它往往決定了一塊板子能不能安全上電。2.3 整改方案下拉電阻加軟啟動時序整改分兩步。硬件上我在每塊B2模塊的EN引腳和GND之間加了一個10K下拉電阻保證上電默認是不使能的。這里要注意下拉電阻不能太小太小會在正常工作時額外消耗電流也會拉低EN高電平的有效性10K對CMOS輸入來說是常規(guī)選擇穩(wěn)定且功耗可忽略。軟件上主控程序重新寫了一條初始化序列先配置GPIO并拉低EN等系統(tǒng)時鐘、CAN外設、定時器全部初始化完成再延時100毫秒最后拉高EN并輸出第一個脈沖。延時的目的不是等驅動器響應而是給驅動器內部的自檢和母線電容充電留時間避免初始化過程中的抖動被當成有效指令。提示所有電機驅動類模塊在上電初始化完成前永遠假設它是會動的。使能引腳必須有確定的默認電平不能依賴主控的初始化速度去搶時間。3. 通信握手失敗CAN總線的三層排查3.1 電壓、終端電阻和波特率第二塊、第三塊模塊換上后沒有再冒煙但新問題來了USB-CAN分析儀發(fā)送指令三塊B2全部沒有應答。第一反應是節(jié)點ID撥碼錯了但反復檢查1、2、3都沒有問題。接著量CAN總線的靜態(tài)電壓CANH對地約2.5VCANL對地約2.5V差分電壓為0V。這個狀態(tài)說明總線處于隱性電平當前總線上沒有節(jié)點在主動發(fā)送數(shù)據(jù)但物理層看起來是正常的。再測終端電阻我在總線兩端各接了一個120歐姆電阻主控端和最后一臺B2端萬用表量總線兩端阻值正好是60歐姆終端也沒問題。硬件沒問題問題大概率出在波特率上。我把USB-CAN分析儀的波特率從默認的250K改到500K再發(fā)指令三塊B2全部正常應答。原因很簡單B2模塊出廠默認波特率是500K而我習慣性地用了250K。這里有個容易被忽略的點CAN總線的波特率不匹配時不是所有設備都會報錯。很多節(jié)點只是安靜地不響應看起來像完全沒通信。用USB轉CAN工具時第一步永遠是確認工具波特率和目標設備一致而不是上來就翻代碼。后來我把主控的CAN初始化參數(shù)固定了下來#define CAN_BAUD 500000U #define CAN_SAMPLE_POINT 80U // 采樣點80%按B2手冊推薦 CAN_Init(CAN_BAUD, CAN_SAMPLE_POINT);采樣點設成80%而不是常見默認的75%是因為這條總線上線纜較長、信號邊沿偏緩80%的采樣點可以避開信號上升沿附近的抖動區(qū)間。B2手冊里明確推薦80%這種參數(shù)按廠商推薦值來就行不要盲目套通用模板。3.2 幀ID過濾器這層最容易忽略波特率對了之后總線能通信了但很快發(fā)現(xiàn)一個更隱蔽的現(xiàn)象部分指令生效部分指令無效。查來查去問題出在我主控板的CAN過濾器上。最初我把接收過濾器配置成只允許標準幀ID在0x100到0x10F范圍內的報文通過而B2模塊的指令幀ID是0x200開頭大部分報文被過濾器直接丟掉。能被收到的那幾條是我測試時恰好用了允許段內的ID表現(xiàn)出來就是時靈時不靈。這個錯誤很蠢但很典型。CAN過濾器一旦配錯接收端完全不知道有人在給它發(fā)數(shù)據(jù)也不會有任何提示表現(xiàn)和總線無數(shù)據(jù)幾乎一樣。排查CAN問題時一定要區(qū)分是物理層沒數(shù)據(jù)還是數(shù)據(jù)到了但被過濾了。打開CAN分析儀的接收窗口如果能看到報文的ID和內容但程序沒響應八成問題就在過濾器或中斷配置上。3.3 固定排查順序的意義經(jīng)過這輪折騰我總結了一條固定的CAN排查順序看總線靜態(tài)電壓電平再量終端電阻再確認波特率再查幀ID過濾器最后查數(shù)據(jù)內容。這個順序之后每次都按它走基本能快速定位八成以上的CAN通信問題。為什么要強調順序因為CAN的問題往往不是單一的。我就碰到過終端電阻正確、波特率正確、但過濾器錯了的情況也碰到過波特率正確、但某一段線纜接觸不良導致偶發(fā)丟幀的情況。如果每次都靠猜效率太低。按順序排查每排除一層就記錄一層后面同類問題可以直接跳過已驗證的環(huán)節(jié)至少能省一半時間。4. 電機抖動、堵轉和偶發(fā)失控控制參數(shù)與信號線沖突4.1 閉環(huán)不能一步到位先從開環(huán)跑通通信正常后開始動電機。B2模塊支持脈沖方向模式、速度模式、位置閉環(huán)模式三種。最初的思路是把三臺電機全部配成位置閉環(huán)模式一步到位直接跑設備邏輯結果三臺電機一上電就劇烈抖動絲桿來回竄動聲音非常刺耳Z軸甚至直接報了堵轉。這個經(jīng)歷給了我很深的教訓閉環(huán)調試不能從冷啟動直接給目標位置。位置閉環(huán)依賴編碼器反饋、PID參數(shù)、加減速曲線任何一個環(huán)節(jié)沒調好驅動器就會在目標位置附近來回修正表現(xiàn)出來就是抖動。正確路徑是先做開環(huán)驗證把電機方向、正反行程、限位邏輯全部確認無誤再切閉環(huán)。于是我把三塊模塊全部切回脈沖方向模式用主控定時器輸出固定頻率脈沖先50Hz再100Hz、500Hz逐步加每臺電機的轉向、步距、加減速都驗證了一遍。這個階段如果方向反了只需要對調A和A-/或者修改方向引腳邏輯比在閉環(huán)模式下排查直觀得多。4.2 方向信號和使能信號的時序競爭切回閉環(huán)模式后設備已能完成基本搬運動作但出現(xiàn)了一個非常隱蔽的問題每次從A點回到B點后再往C點運動時偶爾會先反方向竄一小段然后又正向運動過去。這個現(xiàn)象出現(xiàn)概率不高大概三四次里有一次而且不固定在哪根軸非常難抓。用示波器同時抓方向信號DIR和使能信號EN后發(fā)現(xiàn)B2模塊的EN引腳在閉環(huán)模式下還承擔了清錯功能。主控在改變方向時先翻轉了DIR然后為了清除驅動器內部的位置誤差又短脈沖拉低了一下EN。問題就出在這個順序上。正常情況下這沒問題但如果DIR翻轉和EN拉低之間的時間小于B2模塊內部的采樣周期約200微秒模塊有可能把新的DIR狀態(tài)和舊的EN狀態(tài)一起鎖存導致它認為方向沒變或者在舊方向上執(zhí)行了一小段位置修正表現(xiàn)出來就是反方向竄一下。解決辦法也很直接改變方向時先拉低EN禁能等300微秒再設置DIR再等300微秒最后拉高EN重新使能。順序從翻DIR→拉EN改成拉EN→翻DIR→使能。這個問題讓我意識到不要想當然認為設置引腳是瞬時動作。對驅動器來說每個輸入引腳都是按采樣周期采樣的引腳變化的先后順序本身就是邏輯的一部分必須當協(xié)議來看。4.3 Z軸PID參數(shù)調整記錄閉環(huán)抖動還牽出另一個問題B2模塊內部位置環(huán)PID的默認參數(shù)是按一般水平負載調好的但這套機構里Z軸是垂直安裝重力方向讓上下運動的響應明顯不對稱。上升時跟隨很好下降時總是過沖然后來回修正。一共調了兩輪。第一輪把比例增益P從默認的20降到8積分增益I從5降到1過沖明顯減少但下降到位后還有輕微振蕩。第二輪把微分增益D從0.8提到1.5振蕩消失。最終Z軸參數(shù)如下表軸PID說明X軸2050.8水平安裝負載輕保持默認Y軸2050.8水平安裝負載輕保持默認Z軸811.5垂直安裝重力影響大降低P/I、提高D這里記錄一個快速調參方法先把P和I都調到很小P從能穩(wěn)住的最小值開始加I在P穩(wěn)定后再慢慢加D只在出現(xiàn)超調和振蕩時才加。不要一開始就追求響應速度先把穩(wěn)定性做出來再逐步提高增益。每次只改一個參數(shù)改完跑一個完整往復動作觀察波形再動下一個參數(shù)這樣出問題也知道是哪一步引入的。5. 偶發(fā)停機的物理層真相共阻抗耦合5.1 故障現(xiàn)象與日志盲區(qū)三軸都能正常動作后開始做連續(xù)運行測試結果出現(xiàn)最折磨人的問題偶發(fā)停機。有時一天出現(xiàn)四五次有時幾小時一次完全沒有規(guī)律。停機時主控日志沒有記錄任何錯誤B2模塊也沒有報警燈整個系統(tǒng)就像被人悄悄按了暫停鍵。多軸設備出現(xiàn)這種問題最讓人頭疼因為它不像參數(shù)錯誤那樣每次都能復現(xiàn)屬于典型的現(xiàn)場才會出現(xiàn)、實驗室很難抓到的故障。排查的第一步先看主控日志沒有任何報錯記錄。第二步看B2模塊的報警狀態(tài)也沒有報警。既然軟件層面沒有線索我把示波器接在B2模塊的24V供電線上長時間監(jiān)測終于發(fā)現(xiàn)停機瞬間總伴隨一個很短的電壓跌落從24V降到22.8V左右持續(xù)約300微秒后恢復。這個幅度的跌落對純電阻負載不算什么但對電源管理電路已經(jīng)足夠觸發(fā)一次欠壓復位。5.2 示波器抓到的毛刺與排查鏈路順著電壓跌落的線索繼續(xù)查。我把示波器的一路探頭夾在CANH對地另一路夾在24V上等下一次停機發(fā)生時看到停機前沿出現(xiàn)了一個幅值約4V、寬度約1微秒的毛刺。把這個毛刺出現(xiàn)的時刻和電機換向時刻一對比頻率完全一致問題鎖定在干擾耦合上。根源就是第一節(jié)埋的伏筆CAN線順著電源線走、又緊貼電機動力線。電機是感性負載換向瞬間會在公共地線上產(chǎn)生尖峰電流這個電流在電源線和CAN線共用的那段地線上產(chǎn)生壓降。表面看是停機實際上是通信報文被干擾后模塊收不到主控的心跳信號進入了安全停機狀態(tài)。這里把排查鏈路完整列出來看主控日志無錯誤記錄。看B2報警記錄無報警。示波器抓供電電壓發(fā)現(xiàn)22.8V跌落。示波器同步抓CANH波形發(fā)現(xiàn)停機前沿有4V幅值毛刺。確認毛刺頻率與電機換向頻率一致。5.3 整改措施與波形對比整改動作有三項CAN線改為獨立雙絞線與電機動力線保持至少5厘米距離。電機線和電源線在進入模塊前分別套上磁環(huán)吸收換向尖峰。主控、B2模塊、開關電源三者的地線改為星型單點接地不再共用同一段地線走線。改完之后再測CANH上的毛刺幅值從4V降到0.8V以下連續(xù)24小時運行再沒有出現(xiàn)過一次停機。這一步是整個調試過程中最有價值的排查它讓我切實體會到偶發(fā)性故障看似是軟件問題很多時候物理層才是真兇。而且物理層問題有個特點——它不是每次都觸發(fā)只有當干擾幅度超過某個閾值的那一刻才觸發(fā)所以必須靠長時間監(jiān)測和波形證據(jù)不能靠試。6. 復盤與沉淀調試日志里的幾個習慣6.1 變更記錄怎么記才不白記這次調試踩了太多坑后面我養(yǎng)成了一個習慣每一次接線改動、參數(shù)修改、代碼變更都記錄在調試日志里內容包括時間、變更內容、復測結果以及為什么改。記錄為什么改這一點尤其重要。比如PID參數(shù)從20調到8如果不記原因過兩天就會忘了是為什么等溫度變化引起參數(shù)漂移時根本無從判斷是應該繼續(xù)往小調還是恢復默認值。再比如第一塊模塊上電前加的下拉電阻如果日志里沒有寫明防止EN懸空導致默認使能后面維護的人很可能把它當成多余的器件拆掉故障就會重新出現(xiàn)。6.2 值得長期堅持的幾條原則調試電機驅動類項目我總結了幾條個人經(jīng)驗示波器要一直開著不要只在出問題的時候才拿出來很多偶發(fā)問題在出問題時已經(jīng)晚了要提前觀察正常時的波形基線出問題時才能一眼看出哪里不正常。電源和通信的布線從一開始就按正式規(guī)格來不要覺得調試階段可以偷懶布線引發(fā)的干擾問題是最難查的那一類。驅動器的每個輸入引腳都當協(xié)議來看順序、時序、采樣周期都是邏輯的一部分。最后說點實在的。這次B2調試從頭到尾所有問題回頭看都算顯而易見但每一步都實實在在花掉了時間。我把整個過程完整寫下來一是給后面維護這臺設備的人一份參考二是提醒自己越是看起來簡單的系統(tǒng)越要按順序排查、別跳步。調試記錄這件事本質上是寫給三天后的自己的寫的時候覺得麻煩遇到問題時才知道它值多少錢。