Power PMAC運動控制器 —— 學習筆記1

    有很多朋友跟博主一樣,拿到PMAC控制器後一臉懵逼,技術只給了幾個英文手冊,便什麼都不管了,諮詢問題的時候敷衍了事。爲了避免更多朋友像博主一樣,決定跟大家分享一下Power PMAC運動控制器的使用經驗。


    項目結題,分析原因,我發現我們剛拿到控制器時迷茫的原因有三:

  • 其一,沒有任何經驗,害怕設備損害的害怕心理;
  • 其二,沒有人領進門,即使剛開始的時候技術給提供幫助,在一無所知、大腦一片空白的情況下很快就會忘記技術所給你講過的內容;
  • 其三,手冊的內容太多,且爲英文,而多數人英語閱讀能力有限

        但是,當你瞭解到整個開發過程後,再回過頭來看,發現手冊還是最好的老師

                                                    於2019.08.10修


爲了方便大家檢索,下面列出學習筆記的目錄。

關於 《Power PMAC運動控制器 —— 學習筆記》 系列,目錄如下:

  1. Power PMAC運動控制器——學習筆記1,主要介紹了PMAC與IDE環境的連接以及項目的創建
  2. Power PMAC運動控制器——學習筆記2,主要介紹了電機、EtherCAT網絡在IDE中的配置以及基本的運動程序編寫知識基礎
  3. Power PMAC運動控制器——學習筆記3,主要介紹了PMAC中關於座標系、軸和運動模式的概念,以及運動程序的編寫
  4. Power PMAC運動控制器——學習筆記4,主要介紹了正逆運動學在PMAC中的實現
  5. Power PMAC運動控制器——學習筆記5,主要介紹了PLC程序和子程序的編寫
  6. Power PMAC運動控制器——學習筆記6,主要介紹了Power PMAC中Modbus通信的實現以及EtherCAT網絡的使能
    7. Power PMAC運動控制器——學習筆記7,主要介紹了Power PMAC在機械臂控制上的應用案例

說明

       博主由於項目需要開始接觸PMAC系列運動控制卡 ,奈何資料太少,能找到的資料由於版本不同的原因導致無法使用,本着開源精神,以此記錄整個項目過程中Power PMAC的使用,希望能同各路大神交流分享~

目標:上位機通過Modbus TCP給運動控制卡發送指令實現機械臂的同步控制

1. 硬件介紹

       PMAC全稱Programmable Multi-Axis Controller(可編程多軸運動控制器 ),是美國Delta Tau Data System 公司(現已被歐姆龍收購,說到被收購我就不得不吐槽一下,自從被收購以後技術大牛都走了,遇到技術問題只能用戶自己瞎摸索,歐姆龍你上點心好嘛 😂 )推出的運動控制器[^1],功能很強大,號稱可實現納米級控制,同步性不錯,尤其是插補功能做的非常好,並且支持多廠商的驅動器、光柵尺等。
       本文主要介紹項目中用到的歐姆龍的CK3M型號,模塊化的設計深得我心,可實現單元的擴展,而且單元之間的連接無需工具。規格參數如下圖所示:


性能參數

       系統基本構成如下圖所示:

       更多細節就不多介紹了,詳情請參考官網

2. 準備工作

       首先安裝PowerPMAC IDE,該IDE環境是基於VS2015開發的,如果你熟悉VS工作環境,那麼必然非常容易上手該IDE(如圖所示)。


如果你不清楚環境的使用,可以在工具欄的幫助目錄下找到PowerPMAC IDE手冊,如下所示:

       在熟悉了IDE環境之後(相當於廢話哈哈哈哈,直接上手即可),我們直接開幹~
需要的手冊主要有:軟件參考手冊、用戶使用手冊,所有文件已在百度雲盤共享(失效請留言)。

3. PMAC與上位機的連接

  • step1 用雙絞線電纜建立CK3M與電腦主機的連接,然後給CK3M上電(注意:千萬千萬千萬別接反了,不然稍不留神上萬元就沒了 😂 )。
  • step2 PMAC默認IP爲192.168.0.200,握手成功後我們打開IDE環境,點擊:通訊設置->應用,注意要選擇設備的IP地址。

    在這裏插入圖片描述

①連接成功後,IDE的標題欄會顯示PMAC的版本信息,且由灰色變爲綠色。

在這裏插入圖片描述

②如果連接失敗或者連接沒反應,我們可以通過<運行>功能ping一下PMAC,查看是否已經握手成功,如果已經握手成功(如下圖所示),上位機會收到CK3M的反饋。
運行:window + R


在這裏插入圖片描述

那麼問題可能出在上位機的IP設置上,找到網絡適配器設置,選擇與PMAC連接的接口,按下圖設置,最後單擊確定。(注意:更改適配器的設置可能會導致下次網線連接此口時無法進行網絡訪問,那時需要恢復設置爲【自動獲得IP地址】),修改完畢後重復step2。如果仍然連接失敗,斷開網絡再試試。 😇

在這裏插入圖片描述

4. 創建自己的伺服控制項目

        創建項目的過程跟VS中project的創建幾乎無差,在此不再贅述,參見Power PMAC IDE手冊P139。項目目錄結構如下:


在這裏插入圖片描述

        爲防止在調試過程中由於參數設置不當導致伺服電機或驅動器的損壞,我們可以通過設置虛軸的方式進行模擬調試。
        虛軸設置如下:

//來自官方論壇某大神
// Activate servo algorithms for motors
Motor[1].ServoCtrl=1
Motor[2].ServoCtrl=1
Motor[3].ServoCtrl=1
Motor[4].ServoCtrl=1
Motor[5].ServoCtrl=1
Motor[6].ServoCtrl=1
Motor[7].ServoCtrl=1
Motor[8].ServoCtrl=1

// Write servo output to user shared memory registers
Motor[1].pDac=Sys.Idata[1].a    // Same as EncTable[1].pEnc
Motor[2].pDac=Sys.Idata[2].a    // Same as EncTable[2].pEnc
Motor[3].pDac=Sys.Idata[3].a    // Same as EncTable[3].pEnc
Motor[4].pDac=Sys.Idata[4].a    // Same as EncTable[4].pEnc
Motor[5].pDac=Sys.Idata[5].a    // Same as EncTable[5].pEnc
Motor[6].pDac=Sys.Idata[6].a    // Same as EncTable[6].pEnc
Motor[7].pDac=Sys.Idata[7].a    // Same as EncTable[7].pEnc
Motor[8].pDac=Sys.Idata[8].a    // Same as EncTable[8].pEnc

// Encoder conversion table entry to read and integrate this
EncTable[1].type=1            // 32-bit register read
EncTable[1].pEnc=Sys.idata[1].a    // Same as Motor[1].pDac
EncTable[1].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[1].index1=0            // No shift right of source data
EncTable[1].index2=0            // No shift left of source data
EncTable[1].index3=0            // No accel limiting
EncTable[1].index4=1            // Single integration
EncTable[1].PrevDelta=0        // No bias before integration
EncTable[1].MaxDelta=0        // No velocity limit
EncTable[1].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[2].type=1            // 32-bit register read
EncTable[2].pEnc=Sys.idata[2].a    // Same as Motor[2].pDac
EncTable[2].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[2].index1=0            // No shift right of source data
EncTable[2].index2=0            // No shift left of source data
EncTable[2].index3=0            // No accel limiting
EncTable[2].index4=1            // Single integration
EncTable[2].PrevDelta=0        // No bias before integration
EncTable[2].MaxDelta=0        // No velocity limit
EncTable[2].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[3].type=1            // 32-bit register read
EncTable[3].pEnc=Sys.idata[3].a    // Same as Motor[3].pDac
EncTable[3].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[3].index1=0            // No shift right of source data
EncTable[3].index2=0            // No shift left of source data
EncTable[3].index3=0            // No accel limiting
EncTable[3].index4=1            // Single integration
EncTable[3].PrevDelta=0        // No bias before integration
EncTable[3].MaxDelta=0        // No velocity limit
EncTable[3].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[4].type=1            // 32-bit register read
EncTable[4].pEnc=Sys.idata[4].a    // Same as Motor[4].pDac
EncTable[4].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[4].index1=0            // No shift right of source data
EncTable[4].index2=0            // No shift left of source data
EncTable[4].index3=0            // No accel limiting
EncTable[4].index4=1            // Single integration
EncTable[4].PrevDelta=0        // No bias before integration
EncTable[4].MaxDelta=0        // No velocity limit
EncTable[4].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[5].type=1            // 32-bit register read
EncTable[5].pEnc=Sys.idata[5].a    // Same as Motor[5].pDac
EncTable[5].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[5].index1=0            // No shift right of source data
EncTable[5].index2=0            // No shift left of source data
EncTable[5].index3=0            // No accel limiting
EncTable[5].index4=1            // Single integration
EncTable[5].PrevDelta=0        // No bias before integration
EncTable[5].MaxDelta=0        // No velocity limit
EncTable[5].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[6].type=1            // 32-bit register read
EncTable[6].pEnc=Sys.idata[6].a    // Same as Motor[6].pDac
EncTable[6].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[6].index1=0            // No shift right of source data
EncTable[6].index2=0            // No shift left of source data
EncTable[6].index3=0            // No accel limiting
EncTable[6].index4=1            // Single integration
EncTable[6].PrevDelta=0        // No bias before integration
EncTable[6].MaxDelta=0        // No velocity limit
EncTable[6].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[7].type=1            // 32-bit register read
EncTable[7].pEnc=Sys.idata[7].a    // Same as Motor[7].pDac
EncTable[7].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[7].index1=0            // No shift right of source data
EncTable[7].index2=0            // No shift left of source data
EncTable[7].index3=0            // No accel limiting
EncTable[7].index4=1            // Single integration
EncTable[7].PrevDelta=0        // No bias before integration
EncTable[7].MaxDelta=0        // No velocity limit
EncTable[7].ScaleFactor=1/65536    // 32 bits -> 16 bits

EncTable[8].type=1            // 32-bit register read
EncTable[8].pEnc=Sys.idata[8].a    // Same as Motor[8].pDac
EncTable[8].pEnc1=Sys.pushm        // Dummy read (not used)
EncTable[8].index1=0            // No shift right of source data
EncTable[8].index2=0            // No shift left of source data
EncTable[8].index3=0            // No accel limiting
EncTable[8].index4=1            // Single integration
EncTable[8].PrevDelta=0        // No bias before integration
EncTable[8].MaxDelta=0        // No velocity limit
EncTable[8].ScaleFactor=1/65536    // 32 bits -> 16 bits

// Read the encoder conversion table result as feedback
Motor[1].pEnc=EncTable[1].a        // Position loop feedback source
Motor[1].pEnc2=EncTable[1].a    // Velocity loop feedback source
Motor[2].pEnc=EncTable[2].a        // Position loop feedback source
Motor[2].pEnc2=EncTable[2].a    // Velocity loop feedback source
Motor[3].pEnc=EncTable[3].a        // Position loop feedback source
Motor[3].pEnc2=EncTable[3].a    // Velocity loop feedback source
Motor[4].pEnc=EncTable[4].a        // Position loop feedback source
Motor[4].pEnc2=EncTable[4].a    // Velocity loop feedback source
Motor[5].pEnc=EncTable[5].a        // Position loop feedback source
Motor[5].pEnc2=EncTable[5].a    // Velocity loop feedback source
Motor[6].pEnc=EncTable[6].a        // Position loop feedback source
Motor[6].pEnc2=EncTable[6].a    // Velocity loop feedback source
Motor[7].pEnc=EncTable[7].a        // Position loop feedback source
Motor[7].pEnc2=EncTable[7].a    // Velocity loop feedback source
Motor[8].pEnc=EncTable[8].a        // Position loop feedback source
Motor[8].pEnc2=EncTable[8].a    // Velocity loop feedback source


// Disable overtravel limit inputs
// May be needed if there are no physical switches present
Motor[1].pLimits=0
Motor[2].pLimits=0
Motor[3].pLimits=0
Motor[4].pLimits=0
Motor[5].pLimits=0
Motor[6].pLimits=0
Motor[7].pLimits=0
Motor[8].pLimits=0

// Disable amplifier enable output
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpEnable=0
Motor[2].pAmpEnable=0
Motor[3].pAmpEnable=0
Motor[4].pAmpEnable=0
Motor[5].pAmpEnable=0
Motor[6].pAmpEnable=0
Motor[7].pAmpEnable=0
Motor[8].pAmpEnable=0

// Disable amplifier fault input
// May be needed if channel is also connected to real amplifier
Motor[1].pAmpFault=0
Motor[2].pAmpFault=0
Motor[3].pAmpFault=0
Motor[4].pAmpFault=0
Motor[5].pAmpFault=0
Motor[6].pAmpFault=0
Motor[7].pAmpFault=0
Motor[8].pAmpFault=0

// Set derivative gain term in servo loop to zero
// This is a Type 1 servo (single integration); does not need Kd
Motor[1].Servo.Kvfb=0
Motor[2].Servo.Kvfb=0
Motor[3].Servo.Kvfb=0
Motor[4].Servo.Kvfb=0
Motor[5].Servo.Kvfb=0
Motor[6].Servo.Kvfb=0
Motor[7].Servo.Kvfb=0
Motor[8].Servo.Kvfb=0
// Lower proportional gain term from default
Motor[1].Servo.Kp=1
Motor[2].Servo.Kp=1
Motor[3].Servo.Kp=1
Motor[4].Servo.Kp=1
Motor[5].Servo.Kp=1
Motor[6].Servo.Kp=1
Motor[7].Servo.Kp=1
Motor[8].Servo.Kp=1
// Add integral gain to force to zero error
Motor[1].Servo.Ki=0.01
Motor[2].Servo.Ki=0.01
Motor[3].Servo.Ki=0.01
Motor[4].Servo.Ki=0.01
Motor[5].Servo.Ki=0.01
Motor[6].Servo.Ki=0.01
Motor[7].Servo.Ki=0.01
Motor[8].Servo.Ki=0.01
// Set deadband zone to zero
Motor[1].Servo.BreakPosErr=0
Motor[2].Servo.BreakPosErr=0
Motor[3].Servo.BreakPosErr=0
Motor[4].Servo.BreakPosErr=0
Motor[5].Servo.BreakPosErr=0
Motor[6].Servo.BreakPosErr=0
Motor[7].Servo.BreakPosErr=0
Motor[8].Servo.BreakPosErr=0
// Add feedforward to minimize tracking error
Motor[1].Servo.Kvff=1
Motor[1].Servo.Kaff=1
Motor[2].Servo.Kvff=1
Motor[2].Servo.Kaff=1
Motor[3].Servo.Kvff=1
Motor[3].Servo.Kaff=1
Motor[4].Servo.Kvff=1
Motor[4].Servo.Kaff=1
Motor[5].Servo.Kvff=1
Motor[5].Servo.Kaff=1
Motor[6].Servo.Kvff=1
Motor[6].Servo.Kaff=1
Motor[7].Servo.Kvff=1
Motor[7].Servo.Kaff=1
Motor[8].Servo.Kvff=1
Motor[8].Servo.Kaff=1

        我們把上述代碼拷貝到PMAC腳本語言目錄下的全局變量定義中,如下圖所示:


在這裏插入圖片描述

        然後開始寫入運動程序,在Motion Programs目錄下的prog1.pmc文件中寫入運動程序代碼,此例中我們以兩軸電機繪製矩形爲例,把代碼寫進文件並保存。

/****************************************/
//By Jack Soong
//Time:2019.1.21
&1 //定義座標系1
#1->X; //將電機指定給x,y軸
#2->Y;

 open prog 1 
// --------------------User Code Goes Here------------------------
linear  //直線mode
abs	    //絕對值編程
tm 500  //插補加速參數設置
ta 100
ts 200
dwell 0 Gather.Enable = 2;dwell  0//將數據收集到先前plot設置元素的緩衝區
X0 Y0;
X0 Y100;
X100 Y100;
X100 Y0;
X0 Y0;
dwell 100; //延時
Gather.Enable = 0;dwell 0  //關閉收集
close
/****************************************/

        完成上述步驟後,在解決方案名稱上右擊選擇構建並下載所有程序,將程序下載到CK3M中,注意:如果連接實際硬件,需要在配置完電機後先選擇映射PowerPMAC變量。


        OK!接下來我們就要讓它動起來了,首先打開數據收集功能,在代碼中我們已經開啓了數據收集並保存到緩存中,這是我們需要在程序真正運行之前打開數據收集界面(位於菜單欄中,即繪圖功能),如下圖所示。



        在終端中輸入"#1…2j/“命令先使能電機,然後用命令”&1 b1 r"運行我們的運動程序,在程序運行過程中,繪圖界面上傳數據按鈕下方的進度條會隨着程序的執行過程而有所變化,待進度條滿後點擊上傳數據,並把要繪製的值添加到座標軸(選中要添加的值,然後點擊>>按鈕將其添加到繪製欄,如果需要刪除,則在繪製欄中選中該選項點擊<<即可刪除),此處我們以Motion[1].Cmd Position(即電機1的命令位置,換句話說就是理想輸出位置)爲橫座標,以Motion[2].Cmd Position爲縱座標繪製圖形,得到的繪製圖形如下,我們可以看到繪製的矩形似乎不太聽話 😂 😂 😂,淡定點老鐵,所畫圖形並非方方正正的矩形的原因在於:Power PMAC中有一個狀態位(Coord[x].NoBlend)是用來控制各運動點之間是否進行插補的,Coord[x].NoBlend默認爲0,即使能Move Blending,因此走出來的矩形並非理想形狀,如果設置Coord[x].NoBlend=1那麼這個矩形就比較聽話啦!


5. 學習途徑

[1]前文提到的手冊:軟件參考手冊、用戶使用手冊(都說手冊是最好的教程,但是這個手冊博主個人感覺…… 😂 😂 😂)
[2]官方視頻教程(發佈在Youtube,需要怎麼訪問你懂的,樓主已經刷過一遍,感覺沒啥用,前文提到的5天培訓PPT便是該教程配套的)
[3]官方論壇(活躍人數少,但專業,可能由於收購原因?前段時間服務器直接關閉,近期才重新啓動)
[4]工控論壇PMAC專區(人數多,回覆不及時,目前博主在此論壇沒有找到有價值的ppmac資料,其他版本PMAC資料相對較多)
[5]文大俠博客
[6]Jackie的儲物袋的博客

後記

        這幾周可謂是歷經千辛萬險,終於有所入門,可離結題還是遙遙無期,雖然困難重重,但是問題的解決總會伴隨着慢慢的成就感,越挫越勇才能成就更好的自己~
        第一次寫博文,乾貨不多,只提供給大家一個初步入門的路子,順便也當做學習筆記了。在此要感謝北京機科國創的李工、歐姆龍技術支持周工以及我的林副總師兄提供的幫助。

        下期預告:Power PMAC中運動程序的編寫


	 [1]: https://baike.baidu.com/item/PMAC/1955812?fr=aladdin
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章