“給軸發了插補運動命令,結果軸跑到半路開始亂跑!”,這是我們公司一個程序員在做一個四軸龍門架構的運動控制項目時遇到的問題,我一聽“軸亂跑”,我就知道出了什么問題。
![]()
首先,這個項目是使用運動控制卡控制的伺服驅動器,造成軸亂跑的原因也很簡單,那就是在插補運動過程中,程序又向軸發送了另外一條插補運動的命令導致的!
然后我就把我的判斷結果告訴了他,結果他說他代碼沒有這么寫。
我憑直覺判斷,他的代碼肯定寫得有問題,如果真如他所說,他沒有在軸插補運動中插入其他插補命令,那么只有一個原因,就是有其他線程在他不知道的情況下,在插補運動中發送了另外一個插補運動命令。
簡單地說,他的線程沒有控制好,甚至可能狀態互斥也沒有控制好。
什么是狀態互斥?比如說代碼業務邏輯中有兩種業務,第一個是從A點跑到B點,第二個是從C點跑到D點,并且,跑到B點和跑到D點分別都要做不同的事情。
這時候,跑到B點和跑到D點都會觸發軸停止信號這個狀態,但是,我們要區分到底是在B點停的還是在D點停的。
有人會說,只需要判斷B、D點的坐標就行啦?
某些情況下,判斷B、D點坐標的確可以,也就是在軸停止的時候判斷下坐標到底在B點還是在D點停的。
但是,如果B點和D點在同一個點呢?你仍然無法判斷到底是哪一種狀態下停止的。
解決辦法也很簡單,其實就是在運動前,給本次運動標記一個狀態,比如A到B運動叫“AB運動”、C到D運動叫“CD”運動,這樣,當軸停止的時候,判斷下運動狀態,可能為了更加保險,再判斷下軸坐標,這就萬無一失了!
最后,這個程序員檢查了一下午代碼,終于找出了他程序里面的一個漏洞,并且這個漏洞。
他有另外一個業務邏輯,在軸停止的時候,他需要判斷軸是否在指定位置停止,沒有停止就一直在那等,直到軸到達指定位置為止。
其實他這種寫法觸發了另外一個軸問題,就是我們用的這個運動控制卡,在判斷軸停止時,有概率軸并未完全停止,他可能需要緩沖一段距離才會真正達到停止狀態。
但是,想要知道它有沒有完全停止,只要并行判斷即可,就是判斷軸是停止狀態了,并且,軸停的位置是你想要停的那個位置,這兩個判斷要同時進行。
但凡只判斷一個,再等另外一個,這個停止狀態都有可能是假的。
所以,他的代碼問題在于,先監控了停止狀態,然后一直在監聽軸是否已經停到了指定位置。
然后又因為沒有做好狀態互斥,可能代碼還卡在監控軸位置這一段,他認為軸停了,點了軸復位,此時只能說碰巧,碰巧軸真的停止了,但是因為他點了軸復位,導致判斷軸位置的那段代碼一直沒執行。
此時,他又向軸發送了其他命令,其他命令在運動過程中剛好觸發了他之前軸停止時判斷位置的那段代碼,因此,那段代碼后面的另外一個插補命令被執行。
在軸運動過程中,程序發送了另外一個插補命令,于是軸就開始亂跑了!
所以,這就是整個事情的來龍去脈,看似很復雜的一個問題吧?其實簡單得來說,就是程序里面沒有做好狀態互斥導致的。
知道了這個問題以后,作為部門主管,我有點難受,作為上位機程序員,他有點難受,因為我通過這件事情,知道他整個程序都沒有做狀態互斥,他也知道,因為出了這個事情,整個程序所有運動邏輯都得大改!
因此,做上位機程序員,有時候真不需要你的編程水平有多高,經驗其實是第一位的,寫這個運動控制項目的程序員他本身有十幾年的編程經驗,但是運動控制項目他是第一次做。
還是那句話:做上位機程序員,經驗是最重要的!
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.