16 KiB
欧姆龙 PLC PCB 条码文件判定系统项目计划
1. 项目目标
开发一个 Windows WinForms 上位机程序,实现:
- 通过 FINS/TCP 与欧姆龙 PLC 通信。
- 等待 PLC 发出 PCB 到位信号。
- 同时触发两把 TCP Server 扫描枪。
- 两把扫描枪分别扫描 PCB 正面和反面,任意一把返回有效条码即可。
- 根据条码检查本地目录中的
<条码>.txt文件。 - 将检查结果返回 PLC。
- 通过 WinForms 界面显示 PLC、扫描枪、文件检查和当前任务状态。
- 对通信超时、断线、重复触发和异常情况进行处理并记录日志。
2. 当前需求基线
PLC 通信
| 项目 | 配置 |
|---|---|
| 协议 | Omron FINS/TCP |
| PLC IP | 192.168.2.100 |
| 端口 | 9600 |
| UnitAddress | 0 |
| SourceNodeAddress | 0 |
| EndianFormat | ABCD |
| PLC 区域 | D 区 |
PLC 点位
| 名称 | 地址 | 类型 | 初步用途 |
|---|---|---|---|
| PcbArrived | D101 | Bool | PCB 到位信号 |
| PlcReset | D102 | Bool | PLC 复位本轮流程 |
| PlcAckRelease | D103 | Bool | PLC 确认放行结果 |
| PcBusy | D51 | Bool | 上位机忙碌状态 |
| ReleasePermit | D52 | Bool | 是否允许放行 |
| ResultCode | D401 | Word | 扫描和文件检查结果 |
初版按 D 区字值 0/1 处理 Bool:
0 = False
1 = True
如果 PLC 实际使用 D101.00 这类 bit 位,需要在开发前调整 FINS 读写实现。
扫描枪
| 项目 | 扫描枪 1 | 扫描枪 2 |
|---|---|---|
| IP | 192.168.2.13 |
192.168.2.14 |
| 端口 | 2001 |
2001 |
| 设备角色 | PCB 正面 | PCB 反面 |
| 通信模式 | TCP Server | TCP Server |
| 上位机角色 | TCP Client | TCP Client |
| 触发指令 | T |
T |
| 返回结束符 | 无 | 无 |
| 超时时间 | 2000 ms | 2000 ms |
文件检查
根目录:D:\test
文件规则:D:\test\<条码>.txt
例如条码为:
PCB202608040001
检查文件:
D:\test\PCB202608040001.txt
3. 业务流程
flowchart TD
A["等待 D101 到位信号"] --> B{"D101 是否为 True"}
B -- 否 --> A
B -- 是 --> C["生成任务号并锁存本轮触发"]
C --> D["写入 D51 = 1,进入扫描中"]
D --> E["并行连接两把扫描枪并发送 T"]
E --> F{"是否收到有效条码"}
F -- 是 --> G["记录第一条有效条码"]
F -- 否且未超时 --> E
F -- 超时 --> H["写入扫描超时结果"]
G --> I["检查 D:\\test\\条码.txt"]
I --> J{"文件是否存在"}
J -- 是 --> K["D401 写入通过结果,D52 = 1"]
J -- 否 --> L["D401 写入不通过结果,D52 = 0"]
K --> M["等待 PLC 确认或复位"]
L --> M
H --> M
M --> N{"D102 PlcReset 是否为 True"}
N -- 否 --> M
N -- 是 --> O["清除 D51、D52 和本轮结果"]
O --> P["等待 D101 恢复 False"]
P --> A
4. 详细握手策略
等待到位
- 程序持续读取
D101。 D101=True时只创建一次任务。- 在本轮任务结束前,即使
D101一直保持 True,也不能重复触发扫描。 - 程序重启时,如果发现
D101已经为 True,默认不立即重复处理,等待 PLC 先复位到 False。
扫描阶段
- 设置
D51=1。 - 两把扫描枪并行发送
T。 - 任意一把返回非空条码后结束等待。
- 另一把扫描枪的迟到结果记录为本轮无效数据,不参与下一轮。
- 两把扫描枪都无返回时,2000 ms 后判定扫描超时。
文件判断阶段
- 对条码进行去除空白、长度检查和非法文件名字符检查。
- 禁止条码产生
..、路径分隔符或越过D:\test的路径。 - 使用精确路径检查
<根目录>\<条码>.txt。 - 文件存在即判定为允许放行。
- 文件不存在即判定为不允许放行。
结果保持阶段
D401结果写入后保持。- 文件存在时
D52=1。 - 文件不存在或扫描失败时
D52=0。 D51在本轮任务期间保持为 1。- 收到
D102=True后清除本轮输出。 D103用于记录 PLC 是否确认放行结果;其是否作为必须等待的条件,需要 PLC 程序最终确认。
5. 建议结果编码
结果编码必须最终与 PLC 程序确认,建议如下:
| ResultCode | 含义 |
|---|---|
| 0 | 空闲 |
| 1 | 扫描中 |
| 2 | 文件存在,允许放行 |
| 3 | 文件不存在,不允许放行 |
| 4 | 两把扫描枪均超时 |
| 5 | 扫描枪通信异常 |
| 6 | 条码为空或格式错误 |
| 7 | PLC 通信异常 |
| 8 | PLC 复位 |
| 9 | 系统异常 |
建议 ReleasePermit 只表达一个含义:
D52 = 1:允许放行
D52 = 0:不允许放行
具体 ResultCode 用于区分“不存在文件”“扫描超时”“通信异常”等原因。
6. 系统架构
建议采用分层结构:
src/
PcbCheck.Desktop/
PcbCheck.Application/
PcbCheck.Domain/
PcbCheck.Devices/
PcbCheck.Infrastructure/
tests/
PcbCheck.Tests/
PcbCheck.IntegrationTests/
docs/
architecture.md
plc-protocol.md
scanner-protocol.md
deployment.md
acceptance-checklist.md
PcbCheck.Desktop
负责:
- WinForms 窗体
- 当前状态显示
- 设备连接状态显示
- 当前条码显示
- 文件检查结果显示
- 任务耗时和最近结果显示
- 错误提示
- 手动连接、断开和复位操作
界面层不能直接拼装 FINS 报文或操作 TCP 流。
PcbCheck.Application
负责:
- PCB 检测流程编排
- PLC 到位触发处理
- 双扫描枪并行扫描
- 条码选择策略
- 文件检查调用
- PLC 结果写回
- 超时和异常状态处理
- 任务去重和复位控制
核心流程建议命名为:
PcbInspectionWorkflow
PcbCheck.Domain
负责:
- 任务状态
- 设备状态
- 扫描结果
- 文件检查结果
- PLC 结果编码
- 业务异常类型
该层不引用 WinForms、TCP、FINS、文件系统或第三方 SDK。
PcbCheck.Devices
负责:
- FINS/TCP PLC 客户端
- TCP 扫描枪客户端
- Fake PLC
- Fake 扫描枪
- 设备连接状态和重连机制
建议接口:
IFinsPlcClient
ITcpScannerClient
IIndustrialDevice
PcbCheck.Infrastructure
负责:
- 本地文件检查
- 配置加载
- 日志
- 任务记录
- 文件路径安全校验
- 系统时间和基础设施封装
7. 扫描枪无结束符处理方案
扫描枪返回不带结束符,不能简单地认为一次 TCP Receive 就是一条完整条码,因为 TCP 可能出现:
- 一条报文拆成多次接收;
- 多条报文合并接收;
- 返回后保持连接不断开。
因此开发前必须确认扫描枪的实际行为:
优先方案
扫描枪返回条码后主动关闭本次 TCP 连接。程序读取到连接关闭即认为一条数据完成。
备用方案
如果扫描枪保持长连接,则使用:
- 最大报文长度限制;
- 接收缓冲区;
- 字节间空闲超时;
- 2000 ms 总超时;
- 收到数据后短暂等待后判定报文结束。
该参数需要配置化,不能写死在界面代码中。
8. WinForms 界面计划
设备状态区
显示:
- PLC:已连接、连接中、断开、故障
- 扫描枪 1:已连接、断开、超时
- 扫描枪 2:已连接、断开、超时
- 本地目录:存在、不可访问
当前任务区
显示:
- 当前流程状态
- 当前任务号
- PCB 到位状态
- 当前条码
- 条码来源:正面/反面
- 文件完整路径
- 文件是否存在
- ResultCode
- ReleasePermit
- 本轮耗时
统计区
显示:
- 总扫描数
- 通过数量
- 不通过数量
- 扫描超时数量
- 扫描枪通信异常数量
- PLC 通信异常数量
- 最近一次任务时间
操作区
建议提供:
- 连接设备
- 断开设备
- 清除报警
- 手动复位
- 打开日志目录
- 打开文件根目录
- 进入配置页面
手动写 PLC 点位的功能应限制权限,避免普通操作员误操作生产信号。
9. 配置文件计划
所有通信参数和业务参数放入配置文件,不硬编码在程序中。
{
"Plc": {
"Host": "192.168.2.100",
"Port": 9600,
"UnitAddress": 0,
"SourceNodeAddress": 0,
"EndianFormat": "ABCD",
"MemoryArea": "D",
"Inputs": {
"PcbArrived": 101,
"PlcReset": 102,
"PlcAckRelease": 103
},
"Outputs": {
"PcBusy": 51,
"ReleasePermit": 52
},
"Registers": {
"ResultCode": 401
}
},
"Scanners": [
{
"Name": "FrontScanner",
"Host": "192.168.2.13",
"Port": 2001,
"Trigger": "T",
"TimeoutMs": 2000,
"Encoding": "ASCII"
},
{
"Name": "BackScanner",
"Host": "192.168.2.14",
"Port": 2001,
"Trigger": "T",
"TimeoutMs": 2000,
"Encoding": "ASCII"
}
],
"FileCheck": {
"RootPath": "D:\\test",
"FileNamePattern": "{Barcode}.txt",
"IgnoreCase": false
},
"Workflow": {
"WaitPlcReset": true,
"RequireReleaseAck": false,
"ClearResultAfterReset": true
}
}
RequireReleaseAck 在 PLC 握手确认后再决定是否启用,默认关闭。
10. 日志要求
每一轮 PCB 任务生成唯一任务号,日志至少记录:
- 任务号
- 开始时间和结束时间
- PLC 地址和读写结果
- 到位信号变化
- 两把扫描枪触发内容
- 两把扫描枪原始返回内容
- 选中的条码和来源设备
- 文件检查路径和结果
- ResultCode
- ReleasePermit
- PlcAckRelease
- PlcReset
- 每个步骤耗时
- 异常消息和通信错误
日志按日期滚动保存,例如:
logs\
2026-08-04\
application.log
communication.log
task.log
11. 异常和恢复策略
PLC 断线
- 状态显示为 PLC 断开。
- 停止触发扫描。
- 进入自动重连。
- 重连成功后重新读取当前状态。
- 不重复执行已经完成的任务。
扫描枪断线
- 单把扫描枪断线时,仍允许另一把扫描枪继续工作。
- 两把均断线时,任务判定为通信异常。
- 支持自动重连。
- 记录具体设备名称和异常原因。
PLC 到位信号长时间保持
- 通过任务状态和任务锁避免重复触发。
- 本轮流程未复位前不再次发送
T。 - 复位后要求
D101先恢复 False,再允许下一轮触发。
文件目录不可访问
- 不判定为普通“文件不存在”。
- 返回独立的系统异常码。
- 界面显示目录访问错误。
- 日志记录完整路径和系统异常。
程序重启
- 启动时先连接 PLC 和扫描枪。
- 如果
D101=True,默认等待 PLC 复位,不自动重扫。 - 如果存在上一次未完成任务,记录为中断任务,不自动伪造结果。
12. 开发阶段
阶段一:需求和协议确认
确认:
- D 区 Bool 是字值 0/1 还是 bit;
D103 PlcAckRelease的真实含义;D102 PlcReset的触发和清除时序;D401结果编码;- 扫描枪返回后是否断开 TCP;
- 扫描枪编码格式;
- 条码最大长度和合法字符;
- 两把枪同时返回时的处理规则。
交付物:
- PLC 点位表
- PLC 握手时序图
- 扫描枪报文说明
- 结果编码表
- 文件规则说明
阶段二:项目骨架
实现:
- WinForms 工程
- 分层项目结构
- 配置加载
- 日志系统
- 依赖注入
- 领域状态和结果模型
- 基础状态界面
阶段三:FINS/TCP 通信
实现:
- FINS/TCP 连接
- D 区 Bool 读取
- D 区 Bool 写入
- D401 结果写入
- 连接超时
- 读写超时
- 断线重连
- 原始通信日志
- Fake PLC 测试实现
阶段四:双扫描枪通信
实现:
- 两个 TCP Client
- 自动连接和重连
- 同时发送
T - 无结束符报文接收
- 2000 ms 超时
- 首个有效结果选择
- 空结果和异常处理
- Fake 扫描枪测试实现
阶段五:文件检查和流程编排
实现:
- 条码清洗
- 文件名安全校验
D:\test\<条码>.txt精确检查- PLC 信号与扫描枪流程串联
- 结果保持
- PLC 复位
- 任务去重
- 异常恢复
阶段六:WinForms 状态界面
实现:
- PLC 状态
- 两把扫描枪状态
- 文件目录状态
- 当前任务显示
- 结果和统计显示
- 日志查看入口
- 报警显示
- 手动复位和连接控制
阶段七:测试和交付
实现:
- 单元测试
- Fake 设备流程测试
- 通信异常测试
- 现场联调
- 发布包
- 配置模板
- 操作说明书
- 维护说明书
- 验收记录
13. 测试计划
单元测试
覆盖:
- ResultCode 映射
- 文件路径拼接
- 条码非法字符校验
- 文件存在和不存在
- D101 长保持防重复
- PLC 复位流程
- 扫描超时
- 首个有效条码选择
- 两把扫描枪同时返回
- 连接断开和重连
协议测试
覆盖:
- FINS/TCP 建连
- D 区读取
- D 区写入
- D401 数值写入
- ABCD 字节序
- 错误响应
- 超时响应
- PLC 断电重连
模拟流程测试
覆盖:
- 正常扫描,文件存在。
- 正常扫描,文件不存在。
- 正面扫描成功,反面无结果。
- 反面扫描成功,正面无结果。
- 两把均无结果。
- 一把断线,另一把成功。
- 两把均断线。
- D101 长时间保持 True。
- 扫描过程中收到 D102。
- PLC 结果确认。
- 程序重启时 D101 为 True。
- 文件目录不存在或无权限。
现场测试
硬件测试必须在现场或真实设备环境中执行,模拟测试不能替代现场验收。
现场至少验证:
- PLC 实际 IP 和 FINS 节点;
- D 区真实点位;
- 真实 Bool 表达方式;
- 真实扫描枪触发报文;
- 真实返回报文边界;
- 两把扫描枪同时触发;
- PLC 复位和放行确认;
- 连续生产 30~60 个 PCB 的稳定性。
14. 交付标准
满足以下条件才算完成:
- Release 构建成功。
- 单元测试全部通过。
- Fake PLC 和 Fake 扫描枪流程测试通过。
- 所有设备操作均有超时和取消机制。
- UI 线程无阻塞通信。
- PLC 断线能够显示并重连。
- 扫描枪断线能够显示并恢复。
- D101 长保持不会重复扫描。
- 文件检查路径不可越界。
- 结果能够正确保持和复位。
- 日志能够定位每一轮任务。
- 配置文件不包含硬编码生产密码。
- 完成真实 PLC、扫描枪和本地目录现场验收。
15. 预计开发周期
在 PLC 和扫描枪可及时提供测试的前提下:
| 阶段 | 预计时间 |
|---|---|
| 需求和协议确认 | 0.5~1 天 |
| 项目骨架和配置 | 0.5~1 天 |
| FINS/TCP 通信 | 1~2 天 |
| 双扫描枪通信 | 1~2 天 |
| 流程和文件判断 | 1 天 |
| WinForms 界面 | 1~2 天 |
| 测试和修复 | 1~2 天 |
| 现场联调 | 1~2 天 |
预计开发周期为 6~10 个工作日,现场联调时间取决于 PLC 点位、扫描枪协议和设备可用情况。
16. 当前开发门槛
正式编写现场通信代码前,必须最终确认:
- D101、D102、D103、D51、D52 是否使用 D 字的 0/1。
- 扫描枪返回后是否主动断开 TCP。
D401的正式结果编码。D103 PlcAckRelease的正式握手含义。- 文件不存在时是否直接结束,还是继续等待另一把扫描枪。
- PLC 程序是否要求
D51、D52和D401保持到D102复位。 - 真实条码编码和最大长度。
本计划采用设备接口隔离、后台异步通信、超时与重连、Fake 设备测试和真实设备验收分离的方式,便于先完成可测试的软件闭环,再进行现场通信确认。