一、硬件认知与选型
1. 固高GTS系列产品线
| 型号 | 轴数 | 接口 | 特点 |
|---|---|---|---|
GTS-400 |
4轴 | PCI/PCIe | 基础款,适合小型设备 |
GTS-800 |
8轴 | PCI/PCIe | 主流型号,支持复杂多轴联动 |
GTS-VB系列 |
4~8轴 | PCI/PCIe | 支持VB/C#/LabVIEW多语言开发 |
2. 硬件组成清单
| 组件 | 说明 |
|---|---|
| GTS控制卡(PCI插卡) | 插入工控机PCI/PCIe插槽 |
| 接线板(端子板) | 信号转接,连接驱动器与IO |
| 连接线缆 | 控制卡与接线板之间的专用线缆 |
| 开关电源 | 为接线板和传感器供电(通常24V) |
| 步进/伺服驱动器 | 接收脉冲信号驱动电机 |
| NPN型感应开关 | 原点/限位检测 |
3. 通信架构
cs
PC(上位机)→ PCI/PCIe总线 → GTS控制卡(DSP+FPGA)→ 脉冲/模拟量 → 驱动器 → 电机
↕
编码器反馈
二、开发环境搭建
1. 准备文件
| 文件 | 位置 | 作用 |
|---|---|---|
gts.dll |
项目的 bin\Debug 目录 |
底层动态链接库,运行时必须 |
gts.cs |
项目源码中 | C# P/Invoke 封装类,包含全部API声明 |
GTS800.cfg |
项目目录 | 固高MCT2008工具生成的配置文件 |
2. 项目配置要求
-
框架:.NET Framework(WinForm项目,部分功能不支持.NET Core)
-
平台:Windows,x86 或 AnyCPU
-
添加引用 :将
gts.cs添加到项目类文件中;将gts.dll放入bin\Debug
3. gts.cs 核心结构
gts.cs 中定义了 namespace gts 下的静态类 mc,所有函数通过 [DllImport("gts.dll")] 声明。存在两个版本:单卡版(613行)和多卡版(1265行),函数签名有显著差异:
cs
using System.Runtime.InteropServices;
namespace gts
{
public class mc
{
// ===== 单卡版(613行)签名 =====
[DllImport("gts.dll")]
public static extern short GT_Open(short channel, short param);
// channel: 通信通道(PCI=0),param: 保留参数
[DllImport("gts.dll")]
public static extern short GT_Close();
[DllImport("gts.dll")]
public static extern short GT_LoadConfig(string pFile);
[DllImport("gts.dll")]
public static extern short GT_Reset();
[DllImport("gts.dll")]
public static extern short GT_AxisOn(short axis);
[DllImport("gts.dll")]
public static extern short GT_AxisOff(short axis);
[DllImport("gts.dll")]
public static extern short GT_Stop(int mask, int option);
// mask: 按位选择轴(bit0=轴1),option: 停止方式
// ===== 多卡版(1265行)额外签名 =====
// GT_Open(short cardNum, string configFile, string password)
// 所有函数额外增加 short cardNum 第一参数
}
}
⚠️ 关键区别 :单卡版
GT_Open参数为(short channel, short param),多卡版为(short cardNum, string configFile, string password)。混用会导致崩溃。
三、标准开发流程
1. 控制卡初始化
cs
// ===== 单卡版初始化 =====
// 1. 打开控制卡(channel=0为PCI通道,param=0保留)
short rtn = mc.GT_Open(0, 0);
CheckResult(rtn); // 检查返回值,0=成功
// 2. 复位控制卡
rtn = mc.GT_Reset();
CheckResult(rtn);
// 3. 加载配置文件(由MCT2008工具生成)
rtn = mc.GT_LoadConfig("GTS800.cfg");
CheckResult(rtn);
// 4. 清除各轴状态(从轴1开始,清除8个轴)
rtn = mc.GT_ClrSts(1, 8);
CheckResult(rtn);
注意 :多卡版初始化为
GT_Open(cardNum, "GTS800.cfg", ""),三个参数版本。
返回值约定 :所有GT_函数返回short类型,0表示成功,非0为错误码。
2. 错误码速查表
| 错误码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 命令错误 |
| 2 | host命令参数错误 |
| 3 | 地址错误 |
| 4 | 数据错误 |
| 5 | 功能号错误 |
| 6 | 通信错误 |
| 7 | 超时 |
| 8 | 未知错误 |
| 9 | 设备未找到 |
| 10 | 功能不支持 |
cs
private void CheckResult(short rtn)
{
if (rtn != 0)
{
throw new Exception($"GTS调用失败,错误码: {rtn}");
}
}
四、单轴运动控制
1. 轴使能/关闭
cs
// 使能轴1
mc.GT_AxisOn(1);
// 关闭轴1
mc.GT_AxisOff(1);
2. 点位运动(Trap梯形速度曲线)
适合从A点到B点的精确定位:
cs
// 1. 设置为梯形速度模式(参数为profile号,非轴号)
mc.GT_PrfTrap(1);
// 2. 设置梯形速度参数
mc.TTrapPrm trapPrm = new mc.TTrapPrm();
trapPrm.acc = 0.5; // 加速度(单位/秒²)
trapPrm.dec = 0.5; // 减速度
trapPrm.velStart = 0; // 起始速度
trapPrm.smoothTime = 0; // 平滑时间(short类型)
mc.GT_SetTrapPrm(1, ref trapPrm);
// 3. 设置目标速度
mc.GT_SetVel(1, 50); // 速度 = 50 单位/秒
// 4. 设置目标位置
mc.GT_SetPos(1, 10000); // 目标位置 = 10000 脉冲(int类型)
// 5. 更新运动(按位mask,bit0对应profile1)
mc.GT_Update(1 << 0);
绝对位置 vs 相对位置 :
GT_SetPos设置的是绝对位置值。要实现相对运动,需先用GT_GetEncPos获取当前位置,再加上偏移量设置GT_SetPos。或用GT_ZeroPos(axis, 1)清零后设置。
3. Jog连续运动
适合调试时的手动点动:
cs
// 鼠标按下 → 启动Jog
mc.GT_PrfJog(1);
mc.TJogPrm jogPrm = new mc.TJogPrm();
jogPrm.acc = 0.5; // 加速度
jogPrm.dec = 0.5; // 减速度
jogPrm.smooth = 0; // 平滑系数(double类型)
mc.GT_SetJogPrm(1, ref jogPrm);
mc.GT_SetVel(1, 10); // 正值=正向,负值=反向
mc.GT_Update(1 << 0);
// 鼠标松开 → 停止(mask为按位选择轴,option=0为立即停止)
mc.GT_Stop(1 << 0, 0); // 停止profile1
4. 获取轴状态与位置
cs
// 获取编码器位置(注意:实际签名包含 out uint pClock 参数)
double encPos = 0;
mc.GT_GetEncPos(1, out encPos, 1, out uint encClock);
// 获取规划位置
double prfPos = 0;
mc.GT_GetPrfPos(1, out prfPos, 1, out uint prfClock);
// 获取规划速度
double prfVel = 0;
mc.GT_GetPrfVel(1, out prfVel, 1, out uint velClock);
// 获取轴状态字(count=读取轴数,pClock=时钟)
int sts = 0;
mc.GT_GetSts(1, out sts, 1, out uint stsClock);
// 状态位解析(⚠️ 不同固件版本位定义可能不同,以官方手册为准)
bool posLimit = (sts & 0x0001) != 0; // bit0: 正限位触发
bool negLimit = (sts & 0x0002) != 0; // bit1: 负限位触发
bool alarm = (sts & 0x0004) != 0; // bit2: 驱动器报警
bool homeStatus = (sts & 0x0008) != 0; // bit3: 原点信号
bool isEnable = (sts & 0x0100) != 0; // bit8: 驱动器使能
⚠️ 状态位差异警告 :不同项目中状态位定义不一致(如堆垛机项目中 bit1=报警, bit5=正限位, bit6=负限位, bit9=使能)。必须以你所用控制卡型号的官方编程手册为准,不能直接照搬。
五、多轴插补运动
1. 坐标系建立
插补运动需先建立坐标系,将多个物理轴映射到坐标系维度:
cs
// 建立2D坐标系(X=轴1, Y=轴2)
mc.TCrdPrm crdPrm = new mc.TCrdPrm();
crdPrm.dimension = 2; // 2维
crdPrm.profile1 = 1; // 第1维对应Profile1(轴1)
crdPrm.profile2 = 2; // 第2维对应Profile2(轴2)
crdPrm.synVelMax = 500; // 最大合成速度
crdPrm.synAccMax = 100; // 最大合成加速度
crdPrm.evenTime = 0; // 匀速段时间(short类型)
crdPrm.setOriginFlag = 1; // 设置原点(1=使用originPos作为原点)
crdPrm.originPos1 = 0; // 原点位置X(long类型,非数组)
crdPrm.originPos2 = 0; // 原点位置Y
mc.GT_SetCrdPrm(1, ref crdPrm); // 坐标系1
⚠️ 注意 :
TCrdPrm的原点位置字段是originPos1~originPos8(独立字段,long类型),不是数组 。不同gts.cs版本中可能是long或int类型,混用会导致内存对齐错误。
2. 直线插补
cs
// 清除坐标系1的FIFO 0
mc.GT_CrdClear(1, 0);
// XY直线插补:从当前位置移动到(10000, 20000)
mc.GT_LnXY(1, // 坐标系号
10000, 20000, // 目标X, Y位置(int类型)
100, // 合成速度(double)
0.1, // 合成加速度(double)
0, // 终止速度(double,0=默认)
0); // FIFO号(short)
// 启动插补运动(mask为坐标系bitmask,option保留)
mc.GT_CrdStart(1 << 0, 0); // bit0=坐标系1
3. 圆弧插补
cs
mc.GT_CrdClear(1, 0);
// XY圆弧插补(圆心方式):当前点→终点,以圆心偏移定义圆弧
mc.GT_ArcXYC(1, // 坐标系号
20000, 20000, // 终点X, Y(int)
0, 10000, // 圆心相对起点的偏移X, Y(double)
0, // 方向:0=顺时针,1=逆时针(⚠️与直觉相反)
100, 0.1, 0, 0); // 合成速度、合成加速度、终止速度、FIFO号
mc.GT_CrdStart(1 << 0, 0);
⚠️ 圆弧方向注意 :
INTERPOLATION_CIRCLE_DIR_CW = 0(顺时针),INTERPOLATION_CIRCLE_DIR_CCW = 1(逆时针)。这与数学上"0=逆时针"的直觉相反。
4. 缓冲区IO与延时
插补过程中可插入IO操作和延时,实现边走边控制:
cs
mc.GT_CrdClear(1, 0);
// 第一段直线
mc.GT_LnXY(1, 5000, 5000, 100, 0.1, 0, 0);
// 在插补路径中触发数字输出
// GT_BufIO(crd, doType, doMask, doValue, fifo)
mc.GT_BufIO(1, mc.MC_GPO, // DO类型(MC_GPO=12, 通用输出)
0x0001, // DO掩码(bit0)
0x0001, // DO值(bit0=高电平)
0); // FIFO号
// 在插补路径中延时500ms
mc.GT_BufDelay(1, 500, 0); // crd, delayTime(ms), fifo
// 第二段直线
mc.GT_LnXY(1, 10000, 10000, 100, 0.1, 0, 0);
mc.GT_CrdStart(1 << 0, 0);
5. 前瞻预处理
高速连续插补时需使用前瞻功能,防止速度突变:
cs
// 初始化前瞻
// GT_InitLookAhead(crd, fifo, T, accMax, n, ref pLookAheadBuf)
// T: 转弯时间常数, accMax: 最大允许加速度, n: 前瞻缓冲区大小
mc.TCrdData[] lookAheadBuf = new mc.TCrdData[4096]; // CRD_FIFO_MAX=4096
mc.GT_InitLookAhead(1, 0, 0.05, 10, 256, ref lookAheadBuf[0]);
mc.GT_CrdClear(1, 0);
mc.GT_LnXY(1, 1000, 0, 200, 50, 0, 0);
mc.GT_LnXY(1, 1000, 1000, 200, 50, 0, 0);
mc.GT_LnXY(1, 0, 1000, 200, 50, 0, 0);
mc.GT_LnXY(1, 0, 0, 200, 50, 0, 0);
mc.GT_CrdStart(1 << 0, 0);
六、高级运动模式
1. 电子齿轮
从轴跟随主轴按比例运动:
cs
// 设置轴2为齿轮模式
// GT_PrfGear(profile, dir) --- dir: 跟随方向
mc.GT_PrfGear(2, 0);
// 设置主轴为轴1的规划位置
// GT_SetGearMaster(profile, masterIndex, masterType, masterItem)
mc.GT_SetGearMaster(2, 1, mc.GEAR_MASTER_PROFILE, 0);
// 设置齿轮比:masterEven:slaveEven = 主轴脉冲数:从轴脉冲数
// GT_SetGearRatio(profile, masterEven, slaveEven, masterSlope)
mc.GT_SetGearRatio(2, 1, 2, 0); // 主轴走1个单位,从轴走2个单位
// 启动齿轮(按位mask)
mc.GT_GearStart(1 << 1); // bit1=profile2
2. Follow跟随模式
比电子齿轮更灵活,支持动态调整跟随比例:
cs
// GT_PrfFollow(profile, dir)
mc.GT_PrfFollow(2, 0);
// GT_FollowClear(profile, fifo)
mc.GT_FollowClear(2, 0);
// 设置主轴(轴1规划位置)
// GT_SetFollowMaster(profile, masterIndex, masterType, masterItem)
mc.GT_SetFollowMaster(2, 1, mc.FOLLOW_MASTER_PROFILE, 0);
// 设置循环次数
mc.GT_SetFollowLoop(2, 0); // 0=无限循环
// 设置跟随事件
// GT_SetFollowEvent(profile, followEvent, masterDir, pos)
mc.GT_SetFollowEvent(2, mc.FOLLOW_EVENT_PASS, 1, 0);
// 添加跟随数据
// GT_FollowData(profile, masterSegment, slaveSegment, type, fifo)
mc.GT_FollowData(2, 10000, 5000, mc.FOLLOW_SEGMENT_NORMAL, 0);
// 主轴移动10000,从轴移动5000
// 启动(mask为按位选择,option保留)
mc.GT_FollowStart(1 << 1, 0);
3. 回零运动
cs
// 阶段1:搜索Home信号
// GT_SetCaptureMode(encoder, mode) --- encoder号通常与轴号对应
mc.GT_SetCaptureMode(1, mc.CAPTURE_HOME); // CAPTURE_HOME=1
mc.GT_PrfTrap(1);
mc.TTrapPrm trapPrm = new mc.TTrapPrm();
trapPrm.acc = 0.5;
trapPrm.dec = 0.5;
trapPrm.velStart = 0;
trapPrm.smoothTime = 0;
mc.GT_SetTrapPrm(1, ref trapPrm);
mc.GT_SetVel(1, -10); // 负方向搜索
mc.GT_Update(1 << 0);
// 阶段2:检测Home捕获
// GT_GetCaptureStatus(encoder, out pStatus, out pValue, count, out pClock)
short captureStatus = 0;
int capturePos = 0;
mc.GT_GetCaptureStatus(1, out captureStatus, out capturePos, 1, out uint clock);
if (captureStatus != 0)
{
// 捕获到Home信号,设置当前位置为捕获位置
mc.GT_Stop(1 << 0, 0);
mc.GT_SetPos(1, capturePos);
mc.GT_Update(1 << 0);
}
4. IO控制
cs
// 读取数字输入(DI)
// GT_GetDi(diType, out pValue) --- diType使用MC_GPI=4读取通用输入
int diValue = 0;
mc.GT_GetDi(mc.MC_GPI, out diValue);
// diValue的每一位对应一个输入点
// 设置数字输出(DO)
// GT_SetDo(doType, value) --- MC_ENABLE=10为伺服使能信号
mc.GT_SetDo(mc.MC_ENABLE, 0xFF);
// MC_GPO=12为通用数字输出
// 读取模拟输入(ADC)
// GT_GetAdc(adc, out pValue, count, out pClock)
double adcValue = 0;
mc.GT_GetAdc(1, out adcValue, 1, out uint adcClock);
// 设置模拟输出(DAC)
// GT_SetDac(dac, ref value, count) --- value为raw值,±32767对应±10V
short dacRaw = 3276; // 约1V
mc.GT_SetDac(1, ref dacRaw, 1);
七、实际项目架构参考
1. 封装类设计模式(参考堆垛机项目)
cs
public static class GtsControl
{
// 初始化(单卡版)
public static void Init()
{
mc.GT_Open(0, 0); // channel=0, param=0
mc.GT_Reset();
mc.GT_LoadConfig("GTS800.cfg");
mc.GT_ClrSts(1, 8); // 清除轴1~8状态
}
// 使能/关闭
public static void AxisEnable(short axis) => mc.GT_AxisOn(axis);
public static void AxisDisable(short axis) => mc.GT_AxisOff(axis);
// 停止(按位mask选择轴)
public static void Stop(short axis)
{
// mask = 1 << (axis-1), option = 0b1111111111(急停方式)
mc.GT_Stop(1 << (axis - 1), 0);
}
// 全部停止(mask=-1即所有位为1)
public static void StopAll() => mc.GT_Stop(-1, 0);
// 读取轴状态(异步循环,参考堆垛机项目位定义)
public static async Task StartReadAxisStatus(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
for (short axis = 1; axis <= 8; axis++)
{
mc.GT_GetSts(axis, out int sts, 1, out uint _);
mc.GT_GetEncPos(axis, out double pos, 1, out uint _);
// ⚠️ 以下位定义来自堆垛机项目,与Form1项目不同
bool alarm = ((sts >> 1) & 1) == 1; // bit1: 驱动器报警
bool posLimit = ((sts >> 5) & 1) == 1; // bit5: 正限位
bool negLimit = ((sts >> 6) & 1) == 1; // bit6: 负限位
bool enabled = ((sts >> 9) & 1) == 1; // bit9: 电机使能
// ... 更新UI
}
await Task.Delay(100);
}
}
// 2D坐标系建立
public static void CreateCrd(short crdNum, short xAxis, short yAxis)
{
mc.TCrdPrm crdPrm = new mc.TCrdPrm();
crdPrm.dimension = 2;
crdPrm.profile1 = xAxis;
crdPrm.profile2 = yAxis;
crdPrm.synVelMax = 500;
crdPrm.synAccMax = 100;
crdPrm.setOriginFlag = 0;
mc.GT_SetCrdPrm(crdNum, ref crdPrm);
}
}
2. 状态位解析参考(⚠️ 两种定义并存)
| Bit位 | Form1项目定义 | 堆垛机项目定义 |
|---|---|---|
| bit0 | 正限位触发 (0x0001) | --- |
| bit1 | 负限位触发 (0x0002) | 驱动器报警 |
| bit2 | 驱动器报警 (0x0004) | --- |
| bit3 | 原点信号 (0x0008) | --- |
| bit5 | --- | 正限位触发 |
| bit6 | --- | 负限位触发 |
| bit8 | 驱动器使能 (0x0100) | --- |
| bit9 | --- | 电机使能 |
⚠️ 重要 :两套位定义来自同一品牌不同项目,可能对应不同固件版本或不同配置工具生成的cfg。开发时必须查阅你所用控制卡型号对应的编程手册,或用MCT2008工具的状态监控功能验证实际位定义。
八、易混淆点
GT_Open 单卡版 vs 多卡版
| 对比项 | 单卡版(613行gts.cs) | 多卡版(1265行gts.cs) |
|---|---|---|
| 函数签名 | GT_Open(short channel, short param) |
GT_Open(short cardNum, string configFile, string password) |
| 参数类型 | 两个short | short + string + string |
| 适用场景 | 单控制卡系统 | 多控制卡级联系统 |
| 额外功能 | 无 | 激光控制、螺旋插补、2D补偿、Smart Home等 |
| TCrdPrm.originPos | long 类型 |
int 类型(⚠️ 内存布局不同) |
⚠️ 严重警告 :两个版本的
TCrdPrm结构体中originPos字段类型不同(longvsint),混用gts.cs和gts.dll版本会导致内存对齐错误和崩溃。
Trap vs Jog vs Pt
| 对比项 | Trap(梯形) | Jog(连续) | Pt(位置-时间表) |
|---|---|---|---|
| 适用场景 | A到B定位 | 调试手动移动 | 自定义轨迹曲线 |
| 速度曲线 | 梯形/S形 | 匀速 | 按数据表插值 |
| 停止方式 | 到达目标自动停 | 需手动Stop | 数据结束自动停 |
| 典型调用 | GT_PrfTrap |
GT_PrfJog |
GT_PrfPt |
九、脉冲当量换算与驱动器握手
1. 脉冲当量换算公式
控制卡发出的脉冲数需要换算为实际物理位移,必须代入全部因子:
cs
每转脉冲数 = 步距角(°) × 细分数 / 360°
例:步距角1.8°,细分数16 → 每转脉冲数 = 1.8 × 16 / 360 = 3200 脉冲/转
每毫米脉冲数 = 每转脉冲数 × 减速比 / 丝杆导程(mm)
例:3200脉冲/转,减速比1:1,丝杆导程5mm → 3200 / 5 = 640 脉冲/mm
| 参数 | 含义 | 典型值 |
|---|---|---|
| 步距角 | 电机每步转动角度 | 1.8°(步进)、360°/编码器线数(伺服) |
| 细分数 | 驱动器细分设置 | 1, 2, 4, 8, 16, 32, 256 |
| 减速比 | 减速器输入:输出 | 1:1, 1:3, 1:10, 1:50 |
| 丝杆导程 | 丝杆转一圈直线位移 | 5mm, 10mm, 20mm |
2. 速度与加速度单位换算
cs
目标速度(脉冲/秒) = 目标物理速度(mm/s) × 每毫米脉冲数
例:50mm/s × 640脉冲/mm = 32000 脉冲/秒
目标加速度(脉冲/秒²) = 目标物理加速度(mm/s²) × 每毫米脉冲数
例:500mm/s² × 640 = 320000 脉冲/秒²
⚠️ 验证要点 :设置
GT_SetVel和TTrapPrm.acc/dec时,必须确认单位是"脉冲/秒"还是"物理单位/秒",两者差每毫米脉冲数倍。
3. 脉冲输出模式与驱动器握手
| 模式 | 说明 | 驱动器设置 |
|---|---|---|
| 脉冲+方向 | PULSE控制步数,DIR控制方向 | 驱动器设为"脉冲+方向"模式 |
| 双脉冲(CW+CCW) | CW正转脉冲,CCW反转脉冲 | 驱动器设为"双脉冲"模式 |
| AB相正交 | A相超前B相=正转 | 驱动器设为"AB相"模式 |
模式不一致的后果:控制卡输出"脉冲+方向"但驱动器设为"AB相"→电机不转或乱转。
4. 编码器反馈配置
| 参数 | 说明 | 设置方式 |
|---|---|---|
| 倍频方式 | 1/2/4倍频 | 由驱动器编码器分频设置 |
| 计数方向 | 与电机实际转向一致 | GT_ZeroPos或编码器方向反转配置 |
| Z相捕获 | 每转一圈的原点信号 | GT_SetCaptureMode(CAPTURE_INDEX) |
十、异常处理与安全保护
1. 伺服驱动器报警 vs 控制卡报警
| 报警来源 | 含义 | 处理方式 |
|---|---|---|
| 驱动器报警(ALM信号) | 过流、过压、编码器异常 | 检查驱动器面板错误码,排除硬件故障后清除报警 |
| 控制卡报警状态位 | GT_GetSts检测到报警位 | 确认驱动器报警已排除后,GT_ClrSts清除状态 |
| 跟随误差超限 | 指令位置与实际位置偏差过大 | 检查机械阻力、调整PID增益、降低速度 |
2. 急停后的恢复流程
cs
// 步骤1:停止所有轴运动
mc.GT_Stop(-1, 0); // mask=-1停止全部轴
// 步骤2:关闭所有轴使能
for (short axis = 1; axis <= 8; axis++)
mc.GT_AxisOff(axis);
// 步骤3:排除硬件故障(检查驱动器、机械、限位)
// 步骤4:清除报警状态
mc.GT_ClrSts(1, 8);
// 步骤5:重新使能(确认安全后)
for (short axis = 1; axis <= 8; axis++)
mc.GT_AxisOn(axis);
3. 软限位保护(第二道防线)
cs
// 设置软限位(在硬限位内侧留余量)
// GT_SetSoftLimit(axis, positive, negative) --- 单位:脉冲
mc.GT_SetSoftLimit(1, 100000, -1000); // 正向100000, 负向-1000
// 读取当前软限位设置
mc.GT_GetSoftLimit(1, out int posLimit, out int negLimit);
十一、常见问题排查
错误1:GT_Open返回非0
-
现象:调用GT_Open失败,返回错误码1或9
-
原因:控制卡未插好、驱动未安装、或gts.dll版本不匹配
-
解决:
-
检查设备管理器中是否有固高PCI设备
-
从官网下载并安装最新驱动
-
确认gts.dll与控制卡型号匹配
-
错误2:轴使能后不运动
-
现象:GT_AxisOn成功,但GT_Update后电机不动
-
原因:驱动器未接收到脉冲信号、伺服ON信号未给出、或限位触发
-
解决:
-
检查脉冲线接线(PULSE+/PULSE-、DIR+/DIR-)
-
确认驱动器处于位置模式
-
检查限位开关状态:
GT_GetDi(MC_LIMIT_POSITIVE, ...)
-
错误3:插补运动中途停止
-
现象:插补运动在路径中间停住不继续
-
原因:FIFO缓冲区为空,CrdStatus返回运动已完成
-
解决:
-
检查
GT_CrdStatus返回的剩余空间段数 -
确认所有GT_LnXY/GT_ArcXYC调用返回值为0
-
检查是否需要启用前瞻(
GT_InitLookAhead)
-
总结
-
固高GTS控制卡通过
gts.dll+gts.cs提供完整C# API,大多数函数返回0表示成功 -
开发标准流程:
GT_Open→GT_Reset→GT_LoadConfig→GT_ClrSts→GT_AxisOn→ 运动控制 →GT_Stop→GT_AxisOff→GT_Close -
单轴用
GT_PrfTrap/GT_PrfJog,多轴插补用GT_SetCrdPrm+GT_LnXY/GT_ArcXYC -
状态监控必须定时轮询
GT_GetSts+GT_GetEncPos -
脉冲当量换算必须代入全部因子(步距角、细分数、减速比、丝杆导程),速度/加速度单位必须统一
-
生产项目必须配置软限位作为第二道保护,急停后按"停轴→关使能→排故障→清状态→重新使能"流程恢复
-
状态位定义必须以所用控制卡型号的官方手册为准,不同固件版本位定义可能不同