using NPOI.SS.Formula.Eval; using Rs.Controls; using Rs.DataAccess; using Rs.Framework; using Rs.Motion; using Rs.MotionPlat.Entitys; using Rs.MotionPlat.Flow; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Rs.MotionPlat.Commom { public enum ENozzleStatus { /// /// 空闲 /// IDLE, /// /// 准备测试 /// ToTest, /// /// 准备下料 /// ToUnload } /// /// 排料吸嘴实体类 /// public class Nozzle { SqliteHelper db = new SqliteHelper(); /// /// 是否禁用 /// public bool Enable { get; set; } = false; public TestProduct Product { get; set; } /// /// 吸嘴索引 /// public int NozzleIndex { get; set; } /// /// 吸嘴名称 /// public string NozzleName { get; set; } public ENozzleStatus Status { get; set; } = ENozzleStatus.IDLE; public bool Update() { Task.Run(() => { SqliteHelper db = new SqliteHelper(); string val = Status == ENozzleStatus.IDLE ? "0" : "1"; string updateSql = $"update TrayStatus set status={val} where trayname='DischargeNozzle' and slotindex={NozzleIndex}"; db.ExecuteNonQuery(updateSql); }); //string updateSql = $"update nozzle set fromtype='{FromType}',fromfloor={FromFloor},fromindex={FromIndex},ToType='{ToType}',tofloor={ToFloor},ToIndex={ToIndex},Status='{Status}' where NozzleIndex={NozzleIndex}"; //string updateSql = $"update nozzle set Status='{Status}' where NozzleIndex={NozzleIndex}"; //return db.ExecuteNonQuery(updateSql) > 0; return true; } public void Clear() { Product = null; Status = ENozzleStatus.IDLE; GlobalTray.NozzleTray.ChangeStatus(NozzleIndex, ESlotStatus.NotHave); } /// /// 真空吸操作 /// public void VacSuction(EIoOperate op,string className) { string logInfo = string.Empty; if (op == EIoOperate.Open) { Ops.On($"吸料真空{NozzleIndex}吸"); Thread.Sleep(GlobalVar.LoadNozzleOpenVacSuctionDelaytime); logInfo = $"{className} 打开吸料真空{NozzleIndex}吸"; MessageQueue.Instance.Insert(logInfo); } else { Ops.Off($"吸料真空{NozzleIndex}吸"); Thread.Sleep(GlobalVar.LoadNozzleCloseVacSuctionDelaytime); logInfo = $"{className} 关闭吸料真空{NozzleIndex}吸"; MessageQueue.Instance.Insert(logInfo); } } /// /// 真空破操作 /// public void VacBreak(EIoOperate op, string className) { string logInfo = string.Empty; if (op == EIoOperate.Open) { Ops.On($"吸料真空{NozzleIndex}破"); Thread.Sleep(GlobalVar.LoadNozzleOpenVacBreakDelaytime); logInfo = $"{className} 打开吸料真空{NozzleIndex}破"; MessageQueue.Instance.Insert(logInfo); } else { Ops.Off($"吸料真空{NozzleIndex}破"); Thread.Sleep(GlobalVar.LoadNozzleCloseVacBreakDelaytime); logInfo = $"{className} 打开吸料真空{NozzleIndex}破"; MessageQueue.Instance.Insert(logInfo); } } /// /// 通过真空吸判断吸嘴是否有产品 /// /// public bool HasProduct() { return Ops.IsOn($"吸料真空{NozzleIndex}检测"); } /// /// 获取当前吸嘴的位置 /// /// public double GetCurrentPos() { return Ops.GetCurPosition(NozzleName); } /// /// 切换吸嘴的状态 /// /// public void ChangeStatus(ESlotStatus status) { GlobalTray.NozzleTray.ChangeStatus(NozzleIndex, status); } } public static class NozzleManager { static SqliteHelper db = new SqliteHelper(); private static List nozzles; static NozzleManager() { nozzles = new List(); } public static void Init() { nozzles.Clear(); //string querySql = "select * from nozzle where enable=1"; string querySql = "select * from nozzle"; DataTable dt = db.GetDataTable(querySql); if (dt != null && dt.Rows.Count > 0) { foreach (DataRow dataRow in dt.Rows) { Nozzle nozzle = new Nozzle(); nozzle.NozzleIndex = int.Parse(dataRow["NozzleIndex"].ToString()); if (dataRow["enable"].ToString() == "0") { nozzle.Enable = false; } else { nozzle.Enable = true; nozzle.Status = ENozzleStatus.IDLE; } if (nozzle != null) { nozzles.Add(nozzle); } } } } /// /// 根据吸嘴的状态获取吸嘴 /// /// /// public static List GetNozzlesByStatus(ENozzleStatus status,int exceptNozzle=0) { if (nozzles != null && nozzles.Count > 0) { if(exceptNozzle==0) { if (status == ENozzleStatus.ToUnload) { return nozzles.Where(n => n.Status == status).OrderBy(n => n.NozzleIndex).ToList(); } else { return nozzles.Where(n => n.Status == status && n.Enable == true).OrderBy(n => n.NozzleIndex).ToList(); } } else { if (status == ENozzleStatus.ToUnload) { return nozzles.Where(n => n.Status == status && n.NozzleIndex!=exceptNozzle).OrderBy(n => n.NozzleIndex).ToList(); } else { return nozzles.Where(n => n.Status == status && n.NozzleIndex != exceptNozzle && n.Enable == true).OrderBy(n => n.NozzleIndex).ToList(); } } } return null; } /// /// 获取空闲的吸嘴(索引从小大) /// /// /// public static Nozzle GetIdelNozzle(int exceptNozzle=0) { if (nozzles != null && nozzles.Count > 0) { if(exceptNozzle==0) { if (nozzles.Where(n => n.Status == ENozzleStatus.IDLE).Count() > 0) { return nozzles.Where(n => n.Status == ENozzleStatus.IDLE && n.Enable == true).First(); } } else { if (nozzles.Where(n => n.Status == ENozzleStatus.IDLE && n.NozzleIndex!=exceptNozzle).Count() > 0) { return nozzles.Where(n => n.Status == ENozzleStatus.IDLE && n.NozzleIndex != exceptNozzle && n.Enable == true).First(); } } } return null; } /// /// 获取空闲吸嘴的数量 /// /// public static int GetIdleNozzleCount() { if (nozzles != null && nozzles.Count > 0) { return nozzles.Where(n => n.Status == ENozzleStatus.IDLE && n.Enable).Count(); } return -1; } /// /// 获取要测试的吸嘴 /// /// public static Nozzle GetToTestNozzle(int exceptNozzle=0) { if (nozzles != null && nozzles.Count > 0) { if(exceptNozzle==0) { var nozzlelist = nozzles.Where(n => n.Status == ENozzleStatus.ToTest); if (nozzlelist != null && nozzlelist.Count() > 0) { return nozzlelist.First(); } else return null; } else { var nozzlelist = nozzles.Where(n => n.Status == ENozzleStatus.ToTest && n.NozzleIndex!=exceptNozzle); if (nozzlelist != null && nozzlelist.Count() > 0) { return nozzlelist.First(); } else return null; } } return null; } /// /// 获取要放的吸嘴 /// /// public static Nozzle GetToUnloadNozzle() { if (nozzles != null && nozzles.Count > 0) { var nozzlelist = nozzles.Where(n => n.Status == ENozzleStatus.ToUnload); if (nozzlelist != null && nozzlelist.Count() > 0) { return nozzles.Where(n => n.Status == ENozzleStatus.ToUnload).First(); } else return null; } return null; } /// /// 保存吸嘴的状态 /// /// public static bool SaveAll() { string updateSql = ""; if (nozzles == null) return false; foreach (Nozzle nozzle in nozzles) { updateSql += $"update nozzle set " + $"status='{nozzle.Status.ToString()}'," + $" where NozzleIndex={nozzle.NozzleIndex}"; } return db.ExecuteNonQuery(updateSql) > 0; } /// /// 更新吸嘴的状态 /// /// public static bool UpdateNozzleStatus(int nozzleIndex) { string updateSql = ""; if (nozzles == null) return false; foreach (Nozzle nozzle in nozzles.Where(n => n.NozzleIndex == nozzleIndex).ToList()) { updateSql += $"update nozzle set " + $"status='{nozzle.Status.ToString()}'," + $" where NozzleIndex={nozzle.NozzleIndex}"; } return db.ExecuteNonQuery(updateSql) > 0; } /// /// 通过吸嘴的索引获取吸嘴 /// /// /// public static Nozzle GetNozzle(int nozzleIndex) { return nozzles.Where(n => n.NozzleIndex == nozzleIndex).FirstOrDefault(); } /// /// 获取所有的吸嘴 /// /// public static List GetAllNozzles() { return nozzles; } /// /// 获取排料吸嘴的高度差 /// /// /// public static double GetNozzleOffsetHeight(int nozzleIndex) { double val = 0.0; switch (nozzleIndex) { case 1: val = 0.0; break; case 2: val = GlobalVar.Nozzle2BaseHeight - GlobalVar.Nozzle1BaseHeight; break; case 3: val = GlobalVar.Nozzle3BaseHeight - GlobalVar.Nozzle1BaseHeight; break; case 4: val = GlobalVar.Nozzle4BaseHeight - GlobalVar.Nozzle1BaseHeight; break; } return val; } public static double GetNozzleOffsetX(int nozzleIndex) { double val = 0.0; switch (nozzleIndex) { case 1: val = 0.0; break; case 2: val = GlobalVar.Nozzle2ToNozzle1CenterOffsetX; break; case 3: val = GlobalVar.Nozzle3ToNozzle1CenterOffsetX; break; case 4: val = GlobalVar.Nozzle4ToNozzle1CenterOffsetX; break; } return val; } public static double GetNozzleOffsetY2(int nozzleIndex) { double val = 0.0; switch (nozzleIndex) { case 1: val = 0.0; break; case 2: val = GlobalVar.Nozzle2ToNozzle1CenterOffsetY2; break; case 3: val = GlobalVar.Nozzle3ToNozzle1CenterOffsetY2; break; case 4: val = GlobalVar.Nozzle4ToNozzle1CenterOffsetY2; break; } return val; } /// /// 获取吸嘴到相机中心的偏移X /// /// /// public static double GetNozzleToCameraOffsetX(int nozzleIndex) { switch (nozzleIndex) { case 1: return GlobalVar.Nozzle1ToCameraCenterOffsetX; case 2: return GlobalVar.Nozzle1ToCameraCenterOffsetX + GlobalVar.Nozzle2ToNozzle1CenterOffsetX; case 3: return GlobalVar.Nozzle1ToCameraCenterOffsetX + GlobalVar.Nozzle3ToNozzle1CenterOffsetX; case 4: return GlobalVar.Nozzle1ToCameraCenterOffsetX + GlobalVar.Nozzle4ToNozzle1CenterOffsetX; default: return 0; } } /// /// 获取吸嘴到相机中心的偏移Y2 /// /// /// public static double GetNozzleToCameraOffsetY2(int nozzleIndex) { switch (nozzleIndex) { case 1: return GlobalVar.Nozzle1ToCameraCenterOffsetY2; case 2: return GlobalVar.Nozzle1ToCameraCenterOffsetY2 + GlobalVar.Nozzle2ToNozzle1CenterOffsetY2; case 3: return GlobalVar.Nozzle1ToCameraCenterOffsetY2 + GlobalVar.Nozzle3ToNozzle1CenterOffsetY2; case 4: return GlobalVar.Nozzle1ToCameraCenterOffsetY2 + GlobalVar.Nozzle4ToNozzle1CenterOffsetY2; default: return 0; } } /// /// 获取吸嘴到治具的位置 /// /// /// /// public static TargetPosition GetNozzleToFixturePos(int fixtureIndex,int nozzleIndex) { TargetPosition targetPos = new TargetPosition(); targetPos = FixtureManager.GetFixtureGrabPos(fixtureIndex); MessageQueue.Instance.Insert($"治具拍照位:x:{targetPos.X},y:{targetPos.Y2}"); targetPos.X += GetNozzleToCameraOffsetX(nozzleIndex); targetPos.Y2 += GetNozzleToCameraOffsetY2(nozzleIndex); MessageQueue.Instance.Insert($"吸嘴{nozzleIndex}到相机X:x-{GetNozzleToCameraOffsetX(nozzleIndex)},吸嘴{nozzleIndex}到相机Y2-{GetNozzleToCameraOffsetY2(nozzleIndex)}"); return targetPos; } /// /// 获取某个吸嘴要取某个料盘的某个穴位的点位信息 /// /// /// /// /// public static TargetPosition GetToTraySlot(ETrayType trayType,int slotIndex,int nozzleIndex) { TargetPosition targetPosition=new TargetPosition(); SlotPoint curTakeSlotPoint = null; if(GlobalVar.EnableBeforePlaceProductGrab) { curTakeSlotPoint = TrayPointManager.GetSlotPoint(trayType, slotIndex); } else { if (trayType == ETrayType.Input) { curTakeSlotPoint = TrayPointManager.GetSlotPoint(trayType, slotIndex); } else { curTakeSlotPoint = TrayRunPointManager.GetSlotPoint(trayType, slotIndex); } } //MessageQueue.Instance.Insert($"基础loadx:{curTakeSlotPoint.X},loady2:{curTakeSlotPoint.Y}"); if (curTakeSlotPoint != null) { double nozzleOffsetX = GlobalVar.Nozzle1ToCameraCenterOffsetX + NozzleManager.GetNozzleOffsetX(nozzleIndex); double nozzleOffsetY = GlobalVar.Nozzle1ToCameraCenterOffsetY2 + NozzleManager.GetNozzleOffsetY2(nozzleIndex); MessageQueue.Instance.Insert($"吸嘴偏移x:{nozzleOffsetX},吸嘴偏移x:{nozzleOffsetY}"); targetPosition.X = curTakeSlotPoint.X + GlobalVar.Nozzle1ToCameraCenterOffsetX + NozzleManager.GetNozzleOffsetX(nozzleIndex); targetPosition.Y1 = GlobalVar.StockSideY1; targetPosition.Y2 = curTakeSlotPoint.Y + GlobalVar.Nozzle1ToCameraCenterOffsetY2 + NozzleManager.GetNozzleOffsetY2(nozzleIndex); return targetPosition; } return null; } /// /// 获取某个吸嘴到某个料盘取料位下方位置 /// /// /// /// public static double GetNozzleToTrayTakeProductPos(ETrayType trayType, int nozzleIndex) { double targetPos = 0.0; switch (trayType) { case ETrayType.Ng: targetPos = GlobalVar.NgTrayTakeProductZ; break; case ETrayType.ReTest: targetPos = GlobalVar.RetestTrayTakeProductZ; break; case ETrayType.Grr: targetPos = GlobalVar.GrrTrayTakeProductZ; break; case ETrayType.Ok: targetPos = GlobalVar.OkTrayTakeProductZ; break; case ETrayType.Input: targetPos = GlobalVar.InputTrayTakeProductZ; break; } //获取其他吸嘴和吸嘴1之间的高度差 double offsetHeight=GetNozzleOffsetHeight(nozzleIndex); return targetPos+offsetHeight; } /// /// 吸嘴回安全位 /// /// /// public static bool GotoSafePos(int nozzleIndex) { ErrorCode errCode = AxisControl.GetAxis($"NozzleZ{nozzleIndex}").MovePos(0, GlobalVar.WholeSpeed); if (errCode == ErrorCode.Ok) { return true; } else { //Msgbox.ShowDialog return false; } } /// /// 获取某个吸嘴到某个治具取料位下方位置 /// /// /// /// public static double GetFixtureTakeProductPos(int fixtureIndex, int nozzleIndex) { double targetPos = 0.0; switch (fixtureIndex) { case 1: targetPos = GlobalVar.Fixture1TakeProductZ; break; case 2: targetPos = GlobalVar.Fixture2TakeProductZ; break; case 3: targetPos = GlobalVar.Fixture3TakeProductZ; break; case 4: targetPos = GlobalVar.Fixture4TakeProductZ; break; case 5: targetPos = GlobalVar.Fixture5TakeProductZ; break; case 6: targetPos = GlobalVar.Fixture6TakeProductZ; break; } //获取其他吸嘴和吸嘴1之间的高度差 double offsetHeight = GetNozzleOffsetHeight(nozzleIndex); return targetPos + offsetHeight; } /// /// 吸嘴运动 /// /// /// public static bool Go(Nozzle nozzle,double pos,int speed) { ErrorCode errCode = AxisControl.GetAxis($"NozzleZ{nozzle.NozzleIndex}").MovePos(pos, GlobalVar.WholeSpeed); if (errCode == ErrorCode.Ok) { return true; } else { AlarmEntity alarmEntity = AlarmCollection.Get($"NozzleZ{nozzle.NozzleIndex}运动异常报警"); Msgbox.ShowDialog(alarmEntity, EButtonType.Retry); return false; } } } }