C#程式控制Mach3運動卡的方法(二)
上回寫的程式版本是透過USB HID介面直接控制Mach3, 這次版本是透過Mach3橋接, 用它提供的API做控制, 好處是幾乎所有Mach3功能皆可實作, 壞處是Mach3必須先執行, 這樣做有甚麼好處呢? 主要是二次開發用, 會自已寫程式的人(C# , C++, VB)可加入演算法提升CNC的功能, 例如可在CNC加入OpenCV做影像辨識或做3D工件掃描建模功能, 或者加入類神經網路做深度學習….等等, 下次有機會我們再詳細討論這部份. 本章重點是簡單介紹開發步驟, 以C#程式語言為例(其實任何語言皆可, 只是呼叫方式略有不同而已)如下:
(1)正常機碼必須有下列註冊檔, 否則程式無法呼叫API(有個補救方法, 下載Mach3Registry.reg, 執行可產生).
xxxxxxxxxx : 每套機碼不一樣. [HKEY_CLASSES_ROOT\CLSID\{xxxxxxxxxxx}] @="Mach4.Document"
[HKEY_CLASSES_ROOT\CLSID\{ xxxxxxxxxxx] @="ole32.dll"
[HKEY_CLASSES_ROOT\CLSID\{ xxxxxxxxxxx }\LocalServer32] @="C:\\Mach3\\Mach3.exe"
[HKEY_CLASSES_ROOT\CLSID\{ xxxxxxxxxxx }\ProgID] @="Mach4.Document"
[HKEY_CLASSES_ROOT\Mach4.Document] @="Mach4.Document"
[HKEY_CLASSES_ROOT\Mach4.Document\CLSID] @="{ xxxxxxxxxxx }"
(2)在C# /專案/加入參考/ 將Mach3.exe 加入參考,
並在程式前面加入
using System.Runtime.InteropServices;
using Mach4;
(3)主要操作就是這項, 一旦取得Mach3的handle(mInst), 就可長驅直入使用其提供的所有功能(功能可參考Mach3 Version3.x Macro Programmers Reference Manual.pdf) .
IMyScriptObject mInst = null;
try
{
Mach4 mach = (Mach4.IMach4)
Marshal.GetActiveObject("Mach4.Document");
mInst = (Mach4.IMyScriptObject)
mach.GetScriptDispatch();
}
catch
{
}
(4)程式有點長, 為避免洗版, 只好摘錄部分程式如下(有疑問或有興趣找我研發的也歡迎私訊我!):
//---------------------------------------------------------------------
//Mach3 Control Process
//---------------------------------------------------------------------
private IMyScriptObject GetMachInstance()
{
IMyScriptObject mInst = null;
try
{
IMach4 mach = (Mach4.IMach4)
Marshal.GetActiveObject("Mach4.Document");
mInst = (Mach4.IMyScriptObject)
mach.GetScriptDispatch();
}
catch
{
}
return mInst;
}
//---------------------------------------------------------------------
private bool DoEmButton(short number)
{
if(_mInst != null)
{
_mInst . DoOEMButton(number);
return true;
}
return false;
}
//---------------------------------------------------------------------
private void DoGCode(string code)
{
if(_mInst != null)
_mInst.Code(code);
}
//---------------------------------------------------------------------
private void sendMDI()
{
if(textBoxMDI.Text.Trim() != null)
{
DoGCode(textBoxMDI.Text.Trim());
}
}
//---------------------------------------------------------------------
private double[] UpdateDRO()
{
double[] dro = new double[3];
if(_mInst != null)
{
dro[0] = _mInst.GetOEMDRO(800);
dro[1] = _mInst.GetOEMDRO(801);
dro[2] = _mInst.GetOEMDRO(802);
}
return dro;
}
//---------------------------------------------------------------------
//dir = 0 to + direction, dir = 1 to - direction
private void xJogStart(DirectionType dir)
{
if(_mInst != null)
_mInst.JogOn((short)AxisType.X, (short)dir);
}
//---------------------------------------------------------------------
private void xJogStop()
{
if(_mInst != null)
_mInst.JogOff((short)AxisType.X);
}
//---------------------------------------------------------------------
private void yJogStart(DirectionType dir)
{
if(_mInst != null)
_mInst.JogOn((short)AxisType.Y, (short)dir);
}
//---------------------------------------------------------------------
private void yJogStop()
{
if(_mInst != null)
_mInst.JogOff((short)AxisType.Y);
}
//---------------------------------------------------------------------
private void zJogStart(DirectionType dir)
{
if(_mInst != null)
_mInst.JogOn((short)AxisType.Z, (short)dir);
}
//---------------------------------------------------------------------
private void zJogStop()
{
if(_mInst != null)
_mInst.JogOff((short)AxisType.Z);
}
//---------------------------------------------------------------------
private void buttonStart_Click(object sender, EventArgs e)
{
DoEmButton(1000); //start
}
//---------------------------------------------------------------------
private void buttonFeedhold_Click(object sender, EventArgs e)
{
DoEmButton(1001); //Feedhold
}
//---------------------------------------------------------------------
private void buttonStop_Click(object sender, EventArgs e)
{
DoEmButton(1003); //Stop
}
//---------------------------------------------------------------------
private void buttonMDI_Click(object sender, EventArgs e)
{
if(_mInst != null && textBoxMDI.Text.Trim() != null)
_mInst.Code(textBoxMDI.Text.Trim()); //senMDI
}
//---------------------------------------------------------------------
private void timerUpdateDRO_Tick(object sender, EventArgs e)
{
double[] dro = UpdateDRO();
textBoxX.Text = dro[0].ToString("#0.0000");
textBoxY.Text = dro[1].ToString("#0.0000");
textBoxZ.Text = dro[2].ToString("#0.0000");
}
//---------------------------------------------------------------------
private void buttonPX_MouseDown(object sender, MouseEventArgs e)
{
xJogStart(DirectionType.Positive);
}
//---------------------------------------------------------------------
private void buttonPX_MouseUp(object sender, MouseEventArgs e)
{
xJogStop();
}
//---------------------------------------------------------------------
private void buttonNX_MouseDown(object sender,
MouseEventArgs e)
{
xJogStart(DirectionType.Negtive);
}
//---------------------------------------------------------------------
private void buttonNX_MouseUp(object sender,
MouseEventArgs e)
{
xJogStop();
}
//---------------------------------------------------------------------
p.s. 一手操作一手攝影, 非專業攝影, 影片有些抖動請見諒!
辛育全
2019-04-30 12:37:03
Steve Wu
2019-04-30 13:01:22
張益晟
2019-04-30 18:27:16
Chihfu Huang
2019-04-30 19:13:38
沈宗麟
2019-04-30 21:32:50
徐豪宏
2019-05-01 00:33:13
Yu Tseng
2019-05-01 10:28:23
林志強
2019-05-01 17:14:23
吳治彥
2019-05-04 22:53:05
石小川
2019-05-05 16:23:49
謝謝! 感謝以上兄弟們熱烈回應!
我是有些野人獻曝, 班門弄斧之感, 所幸大家善良. 在本社團內臥虎藏龍, 有經驗的CNC實務高手很多, 不結合一起做出好產品實在可惜, 畢竟要會玩也要會養家糊口, 哈哈哈! 想借此版拋磚引玉一下, 是否可腦力激盪, 集思廣益一下, 大家提出CNC專案或其他智慧機器由有興趣有能力的成員加入一起完成, 至於專案成立, 負責出資, 材料, 利潤分紅等細節我再想想, 會尊重此版規定, 跟管理員商討是公開或私訊方式. 以上是我初步構想, 看是否有正反意見皆可提出!