663 lines
19 KiB
C#
663 lines
19 KiB
C#
/*
|
|
* Copyright Copyright 2016, Steamware s.r.l. & CMS s.p.a.
|
|
*
|
|
* Based on data, code and example by MTC consortium & System Insights, Inc.
|
|
*
|
|
* */
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace MTC_Sim
|
|
{
|
|
using MTConnect;
|
|
using System.Configuration;
|
|
using System.Diagnostics;
|
|
|
|
public partial class CMS_MachineSim : Form
|
|
{
|
|
/// <summary>
|
|
/// adapter globale
|
|
/// </summary>
|
|
Adapter mAdapter = new Adapter();
|
|
|
|
/// <summary>
|
|
/// D.D1.AVAIL - disponibilità
|
|
/// </summary>
|
|
Event mAvail = new Event("avail");
|
|
/// <summary>
|
|
/// XX.XX.STOP - stop per pressione emergenze
|
|
/// </summary>
|
|
Event mEStop = new Event("estop");
|
|
|
|
/// <summary>
|
|
/// D.D1.NAME
|
|
/// </summary>
|
|
Event mName = new Event("Name");
|
|
/// <summary>
|
|
/// D.D1.ID
|
|
/// </summary>
|
|
Event mID = new Event("ID");
|
|
/// <summary>
|
|
/// D.D1.UUID
|
|
/// </summary>
|
|
Event mUUID = new Event("UUID");
|
|
/// <summary>
|
|
/// D.D1.SAMPLE_INTERVAL
|
|
/// </summary>
|
|
Event mSampleInt = new Event("SampleInt");
|
|
|
|
|
|
/// <summary>
|
|
/// CURR_PROG - programma in esecuzione
|
|
/// </summary>
|
|
Event mProgram = new Event("CurrProg");
|
|
/// <summary>
|
|
/// CURR_PROG_ROWNUM - programma in esecuzione
|
|
/// </summary>
|
|
Event mProgRowNum = new Event("CurrProg_RowNum");
|
|
/// <summary>
|
|
/// PartId - particolare prodotto
|
|
/// </summary>
|
|
Event mPartId = new Event("PartID");
|
|
/// <summary>
|
|
/// CURR_PROG_ROWNUM - programma in esecuzione
|
|
/// </summary>
|
|
Event mOperator = new Event("OperatorId");
|
|
|
|
|
|
/// <summary>
|
|
/// D.D1.P1.PATH_MODE - modalità esecuzione
|
|
/// </summary>
|
|
Event mMode = new Event("mode");
|
|
/// <summary>
|
|
/// D.D1.P1.PATH_STATUS - status macchina
|
|
/// </summary>
|
|
Event mExec = new Event("exec");
|
|
|
|
Strobe STROBE_PLC = 0;
|
|
Strobe STROBE_ADP = 0;
|
|
|
|
/// <summary>
|
|
/// M_CODE
|
|
/// </summary>
|
|
Event mCod_M = new Event("Cod_M");
|
|
/// <summary>
|
|
/// S_CODE
|
|
/// </summary>
|
|
Event mCod_S = new Event("Cod_S");
|
|
/// <summary>
|
|
/// T_CODE
|
|
/// </summary>
|
|
Event mCod_T = new Event("Cod_T");
|
|
|
|
|
|
Event mFunctionalMode = new Event("func");
|
|
Message mMessage = new Message("message");
|
|
|
|
Sample mPosition = new Sample("xPosition");
|
|
Sample mxLoad = new Sample("xLoad");
|
|
|
|
Sample mSpeed = new Sample("sSpeed");
|
|
Sample mcLoad = new Sample("sLoad");
|
|
|
|
Condition mSystem = new Condition("system");
|
|
Condition mTemp = new Condition("temp");
|
|
Condition mOverload = new Condition("overload");
|
|
Condition mTravel = new Condition("travel");
|
|
Condition mFillLevel = new Condition("cool_low", true);
|
|
|
|
Event mCommonVariable = new Event("cv");
|
|
|
|
public CMS_MachineSim()
|
|
{
|
|
InitializeComponent();
|
|
// carico i default values
|
|
setDefaults();
|
|
|
|
// item disponibilità
|
|
mAdapter.AddDataItem(mAvail);
|
|
mAvail.Value = "AVAILABLE";
|
|
// emergency stop
|
|
mAdapter.AddDataItem(mEStop);
|
|
|
|
// nome ed ID/UUID - e li imposto...
|
|
mAdapter.AddDataItem(mName);
|
|
mAdapter.AddDataItem(mID);
|
|
mAdapter.AddDataItem(mUUID);
|
|
|
|
// programma e produzione
|
|
mAdapter.AddDataItem(mProgram);
|
|
mAdapter.AddDataItem(mProgRowNum);
|
|
mAdapter.AddDataItem(mPartId);
|
|
mAdapter.AddDataItem(mOperator);
|
|
|
|
// codici speciali M/S/T
|
|
mAdapter.AddDataItem(mCod_M);
|
|
mAdapter.AddDataItem(mCod_S);
|
|
mAdapter.AddDataItem(mCod_T);
|
|
|
|
|
|
mAdapter.AddDataItem(mMode);
|
|
mAdapter.AddDataItem(mExec);
|
|
|
|
mAdapter.AddDataItem(mFunctionalMode);
|
|
mAdapter.AddDataItem(mMessage);
|
|
|
|
mAdapter.AddDataItem(mPosition);
|
|
mAdapter.AddDataItem(mxLoad);
|
|
|
|
mAdapter.AddDataItem(mSpeed);
|
|
mAdapter.AddDataItem(mcLoad);
|
|
|
|
mAdapter.AddDataItem(mSystem);
|
|
mAdapter.AddDataItem(mTemp);
|
|
mAdapter.AddDataItem(mOverload);
|
|
mAdapter.AddDataItem(mTravel);
|
|
mAdapter.AddDataItem(mFillLevel);
|
|
|
|
mAdapter.AddDataItem(mCommonVariable);
|
|
|
|
string[] row = { "1", "2", "3", "4" };
|
|
commonVariables.Rows.Add(row);
|
|
}
|
|
/// <summary>
|
|
/// impostazione valori defaults
|
|
/// </summary>
|
|
private void setDefaults()
|
|
{
|
|
stop.Enabled = false;
|
|
dump.Enabled = false;
|
|
|
|
D1_NAME.Text = utils.CRS("D1_NAME");
|
|
D1_ID.Text = utils.CRS("D1_ID");
|
|
D1_UUID.Text = utils.CRS("D1_UUID");
|
|
program.Text = utils.CRS("D1_PROGRAM");
|
|
PROG_ROW_NUM.Text = "0";
|
|
partID.Text = utils.CRS("PartID");
|
|
OPERATOR_ID.Text = "M9999";
|
|
STATUS_PLC_ADP.Text = binaryForm(utils.CRI("STATUS_PLC_ADP"));
|
|
STATUS_ADP_PLC.Text = binaryForm(utils.CRI("STATUS_ADP_PLC"));
|
|
}
|
|
|
|
protected string binaryForm(int valore)
|
|
{
|
|
string answ = "";
|
|
try
|
|
{
|
|
answ = string.Format(new BinaryFormatter(), "{0:B}", valore);
|
|
}
|
|
catch
|
|
{ }
|
|
return answ;
|
|
}
|
|
|
|
|
|
private void start_Click(object sender, EventArgs e)
|
|
{
|
|
// Start the adapter lib with the port number in the text box
|
|
mAdapter.Port = Convert.ToInt32(port.Text);
|
|
mAdapter.Start();
|
|
|
|
// Disable start and enable stop/dump.
|
|
start.Enabled = false;
|
|
stop.Enabled = true;
|
|
dump.Enabled = true;
|
|
|
|
// Start our periodic timer
|
|
gather.Interval = utils.CRI("timerInt");
|
|
gather.Enabled = true;
|
|
|
|
mSystem.Normal();
|
|
mTemp.Normal();
|
|
mOverload.Normal();
|
|
mTravel.Normal();
|
|
mFillLevel.Normal();
|
|
|
|
//mWave.StartRecording();
|
|
}
|
|
|
|
private void stop_Click(object sender, EventArgs e)
|
|
{
|
|
// Stop everything...
|
|
mAdapter.Stop();
|
|
stop.Enabled = false;
|
|
dump.Enabled = false;
|
|
start.Enabled = true;
|
|
gather.Enabled = false;
|
|
}
|
|
|
|
private void gather_Tick(object sender, EventArgs e)
|
|
{
|
|
mAdapter.Begin();
|
|
|
|
// eseguo eventuali simulazioni x dati/flags
|
|
simulateData();
|
|
|
|
// nome
|
|
mName.Value = D1_NAME.Text;
|
|
mID.Value = D1_ID.Text;
|
|
mUUID.Value = D1_UUID.Text;
|
|
|
|
// programma
|
|
mProgram.Value = program.Text;
|
|
mProgRowNum.Value = PROG_ROW_NUM.Text;
|
|
mPartId.Value = partID.Text;
|
|
mOperator.Value = OPERATOR_ID.Text;
|
|
|
|
// SE presente recupero Cod_M/S/T
|
|
checkCodM();
|
|
checkCodS();
|
|
checkCodT();
|
|
|
|
|
|
|
|
if (estop.Checked)
|
|
mEStop.Value = "TRIGGERED";
|
|
else
|
|
mEStop.Value = "ARMED";
|
|
|
|
if (automatic.Checked)
|
|
mMode.Value = "AUTOMATIC";
|
|
else if (mdi.Checked)
|
|
mMode.Value = "MANUAL_DATA_INPUT";
|
|
else if (edit.Checked)
|
|
mMode.Value = "EDIT";
|
|
else
|
|
mMode.Value = "MANUAL";
|
|
|
|
if (running.Checked)
|
|
mExec.Value = "ACTIVE";
|
|
else if (feedhold.Checked)
|
|
mExec.Value = "FEED_HOLD";
|
|
else if (stopped.Checked)
|
|
mExec.Value = "STOPPED";
|
|
else if (ready.Checked)
|
|
mExec.Value = "READY";
|
|
|
|
mFunctionalMode.Value = functionalMode.Text;
|
|
|
|
if (messageCode.Text.Length > 0)
|
|
{
|
|
mMessage.Code = messageCode.Text;
|
|
mMessage.Value = messageText.Text;
|
|
}
|
|
|
|
mxLoad.Value = xLoad.Value;
|
|
mcLoad.Value = cLoad.Value;
|
|
|
|
if (flazBat.Checked)
|
|
mSystem.Add(Condition.Level.FAULT, "Yur Flaz Bat is flapping", "FLAZBAT");
|
|
if (something.Checked)
|
|
mSystem.Add(Condition.Level.WARNING, "Something went wrong", "AKAK");
|
|
if (noProgram.Checked)
|
|
mSystem.Add(Condition.Level.FAULT, "No program loaded", "PROG");
|
|
|
|
if (overtemp.Checked)
|
|
mTemp.Add(Condition.Level.WARNING, "Temperature is too high", "OT");
|
|
if (overload.Checked)
|
|
mOverload.Add(Condition.Level.FAULT, "Axis overload", "OL");
|
|
if (travel.Checked)
|
|
mTravel.Add(Condition.Level.FAULT, "Travel outside boundaries", "OP");
|
|
|
|
DataGridViewColumnCollection headers = commonVariables.Columns;
|
|
DataGridViewCellCollection cells = commonVariables.Rows[0].Cells;
|
|
string result = "";
|
|
|
|
for (int i = 0; i < cells.Count; i++)
|
|
{
|
|
result += headers[i].HeaderText + ":" + cells[i].Value + " ";
|
|
}
|
|
|
|
mCommonVariable.Value = result;
|
|
|
|
mAdapter.SendChanged();
|
|
}
|
|
|
|
|
|
private void checkCodM()
|
|
{
|
|
if (utils.IsSetAll(STROBE_PLC, Strobe.M_CODE))
|
|
{
|
|
mCod_M.Value = getNextMCode;
|
|
// se il valore è "" allora alzo flag lettura...
|
|
if (mCod_M.Value.ToString() == "") STROBE_ADP = STROBE_ADP | Strobe.M_CODE;
|
|
// refresh stringhe
|
|
refreshCodeMST();
|
|
}
|
|
else
|
|
{
|
|
// resetto eventuali flag di lettura...
|
|
if (utils.IsSetAll(STROBE_ADP, Strobe.M_CODE))
|
|
{
|
|
STROBE_ADP -= Strobe.M_CODE;
|
|
}
|
|
}
|
|
}
|
|
private void checkCodS()
|
|
{
|
|
if (utils.IsSetAll(STROBE_PLC, Strobe.S_CODE))
|
|
{
|
|
mCod_S.Value = getNextSCode;
|
|
// se il valore è "" allora alzo flag lettura...
|
|
if (mCod_S.Value.ToString() == "") STROBE_ADP = STROBE_ADP | Strobe.S_CODE;
|
|
// refresh stringhe
|
|
refreshCodeMST();
|
|
}
|
|
else
|
|
{
|
|
// resetto eventuali flag di lettura...
|
|
if (utils.IsSetAll(STROBE_ADP, Strobe.S_CODE))
|
|
{
|
|
STROBE_ADP -= Strobe.S_CODE;
|
|
}
|
|
}
|
|
}
|
|
private void checkCodT()
|
|
{
|
|
if (utils.IsSetAll(STROBE_PLC, Strobe.T_CODE))
|
|
{
|
|
mCod_T.Value = getNextTCode;
|
|
// se il valore è "" allora alzo flag lettura...
|
|
if (mCod_T.Value.ToString() == "") STROBE_ADP = STROBE_ADP | Strobe.T_CODE;
|
|
// refresh stringhe
|
|
refreshCodeMST();
|
|
}
|
|
else
|
|
{
|
|
// resetto eventuali flag di lettura...
|
|
if (utils.IsSetAll(STROBE_ADP, Strobe.T_CODE))
|
|
{
|
|
STROBE_ADP -= Strobe.T_CODE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void message_Leave(object sender, EventArgs e)
|
|
{
|
|
mMessage.Value = messageText.Text;
|
|
mMessage.ForceChanged();
|
|
mAdapter.SendChanged();
|
|
}
|
|
|
|
private void xLoad_Scroll(object sender, ScrollEventArgs e)
|
|
{
|
|
xLoadValue.Text = xLoad.Value.ToString();
|
|
}
|
|
|
|
private void xPosition_Scroll(object sender, ScrollEventArgs e)
|
|
{
|
|
mPosition.Value = xPosition.Value;
|
|
mAdapter.SendChanged();
|
|
|
|
xPositionValue.Text = xPosition.Value.ToString();
|
|
}
|
|
|
|
private void cLoad_Scroll(object sender, ScrollEventArgs e)
|
|
{
|
|
cLoadValue.Text = cLoad.Value.ToString();
|
|
}
|
|
|
|
private void cSpeed_Scroll(object sender, ScrollEventArgs e)
|
|
{
|
|
mSpeed.Value = cSpeed.Value * 100.0;
|
|
mAdapter.SendChanged();
|
|
|
|
cSpeedValue.Text = mSpeed.Value.ToString();
|
|
}
|
|
|
|
private void coolant_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (coolant.Checked)
|
|
mFillLevel.Add(Condition.Level.WARNING, "Coolant Low", "COOL", "LOW");
|
|
else
|
|
mFillLevel.Clear("COOL");
|
|
mAdapter.SendChanged();
|
|
}
|
|
|
|
private void cuttingToolButton_Click(object sender, EventArgs e)
|
|
{
|
|
#if false
|
|
CuttingToolForm toolWindow = new CuttingToolForm(mAdapter);
|
|
toolWindow.Show(this);
|
|
#endif
|
|
}
|
|
|
|
// apro eseguibile dump
|
|
private void dump_Click(object sender, EventArgs e)
|
|
{
|
|
string path = Application.StartupPath;
|
|
Process.Start(string.Format(@"{0}\..\..\dump\dump.exe", path));
|
|
}
|
|
|
|
|
|
#region area metodi comunicazione con PLC/CNC
|
|
|
|
/// <summary>
|
|
/// recupera primo elemento codaM
|
|
/// </summary>
|
|
protected string getNextMCode
|
|
{
|
|
get
|
|
{
|
|
string answ = "";
|
|
if (codaM.Count > 0)
|
|
{
|
|
// accodo codice M...
|
|
answ = codaM.First();
|
|
// tolgo elemento
|
|
codaM.RemoveAt(0);
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// recupera primo elemento codaS
|
|
/// </summary>
|
|
protected string getNextSCode
|
|
{
|
|
get
|
|
{
|
|
string answ = "";
|
|
if (codaS.Count > 0)
|
|
{
|
|
// accodo codice S...
|
|
answ = codaS.First();
|
|
// tolgo elemento
|
|
codaS.RemoveAt(0);
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// recupera primo elemento codaT
|
|
/// </summary>
|
|
protected string getNextTCode
|
|
{
|
|
get
|
|
{
|
|
string answ = "";
|
|
if (codaT.Count > 0)
|
|
{
|
|
// accodo codice T...
|
|
answ = codaT.First();
|
|
// tolgo elemento
|
|
codaT.RemoveAt(0);
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region classi x simulazione valori vari
|
|
|
|
/// <summary>
|
|
/// simula alcuni dati generando ad esempio numeri casuali... SE abilitato
|
|
/// </summary>
|
|
private void simulateData()
|
|
{
|
|
if (enableDataSim.Checked)
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
Random rnd = new Random();
|
|
PROG_ROW_NUM.Text = rnd.Next(1, 10000).ToString();
|
|
// ora controllo se ci siano eventi M/S/T x alzare flag...
|
|
if (codaM.Count > 0) STROBE_PLC = STROBE_PLC | Strobe.M_CODE;
|
|
if (codaS.Count > 0) STROBE_PLC = STROBE_PLC | Strobe.S_CODE;
|
|
if (codaT.Count > 0) STROBE_PLC = STROBE_PLC | Strobe.T_CODE;
|
|
|
|
// controllo se ci sia il flag di lettura di un evento M/S/T nel qual caso lo abbasso...
|
|
if (STROBE_ADP > 0) STROBE_PLC -= STROBE_ADP;
|
|
|
|
// aggiorno visualizzazione strobe!
|
|
STATUS_PLC_ADP.Text = binaryForm((int)STROBE_PLC);
|
|
STATUS_ADP_PLC.Text = binaryForm((int)STROBE_ADP);
|
|
|
|
#if false
|
|
// verifica se ci sia un evento strobe da recepire...
|
|
if (STATUS_PLC_ADP.Text.IndexOf("1") >= 0)
|
|
{
|
|
// verifica SE sia stato recepito da adapter...
|
|
if (STATUS_ADP_PLC.Text == STATUS_PLC_ADP.Text)
|
|
{
|
|
// in questo caso ripulisco da PLC...
|
|
STATUS_PLC_ADP.Text = binaryForm(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// se era ancora sollevato strobe lettura lo abbasso...
|
|
if (STATUS_ADP_PLC.Text.IndexOf("1") >= 0)
|
|
{
|
|
STATUS_ADP_PLC.Text = binaryForm(0);
|
|
}
|
|
else
|
|
{
|
|
// se il numero è < 1000 (10%) imposto strobe...
|
|
STATUS_PLC_ADP.Text = binaryForm(rnd.Next(1, 10000000));
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
protected List<string> codaM = new List<string>();
|
|
protected List<string> codaS = new List<string>();
|
|
protected List<string> codaT = new List<string>();
|
|
|
|
/// <summary>
|
|
/// aggiorna visualizzazione code...
|
|
/// </summary>
|
|
private void refreshCodeMST()
|
|
{
|
|
lblCodaM.Text = string.Join(",", codaM.ToArray());
|
|
lblCodaT.Text = string.Join(",", codaT.ToArray());
|
|
lblCodaS.Text = string.Join(",", codaS.ToArray());
|
|
}
|
|
|
|
private void accodaCodM()
|
|
{
|
|
if (addCodM.Text.Trim() != "")
|
|
{
|
|
codaM.Add(addCodM.Text.Trim());
|
|
addCodM.Text = "";
|
|
}
|
|
refreshCodeMST();
|
|
}
|
|
private void accodaCodS()
|
|
{
|
|
if (addCodS.Text.Trim() != "")
|
|
{
|
|
codaS.Add(addCodS.Text.Trim());
|
|
addCodS.Text = "";
|
|
}
|
|
refreshCodeMST();
|
|
}
|
|
private void accodaCodT()
|
|
{
|
|
if (addCodT.Text.Trim() != "")
|
|
{
|
|
codaT.Add(addCodT.Text.Trim());
|
|
addCodT.Text = "";
|
|
}
|
|
refreshCodeMST();
|
|
}
|
|
|
|
private void addCodM_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
// accodo testo
|
|
accodaCodM();
|
|
}
|
|
else if (e.KeyCode == Keys.Escape)
|
|
{
|
|
// svuoto!
|
|
addCodM.Text = "";
|
|
}
|
|
}
|
|
private void addCodM_Leave(object sender, EventArgs e)
|
|
{
|
|
accodaCodM();
|
|
}
|
|
|
|
private void addCodS_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
// accodo testo
|
|
accodaCodS();
|
|
}
|
|
else if (e.KeyCode == Keys.Escape)
|
|
{
|
|
// svuoto!
|
|
addCodS.Text = "";
|
|
}
|
|
}
|
|
|
|
private void addCodS_Leave(object sender, EventArgs e)
|
|
{
|
|
accodaCodS();
|
|
}
|
|
|
|
|
|
private void addCodT_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
|
|
if (e.KeyCode == Keys.Enter)
|
|
{
|
|
// accodo testo
|
|
accodaCodT();
|
|
}
|
|
else if (e.KeyCode == Keys.Escape)
|
|
{
|
|
// svuoto!
|
|
addCodT.Text = "";
|
|
}
|
|
}
|
|
private void addCodT_Leave(object sender, EventArgs e)
|
|
{
|
|
accodaCodT();
|
|
}
|
|
|
|
|
|
#endregion
|
|
}
|
|
}
|