FilmPositionDetect.cs 11.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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>
潘栩锋's avatar
潘栩锋 committed
16
    /// 膜位置检测;
17 18
    /// 通过辊接近开关,或者编码器2
    /// </summary>
19
    public class FilmPositionDetect : IFilmPositionDetectService
20
    {
潘栩锋's avatar
潘栩锋 committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
        #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 状态
42 43 44 45 46 47 48 49 50 51
        /// <summary>
        /// 线速度 m/min
        /// </summary>
        public double FilmVelocity { get; private set; }

        /// <summary>
        /// 膜位置, m
        /// </summary>
        public double FilmPosition { get; private set; }

潘栩锋's avatar
潘栩锋 committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
        /// <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 参数
74 75 76
        /// <summary>
        /// 线速度阀值,低于阀值,速度直接变为0
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
77
        public double FilmVThreshold { get; set; } = 2;
78 79 80 81

        /// <summary>
        /// 线速度来源
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
82
        public FilmVSRC FilmVSrc { get; set; } = FilmVSRC.ROUND;
83 84 85 86

        /// <summary>
        /// 线速度:编码器2 mm/pulse
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
87
        public double Encoder2_mmpp { get; set; } = 0.1;
88 89

        /// <summary>
潘栩锋's avatar
潘栩锋 committed
90
        /// 线速度:1圈多少mm
91
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
92
        public double MmOfR { get; set; } = 377;
93 94

        /// <summary>
潘栩锋's avatar
潘栩锋 committed
95 96
        /// 本测厚仪探头与机头测厚仪探头距离单位m
        /// 修改此值,会改变纵向偏移
97
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
98
        public double VDistanceWithHeader { get; set; } = 0;
99

潘栩锋's avatar
潘栩锋 committed
100 101 102 103 104 105 106 107 108 109 110 111
        /// <summary>
        /// 激光探头与 X光的偏移,单位m;
        /// 激光探头 为与 X光的后面, 为正数;
        /// 激光探头 为与 X光的前面, 为负数;
        /// 当主轴脉冲修正后, 当前轨迹 比 机头轨迹要滞后,应该增大VSensorOffset。增大指数值,如原来是-0.200m, 发现滞后了0.010m,那现在应该为 -0.190m;
        /// </summary>
        public double VSensorOffset { get; set; } = 0;

        #endregion
        /// <summary>
        /// 
        /// </summary>
112
        public event PropertyChangedEventHandler PropertyChanged;
潘栩锋's avatar
潘栩锋 committed
113 114 115 116
        /// <summary>
        /// 主轴激光传感器检测到 1->0 变化 事件
        /// </summary>
        public event FilmPosAt01EventHandler FilmPosAt01Event;
117

潘栩锋's avatar
潘栩锋 committed
118
        FlyAD7 flyAd;
119

潘栩锋's avatar
潘栩锋 committed
120 121 122 123 124
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flyAd"></param>
        public void Init(FlyAD7 flyAd)
125
        {
潘栩锋's avatar
潘栩锋 committed
126
            this.flyAd = flyAd;
127 128 129 130


            //------------------------------------------------------------------------------------------------------------------------------------
            //线速度------------------------------------------------------------------------------------------------------------------------------
潘栩锋's avatar
潘栩锋 committed
131
            this.flyAd.PropertyChanged += FlyAd_PropertyChanged;
132 133 134 135

            //------------------------------------------------------------------------------------------------------------------------------------
            //辊信号生成线速度-----------------------------------------------------------------------------------------------------------------------------
            InitRoundFilmVelocity();
潘栩锋's avatar
潘栩锋 committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

            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;

159
            if (e.PropertyName == nameof(flyAd.Speed2))
潘栩锋's avatar
潘栩锋 committed
160 161 162 163 164
            {
                double speed = Pos2ToFilmPos(flyAd.Speed2);// m/s
                speed *= 60;//m/min
                FilmVelocity = speed;
            }
165
            else if (e.PropertyName == nameof(flyAd.Position2))
潘栩锋's avatar
潘栩锋 committed
166 167 168 169
            {
                double filmPos = Pos2ToFilmPos(flyAd.Position2);
                FilmPosition = filmPos;
            }
170
            else if(e.PropertyName == nameof(flyAd.OStatus))
潘栩锋's avatar
潘栩锋 committed
171 172 173 174 175 176 177
            {
                updateIsRunning();
            }
        }

        private void FilmPositionDetect_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
178
            if (e.PropertyName == nameof(VDistanceWithHeader)) //滞后,应该增大
潘栩锋's avatar
潘栩锋 committed
179 180 181 182 183 184
            {
                int pos2 = FilmPosToPos2(VDistanceWithHeader - VDistanceWithHeaderInUsed);

                flyAd.SetPos2Offset(-pos2);//提前
                VDistanceWithHeaderInUsed = VDistanceWithHeader;
            }
185
            else if (e.PropertyName == nameof(VSensorOffset)) //滞后,应该增大
潘栩锋's avatar
潘栩锋 committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
            {
                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 });
                    }
                }
            }
208 209 210 211 212 213 214 215 216 217 218 219 220
        }

        #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);
潘栩锋's avatar
潘栩锋 committed
221
            flyAd.IStatusChangedEvent += mFlyAD_IStatusChangedEvent_round;
222 223 224 225 226 227 228 229
        }


        void mFlyAD_IStatusChangedEvent_round(object sender, IStatusChangedEventArgs e)
        {
            if (FilmVSrc != FilmVSRC.ROUND)
                return;

潘栩锋's avatar
潘栩锋 committed
230
            if (!Misc.MyBase.CHECKBIT(e.IChanged, InIdxOfRound - 1))
231 232
                return;
            
潘栩锋's avatar
潘栩锋 committed
233
            if (Misc.MyBase.CHECKBIT(e.IStatus, InIdxOfRound - 1))
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
                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++;
252
                    FilmPosition = RCnt * MmOfR / 1000.0 + BaseFilmPosition;
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
                }
            }

            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;
298
            if (p2 > MmOfR / 1000.0)
299 300 301 302 303 304 305 306 307 308 309
                p2 = MmOfR / 1000.0;
            p1 += p2;
            if (FilmPosition < p1)
                FilmPosition = p1;
            
            if (dtRound == DateTime.MinValue)
            {
                round_t.Stop();
                return;
            }
        }
310
         
311 312 313 314 315 316
        #endregion


        /// <summary>
        /// 设置膜位置为某值
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
317 318
        /// <param name="filmPos">极片位置m</param>
        public void Reset(double filmPos)
319 320 321
        {
            if (FilmVSrc == FilmVSRC.EN2)
            {
潘栩锋's avatar
潘栩锋 committed
322
                int pos2 = (int)(filmPos * 1000.0 / Encoder2_mmpp);
323
                flyAd.SetPos2(pos2);
324 325 326 327
            }
            else
            {
                RCnt = 0;
潘栩锋's avatar
潘栩锋 committed
328 329
                BaseFilmPosition = filmPos;
                FilmPosition = BaseFilmPosition;
330
            }
潘栩锋's avatar
潘栩锋 committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
            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;
387 388 389 390
        }
    }

}