# 概述
由于先前远程机器没有开机,不能进行调试硬件设备,无法进行灯光功能和警报器功能的开发调试,因此尝试使用本地串口设备模拟来进行协助相应开发调试。
# 报警器控制部分
根据报警器输入输出设备的硬件示意图和相关资料可以得知:
- 其输入输出模块使用了 Modbus 协议,使用读写寄存器来控制对应功能的信号;
- 该模块的输入端有三路接入了硬件设备,分别为红灯、绿灯、报警器;
- 该模块使用 USB 串口设备接入工控机,所以能通过设备管理器找出对应的串口号;
- 该模块的输出端输出一个信号
# 接入虚拟串口设备
根据以上信息,目前首先使用 Vitual Serial Port Driver 来创建虚拟串口连接

其中 COM2-COM3 COM4-COM5 COM6-COM7 分别为三组虚拟串口组用于模拟设备连接,分别对应两个灯光模组,一个报警器的输入输出模组.
# 虚拟 Modbus 从机设备
使用 Modbus Slave 来创建虚拟 Modbus 从设备,来模拟输入输出模块

# 寄存器定义
经过多次测试得知,该模块的寄存器如下:
保持寄存器 4 个,其地址定义为:
0: 绿灯; 1: 红灯; 2: 报警器;
对应的值为 1 时,对应的设备激活.

输入寄存器 1 个,其地址定义为:

0: 信号输入 (当换卷时会出现输入信号,值变为 1, 正常为 0)
代码实现部分使用 ModbusSerialMaster 模块来管理 Modubus 设备.
1
| ModbusSerialMaster master;
|
报警器功能实现,具体逻辑不在此赘述.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
console("Alarm start !", ConsoleColor.Red);
master.WriteSingleRegister(1, 0000, 0); master.WriteSingleRegister(1, 0001, 1); master.WriteSingleRegister(1, 0002, 1);
Thread.Sleep(Duration);
master.WriteSingleRegister(1, 0000, 1); master.WriteSingleRegister(1, 0001, 0); master.WriteSingleRegister(1, 0002, 0);
console("Alarm end !", ConsoleColor.Red);
|
经过测试发现 master.WriteMultipleRegistersAsync () 无效,只能使用 master.WriteSingleRegister () 逐个修改保持寄存器的值.
# 连接测试
在配置文件中将 AlarmPortName 修改到对应的串口 COM3,Modbus Slave 使用 COM2

启动 DebugConsole, 注意到输出串口打开成功

虚拟串口中可以看出,COM2 和 COM3 设备已经完成连接

Modbus 保持寄存器修改

当检测到瑕疵时,对应的寄存器值也被修改

手动修改输入寄存器值

成功触发换卷事件


# 灯光控制部分
# 协议封装
灯光控制模块的通信协议如图

根据协议进行封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public void sendCmd(byte command, byte port, int value) { byte[] senBuffer = new byte[8]; byte[] b_value = new byte[3]; byte[] b_check = new byte[2]; string str1 = value.ToString("X3"); b_value[0] = Convert.ToByte(str1[0]); b_value[1] = Convert.ToByte(str1[1]); b_value[2] = Convert.ToByte(str1[2]);
senBuffer[0] = 0x24; senBuffer[1] = Convert.ToByte(command + 48); senBuffer[2] = Convert.ToByte(port + 48); senBuffer[3] = b_value[0]; senBuffer[4] = b_value[1]; senBuffer[5] = b_value[2];
Check_Dell(ref senBuffer);
if (!serialPort.IsOpen) serialPort.Open(); if (busy) return; busy = true; Console.WriteLine($"port {serialPort.PortName} send cmd:{Encoding.ASCII.GetString(senBuffer)}"); serialPort.Write(Encoding.ASCII.GetString(senBuffer)); serialPort.Close(); busy = false;
}
void Check_Dell(ref byte[] buffer) { buffer[buffer.Length - 2] = 0; for (int i = 0; i < buffer.Length - 2; i++) { buffer[buffer.Length - 2] = Convert.ToByte(buffer[buffer.Length - 2] ^ buffer[i]); } buffer[buffer.Length - 1] = buffer[buffer.Length - 2]; buffer[buffer.Length - 2] >>= 4; buffer[buffer.Length - 1] &= 15; buffer[buffer.Length - 2] = Convert.ToByte(buffer[buffer.Length - 2].ToString("X1")[0]); buffer[buffer.Length - 1] = Convert.ToByte(buffer[buffer.Length - 1].ToString("X1")[0]); }
|
# 连接测试
使用串口调试器打开串口 COM5, 设置灯光控制模块串口为 COM4

测试串口发送消息
1
| lightA.Intensity(1,200);
|
在串口调试器中成功收到串口消息
