简介:EzCad激光打标软件二次开发资料包面向激光加工设备集成商、自动化工程师及具备C++/C#基础的开发者,主要解决打标软件功能定制、产线自动对接与设备兼容扩展等实际问题,适合从入门到进阶的二次开发学习。包体内含EZCAD软件、EzCad2源码以及二次开发动态库MarkEzd.dll,并配套MFC_Test_3等示例工程,展示图形元素创建、激光运动路径控制、用户交互事件处理等核心开发流程;借助MarkEzd.dll导出的接口,开发者可编写自定义插件或独立应用程序,实现与EzCad的深层集成。资源共211个文件,压缩包约97.75MB,以dll、h、cpp、exe等工程文件为主,辅以bmp、ico、jsf、ini等界面与配置资源,整体接近EzCad实际工程目录,便于按模块对应查阅,源码和示例配合可缩短二次开发环境搭建与功能验证时间。当前已有2927人学习下载。若计划将EzCad集成进自动打标产线、定制图形处理算法、增强新型激光设备兼容性或优化操作界面,这套资料都能提供直接可参考的工程落地路径。 做激光加工设备集成的朋友,对EzCad这个名字一定不陌生。EzCad是激光打标控制领域非常常见的软件,很多打标机出厂都预装了它。平时用自带的界面做几个静态文件很容易,但一旦碰到“产品自动流转、扫码枪联动、MES下发工单”这类需求,就不得不走上二次开发这条路。所谓二次开发原件,指的不是EzCad的源码,而是官方提供的SDK开发包、动态库、头文件和示例代码。这篇分享基于我实际调试过的EzCad2.dll,讲讲怎么用这些原件搭一个能用的二次开发工程,适合刚接触上位机开发的集成商工程师,也适合自己折腾打标机的朋友。
1. 先搞清楚原厂SDK里到底有什么
1.1 原厂原件解压后是这些文件
打开SDK压缩包,第一眼看到的是EzCad2.dll、EzCad2.lib、EzCad2.h这几个文件。动态库是核心,所有打标功能都封装在DLL里;头文件是C/C++调用的说明书,里面声明了绝大多数接口;lib文件在编译链接时使用。除了C/C++版本,官方通常还会提供C#、VB等语言的封装文件,比如EzCad2.cs。Sample目录下的示例代码是最值钱的部分,我第一次调通就是在它的基础上改的。
这里提醒一句:拿到“原件”后先别急着写代码,第一个动作是打开头文件对照一下版本。EzCad2和EzCad3的接口差异很大,文件名虽然长得像,但函数返回类型和参数列表都不一样。版本选错,编译期就能报出几十条错误,白白浪费时间。
1.2 外部调用,而不是改源码
很多人第一次接触会问:能不能直接改EzCad主程序的源码,把打标按钮逻辑换掉?答案很现实:拿不到源码,也不建议这么做。原厂软件负责复杂的激光参数调优、振镜校正和系统配置,这些功能用界面操作已经非常成熟。二次开发更像是在旁边开一条控制通道:初始化设备、下发任务、执行打标、获取状态。
这种方式的最大好处是稳定。主程序升级后,只要DLL接口没变,我们自己的程序基本不用动。这一点上,EzCad二次开发跟UG二次开发、SolidWorks二次开发有明显差别。UG和SolidWorks有完整的API文档和插件扩展机制,可以深度嵌入宿主软件内部,修改模型、遍历特征,本质上是进程内的扩展。EzCad的调用则更轻量,多数情况下是外部程序通过DLL和它通信,两者适合的集成深度不同。理解这个区别,决定了你项目的整体架构。
1.3 二次开发能做到哪些事
从应用角度看,主要能覆盖这几类需求:
- 动态替换打标内容,比如日期、流水号、二维码里的工单号
- 加载EzCad设计好的模板文件,程序只负责替换字段和触发打标
- 通过串口、网口、IO信号触发打标,直接嵌入生产线
- 打标完成后返回状态,让上游设备知道“这个工件已经打完”
- 和MES、ERP对接,自动从数据库拿到参数再标刻
但也有做不了的事,比如直接修改EzCad界面上的控件、接管它内部的操作日志。这些活最好绕开,不要纠结。
2. 搭建开发环境与第一个工程
2.1 环境准备与版本核对
先装好EzCad主程序,版本最好和SDK一致。编译时注意位数,32位的DLL就用32位程序调用,64位同理。我踩过的一个坑是,在64位系统上强制编译成x64去调用32位DLL,运行时报“找不到指定的模块”,其实是位数不匹配。解决方案很简单,把工程平台改成x86,或者找对应的x64版本SDK。
驱动和加密狗也要提前装好、插好,否则初始化会失败。另外,最好用管理员权限运行开发环境,因为底层SDK有时需要访问驱动设备,权限不足会出现莫名其妙的状态码。
2.2 初始化与释放的标准流程
用C/C++写,第一步是引入头文件并链接库文件:
#include "EzCad2.h" #pragma comment(lib, "EzCad2.lib") int InitLaser() { int nRet = LMC_PI_Initialize(); if (nRet != 0) { TCHAR szMsg[256] = {0}; LMC_PI_GetErrorMsg(nRet, szMsg, 256); // 把错误信息写到日志里 return -1; } // 设置DPI,1000表示每毫米对应1000个像素点 LMC_PI_SetDPI(1000); return 0; } void ExitLaser() { LMC_PI_Stop(); LMC_PI_Close(); }LMC_PI_Initialize会扫描系统里的板卡并建立连接,程序退出前一定记得调用LMC_PI_Close释放资源。如果不释放,第二次运行很容易出现端口被占用或打标机无法恢复的卡死现象。这一步在开发阶段看不出来,到产线长时间运行时才暴露,所以一开始就要养成成对调用的习惯。
2.3 一个最简单的“打两个字”程序
初始化完成后的最小流程是清空、画文字、执行:
LMC_PI_Clear(); LMC_PI_Text(L"HELLO EZCAD"); LMC_PI_Execute(0);注意Execute是异步的,它只是下发任务,设备在后台执行。要等它真正打完,可以用循环查询工作状态,或者用原厂提供的事件接口。实际项目中我会优先用状态查询加超时控制,万一振镜卡住了,程序还能把设备Stop掉。很多新手第一次写到这里会疑惑:明明调用了Execute,程序也没报错,为什么工件上没字?多数情况是设备还在执行中,你立刻点了退出,任务被中止了。
3. 核心API拆解与常用功能代码
3.1 动态替换文本和二维码
产线需求里,流水号、日期、二维码内容基本都是实时变的。这里关键是拿到模板里某个对象的句柄,然后替换它的文本内容。示例代码如下:
LMC_PI_Clear(); long hText = LMC_PI_GetItemHandleByName(L"Text"); if (hText != 0) { LMC_PI_SetTextHandle(hText, L"SN: 1001"); } LMC_PI_Execute(0);这里有一个非常容易踩的坑:LMC_PI_GetItemHandleByName需要一个已经存在于当前文件里的对象名。很多新手在空文件里直接获取“Text”的句柄,结果返回0,下一步设置就失败了。正确做法是先加载一个设计好的模板文件,比如用LMC_PI_LoadFromFile打开EzCad工程文件,再拿句柄替换内容。模板里的参数、打标顺序、激光功率这些都在EzCad里调好,程序只负责改文本,这是最稳妥也最高效的工作模式。
如果是二维码,原理一样。在EzCad模板里放一个二维码对象并命名为“QRCode”,代码里获取句柄后调用对应设置内容的接口。函数名可能和你手头SDK版本略有差异,以头文件声明为准。
3.2 序列号递增怎么做
序列号有两种实现思路。一种是在EzCad软件里把对象属性设成“序列号”,设定起始值、步长和位数;另一种是外部程序自己维护流水号,把“SN-0001”这类字符串动态写进去。
我推荐第二种,因为流水号往往要和工单、日期、批次绑定,逻辑在业务侧更灵活。比如工单号加日期加三位顺序号,这个字符串在外部程序里拼好,再传给EzCad。这样打标软件只负责执行,出了问题也好排查,到底是内容算错了还是标刻没对准,一眼就能分清。
3.3 外部触发:PLC、扫码枪、MES联动
实际产线里,打标机很少是单独工作的。典型场景是:工件到位,传感器给PLC一个信号,PLC再触发打标程序,打完回到流水线。触发方式可以做成这样:
| 触发方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 串口指令 | 简单通用,开发量小 | 需要双方定义报文格式 | 扫码枪、单机工位 |
| IO输入信号 | 实时性好,可靠 | 需要硬件连线 | PLC产线集成 |
| TCP/UDP指令 | 跨设备,距离远 | 开发量稍大 | MES系统下发 |
我自己做那么多项目,最常用的是TCP。因为和MES对接时,网络最灵活,程序开一个Socket服务端,收到JSON格式的工单信息后解析出打标内容,再调用EzCad接口执行。调试时用网络调试助手发报文,上线后用MES自动下发,切换很平滑。
3.4 打标完成信号怎么给下游
打完一个工件,下游设备往往要等“完成信号”才继续动作。最简单的做法是Execute之后轮询工作状态,等状态空闲再返回。轮询间隔我一般控制在20到50毫秒,太短会多占CPU,太长影响节拍。
还有更稳的做法:把“打标完成”作为一条结果,通过网口或IO反馈给PLC。比如TCP给PLC发送一个“OK”指令,IO模式下拉高一个输出引脚。这样产线调度才有依据,节拍统计也更准确。
4. 常见问题与排查技巧实录
4.1 初始化失败先查这几样
初始化失败是出现频率最高的问题。我一般按这个顺序排查:
- EzCad主程序能不能正常打开,板卡驱动和加密狗是否就绪
- 确认程序编译位数和DLL位数一致,32位DLL不能被64位进程直接调用
- 对比SDK版本和当前安装的EzCad主程序版本
- 用管理员身份重新运行程序
这里面有一个容易忽略的点:如果电脑装了多个版本的EzCad驱动,初始化时SDK可能加载了错误的底层库。这时候最好把旧版本卸载干净,再重新安装和SDK配套的版本。
4.2 中文乱码的根源
C#里调用DLL踩过中文乱码的坑。DllImport默认按ANSI编码封送字符串,中文Windows下ANSI是GBK,大部分情况没问题,但如果工程源码保存为UTF-8,源字符串就是UTF-8,直接传进去就乱了。解决方法是统一编码。
C++里用L前缀写宽字符,C#里把CharSet改成CharSet.Auto,或者用MarshalAs手动指定字符串类型。调试时先打一个纯英文试试,能看出问题就在编码转换。切忌遇到乱码就反复换函数名,那不是接口问题,是数据编码问题。
4.3 打标位置不对、整体偏移
位置不对先查DPI。LMC_PI_SetDPI(1000)代表毫米到像素的换算比例,如果这个值设错,同样坐标画出来的图形会整体缩放,看似偏了,其实是坐标系没对齐。
另外,多文件切换时没有重新Clear,会把上一次残留对象一起打出来,出现“多打了不该有的东西”。所以每次加载新模板时,先Clear,再加载,再替换内容。顺序一定不能乱。
4.4 错误码速查逻辑
原厂SDK接口的返回值是错误码,数值含义以头文件里的宏定义为准。我常用的处理逻辑很简单:
| 错误码特征 | 可能原因 | 处理建议 |
|---|---|---|
| 初始化类 | 驱动、加密狗、版本不匹配 | 检查设备连接和位数 |
| 执行类 | 任务队列冲突、设备忙碌 | 先Stop清空再Execute |
| 参数类 | 坐标越界、DPI设置异常 | 对照EzCad主界面实际值核对 |
遇到不认识的错误码,别猜,直接调用LMC_PI_GetErrorMsg把描述取出来,写进日志。我在程序里做了一个通用的错误包装函数,接口返回值统一走这个函数,日志里有时间戳、函数名、错误码,排起查来效率高很多。
4.5 几条独家避坑经验
这一部分是在真实项目里用时间换来的,写在文档里不多,但很值钱:
- 尽量把EzCad相关调用封装成一个独立模块,提供DoMark(content, position)这类方法,上层业务不关心下位机细节
- 每次打标前验证模板文件是否存在、字段句柄是否有效,不要等到Execute才发现失败
- 设备断电重连问题在产线很常见,程序要能感知设备掉线,并在下次调用时自动重新初始化
- 加一个看门狗:Execute之后再启动一个超时定时器,超过设定时间还没打完就强制Stop,防止卡死影响整条线
5. 个人体会与后续扩展
最后说点个人感受。EzCad二次开发本身的代码量并不大,真正的复杂度在业务侧,比如怎么从ERP/MES取数、怎么处理重号预警、怎么配合视觉定位系统调整标刻坐标。我习惯的落地方式是:把EzCad相关代码做成独立模块,只暴露简单方法给上层调用。这样的话,后续加视觉重校准、自动对焦、多工位切换,都是在这个模块里局部改动,不会牵一发而动全身。
另外一个小建议:哪怕项目再急,也保留一个能单独运行的调试工具,输入文本、点击打标,用来验证设备和模板是否正常。这个工具在产线调试时能省很多事,也能把设备问题和业务问题快速分离开。等你做完三五个项目再回头看,会发现这个不起眼的调试工具,才是整个项目里性价比最高的一段代码。
本文还有配套的精品资源,点击获取