using MegaRobo.Connections; using MegaRobo.Connections.Adapters; using MegaRobo.Connections.Modbus; using MegaRobo.Connections.Sockets.Tcp; using MegaRobo.Contract; using MegaRobo.ControlDevices.Abstractions; using MegaRobo.Logger; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using static MegaRobo.Connections.Modbus.ModbusParams; namespace MegaRobo.C00225155.ControlDevices { /// /// 高温震荡电机驱动器控制服务 /// public class HighTemperatureMotorControlService : ConnectorBase { /// /// 寄存器地址枚举(十六进制转十进制,Modbus 需传入十进制地址) /// private enum MotorRegisterAddress : ushort { 启停控制 = 0x00, // 0x00(十进制0):启停控制 工作模式 = 0x02, // 0x02(十进制2):模式切换 速度指令 = 0x06, // 0x06(十进制6):速度指令 清除故障 = 0x4A, // 0x4A(十进制74):清除故障 驱动器状态 = 0xE3, // 0xE3(十进制227):驱动器状态 电机转速 = 0xE4 // 0xE4(十进制228):电机实际转速 } /// /// 写入数据枚举 /// private enum MotorWriteData : ushort { 停止 = 0x0000, // 启停控制:0=停止 启动 = 0x0001, // 启停控制:1=启动 速度模式 = 0x00C4, // 工作模式:0x00C4=速度模式 位置模式 = 0x00D0 // 工作模式:0x00D0=位置模式 } /// /// 驱动器状态位解析(对应 0xE3 寄存器的 bit 位) /// public class MotorState { public bool 运行状态 { get; set; } // bit0:0=停机,1=启动 public bool 过流故障 { get; set; } // bit1:1=故障 public bool 过压故障 { get; set; } // bit2:1=故障 public bool 编码器故障 { get; set; } // bit3:1=故障 public bool 位置偏差过大 { get; set; }// bit4:1=故障 public bool 欠压故障 { get; set; } // bit5:1=故障 public bool 过载故障 { get; set; } // bit6:1=故障 public bool 外部控制标志 { get; set; }// bit7:0=PC控制,1=PLC控制 public string 故障描述 { get; set; } // 汇总故障信息 } public override async Task Initialize(ICoreService coreService, params object[] args) { CoreService = coreService; try { base.CoreService = coreService; if (args is [IPEndPoint remoteHost, ..]) { base.ConnectorAdapter = new MegaTcpClient { Logger = coreService.Logger, Name = base.Name }; if (base.ConnectorAdapter != null) { base.ConnectorAdapter.DataReceived += ConnectorOnDataReceived; } ConnectionState = await base.ConnectorAdapter.ConnectAsync(remoteHost); } } catch (Exception ex) { Logger.LogException(ex); return await Task.FromResult(ex.Message); } return string.Empty; } private void ConnectorOnDataReceived(object sender, TcpMessage tcpMsg) { if (tcpMsg is null || tcpMsg.Data == null || tcpMsg.Data.Length == 0) return; string hexData = BitConverter.ToString(tcpMsg.Data).Replace("-", " "); Logger.LogInformation($"接收到电机驱动器数据(十六进制):{hexData}"); } public override Task ReconnectAsync() { return base.ReconnectAsync(); } public override async Task CheckConnected() { var state = ConnectionState.None; if (ConnectorAdapter is not null) { state = await ConnectorAdapter.CheckConnectedAsync(); } ConnectionState = state; return state; } /// /// 电机启停控制 /// /// 设备从站号 /// /// public async Task ControlMotorStartStop(byte id, bool isStart) { try { // 1. 确定写入数据:启动=0x0001,停止=0x0000 MotorWriteData writeData = isStart ? MotorWriteData.启动 : MotorWriteData.停止; // 2. 调用 Modbus 写单个寄存器(功能码06),地址=启停控制(0x00),字节顺序AB(高字节在前) var writeResult = ModbusRTU.WriteRegisterSingle( deviceAdress: id, // 从站地址(默认1) startAdress: (ushort)MotorRegisterAddress.启停控制, lstData: (ushort)writeData, byteOrder: ByteOrder.AB // 协议要求高字节在前 ); if (!writeResult.IsSuccessed) { Logger.LogError($"启停控制指令构建失败:{writeResult.Message}"); return false; } // 3. 发送指令并获取响应 var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5)); if (tcpMessage == null || tcpMessage.Data == null) { Logger.LogError("启停控制未收到响应"); return false; } // 4. 验证响应(协议要求写成功后返回原报文) bool isResponseMatch = CompareBytes(writeResult.Respond, tcpMessage.Data); if (!isResponseMatch) { Logger.LogError($"启停控制响应不匹配:发送={BitConverter.ToString(writeResult.Respond)}, 接收={BitConverter.ToString(tcpMessage.Data)}"); return false; } Logger.LogInformation($"{(isStart ? "启动" : "停止")}电机成功"); return true; } catch (Exception ex) { Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "ControlMotorStartStop", 150, false); return false; } } /// /// 设置电机速度(速度模式下) /// /// 设备从站号 /// 目标速度(0-3000 RPM,协议上限3000) public async Task SetMotorSpeed(byte id, int targetSpeed) { try { // 1. 参数校验:速度范围 0-3000 RPM(协议规定) if (targetSpeed < 0 || targetSpeed > 3000) { Logger.LogError($"速度值超出范围(0-3000 RPM):{targetSpeed}"); return false; } // 2. 切换到速度模式(必须先设置模式,再写速度) bool modeSuccess = await SwitchToSpeedMode(id); if (!modeSuccess) { Logger.LogError("切换速度模式失败,无法设置速度"); return false; } // 3. 计算速度指令值:写入值 = (目标速度 / 3000) * 8192(协议公式) ushort speedCommand = (ushort)Math.Round((targetSpeed / 3000.0) * 8192); Logger.LogInformation($"目标速度={targetSpeed} RPM,计算后指令值=0x{speedCommand:X4}"); // 4. 写速度指令到寄存器 0x06(功能码06) var writeResult = ModbusRTU.WriteRegisterSingle( deviceAdress: id, startAdress: (ushort)MotorRegisterAddress.速度指令, lstData: speedCommand, byteOrder: ByteOrder.AB // 高字节在前 ); if (!writeResult.IsSuccessed) { Logger.LogError($"速度指令构建失败:{writeResult.Message}"); return false; } // 5. 发送指令并验证响应 var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5)); if (tcpMessage == null || tcpMessage.Data == null) { Logger.LogError("设置速度未收到响应"); return false; } // 6. 验证响应(写成功返回原报文) bool isResponseMatch = CompareBytes(writeResult.Respond, tcpMessage.Data); if (!isResponseMatch) { Logger.LogError($"速度设置响应不匹配:发送={BitConverter.ToString(writeResult.Respond)}, 接收={BitConverter.ToString(tcpMessage.Data)}"); return false; } Logger.LogInformation($"设置电机速度成功:{targetSpeed} RPM(指令值=0x{speedCommand:X4})"); return true; } catch (Exception ex) { Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "SetMotorSpeed", 150, false); return false; } } /// /// 获取电机驱动器状态(运行状态+故障信息) /// /// 设备从站号 public async Task GetMotorState(byte id) { try { // 1. 构建读状态指令:地址0xE3(十进制227),读1个寄存器(状态是16位) var readResult = ModbusRTU.GetReadMessage( slaveStation: id, readType: ModbusReadCodes.READ_HOLDING_REGISTERS, // 功能码03 startAdr: (ushort)MotorRegisterAddress.驱动器状态, length: 1 // 状态寄存器是1个16位寄存器,长度=1 ); if (!readResult.IsSuccessed) { Logger.LogError($"读状态指令构建失败:{readResult.Message}"); return new MotorState { 故障描述 = "指令构建失败" }; } // 2. 发送指令并获取响应 var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(readResult.Respond, TimeSpan.FromSeconds(5)); if (tcpMessage == null || tcpMessage.Data == null) { Logger.LogError("读状态未收到响应"); return new MotorState { 故障描述 = "未收到响应" }; } // 3. 解析响应(16位状态字,字节顺序AB) var parseResult = ModbusRTU.ReadRegisterUShort(tcpMessage.Data, ByteOrder.AB); if (!parseResult.IsSuccessed) { Logger.LogError($"状态解析失败:{parseResult.Message}"); return new MotorState { 故障描述 = parseResult.Message }; } // 4. 解析状态字的各个bit位(协议表5-22) ushort statusWord = parseResult.Respond[0]; var motorState = new MotorState { 运行状态 = (statusWord & (1 << 0)) != 0, // bit0 过流故障 = (statusWord & (1 << 1)) != 0, // bit1 过压故障 = (statusWord & (1 << 2)) != 0, // bit2 编码器故障 = (statusWord & (1 << 3)) != 0, // bit3 位置偏差过大 = (statusWord & (1 << 4)) != 0,// bit4 欠压故障 = (statusWord & (1 << 5)) != 0, // bit5 过载故障 = (statusWord & (1 << 6)) != 0, // bit6 外部控制标志 = (statusWord & (1 << 7)) != 0 // bit7 }; // 5. 汇总故障描述 var errors = new List(); if (motorState.过流故障) errors.Add("过流"); if (motorState.过压故障) errors.Add("过压"); if (motorState.编码器故障) errors.Add("编码器故障"); if (motorState.位置偏差过大) errors.Add("位置偏差过大"); if (motorState.欠压故障) errors.Add("欠压"); if (motorState.过载故障) errors.Add("过载"); motorState.故障描述 = errors.Count > 0 ? $"故障:{string.Join("、", errors)}" : "无故障"; Logger.LogInformation($"电机状态:运行状态={(motorState.运行状态 ? "启动" : "停止")},{motorState.故障描述}"); return motorState; } catch (Exception ex) { Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "GetMotorState", 150, false); return new MotorState { 故障描述 = $"异常:{ex.Message}" }; } } /// /// 获取电机实际转速 /// /// 设备从站号 public async Task GetMotorActualSpeed(byte id) { try { // 1. 构建读转速指令:地址0xE4(十进制228),读1个寄存器 var readResult = ModbusRTU.GetReadMessage( slaveStation: id, readType: ModbusReadCodes.READ_HOLDING_REGISTERS, startAdr: (ushort)MotorRegisterAddress.电机转速, length: 1 ); if (!readResult.IsSuccessed) { Logger.LogError($"读转速指令构建失败:{readResult.Message}"); return -1; } // 2. 发送指令并获取响应 var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(readResult.Respond, TimeSpan.FromSeconds(5)); if (tcpMessage == null || tcpMessage.Data == null) { Logger.LogError("读转速未收到响应"); return -1; } // 3. 解析转速(16位无符号数,直接表示RPM) var parseResult = ModbusRTU.ReadRegisterUShort(tcpMessage.Data, ByteOrder.AB); if (!parseResult.IsSuccessed) { Logger.LogError($"转速解析失败:{parseResult.Message}"); return -1; } int actualSpeed = parseResult.Respond[0]; Logger.LogInformation($"电机实际转速:{actualSpeed} RPM"); return actualSpeed; } catch (Exception ex) { Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "GetMotorActualSpeed", 150, false); return -1; } } /// /// 清除电机故障 /// /// 设备从站号 /// public async Task ClearMotorFault(byte id) { try { // 协议规定:写入任意值到0x4A即可清除故障,此处写0x0000 var writeResult = ModbusRTU.WriteRegisterSingle( deviceAdress: id, startAdress: (ushort)MotorRegisterAddress.清除故障, lstData: (ushort)0x0000, byteOrder: ByteOrder.AB ); if (!writeResult.IsSuccessed) { Logger.LogError($"清除故障指令构建失败:{writeResult.Message}"); return false; } var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5)); if (tcpMessage == null || tcpMessage.Data == null) { Logger.LogError("清除故障未收到响应"); return false; } bool isResponseMatch = CompareBytes(writeResult.Respond, tcpMessage.Data); if (isResponseMatch) { Logger.LogInformation("清除电机故障成功"); return true; } else { Logger.LogError("清除故障响应不匹配"); return false; } } catch (Exception ex) { Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "ClearMotorFault", 150, false); return false; } } /// /// 切换到速度模式(内部调用,设置模式寄存器0x02为0x00C4) /// /// /// private async Task SwitchToSpeedMode(byte id) { var writeResult = ModbusRTU.WriteRegisterSingle( deviceAdress: id, startAdress: (ushort)MotorRegisterAddress.工作模式, lstData: (ushort)MotorWriteData.速度模式, byteOrder: ByteOrder.AB ); if (!writeResult.IsSuccessed) { Logger.LogError($"切换速度模式指令构建失败:{writeResult.Message}"); return false; } var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5)); if (tcpMessage == null || tcpMessage.Data == null) { Logger.LogError("切换速度模式未收到响应"); return false; } bool isMatch = CompareBytes(writeResult.Respond, tcpMessage.Data); if (isMatch) { Logger.LogInformation("切换到速度模式成功"); return true; } else { Logger.LogError("切换速度模式响应不匹配"); return false; } } /// /// 比较两个字节数组是否相等(验证响应报文) /// private bool CompareBytes(byte[] source, byte[] target) { if (source.Length != target.Length) return false; for (int i = 0; i < source.Length; i++) { if (source[i] != target[i]) return false; } return true; } } }