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;
}
}
}