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 // Modify by shayg 20220407 start // public override bool IsMoving => StateX > 1 || StateY > 1 || StateZ > 1 public override bool IsMoving { get { bool moving = StateX > 1 || StateY > 1 || StateZ > 1 || (LimitX == (int)Border.I && ExcessStepX > 0) || (LimitY == (int)Border.I && ExcessStepY > 0) || (LimitZ == (int)Border.I && ExcessStepZ > 0); //Logs.Write($"StageController.IsMoving={moving}, StateX={StateX}, StateY={StateY}, StateZ={StateZ}"); return moving; } } // Modify by shayg 20220407 end /// /// 等待平台停稳 /// public override void WaitMoveDone() { //Logs.Write("Wait Start..."); //Modify by shayg 20220413 start //do Thread.Sleep(30); //while (IsMoving && IsOpen) ; //Thread.Sleep(100); Thread.Sleep(120); while (IsMoving && IsOpen) { RefreshPosition(); Thread.Sleep(50); } //Logs.Write("Wait End..."); //Modify by shayg 20220413 end } 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 NeedSaveResetStageStatus { get => true; } public override bool FreeOrLockXYEnabled { get => true; } public override bool FreeOrLockZEnabled { get => true; } /// /// 平台是否正常开启 /// 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; //add begin by songxk if (sender == null) return; if (m_curCommand == null) return; //add end by songxk 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; //Add by shayg 20220615 start if (m_curCommand != null && m_curCommand is CommandAllPosition) return; //Add by shayg 20220615 end 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()); // removed begin by songxk 删除以下两行代码就可以使遥控和metis同时对载物台起作用 //AddCommand(new CommandParameter() { AxisSelect = 'x' }); //AddCommand(new CommandParameter() { AxisSelect = 'y' }); // removed end by songxk // 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) { } } }