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 { /// /// 膜位置检测; /// 通过辊接近开关,或者编码器2 /// public class FilmPositionDetect : IFilmPositionDetectService { #region 输入口定义 /// /// 纵向边界 /// const int InIdxOfVSensor = 12; /// /// 控制主轴脉冲启动计数 /// const int OutIdxOfPosition2OnOff = 3; /// /// 控制主轴脉冲启动计数输入, o3 接 i11; /// i11 为 0 计数停止 /// const int InIdxOfPosition2OnOff = 11; /// /// 辊速度 /// const int InIdxOfRound = 11; #endregion #region 状态 /// /// 纵向速度 m/min /// public double FilmVelocity { get; private set; } /// /// 纵向位置, m /// public double FilmPosition { get; private set; } /// /// 纵向位置偏移 m /// public double FilmOffset { get; private set; } /// /// 工作中 /// public bool IsRunning { get; private set; } = true; /// /// 当前正在使用的 与机头测厚仪偏移,单位m /// public double VDistanceWithHeaderInUsed { get; private set; } /// /// 当前正在使用的 激光探头与 X光的偏移,单位m /// public double VSensorOffsetInUsed { get; private set; } #endregion #region 参数 /// /// 线速度阀值,低于阀值,速度直接变为0 /// public double FilmVThreshold { get; set; } = 2; /// /// 线速度来源 /// public FilmVSRC FilmVSrc { get; set; } = FilmVSRC.ROUND; /// /// 线速度:编码器2 mm/pulse /// public double Encoder2_mmpp { get; set; } = 0.1; /// /// 线速度:1圈多少mm /// public double MmOfR { get; set; } = 377; /// /// 本测厚仪探头与机头测厚仪探头距离单位m /// 修改此值,会改变纵向偏移 /// public double VDistanceWithHeader { get; set; } = 0; /// /// 激光探头与 X光的偏移,单位m; /// 激光探头 为与 X光的后面, 为正数; /// 激光探头 为与 X光的前面, 为负数; /// 当主轴脉冲修正后, 当前轨迹 比 机头轨迹要滞后,应该增大VSensorOffset。增大指数值,如原来是-0.200m, 发现滞后了0.010m,那现在应该为 -0.190m; /// public double VSensorOffset { get; set; } = 0; #endregion /// /// /// public event PropertyChangedEventHandler PropertyChanged; /// /// 主轴激光传感器检测到 1->0 变化 事件 /// public event FilmPosAt01EventHandler FilmPosAt01Event; FlyAD7 flyAd; /// /// /// /// 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") { //TODO flyAd.Position2 处理溢出问题!!!!! double filmPos = Pos2ToFilmPos(flyAd.Position2); FilmPosition = filmPos + FilmOffset; } 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) PushFilmPosAt01(e.Position2); } } } void PushFilmPosAt01(int pos2) { double filmPos = Pos2ToFilmPos(pos2) + FilmOffset; //减去偏移 filmPos -= VSensorOffset; FilmPosAt01Event(this, new FilmPosAt01EventArgs() { filmPos = filmPos }); } /// /// 服务器 从 机头得到的 0->1 事件,给机尾 /// /// 极片位置m public void SetFilmPosAt01(double filmPos) { //加上偏移 filmPos += VSensorOffset; int pos2 = FilmPosToPos2(filmPos - FilmOffset); flyAd.SetPos2At01(pos2, false); } #region 辊信号生成 线速度 DispatcherTimer round_t; DateTime dtRound; int RCnt = 0; /// /// 使用辊速传感器时的位置基值 m /// 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 + FilmOffset; } } 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; double filmPosition = p1 + p2 + +BaseFilmPosition + FilmOffset; if (FilmPosition < filmPosition) FilmPosition = filmPosition; if (dtRound == DateTime.MinValue) { round_t.Stop(); return; } } #endregion /// /// 改变硬件测量值,从而设置膜位置为某值 /// /// 极片位置m public void ResetCore(double filmPosition) { double filmPosCore = filmPosition - FilmOffset; //TODO if (FilmVSrc == FilmVSRC.EN2) { int pos2 = (int)(filmPosCore * 1000.0 / Encoder2_mmpp); flyAd.Position2 = pos2; } else { RCnt = 0; BaseFilmPosition = filmPosCore; } FilmPosition = filmPosition; } /// /// 改变逻辑偏移量,从而设置膜位置为某值 /// /// public void ResetOffset(double filmPosition) { FilmOffset += (filmPosition - FilmPosition); } /// /// 把膜位置设置为 -VDistanceWithHeader, 且把逻辑偏移量复位为0 /// public void Reset() { FilmOffset = 0; ResetCore(-VDistanceWithHeader); } /// /// 设置逻辑偏移量 /// /// public void SetOffset(double filmOffset) { double offset = filmOffset - FilmOffset; FilmOffset = filmOffset; FilmPosition += offset; } int FilmPosToPos2(double filmPos) { return (int)(filmPos * 1000.0 / Encoder2_mmpp); } double Pos2ToFilmPos(int pos2) { return pos2 * Encoder2_mmpp / 1000.0; } /// /// 停止测量 /// public void Stop() { if (FilmVSrc == FilmVSRC.EN2) flyAd.SetOutputBit(OutIdxOfPosition2OnOff - 1, false); IsRunning = false; } /// /// 启动测量 /// public void Start() { if (FilmVSrc == FilmVSRC.EN2) flyAd.SetOutputBit(OutIdxOfPosition2OnOff - 1, true); IsRunning = true; } } }