自动化行业的童鞋无法绕过扭力枪的工具,然后涉及到扭力枪的数据收集,通常收集扭力和角度值。扭力枪行业是开放的protocol 协议,基于WEBSCOKET收集响应数据。今天给大家介绍的是atalas的USB通讯,基于MTCOM DLL函数指令通信。
MTCOM是atlas官方的DLL函数库提供了一些关于控制器数据收集的函数指令。一般来说,我们只收集扭矩角度。这里需要注意的一点是,在拧紧工站后,程序需要在短时间内使用读取函数进行读取,否则无法读取,即读取动作需要在工作前拧紧,读取后关闭,并通过轮询读取。先从控制器上找到SN代码,然后初始连接 打开设备,最后轮询数据。
使用的前提需要安装阿特拉斯应用软件ToolsTalk MT,否则类库调用会失败!atlas软件 TOOLSTALK
代码如下,SDKDLL下载路径MTCOM DLL
直接看代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using TestTool.Utility;
namespace TestTool.ToolForm { public partial class Atlas400Form : Form { #region 初始化库 /* * MT_Init * 本函数初始化MTCom DLL,必须在MTCom以前调用任何其他函数使用API */ [DllImport("MTCom.dll", EntryPoint = "MT_Init")] public static extern bool MT_Init();
/* * MT_GetVersion * 该函数用于检索MTCom DLL版本号。如果函数调用成功,将包括版本null版本号字符串的结尾。 */ [DllImport("MTCom.dll", EntryPoint = "MT_GetDllVersion")] public static extern bool MT_GetDllVersion([MarshalAs(UnmanagedType.LPStr)] StringBuilder version);
/* * MT_GetDeviceList * 该函数用于检索当前连接的微环设备的序列号。若函数调用成功,oDevices序列号列表包含分号分隔,oDeviceCount包含连接设备的数量 */ [DllImport("MTCom.dll", EntryPoint = "MT_GetDeviceList")] public static extern bool MT_GetDeviceList([MarshalAs(UnmanagedType.LPStr)] StringBuilder devices, out int deviceCount);
/* * MT_GetDeviceInfo * 该函数用于检索具有给定序列号的设备的信息。calll成功,oDevicestatus将保持连接状态,oDevicetype设备类型将保持连接。两个参数的有效值列表请参考以下表格 */ public enum DeviceStatusEnum : int { MT_DEVICE_NOT_FOUND = 0, MT_DEVICE_PRESENT, MT_DEVICE_CONNECTED, MT_DEVICE_READY }
public enum DeviceTypeEnum : int { MT_DEVICE_UNKNOWN = 0, MT_DEVICE_MICROTEST_MC, MT_DEVICE_MICROTORQUE_G4, MT_DEVICE_ACTA_MT4, MT_DEVICE_MTF400_BASIC, MT_DEVICE_MTF400_ADVANCED }
[DllImport("MTCom.dll", EntryPoint = "MT_GetDeviceInfo")] public static extern bool MT_GetDeviceInfo([MarshalAs(UnmanagedType.LPStr)] string serial, [MarshalAs(UnmanagedType.I4)] out DeviceStatusEnum deviceStatus, [MarshalAs(UnmanagedType.I4)] out DeviceTypeEnum deviceType);
/* * MT_Open * 该函数打开到具有给定序列号的设备的连接,并返回打开的设备的句柄。如果它不能打开到设备的连接,它将返回无效的句柄值。预留作日后使用,并应设为0)保留 */ public readonly static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); [DllImport("MTCom.dll", EntryPoint = "MT_Open")] public static extern IntPtr MT_Open([MarshalAs(UnmanagedType.LPStr)] string serial, int reserved);
/* * MT_Close * 该函数关闭设备的开放连接,不返回任何内容。 */ [DllImport("MTCom.dll", EntryPoint = "MT_Close")] public static extern IntPtr MT_Close(ref IntPtr client);
/* *MT_Clear * 此函数清除指定通道上以前接收的所有数据集。若使用通道号13或14,则可用于清除设备的摘要数据和摘要序列号。 */ [DllImport("MTCom.dll", EntryPoint = "MT_Clear")] public static extern bool MT_Clear(IntPtr client, int channel);
/* *MT_WriteSet &bsp; * 此函数将数据集写入设备。该应用程序可以选择建立整个数据集,包括控制字符,通道号和校验和,并传递给MT WriteSet或它可以选择的命令,让MTCom建设的dat */ [DllImport("MTCom.dll", EntryPoint = "MT_WriteSet")] public static extern bool MT_WriteSet(IntPtr client, int channel, [MarshalAs(UnmanagedType.LPArray)] byte[] dataset, int noBytes);
/* *MT_ReadSet * 这个函数从设备读取数据集。如果发生实际错误,该函数将仅指示失败(返回FALSE)。如果它超时等待数据集,它将返回TRUE并将oBytesRead设置为零。 */ [DllImport("MTCom.dll", EntryPoint = "MT_ReadSet")] public static extern bool MT_ReadSet(IntPtr client, int channel, [MarshalAs(UnmanagedType.LPArray)][Out] byte[] buffer, [MarshalAs(UnmanagedType.I4)] out int noBytes, int timeOut);
/* * MT_GetSummary * 这个函数检索MTCom接收到的最后一个汇总(最后一个联合的结果)。当一个关节完成时,微扭矩设备在通道13和14上自动发送汇总协议数据。由于此函数仅返回MTCom接收到的最后一个摘要,因此依赖于此函数检索摘要数据的应用程序应该跟踪序列号,以确保检索到的摘要是正确的。参见下一章中的示例。作为oSummary传递的字节数组的大小必须等于或大于1kb */ [DllImport("MTCom.dll", EntryPoint = "MT_GetSummary")] public static extern bool MT_GetSummary(IntPtr client, [MarshalAs(UnmanagedType.LPArray)][Out] byte[] summary, [MarshalAs(UnmanagedType.I4)] out int noBytes, [MarshalAs(UnmanagedType.I4)] out int sequenceNo);
/* * MT_GetNoTraceChannels * 该函数用于获得微力矩装置的最大跟踪通道数。 */ [DllImport(@"MTCom.dll", EntryPoint = "MT_GetNoTraceChannels")] public static extern bool MT_GetNoTraceChannels(IntPtr client, [MarshalAs(UnmanagedType.I4)] out int noTraceChannels);
/* * MT_GetTraceInfo * 这个函数用于获取关于MTCom中最后一个被缓冲的关节的跟踪信息。我将检索跟踪中的点数、采样率(以采样/秒为单位)和扭矩单元 */ public enum UnitEnum : int { MTU_mNm = 0, MTU_cNm, MTU_Nm, MTU_mN, MTU_N, MTU_kN, MTU_inlbf, MTU_lbf, MTU_inozf, MTU_gcm, MTU_kgm, MTU_ftlbf, MTU_ozf, MTU_kgf, MTU_gf, MTU_INVALID = -1, }
[DllImport("MTCom.dll", EntryPoint = "MT_GetTraceInfo")] public static extern bool MT_GetTraceInfo(IntPtr client, int traceChannel, [MarshalAs(UnmanagedType.I4)] out int noPoints, [MarshalAs(UnmanagedType.I4)] out int sampleRate, [MarshalAs(UnmanagedType.I4)] out int torqueUnit);
/* * MT_GetTracePoints * 此函数检索MTCom中当前已缓存的跟踪的实际跟踪点。应该首先调用MT GetTraceInfo来获得可用的点数。根据传递给它的参数,可以使用该函数来检索整个跟踪或部分跟踪。变量traceChannel表示MTCom应该为哪个通道检索跟踪数据。通常这是通道0(在G4中是驱动器,在acme - mt4中是第一个传感器)。作为TracePoints传递的MT跟踪点结构数组应该能够保存在变量maxPoints中传递的点的数量。整数起始点指示MTCom应在何处开始复制跟踪数据的跟踪点。 */ [DllImport("MTCom.dll", EntryPoint = "MT_GetTracePoints")] public static extern bool MT_GetTracePoints(IntPtr client, int traceChannel, [MarshalAs(UnmanagedType.LPArray)][Out] TracePointStruct[] points, int startPoint, int maxPoints, [MarshalAs(UnmanagedType.I4)] out int noPoints);
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16)] public struct TracePointStruct { [MarshalAs(UnmanagedType.R8)] public double torque;
[MarshalAs(UnmanagedType.R8)] public double angle; }
/* * MT_GetOutput * 它返回设备内部输出的状态。检索到的值是位掩码,根据查询的设备类型不同,其意义也不同。 */ [DllImport("MTCom.dll", EntryPoint = "MT_GetOutput")] public static extern bool MT_GetOutput(IntPtr client, [MarshalAs(UnmanagedType.I4)] out int output);
/* * MT_GetLastError * 这个函数返回最后一个失败函数的错误代码。它可以在任何MTCom API 1之后调用 */ public enum ErrorCodeEnum : int { MT_OK = 0, MT_ERR_INVALID_VERSION = -1, MT_ERR_INVALID_PARAMETER = -2, MT_ERR_INVALID_DATA = -3, MT_ERR_INVALID_CHECKSUM = -4, MT_ERR_CONNECTION_ERROR = -5, MT_ERR_INVALID_MESSAGE_ID = -6, MT_ERR_MUTEX_TIMEOUT = -7, MT_ERR_PIPE_READ_FAILED = -8, MT_ERR_PIPE_WRITE_FAILED = -9, MT_ERR_USB_READ_FAILED = -10, MT_ERR_USB_WRITE_FAILED = -11, }
[DllImport("MTCom.dll", EntryPoint = "MT_GetLastError")] public static extern ErrorCodeEnum MT_GetLastError();
#endregion public Atlas400Form() { InitializeComponent(); this.Load += Atlas400Form_Load; }
private void ShowLog(string str) { logLines.Insert(0,DateTime.Now.ToString("yyyy-MM-dd HHmmss")+" "+str); this.Invoke(new Action(() => {
TxtLog.Lines = logLines.ToArray(); })); } List<string> logLines = new List<string>(); private void Atlas400Form_Load(object sender, EventArgs e) { bool initMt = MT_Init(); ShowLog($"初始化COM {initMt}"); if (initMt) { } } IntPtr client; private void BtnOpen_Click(object sender, EventArgs e) { if (TxtSn.Text.Trim() == "") { ShowLog("设备SN不能为空"); return; } string serialNo = TxtSn.Text.Trim();
client = MT_Open(serialNo, 0); if (client != INVALID_HANDLE_VALUE) { ShowLog("设备连接成功!"); // byte[] request = System.Text.Encoding.ASCII.GetBytes("IV"); // bool success = MT_WriteSet(client, 5, request, request.Length);
//MT_Close(ref client); } else { ShowLog("设备连接失败!"); } }
private void BtnRead_Click(object sender, EventArgs e) {
bool success = MT_GetTraceInfo(client, 13, out int noNopoints, out int sampleRate, out int torqueUnit);
if (success) { byte[] reply = new byte[4096]; Task.Run(async () => { while (true) { success = MT_ReadSet(client, 13, reply, out int noBytes, 1000); if (noBytes > 0) { ShowLog($"Reply: {System.Text.Encoding.ASCII.GetString(reply, 0, noBytes)}"); break; } else { ShowLog($"读取失败,超时"); // Timed out. } await Task.Delay(1000); } }); //TracePointStruct[] points = new TracePointStruct[noNopoints]; // MT_GetTracePoints(client, TxtChannel.Value.ToInt(), points, 0, points.Length - 1, out int nopoints);
} else { ShowLog($"Operation failed w/err: { MT_GetLastError()}."); } }
private void BtnChannel_Click(object sender, EventArgs e) { MT_GetNoTraceChannels(client, out int num); ShowLog($"通道:{num}"); } } }