--20191118更新程序,程序調整為使用狀態機的方式實現
public void CircleMain() { while(true) { Thread.Sleep(100); #region 超時管理定時器計數 if (delay100Ms < int.MaxValue) { delay100Ms++; } #endregion #region 數據采集及變量映射 var result = ModbusPlc.ReadDiscrete("0", 7); if (!result.IsSuccess) { eSystemStatus = E_system_status.Error; continue; } bool[] mappingResult = result.Content; bReset = mappingResult[0]; bStop = mappingResult[1]; bBeforePrintSensor = mappingResult[2]; bPrintSensor = mappingResult[3]; bAfterPrintSensor = mappingResult[4]; bBeforeSingal = mappingResult[5]; bAfterSingal = mappingResult[6]; #endregion #region 急停按鈕 if (bStop==false) { eSystemStatus = E_system_status.Error; } #endregion #region 狀態機 switch (eSystemStatus) { case E_system_status.Idle: //開始前打印位置有產品,需要取出 if (bPrintSensor) { eSystemStatus = E_system_status.Error; statusMsg = "開始前打印位置有產品,需要取出后才能運行!"; } else { ModbusPlc.WriteCoil(FeedProductAddress, true); //前道要板命令 eSystemStatus = E_system_status.Feed; } break; case E_system_status.Feed: if (bBeforePrintSensor) { ModbusPlc.WriteCoil(MoveBeltAddress, true); ModbusPlc.WriteCoil(FeedProductAddress, false); ModbusPlc.WriteCoil(PrintPosCylinderAddress, true); eSystemStatus = E_system_status.Stable; delay100Ms = 0; } break; case E_system_status.Stable: //5S后還沒有運行到打印位置,可能卡板或者傳感器失效 if (delay100Ms > 30) { eSystemStatus = E_system_status.Error; statusMsg = "3S后還沒有運行到打印位置,可能卡板或者傳感器失效"; } if (bPrintSensor) { eSystemStatus = E_system_status.Ready; //正式噴碼前觸發一次噴印 TcpPrinter.SendData(new byte[] { 0x94, 0x00, 0x00, 0x94 }); delay100Ms = 0; } break; case E_system_status.Ready: if (delay100Ms > 10) { ModbusPlc.WriteCoil(MoveBeltAddress, false); eSystemStatus = E_system_status.Printing; statusMsg = "開始打印......"; //TcpClient.SendData(_startPrint); } break; case E_system_status.Printing: if (nRouteIndex < routeList.Count) { if (ePrintStep == EPrintStep.PrintIdle) { SendPrintPoint(impossiblePointList, false); MoveNextPoint(routeList[nRouteIndex].startX, routeList[nRouteIndex].startY, routeList[nRouteIndex].Angle); ePrintStep = EPrintStep.SendStartPoint; bMoveDone = false; } else if (ePrintStep == EPrintStep.SendStartPoint) { GetStatusOfRtexController(); if (bMoveDone) { ePrintStep = EPrintStep.MoveDoneStartPoint; } } else if (ePrintStep == EPrintStep.MoveDoneStartPoint) { ePrintStep = EPrintStep.SendEndPoint; SendPrinterData(routeList[nRouteIndex]); SendPrintPoint(routeList[nRouteIndex].printPointList, true); MoveNextPoint(routeList[nRouteIndex].endX, routeList[nRouteIndex].endY, routeList[nRouteIndex].Angle); bMoveDone = false; } else if (ePrintStep == EPrintStep.SendEndPoint) { GetStatusOfRtexController(); if (bMoveDone) { ePrintStep = EPrintStep.PrintIdle; nRouteIndex++; } } } else { eSystemStatus = E_system_status.PrintPreEnd; nRouteIndex = 0; } break; case E_system_status.PrintPreEnd: if (bAfterSingal) { MoveToHome(); ModbusPlc.WriteCoil(PrintPosCylinderAddress, false); //氣缸下降 ModbusPlc.WriteCoil(MoveBeltAddress, true); //輸送帶啟動 eSystemStatus = E_system_status.PrintEnd; delay100Ms = 0; } break; case E_system_status.PrintEnd: //卡板或者傳感器失效 if (delay100Ms > 50) { eSystemStatus = E_system_status.Error; statusMsg = "輸出卡板或者后端傳感器失效"; } if (!bAfterSingal) { ModbusPlc.WriteCoil(MoveBeltAddress, false); eSystemStatus = E_system_status.Idle; statusMsg = "打印完成,設備等待打印"; } break; case E_system_status.Error: ModbusPlc.WriteCoil(RedLampAddress, true); ModbusPlc.WriteCoil(GreenLampAddress, false); ModbusPlc.WriteCoil(AlarmBeepAddress, true); if(bReset) { ModbusPlc.WriteCoil(RedLampAddress, false); ModbusPlc.WriteCoil(GreenLampAddress, true); ModbusPlc.WriteCoil(AlarmBeepAddress, false); eSystemStatus = E_system_status.Idle; statusMsg = "已復位"; } break; default: break; } #endregion #region 顯示狀態 Action<string> actionDisplayStatus = (msg) => { this.lblStatus.Text = msg; }; Invoke(actionDisplayStatus, statusMsg + " " + ePrintStep.ToString()); #endregion } }
總結下面幾點
1.與下位機的連接盡量保持長連接,每次用到的時候去連接的話,過一段時間速度明顯下降,什么問題並沒有找到
2.C#中的BitConverter 類可以非常方便的在字節與其他類型之間進行轉換
3.周期性操作使用while循環,避免使用timer定時器
4.操作一些標志位的操作,盡量放到一個線程中,多個線程同時操作變量容易產生奇怪的錯誤
