Commit c87c3df7 authored by 潘栩锋's avatar 潘栩锋 🚴

添加 加热PLC控制精度提升到0.1%

添加 中心偏厚控制
parent 2caca8bf
......@@ -323,10 +323,10 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
CallDiffResult result = new CallDiffResult();
double[] thickpercents0 = ucThickHeatVms[0].GetThickPercents(boltmap, uniformShrinkPercent);
int[] heats0 = ucThickHeatVms[0].GetHeats();
double[] heats0 = ucThickHeatVms[0].GetHeats();
double[] thickpercents1 = ucThickHeatVms[1].GetThickPercents(boltmap, uniformShrinkPercent);
int[] heats1 = ucThickHeatVms[1].GetHeats();
double[] heats1 = ucThickHeatVms[1].GetHeats();
int channelCnt = feedback.ChannelCnt;
......
......@@ -34,7 +34,7 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
/// 厚度%
/// </summary>
public ChartValues<double> ThickPercents { get; } = new ChartValues<double>();
public ChartValues<int> Heats { get; } = new ChartValues<int>();
public ChartValues<double> Heats { get; } = new ChartValues<double>();
public double Kp { get; set; } = 3;
public int MaxHeat { get; set; } = 100;
......@@ -384,7 +384,7 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
//return GetThickPercents(frame.BoltMapInfo.UniformShrinkPercent, frame.BoltMapInfo.MidOffset, frame.Boltmap);
return GetThickPercents(frame.Boltmap, frame.BoltMapInfo.UniformShrinkPercent);
}
public int[] GetHeats()
public double[] GetHeats()
{
return frame.Heats.ToArray();
}
......
......@@ -33,7 +33,7 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
int kp = 3;
int[] heats = new int[nbolts];
double[] heats = new double[nbolts];
for (int i = 0; i < nbolts; i++)
{
heats[i] = (int)((Math.Sin(i * Math.PI / nbolts)) * 20 + 30 + (random.NextDouble() - 0.5) * 5);
......
......@@ -55,17 +55,24 @@
<StackPanel Margin="{StaticResource ControlMargin}">
<TextBlock Style="{StaticResource Styles.Text.FieldHeader.Editable}" Text="控制线" />
<StackPanel Orientation="Horizontal">
<TextBox Style="{StaticResource Styles.Text.FieldContent.Input.Card}" Text="{Binding CtrlLine}"/>
<TextBox Style="{StaticResource Styles.Text.FieldContent.Input.Card}" Text="{Binding CtrlLine,StringFormat={}{0:0.#}}"/>
<TextBlock Style="{StaticResource Styles.Text.FieldContent.Unit}" Text="%" />
</StackPanel>
</StackPanel>
<StackPanel Margin="{StaticResource ControlMargin}" >
<TextBlock Style="{StaticResource Styles.Text.FieldHeader.Editable}" Text="Kp" />
<StackPanel Orientation="Horizontal">
<TextBox Style="{StaticResource Styles.Text.FieldContent.Input.Card}" Text="{Binding Kp, StringFormat={}{0:F1}}"/>
<TextBox Style="{StaticResource Styles.Text.FieldContent.Input.Card}" Text="{Binding Kp, StringFormat={}{0:0.#}}"/>
<TextBlock Style="{StaticResource Styles.Text.FieldContent.Unit}" Text="加热/厚度" />
</StackPanel>
</StackPanel>
<StackPanel Margin="{StaticResource ControlMargin}" >
<TextBlock Style="{StaticResource Styles.Text.FieldHeader.Editable}" Text="中心偏厚" />
<StackPanel Orientation="Horizontal">
<TextBox Style="{StaticResource Styles.Text.FieldContent.Input.Card}" Text="{Binding CenterTarget, StringFormat={}{0:0.#}}"/>
<TextBlock Style="{StaticResource Styles.Text.FieldContent.Unit}" Text="%" />
</StackPanel>
</StackPanel>
<StackPanel Margin="{StaticResource ControlMargin}" >
<TextBlock Style="{StaticResource Styles.Text.FieldHeader.Editable}" Text="平滑阀值" />
<StackPanel Orientation="Horizontal">
......@@ -124,6 +131,7 @@
<TextBlock Style="{StaticResource Styles.Text.FieldContent.Unit}" Text="m" />
</StackPanel>
</StackPanel>
</StackPanel >
<StackPanel Orientation="Horizontal" >
<StackPanel Margin="{StaticResource ControlMargin}">
......@@ -151,7 +159,7 @@
</TextBlock>
</StackPanel>
<StackPanel Margin="{StaticResource ControlMargin}" DataContext="{Binding Feedback}">
<TextBlock Style="{StaticResource Styles.Text.FieldHeader}" Text="风机" />
<TextBlock Style="{StaticResource Styles.Text.FieldHeader}" Text="总电源" />
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource Styles.Text.FieldContent}">
......
......@@ -62,7 +62,7 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
public int[] HeatEffectCurve { get; set; }
public bool IsForbidUpDown { get; set; }
public int CtrlLine { get; set; }
public double CtrlLine { get; set; }
public double Kp { get; set; }
/// <summary>
......@@ -80,6 +80,10 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
/// </summary>
public int RangeOfOffset { get; set; } = 50;
/// <summary>
/// 中心偏厚 单位 %
/// </summary>
public double CenterTarget { get; set; }
/// <summary>
/// 混合数
/// </summary>
......@@ -132,6 +136,8 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.Kp), this, nameof(Kp));
Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.MaxHeat), this, nameof(MaxHeat));
Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.RangeOfOffset), this, nameof(RangeOfOffset));
Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.CenterTarget), this, nameof(CenterTarget));
Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.Step), this, nameof(Step));
Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.HasCheck), this, nameof(HasCheck));
......@@ -226,10 +232,11 @@ namespace FLY.FilmCasting.AutoDie.UI.Client
//参数设置
HeatCell.ThresholdHeatSigma=this.ThresholdHeatSigma;
HeatCell.IsForbidUpDown = this.IsForbidUpDown;
HeatCell.CtrlLine = this.CtrlLine;
HeatCell.CtrlLine = Math.Round(this.CtrlLine, 1);
HeatCell.Kp = this.Kp;
HeatCell.MaxHeat = this.MaxHeat;
HeatCell.RangeOfOffset = this.RangeOfOffset;
HeatCell.CenterTarget = Math.Round(this.CenterTarget, 1);
Feedback.Step=this.Step;
Feedback.HasCheckFilmVelocity=this.HasCheckFilmVelocity;
......
......@@ -34,12 +34,11 @@ namespace FLY.FilmCasting.AutoDie.UI.Client.UiModule
/// 厚度%
/// </summary>
public ChartValues<double> ThickPercents { get; } = new ChartValues<double>();
public ChartValues<int> PreHeats { get; } = new ChartValues<int>();
public ChartValues<int> Heats { get; } = new ChartValues<int>();
public ChartValues<int> HeatOffsets { get; } = new ChartValues<int>();
public ChartValues<double> PreHeats { get; } = new ChartValues<double>();
public ChartValues<double> Heats { get; } = new ChartValues<double>();
public ChartValues<double> HeatOffsets { get; } = new ChartValues<double>();
public ChartValues<bool> Bads { get; } = new ChartValues<bool>();
public ChartValues<bool> IsStables { get; } = new ChartValues<bool>();
public object MapperPreHeats { get; private set; }
[PropertyChanged.DependsOn(nameof(Kp))]
......
......@@ -35,7 +35,7 @@ namespace FLY.FilmCasting.AutoDie.UI.Client.UiModule
{
thickpercents[i] = 100 * (datas[i] - avg) / avg;
}
int[] heatoffsets = new int[nbolts];
var heatoffsets = new double[nbolts];
for (int i = 0; i < nbolts; i++)
{
heatoffsets[i] = (int)(thickpercents[i] * kp);
......@@ -43,13 +43,13 @@ namespace FLY.FilmCasting.AutoDie.UI.Client.UiModule
int baseHeat = 20;
int[] preheats = new int[nbolts];
var preheats = new double[nbolts];
for (int i = 0; i < nbolts; i++)
{
preheats[i] = heatoffsets[i] + baseHeat;
}
int[] heats = new int[nbolts];
var heats = new double[nbolts];
for (int i = 0; i < nbolts; i++)
{
heats[i] = (int)((Math.Sin(i * Math.PI / nbolts)) * 20 + 30 + (random.NextDouble() - 0.5) * 5);
......
......@@ -36,7 +36,7 @@ namespace FLY.FilmCasting.AutoDie.Client
/// <summary>
/// 厚度控制线 , 厚度% 大于 厚度控制线 自动才会加热控制
/// </summary>
public int CtrlLine { get; set; }
public double CtrlLine { get; set; }
/// <summary>
/// 最大加热量 默认100%
......@@ -48,6 +48,10 @@ namespace FLY.FilmCasting.AutoDie.Client
/// </summary>
public int RangeOfOffset { get; set; }
/// <summary>
/// 中心目标厚度 ,希望生产出来的产品中心比较厚点
/// </summary>
public double CenterTarget { get; set; }
#endregion
......@@ -66,7 +70,7 @@ namespace FLY.FilmCasting.AutoDie.Client
/// <summary>
/// 当前方向的加热策略,必须保证 0~100
/// </summary>
public int[] Heats { get; set; }
public double[] Heats { get; set; }
private int Base { get; set; }
......@@ -76,13 +80,13 @@ namespace FLY.FilmCasting.AutoDie.Client
/// <summary>
/// 加热偏移量
/// </summary>
public int[] Offsets { get; set; }
public double[] Offsets { get; set; }
/// <summary>
/// Heats+Offsets+Base
/// </summary>
public int[] PreHeats { get; set; }
public double[] PreHeats { get; set; }
/// <summary>
......
......@@ -7,7 +7,7 @@ namespace FLY.FilmCasting.AutoDie.Common
public class ChannelValuesMark
{
public string name;
public int[] channelValues;
public double[] channelValues;
}
public class ChannelValuesMarkJsonDb
......
......@@ -57,6 +57,7 @@
<Compile Include="IService\IBulkDbService.cs" />
<Compile Include="IService\IHeatBufService.cs" />
<Compile Include="IService\IFeedbackHeatService.cs" />
<Compile Include="IService\IPlcLinkExt.cs" />
<Compile Include="OBJ_INTERFACE\OBJ_INTERFACE_ID.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Server.OBJProxy\OBJProxy.cs" />
......@@ -73,6 +74,7 @@
<Compile Include="Server\Model\LcTable.cs" />
<Compile Include="Server\Model\Lc_AutoMapperProfile.cs" />
<Compile Include="Server\PLCLink.cs" />
<Compile Include="Server\PlcLinkExt.cs" />
<Compile Include="Server\SysParam.cs" />
<Compile Include="Server\TDGage.cs" />
</ItemGroup>
......
......@@ -28,7 +28,7 @@ namespace FLY.FilmCasting.AutoDie.IService
/// <summary>
/// 厚度控制线 , 厚度% 大于 厚度控制线 自动才会加热控制
/// </summary>
int CtrlLine { get; set; }
double CtrlLine { get; set; }
/// <summary>
/// 最大加热量 默认100%, 也是 当前量界面的显示范围
......@@ -40,6 +40,10 @@ namespace FLY.FilmCasting.AutoDie.IService
/// </summary>
int RangeOfOffset { get; set; }
/// <summary>
/// 中心目标厚度 ,希望生产出来的产品中心比较厚点
/// </summary>
double CenterTarget { get; set; }
#endregion
#region 状态
......@@ -55,17 +59,17 @@ namespace FLY.FilmCasting.AutoDie.IService
/// <summary>
/// 当前加热策略,必须保证 0~100
/// </summary>
int[] Heats { get; }
double[] Heats { get; }
/// <summary>
/// 加热偏移量
/// </summary>
int[] Offsets { get; }
double[] Offsets { get; }
/// <summary>
/// Heats+Offsets+Base, 必须保证0~100
/// </summary>
int[] PreHeats { get; }
double[] PreHeats { get; }
/// <summary>
/// PreHeat 每3个计算的sigma, 最大值
......
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FLY.FilmCasting.AutoDie.IService
{
public interface IPlcLinkExt : INotifyPropertyChanged
{
#region 当前值
/// <summary>
/// 当前电流 有没?
/// </summary>
bool HasElectricity { get; }
/// <summary>
/// 风机是否启动?
/// </summary>
bool HasFan { get; }
bool IsConected { get; }
#endregion
#region 输出
void SetChannelCnt(int channelCnt);
/// <summary>
/// 设置加热量
/// </summary>
/// <param name="values"></param>
void SetHeats(IEnumerable<double> values);
#endregion
}
}
......@@ -131,8 +131,8 @@ namespace FLY.FilmCasting.AutoDie.Server
#endregion
IPLCLink plc;
PLCLink basePlc;
PlcLinkExt plc;
FLY.Thick.FilmCasting.IService.IBoltMapFilmCastingService boltMapFilmCasting;
FLY.Thick.FilmCasting.IService.IBulkDbService bulkDb;
FLY.Thick.Base.IService.ITDGageService gageService;
......@@ -153,7 +153,7 @@ namespace FLY.FilmCasting.AutoDie.Server
/// </summary>
string heats_dir = "feedbackheats";
int[] lastHeats;
double[] lastHeats;
/// <summary>
/// 最后一次保存的记录,
/// 用于当加热改变时,保存记录到数据库
......@@ -193,19 +193,14 @@ namespace FLY.FilmCasting.AutoDie.Server
mHistoryDb = historyDb;
plc = new PLCLink(Misc.StringConverter.ToIPEndPoint(PLCep));
basePlc = new PLCLink(Misc.StringConverter.ToIPEndPoint(PLCep));
plc = new PlcLinkExt();
plc.Init(basePlc);
Misc.BindingOperations.SetBinding(plc, nameof(plc.IsConected), this, nameof(IsConnectedWithPLC));
Misc.BindingOperations.SetBinding(plc, nameof(plc.HasElectricity), this, nameof(HasElectricity));
Misc.BindingOperations.SetBinding(plc, nameof(plc.HasFan), this, nameof(HasFan));
Misc.BindingOperations.SetBinding(plc, nameof(plc.IsConected), () => {
if (plc.IsConected == true)
{
//刚成功连接上
//重新复制数据到 PLC
RecoverPLC();
}
});
InitBuf();
......@@ -313,7 +308,8 @@ namespace FLY.FilmCasting.AutoDie.Server
InitError();
((PLCLink)plc).Start();
basePlc.Start();
}
private void DynArea_PropertyChanged(object sender, PropertyChangedEventArgs e)
......@@ -497,15 +493,15 @@ namespace FLY.FilmCasting.AutoDie.Server
return;//异常
//定位加热
int[] heats = new int[mHeatCell.ChannelCnt];
Array.Clear(heats, 0, heats.Count());
heats[boltIndex1-1] = 80;
heats[boltIndex1] = 80;
heats[boltIndex1+1] = 80;
double[] heats = new double[mHeatCell.ChannelCnt];
heats[boltIndex1-1] = mHeatCell.MaxHeat;
heats[boltIndex1] = mHeatCell.MaxHeat;
heats[boltIndex1+1] = mHeatCell.MaxHeat;
heats[boltIndex2 - 1] = 80;
heats[boltIndex2] = 80;
heats[boltIndex2 + 1] = 80;
heats[boltIndex2 - 1] = mHeatCell.MaxHeat;
heats[boltIndex2] = mHeatCell.MaxHeat;
heats[boltIndex2 + 1] = mHeatCell.MaxHeat;
......@@ -612,7 +608,7 @@ namespace FLY.FilmCasting.AutoDie.Server
IsAuto = false;
//备份 加热策略
int[] preheats = mHeatCell.PreHeats.ToArray();
var preheats = mHeatCell.PreHeats.ToArray();
bool needrestore = true;
//停止检测加热棒
......@@ -648,48 +644,11 @@ namespace FLY.FilmCasting.AutoDie.Server
}
void Output(int[] heats)
void Output(double[] heats)
{
List<UInt16> list = new List<UInt16>();
for (int i = 0; i < ChannelCnt; i++)
{
UInt16 heat = (UInt16)heats[i];
if (heat < 0)
heat = 0;
else if (heat > 100)
heat = 100;
list.Add(heat);
}
plc.SetHeat(list);
UInt16 heatupdate = (UInt16)(plc.HeatUpdate_R + 1);
if (heatupdate > 100)
heatupdate = 1;
plc.SetHeatUpdate(heatupdate);
plc.SetHeats(heats);
}
void RecoverPLC()
{
plc.SetChannelCnt((UInt16)ChannelCnt);
if (lastHeats != null)
{
plc.SetHeat(lastHeats.Select(h => (UInt16)h));
}
else
{
//设置全部0进去
plc.SetHeat(new UInt16[ChannelCnt]);
}
//这里是在 plc.IsConnected = true, 才会触发。
//只有读取一次PLC后,IsConnected 才会=true,
//所以 HeatUpdate_R 肯定是对的
UInt16 heatupdate = (UInt16)(plc.HeatUpdate_R + 1);
if (heatupdate > 100)
heatupdate = 1;
plc.SetHeatUpdate(heatupdate);
}
void setLcThickHeatIsStable(Lc_ThickHeat lcThickHeat)
......
......@@ -229,7 +229,10 @@ namespace FLY.FilmCasting.AutoDie.Server
{
for (int i = 0; i < thks.Count(); i++)
{
thickpercents[i] = (thks[i] - avg) / avg * 100;
if (double.IsNaN(thks[i]))
thickpercents[i] = double.NaN;
else
thickpercents[i] = Math.Round((thks[i] - avg) / avg * 100, 2);
}
}
return thickpercents;
......
......@@ -586,24 +586,22 @@ namespace FLY.FilmCasting.AutoDie.Server
}
int[] getSingleHeat_100(int channelcnt, params int[] index)
double[] getSingleHeat_100(int channelcnt, params int[] index)
{
int[] heats = new int[channelcnt];
Array.Clear(heats, 0, heats.Count());
double[] heats = new double[channelcnt];
foreach (int i in index)
heats[i] = 100;
return heats;
}
int[] getSingleHeat_100(int channelcnt, int index)
double[] getSingleHeat_100(int channelcnt, int index)
{
int[] heats = new int[channelcnt];
Array.Clear(heats, 0, heats.Count());
double[] heats = new double[channelcnt];
heats[index] = 100;
return heats;
}
int[] getAllHeat_30(int channelcnt)
double[] getAllHeat_30(int channelcnt)
{
int[] heats = new int[channelcnt];
double[] heats = new double[channelcnt];
for (int i = 0; i < heats.Count(); i++)
{
heats[i] = 30;
......
......@@ -93,7 +93,7 @@ namespace FLY.FilmCasting.AutoDie.Server.Model
/// <summary>
/// 1幅加热数据 %
/// </summary>
public int[] Heats { get; set; }
public double[] Heats { get; set; }
}
......
using FLY.FilmCasting.AutoDie.IService;
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.FilmCasting.AutoDie.Server
{
/// <summary>
/// PlcLink 只有 1~100, 最小单位1, 扩展它, 1~100, 最小单位 0.1
/// </summary>
public class PlcLinkExt: IPlcLinkExt
{
/// <summary>
/// 每颗粒时间 5s
/// </summary>
const int CellSec = 3;
/// <summary>
/// 占空比,总颗粒数
/// </summary>
const int DutyCount = 10;
int channelCnt = 96;
double[] heats;
/// <summary>
/// 当前电流 有没?
/// </summary>
public bool HasElectricity { get; private set; }
/// <summary>
/// 风机是否启动?
/// </summary>
public bool HasFan { get; private set; }
public bool IsConected { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
PLCLink plcLink;
DispatcherTimer timer;
Stopwatch stopwatch;
int dutyIndex = 0;
public PlcLinkExt()
{
}
public void Init(PLCLink plcLink)
{
this.plcLink = plcLink;
Misc.BindingOperations.SetBinding(plcLink, nameof(plcLink.IsConected), this, nameof(IsConected));
Misc.BindingOperations.SetBinding(plcLink, nameof(plcLink.HasElectricity), this, nameof(HasElectricity));
Misc.BindingOperations.SetBinding(plcLink, nameof(plcLink.HasFan), this, nameof(HasFan));
this.PropertyChanged += PlcLinkExt_PropertyChanged;
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += Timer_Tick;
stopwatch = new Stopwatch();
if (plcLink.IsConected)
{
//刚连上,把 之前的数据都重新发给它。
plcLink.SetChannelCnt((UInt16)channelCnt);
DutyStart();
}
}
void DutyStart()
{
stopwatch.Restart();
timer.Start();
dutyIndex = 0;
setHeats();
}
void DutyStop()
{
stopwatch.Stop();
timer.Stop();
}
void setHeats()
{
if (!plcLink.IsConected)
return;
UInt16[] plcHeats = heats.Select(h => {
int h_int = (int)h;
int v = (int)((h - h_int) * DutyCount);
if (v > dutyIndex)
{
return (UInt16)(h_int + 1);
}
else {
return (UInt16)h_int;
}
}) as UInt16[];
plcLink.SetHeat(plcHeats);
UInt16 heatupdate = (UInt16)(plcLink.HeatUpdate_R + 1);
if (heatupdate > 100)
heatupdate = 1;
plcLink.SetHeatUpdate(heatupdate);
}
private void Timer_Tick(object sender, EventArgs e)
{
if (stopwatch.Elapsed < TimeSpan.FromSeconds(CellSec))
{
return;
}
stopwatch.Restart();
setHeats();
dutyIndex++;
if (dutyIndex > DutyCount)
dutyIndex = 0;
}
private void PlcLinkExt_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(plcLink.IsConected))
{
if (plcLink.IsConected)
{
//刚连上,把 之前的数据都重新发给它。
plcLink.SetChannelCnt((UInt16)channelCnt);
DutyStart();
}
else {
DutyStop();
}
}
}
public void SetChannelCnt(int channelCnt)
{
this.channelCnt = channelCnt;
plcLink.SetChannelCnt((UInt16)channelCnt);
}
/// <summary>
/// 设置加热量
/// </summary>
/// <param name="values"></param>
public void SetHeats(IEnumerable<double> values)
{
heats = values.Select(h =>
{
if (h < 0) h = 0;
else if (h > 100) h = 100;
return h;
}).ToArray();
setHeats();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment