一、硬件认知与选型
1. 脉冲卡 vs 总线卡
| 对比项 | 脉冲卡(如DMC3000) | 总线卡(如DMC3800/EtherCAT) |
|---|---|---|
| 控制方式 | 脉冲+方向信号 | 数字网络通信(EtherCAT/CANopen) |
| 适用轴数 | 1~4轴,简单应用 | ≥4轴,多轴联动 |
| 精度 | 中等 | 高精度,支持实时反馈 |
| 布线 | 每轴独立接线 | 两根信号线串联所有电机 |
| 力矩控制 | 不支持 | 支持实时电流/力矩调节 |
| 成本 | 硬件成本低 | 综合成本低(布线少、维护简单) |
| 适用场景 | 简单点位运动 | 复杂自动化、医疗器械、多轴设备 |
选型建议:轴数≤4且只需点位运动选脉冲卡;≥4轴或需要力矩控制、实时反馈选总线卡。总线型是未来趋势。
2. 硬件组成清单
| 组件 | 说明 |
|---|---|
| DMC控制卡(PCI插卡) | 插入工控机PCI/PCIe插槽 |
| 接线盒(端子板) | 信号转接,25pin接口连接驱动器 |
| 25pin引脚线 | 控制卡与接线盒连接 |
| 开关电源 | 为接线盒和传感器供电(24V) |
| 步进/伺服驱动器 | 接收脉冲信号驱动电机 |
| NPN型感应开关 | 原点/限位检测 |
3. 通信架构
cs
PC(上位机)→ PCI/PCIe → DMC控制卡(DSP+FPGA)→ 脉冲/方向 → 驱动器 → 电机
↕
编码器反馈
二、开发环境搭建
1. 准备文件
| 文件 | 位置 | 作用 |
|---|---|---|
LTDMC.dll |
项目的 bin\Debug 目录 |
底层动态链接库,运行时必须 |
LTDMC.cs |
项目源码中(namespace csLTDMC) |
C# P/Invoke 封装类,包含全部API声明 |
2. 项目配置要求
-
框架:.NET Framework 或 .NET 5+(WinForm项目)
-
平台:Windows,x86 或 AnyCPU
-
添加引用 :将
LTDMC.cs添加到项目;将LTDMC.dll放入bin\Debug
3. LTDMC.cs 核心结构
LTDMC.cs 中定义了 namespace csLTDMC 下的 partial class LTDMC,所有函数通过 [DllImport("LTDMC.dll")] 声明,共2110行,覆盖全部DMC系列API:
cs
using System.Runtime.InteropServices;
namespace csLTDMC
{
public partial class LTDMC
{
// 开卡初始化
[DllImport("LTDMC.dll", EntryPoint = "dmc_board_init")]
public static extern short dmc_board_init();
// 硬件复位
[DllImport("LTDMC.dll", EntryPoint = "dmc_board_reset")]
public static extern short dmc_board_reset();
// 关闭控制卡
[DllImport("LTDMC.dll", EntryPoint = "dmc_board_close")]
public static extern short dmc_board_close();
// 设置脉冲输出模式
[DllImport("LTDMC.dll", EntryPoint = "dmc_set_pulse_outmode")]
public static extern short dmc_set_pulse_outmode(ushort CardNo, ushort axis, ushort outmode);
// 设置速度曲线
[DllImport("LTDMC.dll", EntryPoint = "dmc_set_profile")]
public static extern short dmc_set_profile(ushort CardNo, ushort axis,
double Min_Vel, double Max_Vel, double Tacc, double Tdec, double stop_vel);
// 单轴定长运动
[DllImport("LTDMC.dll", EntryPoint = "dmc_pmove")]
public static extern short dmc_pmove(ushort CardNo, ushort axis, int Dist, ushort posi_mode);
// 检查运动是否完成
[DllImport("LTDMC.dll", EntryPoint = "dmc_check_done")]
public static extern short dmc_check_done(ushort CardNo, ushort axis);
// ... 更多函数见完整LTDMC.cs
}
}
三、标准开发流程
1. 开卡初始化
cs
using csLTDMC;
// 1. 初始化控制卡(搜索并打开所有在线控制卡)
short res = LTDMC.dmc_board_init();
if (res <= 0 || res > 8)
{
Console.WriteLine("轴卡初始化失败");
return;
}
Console.WriteLine($"初始化成功,找到 {res} 张卡");
// 2. 获取控制卡信息
ushort cardNum = 0;
uint[] cardTypes = new uint[8];
ushort[] cardIds = new ushort[8];
LTDMC.dmc_get_CardInfList(ref cardNum, cardTypes, cardIds);
Console.WriteLine($"卡号: {cardIds[0]}, 固件版本: 0x{cardTypes[0]:X}");
// 3. 获取卡的总轴数
uint totalAxis = 0;
LTDMC.dmc_get_total_axes(cardIds[0], ref totalAxis);
Console.WriteLine($"总轴数: {totalAxis}");
// 4. 关闭控制卡
// LTDMC.dmc_board_close();
2. 返回值约定
| 返回值 | 含义 |
|---|---|
| 0 | 成功(大多数函数) |
| 正数 | 设备数量(仅 dmc_board_init 返回) |
| 负数 | 错误码(具体含义参考官方文档) |
⚠️ 特殊返回值函数 :以下函数不是返回0=成功,而是直接返回业务数据:
dmc_get_position→ 返回Int32位置值
dmc_get_encoder→ 返回Int32编码器值
dmc_read_current_speed→ 返回double速度值
dmc_check_done→ 返回short(0=运动中, 1=完成)
dmc_read_inbit→ 返回short(0/1 电平状态)
dmc_read_inport→ 返回UInt32端口值
dmc_get_latch_value→ 返回Int32锁存位置
四、单轴运动控制
1. 设置运动参数
cs
ushort cardNo = 0;
ushort axis = 0; // 第0轴
// 设置脉冲输出模式(0=脉冲+方向,1=双脉冲...)
LTDMC.dmc_set_pulse_outmode(cardNo, axis, 0);
// 设置速度曲线参数(起始速度, 运行速度, 加速时间s, 减速时间s, 停止速度)
LTDMC.dmc_set_profile(cardNo, axis, 100, 5000, 0.5, 0.5, 100);
// 设置S段时间(平滑加减速)
LTDMC.dmc_set_s_profile(cardNo, axis, 0, 0.1); // s_mode=0, s_para=0.1秒
2. 绝对位置运动(定长运动)
cs
// 绝对位置模式(posi_mode=1)
LTDMC.dmc_pmove(cardNo, axis, 10000, 1); // 移动到绝对位置10000脉冲
// 等待运动完成
while (LTDMC.dmc_check_done(cardNo, axis) != 1)
{
System.Threading.Thread.Sleep(100);
}
Console.WriteLine("运动完成");
3. 相对位置运动
cs
// 相对位置模式(posi_mode=0)
LTDMC.dmc_pmove(cardNo, axis, 5000, 0); // 从当前位置正向移动5000脉冲
4. Jog连续运动
cs
// 正向连续运动
LTDMC.dmc_vmove(cardNo, axis, 0); // direction: 0=正向, 1=负向
// 停止
LTDMC.dmc_stop(cardNo, axis, 0); // stop_mode: 0=减速停止, 1=立即停止
5. 获取当前位置与状态
cs
// ⚠️ 以下三个函数返回值直接作为函数返回值,不是通过ref参数传出
// 获取指令位置(返回类型Int32,单位:脉冲)
int cmdPos = LTDMC.dmc_get_position(cardNo, axis);
// 获取编码器位置(返回类型Int32,单位:脉冲)
int encPos = LTDMC.dmc_get_encoder(cardNo, axis);
// 获取当前速度(返回类型double,单位:脉冲/秒)
double vel = LTDMC.dmc_read_current_speed(cardNo, axis);
// 获取运动状态(返回short:0=运动中, 1=运动完成)
short done = LTDMC.dmc_check_done(cardNo, axis);
五、多轴插补运动
1. 直线插补
cs
// 2轴直线插补
ushort[] axes = new ushort[] { 0, 1 }; // 参与插补的轴号
double[] targetPos = new double[] { 10000, 20000 }; // ⚠️ double类型,非int
// 设置插补速度参数
LTDMC.dmc_set_profile(cardNo, axes[0], 0, 500, 0.5, 0.5, 0);
// 执行直线插补
// dmc_line_unit(CardNo, Crd, AxisNum, AxisList, Target_Pos, posi_mode)
// ⚠️ 实际签名:6个参数,最后一个posi_mode(0=相对, 1=绝对)
LTDMC.dmc_line_unit(cardNo, 0, 2, axes, targetPos, 1); // Crd=0, 绝对坐标
// 等待完成(检查第一个参与插补的轴)
while (LTDMC.dmc_check_done(cardNo, axes[0]) != 1)
{
Thread.Sleep(50);
}
⚠️ 关键纠正 :
dmc_line_unit的Target_Pos参数类型是double[](不是int\[\]),且最后一个参数是posi_mode(0=相对, 1=绝对),不是速度 。速度需提前通过dmc_set_profile设置。
2. 圆弧插补(圆心方式)
cs
ushort[] axes = new ushort[] { 0, 1 };
double[] targetPos = new double[] { 20000, 0 }; // ⚠️ double类型
double[] center = new double[] { 10000, 0 }; // ⚠️ double类型,圆心相对起点偏移
ushort dir = 0; // 0=逆时针, 1=顺时针
// ⚠️ 函数名必须带 _unit 后缀!dmc_arc_move_center 不存在
// dmc_arc_move_center_unit(CardNo, Crd, AxisNum, AxisList, Target_Pos, Cen_Pos, Arc_Dir, Circle, posi_mode)
// Circle: 圈数(0=不整圆,1=整圆一圈)
LTDMC.dmc_arc_move_center_unit(cardNo, 0, 2, axes, targetPos, center, dir, 0, 1);
3. 圆弧插补(半径方式)
cs
ushort[] axes = new ushort[] { 0, 1 };
double[] targetPos = new double[] { 20000, 0 }; // ⚠️ double类型
double radius = 10000; // 半径(正值=优弧,负值=劣弧)
ushort dir = 0; // 0=逆时针, 1=顺时针
// ⚠️ 函数名必须带 _unit 后缀!dmc_arc_move_radius 不存在
// dmc_arc_move_radius_unit(CardNo, Crd, AxisNum, AxisList, Target_Pos, Arc_Radius, Arc_Dir, Circle, posi_mode)
LTDMC.dmc_arc_move_radius_unit(cardNo, 0, 2, axes, targetPos, radius, dir, 0, 1);
⚠️ 致命错误纠正 :LTDMC.dll 中不存在
dmc_arc_move_center和dmc_arc_move_radius,必须使用_unit后缀版本。函数签名也完全不同------9个参数,含坐标系号Crd、圈数Circle、坐标模式posi_mode。
4. 连续插补(小线段前瞻)
适合连续轨迹加工(如切割、雕刻):
cs
// 1. 打开连续插补
// ⚠️ dmc_conti_open_list 有4个参数,需要指定参与插补的轴
ushort[] axes = new ushort[] { 0, 1 };
LTDMC.dmc_conti_open_list(cardNo, 0, 2, axes); // CardNo, Crd, AxisNum, AxisList
// 2. 设置连续插补速度参数(需使用unit版本,单位为物理单位)
LTDMC.dmc_set_profile_unit(cardNo, 0, 0, 100, 0.5, 0.5, 0);
// 3. 添加连续直线段
// ⚠️ dmc_conti_line_unit 签名:(CardNo, Crd, AxisNum, AxisList, Target_Pos, posi_mode, mark)
double[] pos1 = new double[] { 1000, 0 };
LTDMC.dmc_conti_line_unit(cardNo, 0, 2, axes, pos1, 1, 0); // posi_mode=1绝对, mark=0
double[] pos2 = new double[] { 1000, 1000 };
LTDMC.dmc_conti_line_unit(cardNo, 0, 2, axes, pos2, 1, 0);
// 4. 启动连续插补
LTDMC.dmc_conti_start_list(cardNo, 0);
// 5. 等待连续插补完成
// dmc_conti_get_run_state 返回值:0=运行中, 1=暂停, 2=急停, 3=未启动
while (LTDMC.dmc_conti_get_run_state(cardNo, 0) == 0)
{
Thread.Sleep(50);
}
⚠️ 关键纠正:
dmc_conti_open_list实际有4个参数(CardNo, Crd, AxisNum, AxisList),不是2个
dmc_conti_line_unit最后两个参数是(posi_mode, mark),不是(synVel, synAcc)
dmc_conti_get_run_state返回0表示运行中,等待条件应为== 0(不是!= 0)
连续插补要点 :连续插补适合小线段高速加工(切割、雕刻等),内部有前瞻缓冲区处理速度平滑。需先调用
dmc_conti_open_list,添加完所有线段后调用dmc_conti_start_list启动。
六、IO控制
1. 数字输入(DI)
cs
// ⚠️ dmc_read_inbit 返回值直接是函数返回值,不是ref参数
// 读取单个输入点(返回short:0=低电平, 1=高电平)
short diState = LTDMC.dmc_read_inbit(cardNo, 0); // bitNo=0
Console.WriteLine($"DI0 = {diState}");
// ⚠️ dmc_read_inport 返回类型是UInt32,直接返回
// 批量读取输入端口(返回UInt32,每一位对应一个输入点)
uint portValue = LTDMC.dmc_read_inport(cardNo, 0); // portNo=0
2. 数字输出(DO)
cs
// 设置单个输出点(on_off: 0=低电平, 1=高电平)
LTDMC.dmc_write_outbit(cardNo, 0, 1); // bitNo=0, value=1
// 批量设置输出端口(outport_val: 32位,每一位对应一个输出点)
LTDMC.dmc_write_outport(cardNo, 0, 0xFF); // portNo=0, 低8位全部高电平
3. 模拟量(DA/AD)
cs
// ⚠️ 函数名不是 da_set_output,而是 dmc_set_da_output
// 设置DA输出(DMC5X10系列,单位:伏特)
LTDMC.dmc_set_da_output(cardNo, 0, 3.3); // 通道0, 输出3.3V
// ⚠️ 函数名不是 ad_get_input,而是 dmc_get_ad_input
// 读取AD输入(单位:伏特)
double adValue = 0;
LTDMC.dmc_get_ad_input(cardNo, 0, ref adValue); // 通道0
七、回零运动
1. 设置回零模式
cs
// 设置原点信号逻辑
// dmc_set_home_pin_logic(CardNo, axis, org_logic, filter)
// org_logic: 0=低电平有效, 1=高电平有效
// filter: 去抖滤波时间(秒),如0.001=1ms
LTDMC.dmc_set_home_pin_logic(cardNo, axis, 0, 0.001);
// ⚠️ dmc_home_move 只有2个参数,不是4个!回零模式由硬件配置决定
LTDMC.dmc_home_move(cardNo, axis);
2. 等待回零完成
cs
while (LTDMC.dmc_check_done(cardNo, axis) != 1)
{
Thread.Sleep(100);
}
// 回零完成后清零位置
LTDMC.dmc_set_position(cardNo, axis, 0); // Int32类型
LTDMC.dmc_set_encoder(cardNo, axis, 0); // Int32类型
八、位置比较与高速锁存
1. 位置比较输出
cs
// ⚠️ dmc_compare_set_config 参数含义纠正
// dmc_compare_set_config(CardNo, axis, enable, cmp_source)
// enable: 0=禁用, 1=启用
// cmp_source: 0=指令位置, 1=编码器位置
LTDMC.dmc_compare_set_config(cardNo, 0, 1, 1); // 轴0, 启用, 编码器位置
// ⚠️ dmc_compare_add_point 实际有6个参数!
// dmc_compare_add_point(CardNo, axis, pos, dir, action, actpara)
// pos: 比较位置(脉冲)
// dir: 方向(0=负方向, 1=正方向, 2=双向)
// action: 比较动作(0=输出脉冲, 1=输出电平)
// actpara: 动作参数(脉冲宽度us 或 电平值)
LTDMC.dmc_compare_add_point(cardNo, 0, 10000, 2, 0, 50); // 双向, 输出50us脉冲
LTDMC.dmc_compare_add_point(cardNo, 0, 20000, 2, 0, 50);
// 2D高速位置比较(适用于飞拍等场景)
// 使用 dmc_hcmp_2d_set_config 和 dmc_hcmp_2d_add_point
// ⚠️ dmc_2d_compare_set_config / dmc_2d_compare_add_point 不存在
2. 高速锁存
cs
// ⚠️ dmc_set_ltc_mode 有5个参数,含滤波时间
// dmc_set_ltc_mode(CardNo, axis, ltc_logic, ltc_mode, filter)
// ltc_logic: 0=低电平, 1=高电平
// ltc_mode: 0=AB相, 1=锁存信号
// filter: 去抖滤波时间(秒)
LTDMC.dmc_set_ltc_mode(cardNo, axis, 0, 1, 0.001);
// ⚠️ dmc_get_latch_value 返回类型是Int32,直接返回,不是ref参数
int ltcValue = LTDMC.dmc_get_latch_value(cardNo, axis);
九、实际项目代码参考
1. 完整的初始化+运动+关闭流程(参考官方示例)
cs
using csLTDMC;
class Program
{
static ushort _cardNo;
static bool _isInit;
static void Main(string[] args)
{
try
{
// 1. 初始化
Init();
// 2. 设置运动参数
SetMoveParameters(axis: 0, startVel: 100, runVel: 5000,
accTime: 0.5, decTime: 0.5, stopVel: 100);
// 3. 绝对位置运动
MoveAbsolute(axis: 0, position: 10000);
// 4. 等待完成
WaitForDone(axis: 0);
Console.WriteLine("运动完成");
}
finally
{
// 5. 关闭
if (_isInit) LTDMC.dmc_board_close();
}
}
static void Init()
{
// dmc_board_init返回在线卡数量,0=失败
short res = LTDMC.dmc_board_init();
if (res <= 0 || res > 8)
throw new Exception("初始化失败");
// 获取卡信息列表
ushort cardNum = 0;
uint[] types = new uint[8];
ushort[] ids = new ushort[8];
LTDMC.dmc_get_CardInfList(ref cardNum, types, ids);
_cardNo = ids[0]; // 使用第一张卡的ID
_isInit = true;
}
static void SetMoveParameters(ushort axis, double startVel, double runVel,
double accTime, double decTime, double stopVel)
{
// 设置S段时间(平滑加减速)
LTDMC.dmc_set_s_profile(_cardNo, axis, 0, 0.1);
// 设置速度曲线:起始速度, 运行速度, 加速时间(秒), 减速时间(秒), 停止速度
LTDMC.dmc_set_profile(_cardNo, axis, startVel, runVel, accTime, decTime, stopVel);
// 设置减速停止时间
LTDMC.dmc_set_dec_stop_time(_cardNo, axis, decTime);
}
static void MoveAbsolute(ushort axis, int position)
{
// posi_mode: 0=相对运动, 1=绝对运动
LTDMC.dmc_pmove(_cardNo, axis, position, 1);
}
static void MoveRelative(ushort axis, int distance)
{
LTDMC.dmc_pmove(_cardNo, axis, distance, 0);
}
static void WaitForDone(ushort axis)
{
// dmc_check_done: 0=运动中, 1=运动完成
while (LTDMC.dmc_check_done(_cardNo, axis) != 1)
Thread.Sleep(100);
}
}
2. 15轴多工位项目架构参考
cs
// 基于DMC3000的15轴项目,分5个工位(每工位XYZ 3轴)
public class WorkStation
{
private ushort _cardNo;
private ushort _xAxis, _yAxis, _zAxis;
public WorkStation(ushort cardNo, ushort stationIndex)
{
_cardNo = cardNo;
_xAxis = (ushort)(stationIndex * 3);
_yAxis = (ushort)(stationIndex * 3 + 1);
_zAxis = (ushort)(stationIndex * 3 + 2);
}
// Z轴下降到取料位
public void ZDownToPick() => LTDMC.dmc_pmove(_cardNo, _zAxis, -50000, 0);
// XY移动到目标位置
public void MoveToXY(int x, int y)
{
LTDMC.dmc_pmove(_cardNo, _xAxis, x, 1);
LTDMC.dmc_pmove(_cardNo, _yAxis, y, 1);
}
// 等待所有轴到位
public void WaitAllDone()
{
while (LTDMC.dmc_check_done(_cardNo, _xAxis) != 1 ||
LTDMC.dmc_check_done(_cardNo, _yAxis) != 1 ||
LTDMC.dmc_check_done(_cardNo, _zAxis) != 1)
Thread.Sleep(50);
}
}
十、易混淆点
dmc_board_init vs dmc_board_init_onecard
| 对比项 | dmc_board_init |
dmc_board_init_onecard |
|---|---|---|
| 功能 | 初始化所有在线控制卡 | 初始化指定单张卡 |
| 参数 | 无 | CardNo(卡号) |
| 返回值 | 成功:卡数量;失败:≤0 | 成功:0 |
| 适用场景 | 大多数项目 | 多卡系统中单独初始化某张卡 |
dmc_set_profile vs dmc_set_profile_unit
| 对比项 | dmc_set_profile |
dmc_set_profile_unit |
|---|---|---|
| 单位 | 脉冲数 | 物理单位(mm/度,需先设equiv) |
| 适用卡型 | DMC3000系列 | DMC5X10系列/EtherCAT/RTEX |
| 精度 | 原始脉冲 | 用户自定义单位 |
dmc_pmove 的 posi_mode
| 值 | 模式 | 说明 |
|---|---|---|
| 0 | 相对运动 | 从当前位置移动指定距离 |
| 1 | 绝对运动 | 移动到指定的绝对位置 |
脉冲卡 vs 总线卡API差异
| 对比项 | 脉冲卡 | 总线卡 |
|---|---|---|
| 初始化 | dmc_board_init |
dmc_board_init + nmc_open |
| 运动指令 | dmc_pmove |
dmc_pmove_unit / nmc_move_* |
| 编码器 | dmc_get_encoder |
nmc_get_encoder |
| IO读写 | dmc_read_inbit |
通用,总线IO通过 nmc_* |
| 总线特有 | 无 | nmc_get_node_state、nmc_set_mode_of_operation |
十一、脉冲当量换算与驱动器握手
1. 脉冲当量换算公式
cs
每转脉冲数 = 步距角(°) × 细分数 / 360°
每毫米脉冲数 = 每转脉冲数 × 减速比 / 丝杆导程(mm)
例:步距角1.8°, 细分16, 减速比1:1, 导程5mm
→ 1.8×16/360 = 3200脉冲/转 → 3200/5 = 640脉冲/mm
雷赛卡支持 dmc_set_equiv(CardNo, axis, equiv) 设置脉冲当量(每脉冲对应的物理单位),设置后可使用 _unit 系列函数以物理单位操作。
2. 脉冲输出模式与驱动器握手
| outmode值 | 模式 | 说明 |
|---|---|---|
| 0 | 脉冲+方向 | 最常用,PULSE+DIR |
| 1 | 双脉冲 | CW正转+CCW反转 |
| 2 | AB相正交 | A相超前B相=正转 |
⚠️ 必须与驱动器接收模式一致 :
dmc_set_pulse_outmode的 outmode 值必须和驱动器参数设置的脉冲接收模式完全匹配。
3. 限位与原点IO极性配置
| 函数 | 作用 | 关键参数 |
|---|---|---|
dmc_set_el_mode |
硬限位配置 | el_enable, el_logic(0=常开/1=常闭), el_mode |
dmc_set_emg_mode |
急停信号配置 | enable, emg_logic |
dmc_set_home_pin_logic |
原点信号配置 | org_logic(0=低有效/1=高有效), filter(去抖时间) |
dmc_set_softlimit |
软限位配置 | enable, source_sel, SL_action, N_limit, P_limit |
⚠️ 极性不一致的后果:限位设为"常开"但实际接线为"常闭"→限位永远触发或永远不触发→撞机。
十二、异常处理与安全保护
1. 驱动器报警 vs 控制卡报警
| 报警来源 | 检测方式 | 处理方式 |
|---|---|---|
| 驱动器报警 | DI读取ALM信号 | 检查驱动器面板错误码,排除硬件故障 |
| 控制卡软限位触发 | 运动指令返回错误 | 调整软限位范围或清除状态 |
| 跟随误差超限 | 驱动器报警 | 检查机械阻力、降低速度、调整增益 |
2. 急停后恢复流程
cs
// 1. 立即停止所有轴
LTDMC.dmc_stop(cardNo, axis, 1); // stop_mode=1 立即停止(不减速)
// 2. 关闭使能
LTDMC.dmc_write_outbit(cardNo, servoOnBit, 0); // 关闭伺服ON
// 3. 排除故障后,清除报警
LTDMC.dmc_board_reset(); // 硬件复位(注意:会复位所有轴)
// 4. 重新初始化
LTDMC.dmc_board_init();
// 5. 重新使能
LTDMC.dmc_write_outbit(cardNo, servoOnBit, 1);
3. 软限位保护(第二道防线)
cs
// 设置软限位(在硬限位内侧留安全余量)
// dmc_set_softlimit(CardNo, axis, enable, source_sel, SL_action, N_limit, P_limit)
// source_sel: 0=指令位置, 1=编码器位置
// SL_action: 0=减速停止, 1=立即停止
LTDMC.dmc_set_softlimit(cardNo, axis, 1, 1, 0, -500, 99500);
// 编码器位置源, 减速停止, 负向-500, 正向99500
十三、常见问题排查
错误1:dmc_board_init返回0或负数
-
现象 :
dmc_board_init()返回 ≤0 -
原因:控制卡未插好、驱动未安装、或LTDMC.dll版本不匹配
-
解决:
-
检查设备管理器中是否有雷赛PCI设备
-
从雷赛官网下载对应型号驱动
-
确认LTDMC.dll与控制卡型号匹配(DMC3000/DMC5000/DMC5X10)
-
错误2:电机不转
-
现象 :
dmc_pmove调用返回0,但电机不动 -
原因:脉冲模式不匹配、驱动器未使能、或限位触发
-
解决:
-
检查
dmc_set_pulse_outmode设置是否与驱动器脉冲接收模式匹配 -
确认驱动器SERVO ON信号已给出:
dmc_write_outbit(cardNo, servoOnBit, 1) -
检查限位开关:
dmc_read_inbit(cardNo, limitBit)读取限位输入 -
检查
dmc_check_done返回值确认轴是否在运动中
-
错误3:运动抖动
-
现象:电机运动时有明显抖动或异响
-
原因:PID参数不合适、机械共振、信号干扰
-
解决:
-
降低加速度和运行速度测试
-
检查脉冲线是否有屏蔽层接地
-
在驱动器端调整增益参数
-
错误4:位置不准
-
现象:多次运动到同一位置,实际位置有偏差
-
原因:脉冲丢失、电子齿轮比错误、机械背隙
-
解决:
-
使用编码器闭环检查:对比
dmc_get_position和dmc_get_encoder -
检查丝杆导程、减速比计算是否正确
-
设置背隙补偿:
dmc_set_backlash_unit
-
总结
-
雷赛DMC控制卡通过
LTDMC.dll+LTDMC.cs(namespacecsLTDMC)提供完整C# API -
开发标准流程:
dmc_board_init→dmc_get_CardInfList→dmc_set_pulse_outmode→dmc_set_profile→dmc_pmove→dmc_check_done→dmc_board_close -
所有函数第一个参数为
CardNo(卡号),支持多卡系统 -
关键函数返回值差异 :
dmc_get_position/dmc_get_encoder/dmc_read_current_speed/dmc_read_inbit/dmc_read_inport/dmc_get_latch_value直接返回业务值,不是0=成功 -
圆弧插补函数必须用
_unit后缀版本(dmc_arc_move_center_unit/dmc_arc_move_radius_unit),原版不存在 -
脉冲当量换算必须代入全部因子,限位IO极性必须与硬件接线一致
-
生产项目必须配置软限位作为第二道防线,急停后按"停轴→关使能→排故障→复位→重新使能"流程恢复