using FLY.Thick.Base.Common; using FLY.Thick.Base.IService; using FlyADBase; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; namespace FLY.Thick.Base.Server { /// <summary> /// 膜位置检测; /// 通过辊接近开关,或者编码器2 /// </summary> public class FilmPositionDetect : IFilmPositionDetectService { #region 输入口定义 /// <summary> /// 纵向边界 /// </summary> const int InIdxOfVSensor = 12; /// <summary> /// 控制主轴脉冲启动计数 /// </summary> const int OutIdxOfPosition2OnOff = 3; /// <summary> /// 控制主轴脉冲启动计数输入, o3 接 i11; /// i11 为 0 计数停止 /// </summary> const int InIdxOfPosition2OnOff = 11; /// <summary> /// 辊速度 /// </summary> const int InIdxOfRound = 11; #endregion #region 状态 /// <summary> /// 线速度 m/min /// </summary> public double FilmVelocity { get; private set; } /// <summary> /// 膜位置, m /// </summary> public double FilmPosition { get; private set; } /// <summary> /// 工作中 /// </summary> public bool IsRunning { get; private set; } = true; /// <summary> /// 当前正在使用的 与机头测厚仪偏移,单位m /// </summary> public double VDistanceWithHeaderInUsed { get; private set; } /// <summary> /// 当前正在使用的 激光探头与 X光的偏移,单位m /// </summary> public double VSensorOffsetInUsed { get; private set; } /// <summary> /// 已经重新开始测量 /// </summary> public bool HasReset { get; private set; } #endregion #region 参数 /// <summary> /// 线速度阀值,低于阀值,速度直接变为0 /// </summary> public double FilmVThreshold { get; set; } = 2; /// <summary> /// 线速度来源 /// </summary> public FilmVSRC FilmVSrc { get; set; } = FilmVSRC.ROUND; /// <summary> /// 线速度:编码器2 mm/pulse /// </summary> public double Encoder2_mmpp { get; set; } = 0.1; /// <summary> /// 线速度:1圈多少mm /// </summary> public double MmOfR { get; set; } = 377; /// <summary> /// 本测厚仪探头与机头测厚仪探头距离单位m /// 修改此值,会改变纵向偏移 /// </summary> public double VDistanceWithHeader { get; set; } = 0; /// <summary> /// 激光探头与 X光的偏移,单位m; /// 激光探头 为与 X光的后面, 为正数; /// 激光探头 为与 X光的前面, 为负数; /// 当主轴脉冲修正后, 当前轨迹 比 机头轨迹要滞后,应该增大VSensorOffset。增大指数值,如原来是-0.200m, 发现滞后了0.010m,那现在应该为 -0.190m; /// </summary> public double VSensorOffset { get; set; } = 0; #endregion /// <summary> /// /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 主轴激光传感器检测到 1->0 变化 事件 /// </summary> public event FilmPosAt01EventHandler FilmPosAt01Event; FlyAD7 flyAd; /// <summary> /// /// </summary> /// <param name="flyAd"></param> public void Init(FlyAD7 flyAd) { this.flyAd = flyAd; //------------------------------------------------------------------------------------------------------------------------------------ //线速度------------------------------------------------------------------------------------------------------------------------------ this.flyAd.PropertyChanged += FlyAd_PropertyChanged; //------------------------------------------------------------------------------------------------------------------------------------ //辊信号生成线速度----------------------------------------------------------------------------------------------------------------------------- InitRoundFilmVelocity(); flyAd.IStatusChangedEvent += mFlyAD_IStatusChangedEvent; this.PropertyChanged += FilmPositionDetect_PropertyChanged; updateIsRunning(); VDistanceWithHeaderInUsed = VDistanceWithHeader; VSensorOffsetInUsed = VSensorOffset; } void updateIsRunning() { if (FilmVSrc == FilmVSRC.EN2) { IsRunning = Misc.MyBase.CHECKBIT(flyAd.OStatus, OutIdxOfPosition2OnOff - 1); } } private void FlyAd_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (FilmVSrc != FilmVSRC.EN2) return; if (e.PropertyName == "Speed2") { double speed = Pos2ToFilmPos(flyAd.Speed2);// m/s speed *= 60;//m/min FilmVelocity = speed; } else if (e.PropertyName == "Position2") { double filmPos = Pos2ToFilmPos(flyAd.Position2); FilmPosition = filmPos; } else if(e.PropertyName == "OStatus") { updateIsRunning(); } } private void FilmPositionDetect_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "VDistanceWithHeader") //滞后,应该增大 { int pos2 = FilmPosToPos2(VDistanceWithHeader - VDistanceWithHeaderInUsed); flyAd.SetPos2Offset(-pos2);//提前 VDistanceWithHeaderInUsed = VDistanceWithHeader; } else if (e.PropertyName == "VSensorOffset") //滞后,应该增大 { int pos2 = FilmPosToPos2(VSensorOffset - VSensorOffsetInUsed); flyAd.SetPos2Offset(pos2);//提前 VSensorOffsetInUsed = VSensorOffset; } } void mFlyAD_IStatusChangedEvent(object sender, IStatusChangedEventArgs e) { if (Misc.MyBase.CHECKBIT(e.IChanged, InIdxOfVSensor - 1)) { if (Misc.MyBase.CHECKBIT(e.IStatus, InIdxOfVSensor - 1)) { if (FilmPosAt01Event != null) { //减去偏移 double filmPos = Pos2ToFilmPos(e.Position2); filmPos -= VSensorOffset; FilmPosAt01Event(this, new FilmPosAt01EventArgs() { filmPos = filmPos }); } } } } #region 辊信号生成 线速度 DispatcherTimer round_t; DateTime dtRound; int RCnt = 0; double BaseFilmPosition = 0; void InitRoundFilmVelocity() { round_t = new DispatcherTimer(); round_t.Interval = TimeSpan.FromSeconds(1); round_t.Tick += new EventHandler(round_t_Tick); flyAd.IStatusChangedEvent += mFlyAD_IStatusChangedEvent_round; } void mFlyAD_IStatusChangedEvent_round(object sender, IStatusChangedEventArgs e) { if (FilmVSrc != FilmVSRC.ROUND) return; if (!Misc.MyBase.CHECKBIT(e.IChanged, InIdxOfRound - 1)) return; if (Misc.MyBase.CHECKBIT(e.IStatus, InIdxOfRound - 1)) return; //1->0 DateTime dt = e.Time; if (dt <= dtRound) return; if (dtRound != DateTime.MinValue) { double v = MmOfR / 1000.0 / (dt - dtRound).TotalMinutes; if (v < 2)//太慢了 { dt = DateTime.MinValue; v = 0; } FilmVelocity = v; if (v > 0) { RCnt++; FilmPosition = RCnt * MmOfR / 1000.0 + BaseFilmPosition; } } dtRound = dt; if (dtRound != DateTime.MinValue) { if (!round_t.IsEnabled) round_t.Start(); } } void round_t_Tick(object sender, EventArgs e) { if (FilmVSrc != FilmVSRC.ROUND) { round_t.Stop(); return; } if (dtRound == DateTime.MinValue) { round_t.Stop(); return; } //1->0 DateTime dt = DateTime.Now; if (dt <= dtRound) return; double v = MmOfR / 1000.0 / (dt - dtRound).TotalMinutes; if (v < (FilmVelocity - 1)) { if (v < 2) { dtRound = DateTime.MinValue; v = 0; } FilmVelocity = v; } double p1 = RCnt * MmOfR / 1000.0; double p2 = (dt - dtRound).TotalMinutes * FilmVelocity; if (p2 > MmOfR / 1000.0) p2 = MmOfR / 1000.0; p1 += p2; if (FilmPosition < p1) FilmPosition = p1; if (dtRound == DateTime.MinValue) { round_t.Stop(); return; } } #endregion /// <summary> /// 设置膜位置为某值 /// </summary> /// <param name="filmPos">极片位置m</param> public void Reset(double filmPos) { if (FilmVSrc == FilmVSRC.EN2) { int pos2 = (int)(filmPos * 1000.0 / Encoder2_mmpp); flyAd.Position2 = pos2; } else { RCnt = 0; BaseFilmPosition = filmPos; FilmPosition = BaseFilmPosition; } HasReset = true; } /// <summary> /// 把膜位置设置为 -VDistanceWithHeader /// </summary> public void Reset() { Reset(-VDistanceWithHeader); } /// <summary> /// 清除 hasReset标志位 /// </summary> public void ClearResetState() { HasReset = false; } /// <summary> /// 服务器 从 机头得到的 0->1 事件,给机尾 /// </summary> /// <param name="filmPos">极片位置m</param> public void SetFilmPosAt01(double filmPos) { //加上偏移 filmPos += VSensorOffset; int pos2 = FilmPosToPos2(filmPos); flyAd.SetPos2At01(pos2, false); } int FilmPosToPos2(double filmPos) { return (int)(filmPos * 1000.0 / Encoder2_mmpp); } double Pos2ToFilmPos(int pos2) { return pos2 * Encoder2_mmpp / 1000.0; } /// <summary> /// 停止测量 /// </summary> public void Stop() { if (FilmVSrc == FilmVSRC.EN2) flyAd.SetOutputBit(OutIdxOfPosition2OnOff - 1, false); IsRunning = false; } /// <summary> /// 启动测量 /// </summary> public void Start() { if (FilmVSrc == FilmVSRC.EN2) flyAd.SetOutputBit(OutIdxOfPosition2OnOff - 1, true); IsRunning = true; } } }