汇川PLC数据采集集成阿标标签实现贴标打印

二次开发 admin 2026-09-10 13:33 53 0

image.png

程序从PLC用MODBUS协议读取称重数据,调试过程发现一个奇怪问题。就是读到的重量有时正确,有时会有一点误差,一般都是小数点的问题。总结是精度问题。

读取PLC重量数据时,数值存在偏差。例如实际18.1kg,程序显示18.0kg,差100克。


## 测试数据


| 实际值        | 程序读到  | 偏差   |

|---------------|-----------|--------|

| 18.1          | 18.0      | -0.1   |

| 12.75         | 12.75     | 0      |

| 17.979998     | 17.88     | -0.105 |


## 原因分析


18.1 的 IEEE 754 浮点表示:0x4190CCCD

- 高16位(D1801)= 0x4190

- 低16位(D1800)= 0xCCCD


错误配置:

- 地址 41802(D1801)→ 读偏了1个寄存器

- 字节序 ABCD → 与PLC实际的CDAB不匹配


两个错误叠加导致:

- 只读到高16位 0x4190

- 低16位变成 0x0000

- 解码结果丢失了低16位的数据


12.75 读对是因为低16位恰好是 0x0000(巧合)。


## 解决方案


修改 AppConfig.json:

- WeightRegisterAddress: 41801(原来41802)

- WeightByteOrder: CDAB(原来ABCD)


示例:

{

  "Plc": {

    "IpAddress": "192.168.10.150",

    "Port": 502,

    "SlaveId": 1,

    "WeightRegisterAddress": 41801,

    "BarcodeRegisterStart": 40551,

    "BarcodeRegisterLength": 20,

    "ProductCounterRegisterAddress": 40501,

    "ResultSequenceRegisterAddress": 40504,

    "ResultStatusRegisterAddress": 40506,

    "BarcodeByteOrder": "HighByteFirst",

    "WeightByteOrder": "CDAB"

  },

阿标SDK打印部分代码:


    // ══════════════════════════════════════════════════
    //  GDI 打印(本机驱动)
    // ══════════════════════════════════════════════════
    private async System.Threading.Tasks.Task RunPrint(bool useGdi)
    {
        if (_templatePath == null || !File.Exists(_templatePath))
        {
            Log("未选择模板,自动生成测试模板...");
            GenerateTestTemplate();
        }

        BtnRun.IsEnabled = false;
        BtnPrintGfa.IsEnabled = false;
        BtnSelect.IsEnabled = false;
        _sb.Clear();
        LogBox.Text = "";

        var totalSw = Stopwatch.StartNew();

        try
        {
            Log("=== GDI 打印 ===");
            Log($"模板: {Path.GetFileName(_templatePath)}");
            Log("");

            var sw = Stopwatch.StartNew();
            var engine = new LabelEngine();
            engine.LoadTemplate(_templatePath);
            sw.Stop();
            Log($"[1] 加载模板: {engine.Components.Count} 组件, {sw.Elapsed.TotalMilliseconds:F2}ms");

            var variables = GetVariables();
            sw.Restart();
            engine.SetData(variables);
            sw.Stop();
            Log($"[2] 写入变量: {sw.Elapsed.TotalMilliseconds:F2}ms");

            string printer = CmbPrinter.SelectedItem as string ?? "";
            if (string.IsNullOrEmpty(printer))
            {
                Log("未选择打印机");
            }
            else
            {
                Log($"[3] GDI 打印 → {printer}");
                sw.Restart();
                engine.OnPrintMessage += msg => Log($"    {msg}");
                bool ok = await engine.PrintWithGdiAsync(printer, copies: 1, showDialog: false);
                sw.Stop();
                Log($"    {(ok ? "成功" : "失败")}, {sw.Elapsed.TotalMilliseconds:F2}ms");
            }
        }
        catch (Exception ex) { Log($"异常: {ex.Message}"); }

        totalSw.Stop();
        Log($"总耗时: {totalSw.Elapsed.TotalMilliseconds:F2}ms");
        ResetButtons();
    }

    // ══════════════════════════════════════════════════
    //  ZPL 打印(GFA 不压缩)
    // ══════════════════════════════════════════════════
    private async System.Threading.Tasks.Task RunPrintZpl(bool useZ64)
    {
        if (_templatePath == null || !File.Exists(_templatePath))
        {
            Log("未选择模板,自动生成测试模板...");
            GenerateTestTemplate();
        }

        string printer = CmbPrinter.SelectedItem as string ?? "";
        if (string.IsNullOrEmpty(printer))
        {
            Log("未选择打印机");
            return;
        }

        BtnRun.IsEnabled = false;
        BtnPrintGfa.IsEnabled = false;
        BtnPrintZ64.IsEnabled = false;
        BtnSelect.IsEnabled = false;
        _sb.Clear();
        LogBox.Text = "";

        var totalSw = Stopwatch.StartNew();

        try
        {
            string mode = useZ64 ? "Z64 压缩" : "ASCII hex 不压缩";
            Log($"=== ZPL 打印: {mode} ===");
            Log($"模板: {Path.GetFileName(_templatePath)}");

            var engine = new LabelEngine();
            engine.LoadTemplate(_templatePath);

            var variables = GetVariables();
            engine.SetData(variables);

            var sw = Stopwatch.StartNew();
            ZplChineseService.UseZ64 = useZ64;
            var zpl = engine.GenerateZPL();
            sw.Stop();
            Log($"ZPL 生成: {sw.Elapsed.TotalMilliseconds:F2}ms");
            Log($"ZPL 长度: {zpl?.Length ?? 0} 字节");
            Log($"打印机: {printer}");
            Log("");
            Log($"=== ZPL 代码 ({mode}) ===");
            Log(zpl ?? "(空)");
            Log("=== 发送打印 ===");
            sw.Restart();
            var svc = new PrintService { PrinterName = printer };
            bool ok = await svc.PrintRawZPLAsync(zpl);
            sw.Stop();
            Log(ok ? "打印成功" : "打印失败");
            Log($"耗时: {sw.Elapsed.TotalMilliseconds:F2}ms");
        }
        catch (Exception ex) { Log($"异常: {ex.Message}"); }

        totalSw.Stop();
        Log($"总耗时: {totalSw.Elapsed.TotalMilliseconds:F2}ms");
        ResetButtons();
    }


评论区

搜索