激光打标工位最要命的两种事故:一是打错——上位机换了工单,打标机里还躺着上一个型号的固定文本,整批件刻着别人的码;二是打重——打标软件里的静态计数器和上位机发码各走各的,同一张码刻在两件产品上。更隐蔽的是打标"成功"了但二维码浅得读不出,到了包装站才发现,工件已经流转了三站。激光打标对接的核心不是"让机器出光",而是内容由上位机唯一发放、打标结果必须读码回验、设备只负责执行不负责编号

一、什么时候必须上激光:贴标解决不了的四个场景

场景贴标签(ZPL,113篇)激光直接打标 DPM
金属/塑料件本体标识标签易翘起、油污环境脱落直接刻在零件上,与件同寿命
耐高温/后道热处理、喷涂标签过炉报废打标安排在热处理后或选用耐高温工艺,永久可读
防伪/防篡改标签可撕可换刻码无法无损移除,配合追溯防串货
小件/曲面/高速节拍贴标机构对小曲面适应性差振镜打标几百毫秒一件,二维码 3mm 也能刻

激光器按材质选:金属件主流光纤激光器(1064nm),有机塑料/木头/亚克力用 CO2(10.6μm),透明塑料/玻璃精细打白、食品包装冷打码用紫外(355nm,热影响区极小但贵)。选机器时把本厂实际材料样件寄给集成商打样并验读码等级,比看功率参数表靠谱得多。

二、系统构成与三种二次开发方式

一套激光打标设备 = 激光器 + 振镜扫描头 + 打标控制卡(插在工控机 PCIe 或以太网连接)+ 打标软件。国产打标卡九成以上是金橙子 EZCAD 生态,模板文件 .ezd 里画好固定文本、图形和命名的"可变文本对象"。上位机二次开发有三条路:

① 打标卡 SDK(推荐)

引用随卡 LMCardDll(x86/x64 必须与程序位数一致),P/Invoke 调初始化→加载 ezd→替换命名文本→打标。实时可控,能拿到完成/错误码,适合联机自动工位。

② 目录/文件监听

打标软件配置为监控某 txt 文件或串口,上位机只负责把 SN 写进文件。开发量最小但反馈弱,适合小厂半自动工位、不方便拿 SDK 的杂牌设备。

③ 智能一体机 TCP/串口

一体式激光机(基恩士/大族智能机等)自带命令协议,上位机走 TCP 或串口发文本与打标触发。不依赖板卡和驱动,部署最干净,但协议各厂家不通用。

// ===== 方式①:EZCAD2 打标卡 SDK 的 .NET 封装(32位典型声明)=====
// 注意:dll 必须与进程位数匹配(LMCardDll.dll=x86 / LMCardDll_x64.dll=x64),
//       且打标卡 SDK 通常只允许同机一个进程实例持有板卡。
public static class EzCadSdk
{
    private const string Dll = "LMCardDll.dll";

    [DllImport(Dll)] public static extern int LMCard_Initial();
    [DllImport(Dll)] public static extern int LMCard_CreateMark(ref int card);
    [DllImport(Dll)] public static extern int LMCard_DownLoadEzdb(int card,
        [MarshalAs(UnmanagedType.LPStr)] string ezdFile);
    [DllImport(Dll)] public static extern int LMCard_Mark(int card);
    [DllImport(Dll)] public static extern int LMCard_StopMark(int card);

    // 替换模板里命名的可变文本对象(不同SDK版本函数名/参数以随卡手册为准)
    [DllImport(Dll)] public static extern int LMCard_SetTextByName(int card,
        [MarshalAs(UnmanagedType.LPStr)] string objName,
        [MarshalAs(UnmanagedType.LPStr)] string text);
    [DllImport(Dll)] public static extern int LMCard_GetProgress(int card,
        ref int progress);
}

public class LaserMarker : IDisposable
{
    private int _card;
    public void Open(string templateEzd)
    {
        if (EzCadSdk.LMCard_Initial() != 0) throw new Exception("打标卡初始化失败:查驱动/加密狗/被其他进程占用");
        EzCadSdk.LMCard_CreateMark(ref _card);
        int rc = EzCadSdk.LMCard_DownLoadEzdb(_card, templateEzd);
        if (rc != 0) throw new FileNotFoundException("模板加载失败", templateEzd);
    }

    public bool Mark(string sn)
    {
        if (EzCadSdk.LMCard_SetTextByName(_card, "sn", sn) != 0) return false;
        if (EzCadSdk.LMCard_Mark(_card) != 0) return false;   // 同步返回,打标耗时约0.3~1s
        return true;
    }
    public void Dispose() => EzCadSdk.LMCard_StopMark(_card);
}
进场调试 SDK 的四个高频坑。① 位数不匹配直接 BadImageFormatException,x86 的 dll 配 x86 的工程;② 板卡驱动和 SDK 版本要配套,重装系统后先装驱动再插卡;③ 多数 SDK 调用是同步阻塞的,打标期间绝不能占用 UI 线程;④ SDK 函数随版本差异不小(替换文本有的版本用对象索引而非名称),以随卡手册为准,不要照搬网上旧例

三、打标闭环:到位→发码→打标→回验,五拍缺一不可

PLC / 工装
工件到位传感器 ON,夹紧到位,给上位机"允许打标"信号
收到上位机 OK 才放行/启动转盘;NG 则停在剔除位,禁止物理流出
上位机
向发码服务取预占 SN(号段方案见 113 篇),校验当前工单/型号,替换模板
读码器结果回传后比对:内容一致 + 码制正确 + 读码等级达标,写结果并回写 PLC
打标机 / 读码器
打标卡执行打标,完成回码;紧接着固定读码器触发拍照解码(成功/失败+内容+等级)
public class MarkService
{
    public async Task<MarkResult> MarkOneAsync(string workOrder, CancellationToken ct)
    {
        // ② 发码服务发号:数据库号段预占,保证全局唯一,绝不使用打标机自带计数器
        string sn = await _numberSvc.AllocateAsync(workOrder, ct);

        // ③ 替换模板内容并打标(在线程池执行,SDK是阻塞调用)
        bool fired = await Task.Run(() => _laser.Mark(sn), ct);
        if (!fired) return MarkResult.HardwareFail(sn);

        // ④ 读码回验:给固定读码器留出光时间,超时/不一致都判NG
        var read = await _reader.ReadOnceAsync(TimeSpan.FromSeconds(2), ct);
        if (read.Timeout) return await FailAsync(sn, "读码超时:码过浅或读码器位置偏移");
        if (read.Text != sn)    return await FailAsync(sn, "回验不一致:打标内容异常");
        if (read.Grade < Grade.B) return await FailAsync(sn, "读码等级低于B:标记质量退化");

        // ⑤ 成功:SN建档(与121篇首站激活同一动作),通知PLC放行
        await _trace.ActivateSnAsync(sn, workOrder, ct);
        _plc.Write("DB8.DBX0.1", true);
        return MarkResult.Ok(sn);
    }

    private async Task<MarkResult> FailAsync(string sn, string reason)
    {
        await _numberSvc.MarkFailedAsync(sn, reason);  // 该SN置"打标失败",不释放给第二件货重用
        _plc.Write("DB8.DBX0.2", true);              // NG剔除信号
        return MarkResult.Ng(sn, reason);
    }
}
"打标成功"不等于"标识可用",必须回验。激光器出光正常但内容缺失(模板文本对象名写错、字体被删)、二维码打出但静区被治具遮挡、焦距漂移导致码变浅——这些故障打标卡全部返回成功。固定读码器做内容回验是唯一可靠的闭环:读不到、内容不等、等级不够,一律 NG 剔除并报警,SN 标记失败后不允许复用。

四、方式②补充:目录监听怎么写才不丢单

// 打标软件监控某文件,上位机写文件触发打标。
// 必须用"临时文件+原子替换",否则打标软件可能读到写了一半的内容
private void PushSnByFile(string sn)
{
    var dir = @"D:\Laser\watch";
    var tmp = Path.Combine(dir, Guid.NewGuid().ToString("N") + ".tmp");
    var target = Path.Combine(dir, "markdata.txt");
    File.WriteAllText(tmp, sn + Environment.NewLine, Encoding.ASCII);
    File.Copy(tmp, target, overwrite: true);   // Copy/Move 是原子的,监听方不会读到半截
    File.Delete(tmp);
}

// 同时用 FileSystemWatcher 监听打标软件写出的完成回执文件;
// OnCreated 里加 200ms 重试打开,文件可能尚未 flush 完句柄。

目录方式拿不到结构化结果,回验仍需独立的读码器通道;它只解决"把内容送进去"。节拍快、要结果绑定的正规自动线,直接选方式①或③。

// 方式③:智能一体机 TCP 命令(各机协议不同,以下为典型"连接-发文本-触发"骨架)
public class IpLaserClient : IDisposable
{
    private TcpClient _tcp = new TcpClient();
    private NetworkStream _stream;

    public async Task ConnectAsync(string ip, int port, CancellationToken ct)
    {
        await _tcp.ConnectAsync(ip, port, ct);
        _stream = _tcp.GetStream();
        // 多数一体机要求先发"远程模式"使能命令,防止面板本地操作与上位机抢触发
        await SendAsync("REMOTE:ON\r\n", ct);
    }

    public async Task<bool> MarkAsync(string sn, CancellationToken ct)
    {
        await SendAsync($"TEXT:sn:{sn}\r\n", ct);   // 更新机内文本对象
        await SendAsync("MARK:START\r\n", ct);    // 触发出光
        string ack = await ReadLineAsync(TimeSpan.FromSeconds(3), ct);
        return ack.StartsWith("MARK:OK");             // 协议响应同样不能替代读码回验
    }
}
三种方式选型一句话:新线集成优先 ①SDK(可控性最强),标准智能整机选 ③TCP(部署最干净),只有改造老设备、拿不到开发资料时才退而用 ②文件监听。无论哪种,SN 发号与读码回验都必须在上位机侧独立完成,设备协议返回的"成功"只代表执行完,不代表码可读。

五、工艺参数与读码质量:软件管不了的部分要写进点检

参数/项目影响管控方式
功率/打标速度/频率/填充间距决定刻线深浅与对比度,参数组合按材料打样定模板参数随工艺版本保存,换型换模板,不允许工位私改
焦距偏焦最常见,码直接变浅读不出治具定位面统一高度,班前用首件读码等级点检
二维码尺寸/静区DPM 码建议 ≥4mm,四周留 ≥4 个模块静区模板评审时检查,治具压块不能伸进静区
读码等级按 ISO/IEC 15415(二维)分级 A~F关键工位 ≥B,回验结果里长期记录等级趋势,低于阈值提前清洁镜头/报修激光器
激光安全是硬红线。工位必须全封闭遮光(光纤激光为四类激光,反射散射都伤眼),安全门与激光使能硬联锁——门开着激光器物理上不能出光,这个联锁走安全继电器/PLC 安全回路,不要只在上位机软件里判断。配烟尘抽排(金属打标烟尘大),操作工戴对应波长防护眼镜只作辅助。

六、防重号与对账:设备计数永远只当旁证

  • SN 唯一来源是上位机发码服务:打标机内静态计数器、条码软件自带流水号全部禁用,避免两套号源并发产生重码(号段预占与防重见 113、121 两篇);
  • 打标失败的 SN 不复用:刻废的码号做"作废"留痕,下一件货发新号,防止"废件上的旧码"在系统里又被激活;
  • 班末三方对账:发码服务发出数 = 打标成功建档数 + 打废数;打标卡内部计数只作旁证参考,差异必须当班查清(常见是人工模式偷打或急停中断);
  • 急停恢复:打标中途急停后,当前 SN 状态未知,复位时该件强制走读码回验判定,读不到就按打废处理重发新号,绝不默认成功。

七、上线验收清单

  1. 内容唯一:连续打 100 件,SN 全部唯一且与发码记录逐条对平,打标机无自编号残留;
  2. 回验拦截:人为遮住打标区/调偏焦距制造废码,系统判 NG、剔除动作正确、PLC 不放行;
  3. 换型防错:切换工单后首件打标内容为新型号规则,旧模板不会被误用;模板名与工单版本绑定;
  4. 急停恢复:打标中拍急停,复位后该件走回验或作废重号,不产生"幽灵成功";
  5. 安全联锁:安全门打开时激光物理无法出光(硬线验证,不是看软件提示);
  6. 稳定性:连续运行一个班次无 SDK 崩溃/板卡掉线,读码等级记录无持续下滑,班末三方计数对平。

激光打标工位接好了,它就从一台"听人敲字的刻字机"变成追溯链上最可靠的起点:工单定型号、服务定号码、设备只执行、读码做裁判、PLC 管物理放行。每一件流出工位的产品,身上刻的码都经过了"发得对、刻得上、读得出、查得着"四重确认——后续条码追溯(121 篇)的所有价值,都从这一道闭环开始。