FilmPositionDetect.cs 11.5 KB
Newer Older
1 2 3
using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
using FlyADBase;
潘栩锋's avatar
潘栩锋 committed
4
using FObjBase;
5 6 7 8 9 10 11 12 13 14 15 16
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
17
    /// 膜位置检测;
潘栩锋's avatar
潘栩锋 committed
18 19
    /// 通过辊接近开关,或者编码器2;
    /// 可以用于2台测厚仪同步主轴位置
20
    /// </summary>
21
    public class FilmPositionDetect : IFilmPositionDetectService
22
    {
潘栩锋's avatar
潘栩锋 committed
23 24
        const int MARKNO_SYNC_HIGH = 1;
        public event PropertyChangedEventHandler PropertyChanged;
潘栩锋's avatar
潘栩锋 committed
25
        #region 状态
26 27 28 29 30 31 32 33 34 35
        /// <summary>
        /// 线速度 m/min
        /// </summary>
        public double FilmVelocity { get; private set; }

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

潘栩锋's avatar
潘栩锋 committed
36
        /// <summary>
潘栩锋's avatar
潘栩锋 committed
37
        /// 复位标识,从同步服务器发送过来的
潘栩锋's avatar
潘栩锋 committed
38
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
39
        public int ResetMark { get; private set; }
潘栩锋's avatar
潘栩锋 committed
40 41 42
        #endregion

        #region 参数
43 44 45
        /// <summary>
        /// 线速度阀值,低于阀值,速度直接变为0
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
46
        public double FilmVThreshold { get; set; } = 2;
47 48 49 50

        /// <summary>
        /// 线速度来源
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
51
        public FilmVSRC FilmVSrc { get; set; } = FilmVSRC.ROUND;
52 53 54 55

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

        /// <summary>
潘栩锋's avatar
潘栩锋 committed
59
        /// 线速度:1圈多少mm
60
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
61 62 63
        public double MmOfR { get; set; } = 314;

        #endregion
64 65


潘栩锋's avatar
潘栩锋 committed
66
        /// <summary>
潘栩锋's avatar
潘栩锋 committed
67 68 69
        /// 纵向光纤传感器检测到 0到1 变化 事件 
        /// 或
        /// sysTime同步信号触发 0到1 变化 事件 
潘栩锋's avatar
潘栩锋 committed
70
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
71 72
        public event EventHandler SysTimeFilmPosEvent;

潘栩锋's avatar
潘栩锋 committed
73 74 75 76

        /// <summary>
        /// 
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
77 78
        double reset_filmPos;

潘栩锋's avatar
潘栩锋 committed
79
        /// <summary>
潘栩锋's avatar
潘栩锋 committed
80
        /// 复位时,对应的pos2脉冲
潘栩锋's avatar
潘栩锋 committed
81
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
82
        int reset_pos2;
83

潘栩锋's avatar
潘栩锋 committed
84
        FlyAD7 flyAd;
85

潘栩锋's avatar
潘栩锋 committed
86 87 88 89 90
        /// <summary>
        /// 
        /// </summary>
        /// <param name="flyAd"></param>
        public void Init(FlyAD7 flyAd)
91
        {
潘栩锋's avatar
潘栩锋 committed
92
            this.flyAd = flyAd;
93 94 95 96


            //------------------------------------------------------------------------------------------------------------------------------------
            //线速度------------------------------------------------------------------------------------------------------------------------------
潘栩锋's avatar
潘栩锋 committed
97
            this.flyAd.PropertyChanged += FlyAd_PropertyChanged_EN2;
98 99 100 101

            //------------------------------------------------------------------------------------------------------------------------------------
            //辊信号生成线速度-----------------------------------------------------------------------------------------------------------------------------
            InitRoundFilmVelocity();
潘栩锋's avatar
潘栩锋 committed
102 103 104

            flyAd.IStatusChangedEvent += mFlyAD_IStatusChangedEvent;

潘栩锋's avatar
潘栩锋 committed
105 106
            //复位
            Misc.BindingOperations.SetBinding(this.flyAd, nameof(this.flyAd.IsReady), () =>
潘栩锋's avatar
潘栩锋 committed
107
            {
潘栩锋's avatar
潘栩锋 committed
108 109 110 111
                //刚连接上,复位
                ResetMark = 0;
                Reset(0);
            });
潘栩锋's avatar
潘栩锋 committed
112
        }
潘栩锋's avatar
潘栩锋 committed
113 114 115


        private void FlyAd_PropertyChanged_EN2(object sender, PropertyChangedEventArgs e)
潘栩锋's avatar
潘栩锋 committed
116 117 118 119
        {
            if (FilmVSrc != FilmVSRC.EN2)
                return;

120
            if (e.PropertyName == nameof(flyAd.Speed2))
潘栩锋's avatar
潘栩锋 committed
121
            {
潘栩锋's avatar
潘栩锋 committed
122
                double speed = flyAd.Speed2 * Encoder2_mmpp / 1000.0;// m/s
潘栩锋's avatar
潘栩锋 committed
123 124 125
                speed *= 60;//m/min
                FilmVelocity = speed;
            }
126
            else if (e.PropertyName == nameof(flyAd.Position2))
潘栩锋's avatar
潘栩锋 committed
127
            {
潘栩锋's avatar
潘栩锋 committed
128
                FilmPosition = Pos2ToFilmPos(flyAd.Position2);
潘栩锋's avatar
潘栩锋 committed
129 130 131
            }
        }

潘栩锋's avatar
潘栩锋 committed
132
        class DateTimeUnit
潘栩锋's avatar
潘栩锋 committed
133
        {
潘栩锋's avatar
潘栩锋 committed
134 135 136 137 138 139 140 141
            public DateTime dt { get; set; }
            public int data;
        }
        List<DateTimeUnit> pos2Pool = new List<DateTimeUnit>();
        void AddPos2(DateTime time, int pos2)
        {
            pos2Pool.Add(new DateTimeUnit() { dt = time, data = pos2 });
            if (pos2Pool.Last().dt - pos2Pool.First().dt > TimeSpan.FromMinutes(1))
潘栩锋's avatar
潘栩锋 committed
142
            {
潘栩锋's avatar
潘栩锋 committed
143
                pos2Pool.RemoveAt(0);
潘栩锋's avatar
潘栩锋 committed
144 145
            }
        }
潘栩锋's avatar
潘栩锋 committed
146 147 148 149 150 151 152 153 154
        bool FindPos2(DateTime time, out int pos2)
        {
            pos2 = 0;
            var unit = pos2Pool.Find(u => u.dt == time);
            if (unit == null)
                return false;
            pos2 = unit.data;
            return true;
        }
潘栩锋's avatar
潘栩锋 committed
155 156
        void mFlyAD_IStatusChangedEvent(object sender, IStatusChangedEventArgs e)
        {
潘栩锋's avatar
潘栩锋 committed
157
            if (Misc.MyBase.CHECKBIT(e.IChanged, FlyADIODefine.Instance.InNo_VSign))
潘栩锋's avatar
潘栩锋 committed
158
            {
潘栩锋's avatar
潘栩锋 committed
159
                if (Misc.MyBase.CHECKBIT(e.IStatus, FlyADIODefine.Instance.InNo_VSign))
潘栩锋's avatar
潘栩锋 committed
160
                {
潘栩锋's avatar
潘栩锋 committed
161
                    if (FilmVSrc == FilmVSRC.EN2)//不是用编码器, 纵向光纤也不会安装
潘栩锋's avatar
潘栩锋 committed
162
                    {
潘栩锋's avatar
潘栩锋 committed
163 164 165 166 167 168 169 170
                        SysTimeFilmPosEvent?.Invoke(this, new SysTimeFilmPosEventArgs()
                        {
                            IsSysTimeSync = false,
                            SysTime = e.Time,
                            FilmPos = Pos2ToFilmPos(e.Position2)
                        });

                        AddPos2(e.Time, e.Position2);
潘栩锋's avatar
潘栩锋 committed
171 172 173
                    }
                }
            }
潘栩锋's avatar
潘栩锋 committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
            else if (Misc.MyBase.CHECKBIT(e.IChanged, FlyADIODefine.Instance.InNo_Sync))
            {
                if (Misc.MyBase.CHECKBIT(e.IStatus, FlyADIODefine.Instance.InNo_Sync))
                {
                    if (FilmVSrc == FilmVSRC.EN2)
                    {
                        AddPos2(e.Time, e.Position2);
                        FilmPosition = Pos2ToFilmPos(e.Position2);
                    }

                    SysTimeFilmPosEvent?.Invoke(this, new SysTimeFilmPosEventArgs()
                    {
                        IsSysTimeSync = true,
                        SysTime = e.Time,
                        FilmPos = FilmPosition
                    });
                }
            }
192 193 194 195 196 197 198 199 200 201 202 203 204
        }

        #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
205
            flyAd.IStatusChangedEvent += mFlyAD_IStatusChangedEvent_round;
206 207 208 209 210 211 212 213
        }


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

潘栩锋's avatar
潘栩锋 committed
214
            if (!Misc.MyBase.CHECKBIT(e.IChanged, FlyADIODefine.Instance.InNo_Roll))
215
                return;
潘栩锋's avatar
潘栩锋 committed
216
            if (Misc.MyBase.CHECKBIT(e.IStatus, FlyADIODefine.Instance.InNo_Roll))
217
                return;
潘栩锋's avatar
潘栩锋 committed
218

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
            //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++;
235
                    FilmPosition = RCnt * MmOfR / 1000.0 + BaseFilmPosition;
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
                }
            }

            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
潘栩锋's avatar
潘栩锋 committed
263
            DateTime dt = flyAd.Now;
264 265 266 267 268
            if (dt <= dtRound)
                return;

            double v = MmOfR / 1000.0 / (dt - dtRound).TotalMinutes;

269 270 271 272
            if (v >= (FilmVelocity - 1))
                return;

            FilmVelocity = v;
潘栩锋's avatar
潘栩锋 committed
273 274


275 276
            double p1 = RCnt * MmOfR / 1000.0;
            double p2 = (dt - dtRound).TotalMinutes * FilmVelocity;
277
            if (p2 > MmOfR / 1000.0)
278 279 280 281
                p2 = MmOfR / 1000.0;
            p1 += p2;
            if (FilmPosition < p1)
                FilmPosition = p1;
潘栩锋's avatar
潘栩锋 committed
282 283 284


            if (FilmVelocity <= FilmVThreshold)
285
            {
潘栩锋's avatar
潘栩锋 committed
286 287
                dtRound = DateTime.MinValue;
                FilmVelocity = 0;
288 289 290 291
                round_t.Stop();
                return;
            }
        }
潘栩锋's avatar
潘栩锋 committed
292

293 294 295
        #endregion


潘栩锋's avatar
潘栩锋 committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313


        /// <summary>
        /// 让同步信号输出 1到0 1秒后, 0到1
        /// </summary>
        public void SyncSysTime()
        {
            flyAd.SetOutputBit(FlyADIODefine.Instance.OutNo_Sync, false);

            //1秒后,复位同步信号
            PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD,
                () => {
                    flyAd.SetOutputBit(FlyADIODefine.Instance.OutNo_Sync, true);
                },
                TimeSpan.FromSeconds(1), true, false, this, MARKNO_SYNC_HIGH, true);
        }


314 315 316
        /// <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 323
                reset_pos2 = flyAd.Position2;
                reset_filmPos = filmPos;
潘栩锋's avatar
潘栩锋 committed
324
                FilmPosition = Pos2ToFilmPos(flyAd.Position2);
325 326 327 328
            }
            else
            {
                RCnt = 0;
潘栩锋's avatar
潘栩锋 committed
329
                BaseFilmPosition = filmPos;
潘栩锋's avatar
潘栩锋 committed
330
                FilmPosition = filmPos;
331
            }
潘栩锋's avatar
潘栩锋 committed
332 333 334
        }

        /// <summary>
潘栩锋's avatar
潘栩锋 committed
335
        /// 设置膜位置为某值; 同步服务器调用的
潘栩锋's avatar
潘栩锋 committed
336 337
        /// </summary>
        /// <param name="filmPos">极片位置m</param>
潘栩锋's avatar
潘栩锋 committed
338 339 340
        /// <param name="sysTime">AD盒sysTime</param>
        /// <param name="resetMark">复位标识</param>
        public void Reset(double filmPos, DateTime sysTime, int resetMark)
潘栩锋's avatar
潘栩锋 committed
341
        {
潘栩锋's avatar
潘栩锋 committed
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
            ResetMark = resetMark;

            if (FilmVSrc == FilmVSRC.EN2)
            {
                reset_filmPos = filmPos;

                //找回 sysTime 时,对应的flyAd.Position2
                if (FindPos2(sysTime, out int pos2))
                {
                    reset_pos2 = pos2;
                }
                else
                {
                    reset_pos2 = flyAd.Position2;
                }
潘栩锋's avatar
潘栩锋 committed
357
                FilmPosition = Pos2ToFilmPos(flyAd.Position2);
潘栩锋's avatar
潘栩锋 committed
358 359 360 361 362
            }
            else
            {
                RCnt = 0;
                BaseFilmPosition = filmPos;
潘栩锋's avatar
潘栩锋 committed
363
                FilmPosition = filmPos;
潘栩锋's avatar
潘栩锋 committed
364
            }
潘栩锋's avatar
潘栩锋 committed
365
            
潘栩锋's avatar
潘栩锋 committed
366 367
        }

潘栩锋's avatar
潘栩锋 committed
368 369

        double Pos2ToFilmPos(int pos2)
潘栩锋's avatar
潘栩锋 committed
370
        {
潘栩锋's avatar
潘栩锋 committed
371 372 373 374 375 376 377 378 379 380 381 382 383
            int distance_p = pos2 - reset_pos2;

            double distance_m = distance_p * Encoder2_mmpp / 1000.0;

            double filmPos = distance_m + reset_filmPos;

            if (Math.Abs(distance_p) > 1000000)//不让它太大,不然乘法会溢出
            {
                //当距离很远,需要复位一下
                reset_pos2 = pos2;
                reset_filmPos = filmPos;
            }
            return filmPos;
384 385 386 387
        }
    }

}