From 1fd730e4ef6ae5c166db82c2e7e2fa4e09dc052d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A6=82=E6=84=8F=20=E5=BD=AD?= <2417589739@qq.com> Date: Sat, 5 Mar 2022 16:58:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E9=80=BB=E8=BE=91=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HBLConsole.Business/Devices/MORKS.cs | 334 +++++++++++++++++++- HBLConsole.Business/MessageServer/Base.cs | 1 + HBLConsole.Communication/ModbusTcpHelper.cs | 14 +- HBLConsole.GVL/MORKS.cs | 152 ++++++++- HBLConsole.MainConsole/Main.cs | 1 + HBLConsole.Service/RTrig.cs | 41 +++ 6 files changed, 531 insertions(+), 12 deletions(-) create mode 100644 HBLConsole.Service/RTrig.cs diff --git a/HBLConsole.Business/Devices/MORKS.cs b/HBLConsole.Business/Devices/MORKS.cs index 48e52a9..5187fe2 100644 --- a/HBLConsole.Business/Devices/MORKS.cs +++ b/HBLConsole.Business/Devices/MORKS.cs @@ -1,4 +1,5 @@ -using HBLConsole.Communication; +using BPA.Message; +using HBLConsole.Communication; using HBLConsole.Factory; using HBLConsole.Interface; using HBLConsole.Model; @@ -7,7 +8,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; +using BPA.Message.Enum; namespace HBLConsole.Business.Devices { @@ -17,6 +20,8 @@ namespace HBLConsole.Business.Devices public static MORKS GetInstance => _Instance ?? (_Instance = new MORKS()); private MORKS() { } + GVL.MORKS mORKS = new GVL.MORKS(); + /// /// 写入配方数据到 PLC /// @@ -42,6 +47,9 @@ namespace HBLConsole.Business.Devices ActionManagerment.GetInstance.Register(new Action(() => { WriteRecipeBoms(); + ReadPlcData(); + DataParse(); + Main(); }), "ConnectOk"); //获取物料信息 @@ -50,6 +58,330 @@ namespace HBLConsole.Business.Devices //Modbus Tcp 连接 ModbusTcpHelper.GetInstance.ModbusTcpConnect("127.0.0.1"); } + + /// + /// 数据读取 + /// + private void ReadPlcData() + { + ThreadManagerment.GetInstance.StartLong(new Action(() => + { + object result; + result = ModbusTcpHelper.GetInstance.Read(1120, ReadType.Coils, 16); + if (result != null) + { + if (result is bool[] bools) + { + if (bools.Length == 16) + { + mORKS.InitComplete = bools[0]; + mORKS.TakeBowlIdle = bools[1]; + mORKS.TemperatureReached = bools[2]; + mORKS.AllowFallNoodle = bools[3]; + mORKS.RbTakeNoodleComplete = bools[4]; + mORKS.RbFallNoodleComplete = bools[5]; + mORKS.RbOutMealComplete = bools[6]; + mORKS.RobotIdle = bools[7]; + mORKS.TakeMealDetect = bools[8]; + mORKS.MissingBowl = bools[9]; + mORKS.TurntableLowerLimit = bools[11]; + } + } + } + + //读取煮面栏状态 + result = ModbusTcpHelper.GetInstance.Read(1136, ReadType.Coils, 6); + if (result != null) + { + if (result is bool[] bools) + { + if (bools.Length == 6) + { + for (int i = 0; i < 6; i++) + { + mORKS.NoodleCookerStatus[i] = bools[i]; + } + } + } + } + + //读取煮面炉完成信号 + result = ModbusTcpHelper.GetInstance.Read(1144, ReadType.Coils, 6); + if (result != null) + { + if (result is bool[] bools) + { + if (bools.Length == 6) + { + for (int i = 0; i < 6; i++) + { + mORKS.CookNoodlesComplete[i] = bools[i]; + } + } + } + } + Thread.Sleep(500); + }), "Read PLC Data"); + } + + /// + /// 数据解析 + /// + private void DataParse() + { + ActionManagerment.GetInstance.Register(new Action((o) => + { + if (o is MorkOrderPush morkOrderPush) + { + foreach (var item in morkOrderPush.GoodBatchings) + { + var res = Json.GetInstance.Base.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingId == item.BatchingId); + if (res != null) + { + if (ushort.TryParse(res.BatchingLoc, out ushort loc)) + { + if (loc >= 1 && loc <= 5) + { + mORKS.RBTakeNoodleTask.Enqueue(new GVL.OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId }); + } + else if (loc >= 10 && loc <= 11) + { + mORKS.TakeBowlTask.Enqueue(new GVL.OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId, RecipeNumber = (ushort)morkOrderPush.RecipeId }); + } + } + } + } + } + }), "MorksParse"); + } + + bool AllowRun = false; + string TakeBowlId = string.Empty;//取碗订单ID + string IngredientsCompleteId = string.Empty;//配料完成订单ID + string[] CookNodelId = new string[6] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, }; + bool RobotTaskInterlock = false;//机器人任务互锁信号 + string OutMealId = string.Empty; + + private void Main() + { + ThreadManagerment.GetInstance.StartLong(new Action(() => + { + AllowRun = mORKS.InitComplete && mORKS.TemperatureReached; + + if (AllowRun) + { + TakeBowlTask(); + + TakeNoodleTask(); + } + OutNoodleTask(); + SingleDetect(); + + Thread.Sleep(1); + }), "Main Task"); + + } + + /// + /// 取碗控制 + /// + private void TakeBowlTask() + { + //取碗控制 + if (RTrig.GetInstance("TakeBowl").Start(mORKS.TakeBowlIdle && mORKS.TakeBowlTask.Count > 0)) + { + if (mORKS.TakeBowlTask.TryDequeue(out GVL.OrderLocInfo orderLocInfo)) + { + TakeBowlId = orderLocInfo.SuborderId; + TakeBowlControl(orderLocInfo.Loc); + SetRecipeNumber(orderLocInfo.RecipeNumber); + SimpleFactory.GetInstance.OrderChanged(TakeBowlId, ORDER_STATUS.COOKING); + MessageLog.GetInstance.Show($"订单【{TakeBowlId}】,位置:[{orderLocInfo.Loc}]"); + } + } + } + + /// + /// 取面任务 + /// + private void TakeNoodleTask() + { + //取面控制 + if (!RobotTaskInterlock) + { + if (RTrig.GetInstance("TakeNoodle").Start(mORKS.RobotIdle && mORKS.RBTakeNoodleTask.Count > 0)) + { + if (mORKS.RBTakeNoodleTask.TryDequeue(out GVL.OrderLocInfo orderLocInfo)) + { + //设置转台位置 + SetTurntableLoc(orderLocInfo.Loc); + + //设置倒面位置 + int loc = Array.FindIndex(mORKS.NoodleCookerStatus, p => p == false);//查找煮面炉空闲位置 + if (loc >= 0 && loc <= 5) + { + CookNodelId[loc] = orderLocInfo.SuborderId; + SetFallNoodleLoc((ushort)(loc + 1)); + } + + //机器人开始取面 + RobotTakeNoodle(); + + SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING); + + MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,转台:[{orderLocInfo.Loc}],煮面栏:[{loc}]"); + + } + } + } + } + + /// + /// 出餐控制 + /// + private void OutNoodleTask() + { + if (RobotTaskInterlock) + { + if (mORKS.AllowFallNoodle && mORKS.RobotIdle && !mORKS.TakeMealDetect) + { + int loc = Array.FindIndex(CookNodelId, p => p == IngredientsCompleteId); + if (loc >= 0 && loc <= 5) + { + if (mORKS.CookNoodlesComplete[loc]) + { + SetTakeNoodleLoc((ushort)(loc + 1)); + RobotOutMeal(); + CookNoodleStatusReset((ushort)(loc + 1)); + OutMealId = IngredientsCompleteId; + IngredientsCompleteId = string.Empty; + CookNodelId[loc] = string.Empty; + } + } + + } + } + } + + /// + /// 信号检测 + /// + private void SingleDetect() + { + if (RTrig.GetInstance("AllowFallNoodle").Start(mORKS.AllowFallNoodle)) + { + IngredientsCompleteId = TakeBowlId; + TakeBowlId = string.Empty; + } + + if (RTrig.GetInstance("CompleteChange").Start(mORKS.RbOutMealComplete)) + { + SimpleFactory.GetInstance.OrderChanged(OutMealId, ORDER_STATUS.COMPLETED_COOK); + MessageLog.GetInstance.Show($"订单【{OutMealId}】制作完成"); + } + + if (DelayRTrig.GetInstance("CompleteChange1").Start(mORKS.RbOutMealComplete && !mORKS.TakeMealDetect, 2)) + { + SimpleFactory.GetInstance.OrderChanged(OutMealId, ORDER_STATUS.COMPLETED_TAKE); + MessageLog.GetInstance.Show($"订单【{OutMealId}】取餐完成"); + OutMealId = string.Empty; + } + + RobotTaskInterlock = mORKS.RobotIdle && mORKS.AllowFallNoodle && mORKS.NoodleCookerStatus.Where(p => p == true).ToList().Count >= 3; + } + + + + + /// + /// 取面完成复位 + /// + private void TakeNoodleCompleteReset() + { + ModbusTcpHelper.GetInstance.Write(1124, WriteType.Coils, false); + } + + /// + /// 指定煮面口状态复位 + /// + /// + private void CookNoodleStatusReset(int num) + { + if (num >= 1 && num <= 6) + { + ushort addRess = (ushort)(1136 + num - 1); + ModbusTcpHelper.GetInstance.Write(1136, WriteType.Coils, false); + } + } + + /// + /// 写配方编号 + /// + /// + private void SetRecipeNumber(ushort num) + { + ModbusTcpHelper.GetInstance.Write(100, WriteType.HoldingRegisters, num); + } + + /// + /// 设置转台位置 + /// + /// + private void SetTurntableLoc(ushort loc) + { + ModbusTcpHelper.GetInstance.Write(101, WriteType.HoldingRegisters, loc); + } + + /// + /// 设置倒面位置 + /// + /// + private void SetFallNoodleLoc(ushort loc) + { + ModbusTcpHelper.GetInstance.Write(102, WriteType.HoldingRegisters, loc); + } + + /// + /// 设置取面位置 + /// + /// + private void SetTakeNoodleLoc(ushort loc) + { + ModbusTcpHelper.GetInstance.Write(103, WriteType.HoldingRegisters, loc); + } + + /// + /// 取碗控制 + /// + /// + private void TakeBowlControl(ushort loc) + { + if (loc == 10) + { + ModbusTcpHelper.GetInstance.Write(321, WriteType.Coils, true); + } + else if (loc == 11) + { + ModbusTcpHelper.GetInstance.Write(322, WriteType.Coils, true); + } + } + + /// + /// 机器人取面 + /// + private void RobotTakeNoodle() + { + ModbusTcpHelper.GetInstance.Write(323, WriteType.Coils, true); + } + + /// + /// 机器人取餐 + /// + private void RobotOutMeal() + { + ModbusTcpHelper.GetInstance.Write(324, WriteType.Coils, true); + } + } } diff --git a/HBLConsole.Business/MessageServer/Base.cs b/HBLConsole.Business/MessageServer/Base.cs index cc31c74..b777f56 100644 --- a/HBLConsole.Business/MessageServer/Base.cs +++ b/HBLConsole.Business/MessageServer/Base.cs @@ -28,6 +28,7 @@ namespace HBLConsole.Business.MessageServer OrderPush = morkOrderpush }); ActionManagerment.GetInstance.Send("AddOrder", morkOrderpush); + ActionManagerment.GetInstance.Send("MorksParse", morkOrderpush); } } diff --git a/HBLConsole.Communication/ModbusTcpHelper.cs b/HBLConsole.Communication/ModbusTcpHelper.cs index 3034115..525996c 100644 --- a/HBLConsole.Communication/ModbusTcpHelper.cs +++ b/HBLConsole.Communication/ModbusTcpHelper.cs @@ -112,8 +112,11 @@ namespace HBLConsole.Communication catch (Exception ex) { MessageLog.GetInstance.Show(ex.ToString()); - tcpClient = null; - Connect(); + if (ex.InnerException is SocketException) + { + tcpClient = null; + Connect(); + } } return result; } @@ -174,8 +177,11 @@ namespace HBLConsole.Communication catch (Exception ex) { MessageLog.GetInstance.Show(ex.ToString()); - tcpClient = null; - Connect(); + if (ex.InnerException is SocketException) + { + tcpClient = null; + Connect(); + } } return true; } diff --git a/HBLConsole.GVL/MORKS.cs b/HBLConsole.GVL/MORKS.cs index 3ca4361..231f605 100644 --- a/HBLConsole.GVL/MORKS.cs +++ b/HBLConsole.GVL/MORKS.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using HBLConsole.Interface; +using System.Collections.Concurrent; namespace HBLConsole.GVL { @@ -12,34 +13,171 @@ namespace HBLConsole.GVL /// public class MORKS : IGvl { - /// - /// 初始化完成 - /// - public bool InitComplete { get; set; } + /// /// 机器人取面 + /// PLC -> M0.3 + /// ModbusTcp -> 323 /// public bool RobotTakeNoodle { get; set; } /// /// 机器人出餐 + /// PLC -> M0.4 + /// ModbusTcp -> 324 /// public bool RobotOutMeal { get; set; } /// /// 移动转台 + /// PLC -> M0.5 + /// ModbusTcp -> 325 /// public bool MoveTurntable { get; set; } + + + /// - /// 煮面炉状态 + /// 初始化完成 + /// PLC -> M100.0 + /// ModbusTcp -> 1120 /// - public bool[] NoodleCookerStatus { get; set; } = new bool[6] { false, false, false, false, false, false }; + public bool InitComplete { get; set; } /// - /// 取完空闲 + /// 取碗机构空闲,True:忙碌,false:空闲 + /// PLC -> M100.1 + /// ModbusTcp -> 1121 /// public bool TakeBowlIdle { get; set; } + + /// + /// 温度到达,True:表示到达,false:未到达 + /// PLC -> M100.2 + /// ModbusTcp -> 1122 + /// + public bool TemperatureReached { get; set; } + + /// + /// 允许到面,配料完成 + /// PLC -> M100.3 + /// ModbusTcp -> 1123 + /// + public bool AllowFallNoodle { get; set; } + + /// + /// 机器人取面完成 + /// PLC -> M100.4 + /// ModbusTcp -> 1124 + /// + public bool RbTakeNoodleComplete { get; set; } + + /// + /// 机器人倒面完成 + /// PLC -> M100.5 + /// ModbusTcp -> 1125 + /// + public bool RbFallNoodleComplete { get; set; } + + /// + /// 机器人出餐完成,上报取餐完成 + /// PLC -> M100.6 + /// ModbusTcp -> 1126 + /// + public bool RbOutMealComplete { get; set; } + + /// + /// 机器人空闲 + /// PLC -> M100.7 + /// ModbusTcp -> 1127 + /// + public bool RobotIdle { get; set; } + + /// + /// 取餐口检测 + /// PLC -> M101.0 + /// ModbusTcp -> 1128 + /// + public bool TakeMealDetect { get; set; } + + /// + /// 缺碗信号,false:缺碗,true:有碗 + /// PLC -> M101.1 + /// ModbusTcp -> 1129 + /// + public bool MissingBowl { get; set; } + + /// + /// 转台下限检测 + /// PLC -> M101.3 + /// ModbusTcp -> 1131 + /// + public bool TurntableLowerLimit { get; set; } + + /// + /// 煮面炉状态,True:忙碌,false:空闲 + /// M102.0 - M102.5 + /// 1136 - 1141 + /// + public bool[] NoodleCookerStatus { get; set; } = new bool[6] { false, false, false, false, false, false }; + + /// + /// 煮面完成,上升后给信号 + /// M103.0 - M103.5 + /// 1144 - 1149 + /// + public bool[] CookNoodlesComplete { get; set; } = new bool[6] { false, false, false, false, false, false }; + + /// + /// 配方编号 + /// PLC -> VW0 + /// ModbusTcp -> 100 + /// + public ushort RecipeNumber { get; set; } + + /// + /// 转台位置 + /// PLC -> VW2 + /// ModbusTcp -> 101 + /// + public ushort TurntableLoc { get; set; } + + /// + /// 到面至煮面炉位置 + /// PLC -> VW4 + /// ModbusTcp -> 102 + /// + public ushort FallNoodleLoc { get; set; } + + /// + /// 取面位置 + /// PLC -> VW6 + /// ModbusTcp -> 103 + /// + public ushort TakeNoodleLoc { get; set; } + + + + + /// + /// 机器人取面位置队列 + /// + public ConcurrentQueue RBTakeNoodleTask { get; set; } = new ConcurrentQueue(); + + public ConcurrentQueue TakeBowlTask { get; set; } = new ConcurrentQueue(); + + } + + public class OrderLocInfo + { + public string SuborderId { get; set; } + public ushort Loc { get; set; } + public ushort RecipeNumber { get; set; } } + + + + } diff --git a/HBLConsole.MainConsole/Main.cs b/HBLConsole.MainConsole/Main.cs index 256aa42..b87770a 100644 --- a/HBLConsole.MainConsole/Main.cs +++ b/HBLConsole.MainConsole/Main.cs @@ -32,6 +32,7 @@ namespace HBLConsole.MainConsole { Json.GetInstance.Save(); Json.GetInstance.Save(); + TextHelper.GetInstance.SaveLogInfo(MessageLog.GetInstance.LogInfo, "LogInfo"); } public void BusinessInit() diff --git a/HBLConsole.Service/RTrig.cs b/HBLConsole.Service/RTrig.cs new file mode 100644 index 0000000..2a9547d --- /dev/null +++ b/HBLConsole.Service/RTrig.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HBLConsole.Service +{ + public class RTrig + { + + private volatile static ConcurrentDictionary _Instance; + public static RTrig GetInstance(string name) + { + if (_Instance == null) _Instance = new ConcurrentDictionary(); + if (!_Instance.ContainsKey(name)) _Instance.TryAdd(name, new RTrig()); + return _Instance[name]; + } + private RTrig() { } + + private bool flag1; + public bool Q { get; private set; } + private bool IN1 + { + set + { + Q = value && !flag1; + flag1 = value; + } + } + public bool Start(bool IN) + { + IN1 = IN; + return Q; + } + + + + } +}