using System; using System.Collections.Concurrent; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using PaintDotNet.Base.SettingModel; namespace StageController { public class M3HController : AxisController { #region Com Connection private SerialPort m_serialPort; private string m_portName; private int m_baudRate; #endregion public override bool IsMoving => StateX > 1 || StateY > 1 || StateZ > 1; /// /// 等待平台停稳 /// public override void WaitMoveDone() { // Console.WriteLine(string.Format("{0} {1} {2}", StateX, StateY, StateZ)); do Thread.Sleep(30); while (IsMoving && IsOpen); Thread.Sleep(100); } public M3HController() : base() { m_cmdQueueM = new ConcurrentQueue(); CommandBase.AddReceivedHandle(typeof(CommandAllPosition), new Action(PositionUpdate)); CommandBase.AddReceivedHandle(typeof(CommandVersion), new Action(VersionUpdate)); } public override object LoadingStageModel { set { var m_loadingStageModel = value as LoadingStageModel; m_portName = m_loadingStageModel.BaseSetPort; m_baudRate = m_loadingStageModel.BaseSetBps; base.LoadingStageModel = value; m_workSpeedXY = m_loadingStageModel.items[m_loadingStageModel.WorkSpeedSelect].LSpeed; m_workSpeedZ = m_loadingStageModel.items[m_loadingStageModel.WorkSpeedSelect].ZSpeed; } } #region Open Close /// /// 平台是否正常开启 /// public override bool IsOpen { get => m_running; } public override string Version { get; internal set; } // TODO: 此函数测试期间使用 public override string Open() { try { if (!m_running) Open(m_portName, m_baudRate, Parity.None, 8, StopBits.One); return ""; } catch (Exception ex) { return ex.Message; } } public override void Open(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) { if (m_serialPort == null || !m_serialPort.IsOpen) { m_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits); m_serialPort.Encoding = Encoding.ASCII; m_serialPort.ReadTimeout = 500; m_serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived); m_serialPort.Open(); var cmd = new CommandGlobal(M3H.ControlType.F); cmd.Send(); Thread.Sleep(100); if (cmd.State == 1) throw new Exception("Connection Failed!"); CommandBase.SerialPort = m_serialPort; } if (!m_running) { m_cmdQueueM = new ConcurrentQueue(); m_curCommand = null; base.Open(); ResetParameter(); } } public override void Close() { if (IsOpen) { FreeStage(); FreeZ(); _closing = true; } } #endregion // 接收串口返回数据 private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { if (!m_running) return; string recvData = ((SerialPort)sender).ReadExisting(); m_curCommand.Receive(recvData); } #region Command Runtime private CommandBase m_curCommand = null; /// /// 发送试错次数 /// private int m_retryCount = 3; protected override void Process() { base.Process(); #region 执行当前指令 if (m_curCommand != null) { switch (m_curCommand.State) { case -1: //error:停止当前运动控制服务. if (m_curCommand.SendCount > m_retryCount) CommandError(); m_curCommand.Send(); return; case 1: //等待平台应答 if (m_curCommand.IsTimeout) { if (_timeoutTimes > 1) CommandTimeout(); m_curCommand = null; _timeoutTimes++; } break; case 2: //完成应答处理 m_curCommand = null; _timeoutTimes = 0; break; case 0: //初始值, 此处不应该出现0的情况 CommandError(); break; default: break; } } #endregion #region 开始一个新指令, if (m_curCommand == null) { if (m_cmdQueueM.IsEmpty && _closing) { m_running = false; _closing = false; return; } if (m_cmdQueueM.IsEmpty || !m_cmdQueueM.TryDequeue(out m_curCommand)) { // 空闲时间刷新位置 //m_curCommand = new CommandAllPosition(); } if (m_curCommand != null && !m_curCommand.Send()) { //指令发送失败 CommandError(); } } #endregion } protected override void CommandError() { Dispose(); base.CommandError(); } private void Dispose() { m_running = false; m_serialPort.Close(); m_curCommand = null; m_currentMoveflow?.Stop(); } int _timeoutTimes = 0; protected override void CommandTimeout() { Dispose(); base.CommandTimeout(); } public override void RefreshPosition() { if (m_cmdQueueM.Any(e => e is CommandAllPosition)) return; AddCommand(new CommandAllPosition()); } private void VersionUpdate(CommandBase cmd) { Version = (cmd as CommandVersion).Version; } #endregion #region Moveflow private bool IsSimulation = false; /// /// 平台中心位置 /// protected override int _centerX => 106500; /// /// 平台中心位置 /// protected override int _centerY => 73500; /// /// 正边界 /// const int LIMIT_P = (int)Border.F; private bool _closing; /// /// 开始中心移动流程 /// public override void ToCenter() { if (IsSimulation) return; base.ToCenter(); } protected override void ClearPosXY() { base.ClearPosXY(); AddCommand(new CommandAllPosition()); } /// /// 开始复位流程 /// public override void ResetStage(Action actDone) { if (IsSimulation)//模拟模式 { ClearPosXY(); actDone(); return; } new System.Threading.Tasks.Task(new Action(() => { while (m_cmdQueueM.Count > 0) { Thread.Sleep(100); } StartResetStage(actDone); })).Start(); } private void StartResetStage(Action actDone) { var mf = StartMoveflow(); mf.Add(() => { _LockStage(); }, null ); mf.Add(() => { this.Slide(AxisType.X, false); this.Slide(AxisType.Y, false); }, () => { RefreshPosition(); return IsLimitXY();// m_AxisX.Limit == LIMIT_N && m_AxisY.Limit == LIMIT_N; }); mf.Add(() => { ClearPosXY(); }, null); mf.Start(); mf.OnMoveflowDone += actDone; m_currentMoveflow = mf; } public override void ZScan(double start, double steplen, int times, Action shoot, Action package, Action actDone) { if (IsSimulation)//模拟模式 return; base.ZScan(start, steplen, times, shoot, package, actDone); } #endregion #region Speed int m_workSpeedXY; int m_workSpeedZ; public override void SetWorkspeedXY() { SetSpeedXY(m_workSpeedXY); SetSpeedZ(m_workSpeedZ); } #endregion public void ResetParameter() { AddCommand(new CommandAllPosition()); AddCommand(new CommandParameter() { AxisSelect = 'x' }); AddCommand(new CommandParameter() { AxisSelect = 'y' }); // AddCommand(new CommandParameter() { AxisSelect = 'z', LockOrFree = 'F' }); // z轴参数下发不识别 AddCommand(new CommandVersion()); } /// /// 拼图模式 /// public override void SetMergeMode(bool isMerge) { if (isMerge) AddCommand(new CommandGlobal(M3H.ControlType.P)); else AddCommand(new CommandGlobal(M3H.ControlType.Q)); } /// /// 启用/禁用摇杆 /// /// 摇杆可用 public override void SetRockerEnabel(bool isAvailable) { } } }