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

程序从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();
}








