今天,æ£é‹å‹•å°åŠ©æ‰‹ç‚ºå¤§å®¶åˆ†äº«ä¸€ä¸‹æ‡‰ç”¨C#開發一個多段連續æ’補的é‹å‹•控制應用。
  我們主è¦å¾žæ–°å»ºé …ç›®ï¼Œæ·»åŠ å‡½æ•¸åº«è¬›èµ·ï¼Œå†äº†è§£PC函數使用,最åŽé€šéŽé …目實戰——連續æ’補é‹å‹•ä¾‹ç¨‹è¬›è§£ï¼Œä¾†è®“å¤§å®¶ç†Ÿæ‚‰å®ƒçš„é …ç›®é–‹ç™¼ã€‚
  在æ£å¼å¸ç¿’之å‰ï¼Œæˆ‘們先了解一下æ£é‹å‹•技術的é‹å‹•控制å¡ECI2418å’ŒECI2618。這兩款產å“分別是4軸,6軸é‹å‹•控制å¡ã€‚
  
  
  
  ECI2418支æŒ4軸脈沖輸入與編碼器å饋,æ¿è¼‰24點輸入,16點輸出,2AD,2DAï¼Œæ”¯æŒæ‰‹è¼ªæŽ¥å£ï¼Œå…¶ä¸ç‰¹å®šè¼¸å‡ºå£æ”¯æŒé«˜é€ŸPWM控制。
  
  
  
  ECI2618支æŒ6軸脈沖輸入與編碼器å饋,æ¿è¼‰24點輸入,16點輸出,2AD,2DAï¼Œæ”¯æŒæ‰‹è¼ªæŽ¥å£ï¼Œå…¶ä¸ç‰¹å®šè¼¸å‡ºå£æ”¯æŒé«˜é€ŸPWM控制。
  
  
  
  ECI2418,ECI2618å‡ä½¿ç”¨åŒä¸€å¥—APIå‡½æ•¸ï¼Œå‡æ”¯æŒCã€C++ã€C#ã€LabVIEWã€Pythonã€Delphiç‰é–‹ç™¼èªžè¨€ï¼Œæ”¯æŒVC6.0ã€VB6.0ã€Qtã€.Netç‰å¹³è‡ºï¼Œæ”¯æŒWindowsã€Linuxã€WinCEã€iMacç‰æ“作系統。
  以下是C#
  開發æµç¨‹
  01 新建MFCé …ç›®ï¼Œæ·»åŠ å‡½æ•¸åº«ã€‚
  
  1.在VS2015èœå–®â€œæ–‡ä»¶â€â†’“新建â€â†’ â€œé …ç›®â€ ï¼Œå•Ÿå‹•å‰µå»ºé …ç›®å‘導。
  
  
  
  2.鏿“‡é–‹ç™¼èªžè¨€ç‚ºâ€œVisual C#â€å’Œ.NET Framework 4以åŠWindows 窗體應用程åºã€‚
  
  
  
  3.æ‰¾åˆ°å» å®¶æä¾›çš„光盤資料里é¢çš„C#函數庫,路徑如下(64ä½åº«ç‚ºä¾‹):
  1)進入光盤資料找到PC函數文件夾。
  
  
  
  2)鏿“‡å‡½æ•¸åº«2.1。
  
  
  
  3)Windows平臺。
  
  
  
  4)æ ¹æ“šéœ€è¦é¸æ“‡å°æ‡‰çš„å‡½æ•¸åº«é€™é‡Œé¸æ“‡64ä½åº«ã€‚
  
  
  
  5)解壓C++的壓縮包,é‡Œé¢æœ‰C#å°æ‡‰çš„函數庫。
  
  
  
  6)函數庫具體路徑如下圖所示。
  
  
  
  4.å°‡å» å•†æä¾›çš„C#的庫文件以åŠç›¸é—œæ–‡ä»¶å¾©åˆ¶åˆ°æ–°å»ºçš„é …ç›®é‡Œé¢ã€‚
  1)å°‡zmcaux.csæ–‡ä»¶å¾©åˆ¶åˆ°æ–°å»ºçš„é …ç›®é‡Œé¢ä¸ã€‚
  
  
  
  2)å°‡zaux.dllå’Œzmotion.dll文件放入bin\debug文件夾ä¸ã€‚
  
  
  
  5.用vsæ‰“é–‹æ–°å»ºçš„é …ç›®æ–‡ä»¶ï¼Œåœ¨å³é‚Šçš„解決方案資æºç®¡ç†å™¨ä¸é»žæ“Šé¡¯ç¤ºæ‰€æœ‰ï¼Œç„¶åŽé¼ 標å³éµé»žæ“Šzmcaux.csæ–‡ä»¶ï¼Œé»žæ“ŠåŒ…æ‹¬åœ¨é …ç›®ä¸ã€‚
  
  
  
  
  6.雙擊Form1.cs里é¢çš„Form1,出ç¾ä»£ç¢¼ç·¨è¼¯ç•Œé¢ï¼Œåœ¨æ–‡ä»¶é–‹é 寫入 using cszmcaux,å¹¶è²æ˜ŽæŽ§åˆ¶å™¨å¥æŸ„g_handle。
  
  
  
  至æ¤é …目新建完æˆã€‚
  02 查看PC函數手冊,了解其用法。
  
  1.PC函數手冊也在光盤資料里é¢ï¼Œå…·é«”路徑如下。
  
  
  
  2.PCç·¨ç¨‹ï¼Œä¸€èˆ¬å…ˆæ ¹æ“šæŽ§åˆ¶å™¨é€£æŽ¥æ–¹å¼é¸æ“‡å°æ‡‰çš„é€£æŽ¥å‡½æ•¸é€£æŽ¥æŽ§åˆ¶å™¨ï¼Œè¿”å›žæŽ§åˆ¶å™¨å¥æŸ„ã€‚æŽ¥è‘—ç”¨è¿”å›žçš„æŽ§åˆ¶å™¨å¥æŸ„,實ç¾å°æŽ§åˆ¶å™¨çš„æŽ§åˆ¶ã€‚
  3.比如通éŽç¶²å£é€£æŽ¥æŽ§åˆ¶å™¨ï¼Œå…ˆä½¿ç”¨ZAux_OpenEth()éˆæŽ¥æŽ§åˆ¶å™¨ï¼Œç²å–æŽ§åˆ¶å™¨å¥æŸ„handle。
  
  
  
ã€€ã€€é …ç›®æ‡‰ç”¨æˆªåœ–
  4.通éŽç²å–åˆ°çš„æŽ§åˆ¶å™¨å¥æŸ„handleï¼Œå°æŽ§åˆ¶å™¨é€²è¡Œå–®è»¸é‹å‹•控制。
  
  
  
  5.通éŽç²å–åˆ°çš„æŽ§åˆ¶å™¨å¥æŸ„handleï¼Œé€²è¡Œå¤šè»¸çµ•å°æ’補é‹å‹•。
  
  
  
  int[] axislist = { 0, 1, 2, 3 }; //軸列表
  float[] destdis = { 100, 100, 200, 100 }; //é‹å‹•è·é›¢åˆ—表
  zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
  
  6.通éŽç²å–åˆ°çš„æŽ§åˆ¶å™¨å¥æŸ„handle,ç²å–控制器緩沖å€å‰©ä½™çš„緩沖數é‡ã€‚
  
  
  
  03 é …ç›®å¯¦æˆ°ä¹‹é€£çºŒæ’補é‹å‹•例程講解。
  
  1.例程以建立æ¿å¡çš„連接,執行4æ®µé€£çºŒè»Œè·¡çš„åŠ å·¥ç‚ºç›®æ¨™ã€‚
  
  
  
  2.例程簡易æµç¨‹åœ–。
  
  
  
  3.通éŽç¶²å£æ–¹å¼é€£æŽ¥æŽ§åˆ¶å™¨ï¼Œç²å–æŽ§åˆ¶å™¨é€£æŽ¥å¥æŸ„。
  //連接控制器
  private void button_link_Click(object sender, EventArgs e)
  {
   if (g_handle != (IntPtr)0)
   {
   zmcaux.ZAux_Close(g_handle);//斷開連接
   g_handle = (IntPtr)0;
   }
   zmcaux.ZAux_OpenEth(comboBox_IpList.Text, out g_handle);//連接控制器
   if (g_handle != (IntPtr)0)
   {
   this.Text = "已連接";
   timer1.Enabled = true;
   //åˆå§‹åŒ–è»¸åƒæ•¸
   for (int i = 0; i < 4; i++)
   {
   zmcaux.ZAux_Direct_SetAtype(g_handle, i, 1);//軸類型 脈沖軸
   zmcaux.ZAux_Direct_SetUnits(g_handle, i, 1);//脈沖當é‡
   }
  }
   else
   {
  MessageBox.Show("æŽ§åˆ¶å™¨éˆæŽ¥å¤±æ•—ï¼Œè«‹æª¢æ¸¬IP地å€!", "è¦å‘Š");
   }
  }
  
  4.通éŽå®šæ™‚器1更新控制器軸0-3çš„ä½ç½®å’Œé€Ÿåº¦ç‰ä¿¡æ¯ã€‚
  
  //定時器刷新
  private void timer1_Tick(object sender, EventArgs e)
  {
   int runstate = 0;
   float[] curpos = new float[4];
   float vspeed = 0;
   int remin_buff = 0;
   int curmark = 0;
   //ç²å–軸ä½ç½®
   for (int i = 0; i < 4; i++)
   {
   zmcaux.ZAux_Direct_GetDpos(g_handle, i, ref curpos[i]);
   }
   //ç²å–軸é‹å‹•狀態
   zmcaux.ZAux_Direct_GetIfIdle(g_handle, 0, ref runstate);
   //ç²å–æ’補é‹å‹•åˆé€Ÿåº¦
   zmcaux.ZAux_Direct_GetVpSpeed(g_handle, 0, ref vspeed);
   //åˆ¤æ–·å˜æ”¾ç›´ç·šçš„剩余緩沖
   zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);
   //判斷當å‰é‹å‹•到第幾æ¢é‹å‹•,
   zmcaux.ZAux_Direct_GetMoveCurmark(g_handle, 0, ref curmark);
   label_pos.Text = "X:" + curpos[0] + " Y:" + curpos[1] + " Z:" + curpos[2] + " U:" + curpos[3];
   label_state.Text = Convert.ToString(runstate == 0 ? " é‹è¡Œç‹€æ…‹ï¼šé‹è¡Œä¸" : " é‹è¡Œç‹€æ…‹ï¼šåœæ¢ä¸");
   label_vspeed.Text = "ç•¶å‰é€Ÿåº¦ï¼š" + vspeed;
   label_buff.Text = "剩余緩沖:" + remin_buff;
   label_mark.Text = "ç•¶å‰MARK:" + curmark;
  }
  
 5.通éŽå•Ÿå‹•按鈕的事件處ç†å‡½æ•¸ä¾†å•Ÿå‹•æ’補é‹å‹• 
  //啟動按鈕
  private void button_start_Click(object sender, EventArgs e)
  {
   int[] axislist = { 0, 1, 2, 3 }; //軸列表
   float[] destdis = { 0, 0, 0, 0 }; //é‹å‹•è·é›¢åˆ—表
   int corner_mode = 0; //æ‹è§’模å¼
   int merge_flag = 0; //連續æ’補
   int iresult = 0; //PC函數返回值
   int remin_buff = 0; //剩余直線緩沖數
   if (checkBox1.Checked)
   {
   corner_mode = corner_mode + 2;
   }
   if(checkBox2.Checked)
   {
   corner_mode = corner_mode + 8;
   }
   if(checkBox3.Checked)
  {
   corner_mode = corner_mode + 32;
   }
   if (checkBox4.Checked)
   {
   merge_flag = 1;
   }
   //è¨ç½®æ’補速度
   zmcaux.ZAux_Direct_SetSpeed(g_handle, axislist[0], Convert.ToSingle(textBox_sp.Text));
   //è¨ç½®æ’è£œåŠ é€Ÿåº¦
   zmcaux.ZAux_Direct_SetAccel(g_handle, axislist[0], Convert.ToSingle(textBox_acc.Text));
   //è¨ç½®æ’補減速度
   zmcaux.ZAux_Direct_SetDecel(g_handle, axislist[0], Convert.ToSingle(textBox_dec.Text));
   //è¨ç½®é€£çºŒæ’補
   zmcaux.ZAux_Direct_SetMerge(g_handle, axislist[0], merge_flag);
   //S曲線時間
   zmcaux.ZAux_Direct_SetSramp(g_handle, axislist[0], Convert.ToSingle(SRAMP.Text));
   //è¨ç½®SP速度
   zmcaux.ZAux_Direct_SetForceSpeed(g_handle, axislist[0], Convert.ToSingle(textBox_for_sp.Text));
   //è¨ç½®æ‹è§’模å¼
   zmcaux.ZAux_Direct_SetCornerMode(g_handle, axislist[0], corner_mode);
   //開始減速角度,轉æ›ç‚ºå¼§åº¦
   zmcaux.ZAux_Direct_SetDecelAngle(g_handle, axislist[0], (float)(Convert.ToSingle(textBox_ang1.Text) * 3.14 / 180));
   //åœæ¢æ¸›é€Ÿè§’度,轉æ›ç‚ºå¼§åº¦
   zmcaux.ZAux_Direct_SetStopAngle(g_handle, axislist[0], (float)(Convert.ToSingle(textBox_ang2.Text) * 3.14 / 180));
   //å°åœ“åŠå¾‘
   zmcaux.ZAux_Direct_SetFullSpRadius(g_handle, axislist[0], Convert.ToSingle(textBox_radio.Text));
   //倒角
   zmcaux.ZAux_Direct_SetZsmooth(g_handle, axislist[0], Convert.ToSingle(textBox_zsmooth.Text));
   //è¨ç½®MARK = 0 ,來通éŽè®€å–CURMARK實ç¾åˆ¤æ–·ç•¶å‰åŸ·è¡Œåˆ°é‚£é‡Œ
   zmcaux.ZAux_Direct_SetMovemark(g_handle, axislist[0], 0);
   //鏿“‡base軸
   zmcaux.ZAux_Direct_Base(g_handle, 4, axislist);
   zmcaux.ZAux_Trigger(g_handle);
   //計算剩余直線緩沖數é‡
   zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);
   while(remin_buff<4)
   {
   zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);
   System.Threading.Thread.Sleep(1); //1毫秒
   }
   //第一段æ’補é‹å‹•
   destdis[0] = Convert.ToSingle(destdis1_X.Text);
   destdis[1] = Convert.ToSingle(destdis1_Y.Text);
   destdis[2] = Convert.ToSingle(destdis1_Z.Text);
   destdis[3] = Convert.ToSingle(destdis1_U.Text);
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸æ’補指令
   //函數返回éž0 則表示發é€ä¸æˆåŠŸï¼Œç·©æ²–å€å¯èƒ½æ»¿äº†ï¼Œé‡æ–°ç™¼é€
   while (iresult != 0)
   {
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
   System.Threading.Thread.Sleep(1); //1毫秒
   }
   //第二段æ’補é‹å‹•
   destdis[0] = Convert.ToSingle(destdis2_X.Text);
   destdis[1] = Convert.ToSingle(destdis2_Y.Text);
   destdis[2] = Convert.ToSingle(destdis2_Z.Text);
   destdis[3] = Convert.ToSingle(destdis2_U.Text);
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸æ’補指令
   //函數返回éž0 則表示發é€ä¸æˆåŠŸï¼Œç·©æ²–å€å¯èƒ½æ»¿äº†ï¼Œé‡æ–°ç™¼é€
  while (iresult != 0)
   {
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
   System.Threading.Thread.Sleep(1); //1毫秒
   }
   //第三段æ’補é‹å‹•
   destdis[0] = Convert.ToSingle(destdis3_X.Text);
   destdis[1] = Convert.ToSingle(destdis3_Y.Text);
   destdis[2] = Convert.ToSingle(destdis3_Z.Text);
   destdis[3] = Convert.ToSingle(destdis3_U.Text);
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸æ’補指令
   //函數返回éž0 則表示發é€ä¸æˆåŠŸï¼Œç·©æ²–å€å¯èƒ½æ»¿äº†ï¼Œé‡æ–°ç™¼é€
   while (iresult != 0)
   {
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
   System.Threading.Thread.Sleep(1); //1毫秒
   }
   //第四段æ’補é‹å‹•
   destdis[0] = Convert.ToSingle(destdis4_X.Text);
   destdis[1] = Convert.ToSingle(destdis4_Y.Text);
   destdis[2] = Convert.ToSingle(destdis4_Z.Text);
   destdis[3] = Convert.ToSingle(destdis4_U.Text);
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);//4軸æ’補指令
   //函數返回éž0 則表示發é€ä¸æˆåŠŸï¼Œç·©æ²–å€å¯èƒ½æ»¿äº†ï¼Œé‡æ–°ç™¼é€
   while (iresult != 0)
   {
   iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);
   System.Threading.Thread.Sleep(1); //1毫秒
   }
   }
  
  6.通éŽåœæ¢æŒ‰éˆ•的事件處ç†å‡½æ•¸ä¾†åœæ¢æ’補é‹å‹•。
  
  //åœæ¢é‹å‹•
  private void button_stop_Click(object sender, EventArgs e)
  {
   //å–æ¶ˆä¸»è»¸é‹å‹•
   zmcaux.ZAux_Direct_Single_Cancel(g_handle, 0, 2);
  }
  
  7.è»¸åæ¨™æ¸…零。
  
  //忍™æ¸…é›¶
  private void button_zero_Click(object sender, EventArgs e)
  {
   if (g_handle == (IntPtr)0)
   {
   MessageBox.Show("æœªéˆæŽ¥åˆ°æŽ§åˆ¶å™¨!", "æç¤º");
   }
   else
   {
   for (int i = 0; i < 4; i++)
   {
   zmcaux.ZAux_Direct_SetDpos(g_handle, i, 0);
   }
   }
  }
  
  8. ç·¨è¯é‹è¡Œæ¼”示。
  編è¯é‹è¡Œç¤ºæ•™ä¾‹ç¨‹ï¼ŒåŒæ™‚通éŽZDevelop軟件連接控制器,å°é‹å‹•æŽ§åˆ¶çš„è»¸åƒæ•¸é€²è¡Œç›£æŽ§ã€‚
  9.連續æ’è£œåŠ è‡ªå‹•å€’è§’çš„ä½ç½®æ³¢å½¢ã€‚
  
  
  
  10.ä¸é–‹å•Ÿé€£çºŒæ’補的速度波形。
  
  
  
  
  11.連續æ’è£œåŠ åˆé©çš„æ‹è§’æ¸›é€Ÿçš„é€Ÿåº¦æ³¢å½¢ã€‚
  
  
  
  
  æ£é‹å‹•技術《é‹å‹•æŽ§åˆ¶å¡æ‡‰ç”¨é–‹ç™¼æ•™ç¨‹ä¹‹C#》就講到這里。更多å¸ç¿’è¦–é »åŠåœ–文,請關注我們的公眾號“æ£é‹å‹•å°åŠ©æ‰‹â€ã€‚
  本文由æ£é‹å‹•å°åŠ©æ‰‹åŽŸå‰µï¼Œæ¡è¿Žå¤§å®¶è½‰è¼‰ï¼Œå…±åŒå¸ç¿’,一起æé«˜ä¸åœ‹æ™ºèƒ½åˆ¶é€ æ°´å¹³ã€‚æ–‡ç« ç‰ˆæ¬Šæ¸æ£é‹å‹•æŠ€è¡“æ‰€æœ‰ï¼Œå¦‚æœ‰è½‰è¼‰è«‹æ³¨æ˜Žæ–‡ç« ä¾†æºã€‚
  
  