Files
CMS-MTConn/MTC_Sim/MTC_Sim/AdapterESA.cs
T
2016-07-19 15:28:12 +02:00

532 lines
20 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SCMCncLib;
using XSimGph;
using System.Windows.Forms;
using System.Threading;
using System.IO;
namespace MTC_Adapter
{
public class AdapterESA : AdapterGeneric
{
/// <summary>
/// oggetto onnessione ESA
/// </summary>
protected thdNcEsaGvKvara ncDevice;
/// <summary>
/// thread del processo comunicazione esa
/// </summary>
protected Thread thdDevice;
/// <summary>
/// estende l'init della classe base...
/// </summary>
/// <param name="caller"></param>
/// <param name="adpConf"></param>
public AdapterESA(MainForm caller, AdapterConf adpConf) : base(caller, adpConf)
{
string iniPath = string.Format(@"{0}\{1}\{2}", Application.StartupPath, utils.CRS("adapterConfPath"), utils.CRS("defaultEsaFile"));
if (utils.CRB("verbose")) lg.Info("Start init Adapter ESA dal file {0}", iniPath);
IniFiles.IniFile EsaIni = new IniFiles.IniFile(iniPath);
ncDevice = new thdNcEsaGvKvara(EsaIni);
// inizializzo posizioni assi...
prevPosAxis = new double[adpConf.nAxis];
prevDirAxis = new int[adpConf.nAxis];
// verifica avvio...
if (utils.CRB("verbose")) lg.Info("ESA: tryConnect");
tryConnect();
#if false
// avvio il thread...
if (utils.CRB("verbose")) lg.Info("ESA: try avvio thread");
// !!! 2016.05.25 verificare funzionamento thread... eventualmente portare entro metodo questo thread con suoi timing...
thdDevice = new Thread(ncDevice.Execute);
#endif
if (utils.CRB("verbose")) lg.Info("End init Adapter ESA");
}
public override void tryDisconnect()
{
base.tryDisconnect();
// disconnetto
ncDevice.Disconnect();
}
public override void tryConnect()
{
base.tryConnect();
// se non già connesso provo a connettermi...
if (!ncDevice.Connected)
{
// provo a collegarmi
if (!ncDevice.Connect())
{
//altrimenti disconnette...
ncDevice.Disconnect();
}
}
}
/// <summary>
/// Verifico connessione ESA...
/// </summary>
/// <returns></returns>
public override bool connectionOk
{
get
{
return ncDevice.Connected;
}
}
/// <summary>
/// Effettuo lettura memorie strobe/status
/// </summary>
public override void getStrobeAndAckStatus()
{
base.getStrobeAndAckStatus();
}
public override void getGlobalData()
{
base.getGlobalData();
// accodo dati path in DataMonitor......
StringBuilder sb = new StringBuilder();
if (connectionOk)
{
// leggo TUTTO il blocco di memoria
inizio = DateTime.Now;
ncDevice.ReadBuffer();
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R-PLC_FullMemoryRead", ncDevice.PLC_MemoryRead.Length), DateTime.Now.Subtract(inizio).Ticks);
}
else
{
lg.Error("Errore connessione mancante in getStrobeAndAckStatus");
}
// dati override feed/speed...
Byte v82 = ncDevice.PLC_MemoryAreaV[14];
Byte v83 = ncDevice.PLC_MemoryAreaV[15];
// 2 byte x speed da copiare...
byte[] tmpByte = new byte[2];
Buffer.BlockCopy(ncDevice.PLC_MemoryAreaV, 16, tmpByte, 0, 2);
short v84 = BitConverter.ToInt16(tmpByte, 0);
// lista allarmi PLC/CNC
Byte v87 = ncDevice.PLC_MemoryAreaV[19]; // Allarme CN (almeno 1?!?)
// -------------------------------------------
// recupero dati Feed/Speed/override
// FeedOver: 100% = 213 (il pannello è 0-120 --> 0-255, quindi 100% è 100/120*255=213)
FeedRateOver = Convert.ToInt16((decimal)(v82 * 100) / 213);
sb.AppendLine(string.Format("FeedRateOver: {0} %", FeedRateOver));
// SpeedOver: 50% = 128
SpeedRateOver = Convert.ToInt16((decimal)(v83 * 100) / 255);
sb.AppendLine(string.Format("SpeedRateOver: {0} %", SpeedRateOver));
// Speed S5000 OK!!!
SpeedRate = v84;
sb.AppendLine(string.Format("SpeedRate: {0} rpm", SpeedRate));
// -------------------------------------------
// da recuperare da qualche parte?!?
UnOpLoad = 0;
sb.AppendLine(string.Format("Load: {0}", UnOpLoad));
// -------------------------------------------
// recupero dati dai contatori EOK
bool needSave = false;
// ore totali accensione
int MinMaccOn = (int)ncDevice.PLC_MemoryAreaEOK[0];
int OreMaccOn = (int)ncDevice.PLC_MemoryAreaEOK[1];
istOreMaccOn = OreMaccOn + (double)MinMaccOn / 60;
needSave = procOreMaccOn(needSave);
// ore totali lavoro
int MinMaccLav = (int)ncDevice.PLC_MemoryAreaEOK[2];
int OreMaccLav = (int)ncDevice.PLC_MemoryAreaEOK[3];
istOreMaccLav = OreMaccLav + (double)MinMaccLav / 60;
needSave = procOreMaccLav(needSave);
// giri totali degli elettromandrini!
for (int i = 0; i < currAdpConf.nUnOp; i++)
{
istGiriElettrom[i] = (uint)ncDevice.PLC_MemoryAreaEOK[4 + i];
}
needSave = procGiriTotUnOp(needSave);
needSave = procNumCU(needSave);
// spostamento totale assi!
for (int i = 0; i < 3; i++)
{
// primo è metri, secondo km (moltiplico x 1000)
istDistMovAssi[i] = ncDevice.PLC_MemoryAreaEOK[8 + 2 * i] + ncDevice.PLC_MemoryAreaEOK[9 + 2 * i] * 1000;
}
needSave = procMovTotAssi(needSave);
needSave = procPartId(needSave);
needSave = procPzProd(needSave);
needSave = procNumInvAssi(needSave);
needSave = procVacPump(needSave);
needSave = procVacAct(needSave);
needSave = procLubro(needSave);
// salvo se necessario!
if (needSave) parentForm.persistXmlData();
// -------------------------------------------
// copio allarmi in vettore generale AlarFlags (dove lo gestisce)...
Buffer.BlockCopy(ncDevice.PLC_MemAreaAlarm_tmp, 0, AlarmFlags, 0, ncDevice.PLC_MemAreaAlarm_tmp.Length);
parentForm.dataMonitor = sb.ToString();
}
/// <summary>
/// Path percorso file prod
/// </summary>
protected string ScmProdFileName
{
get
{
return string.Format(@"{0}\{1}", Application.StartupPath, utils.CRS("ScmProdFile"));
}
}
/// <summary>
/// Oggetto elenco dati produzione
/// </summary>
public datiProdSCM[] elencoDatiProd;
/// <summary>
/// leggo altri file:
/// - dati produzione
/// </summary>
public override void getSlowChangingData()
{
base.getSlowChangingData();
// carico dati x Maintenance
if (utils.CRB("verbose")) lg.Info(string.Format("Inizio caricamento file dati produzione ({0})", ScmProdFileName));
int totRighe = 0;
string linea;
// controllo se file esista, altrimenti loggo errore!
if (!File.Exists(ScmProdFileName))
{
lg.Error(string.Format("ATTENZIONE! file dati produzione ({0}) non trovato!", ScmProdFileName));
}
else
{
totRighe = File.ReadLines(ScmProdFileName).Count();
// creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
datiProdSCM[] elencoDatiProdNew = new datiProdSCM[File.ReadLines(ScmProdFileName).Count()];
// carica da file...
System.IO.StreamReader file = new System.IO.StreamReader(ScmProdFileName);
// leggo 1 linea alla volta...
int rumRiga = 0;
while ((linea = file.ReadLine()) != null)
{
// SE non è un valore totale... lungh > 50 e 22 virgole (23 valori)
if (linea.Length > 50)
{
// comma separated!
elencoDatiProdNew[rumRiga] = decodeScmProdLine(linea, ',');
// se !=null conto!
if (elencoDatiProdNew != null) rumRiga++;
}
}
// chiudo file
file.Close();
// ora trimmo vettore al solo numero VERO degli allarmi caricati...
Array.Resize<datiProdSCM>(ref elencoDatiProdNew, rumRiga);
/*--------------------------------------------------
* Gestione verifica dati prod (naive)
* - se file curr vuoto --> inizio a popolare
* - se i 2 file hannos tessa lunghezza --> verifico +update last row
* - se nNew > nCurr --> accodo
* - se nCurr > nNew e nNew ==0 --> aggiorno last row giorno prec
* - se nCurr > nNew e nNew > 0 --> svuoto file curr e riparto
*--------------------------------------------------*/
// verifica preliminare dati da lung vettori
int nRecCur = 0;
int nRecIst = 0;
if (elencoDatiProd != null)
{
try
{
nRecCur = elencoDatiProd.Length;
}
catch
{ }
}
if (elencoDatiProdNew != null)
{
try
{
nRecIst = elencoDatiProdNew.Length;
}
catch
{ }
}
// uso un INT x delta qta da sommare...
int deltaQta = 0;
// in primis devo verificare che sia > 0 num oggetti su entrambi i vettori
if (nRecCur + nRecIst > 0)
{
// verifico se ho meno valori CURR e quindi devo accodare
if (nRecCur < nRecIst)
{
// resize vettore!
Array.Resize<datiProdSCM>(ref elencoDatiProd, nRecCur + 1);
// carico nuovo record
elencoDatiProd[nRecCur] = elencoDatiProdNew[nRecCur];
deltaQta = elencoDatiProd[nRecCur].qta;
nRecCur++;
}
else if (nRecCur == nRecIst)
{
// devo confrontare ULTIMO record Curr con equivalente record NEW x verificare se sia variato.. verifico PRG + start
bool checkName = elencoDatiProd[nRecCur - 1].fileName == elencoDatiProdNew[nRecCur - 1].fileName;
bool checkStart = elencoDatiProd[nRecCur - 1].start == elencoDatiProdNew[nRecCur - 1].start;
if (checkName && checkStart)
{
// salvo se variata quantità...
deltaQta = elencoDatiProdNew[nRecCur - 1].qta - elencoDatiProd[nRecCur - 1].qta;
elencoDatiProd[nRecCur - 1] = elencoDatiProdNew[nRecCur - 1];
}
}
else
{
// inizio svuotando elenco eventi CURR (migliorabile leggendo da data prec?!?)
elencoDatiProd = null;
nRecCur = 0;
}
// riporto comunque ultima riga del vettore CURR (sia perché variato sia perché aggiunto)
if (nRecCur > 0)
{
string prgName = elencoDatiProd[nRecCur - 1].fileName;
prgName = prgName.Substring(prgName.LastIndexOf(@"\") + 1);
// se il mio articolo NON cambia...
if (istPathPartId[0] == prgName)
{
istPathPartCount[0] += (uint)deltaQta;
}
else
{
istPathPartId[0] = prgName;
istPathPartCount[0] = Convert.ToUInt32(elencoDatiProd[nRecCur - 1].qta);
}
}
}
}
}
/// <summary>
/// Processo stti macchina...
/// </summary>
public override void processStatus()
{
// HARD CODE: forzo path 1 (indice 0...)
int idxPath = 0;
// verifica macchina accesa...
Byte V73 = ncDevice.PLC_MemoryAreaV[5];
if (((StFlag8)V73).HasFlag(StFlag8.B2))
{
mPower.Value = "ON";
}
else
{
mPower.Value = "OFF";
}
// switch su EXE mode...
/*
* MODO_X V[70/71] --> byte (2-3)
* V70.2 = Modo RUN 
* V70.3 = Modo FeedHold
* V71.5 = Ready
* */
Byte V70 = ncDevice.PLC_MemoryAreaV[2];
Byte V71 = ncDevice.PLC_MemoryAreaV[3];
if (((StFlag8)V70).HasFlag(StFlag8.B3))
{
vettPath[idxPath].mPathExeMode.Value = "FEEDHOLD";
}
else if (((StFlag8)V70).HasFlag(StFlag8.B2))
{
vettPath[idxPath].mPathExeMode.Value = "RUN";
}
else if (((StFlag8)V71).HasFlag(StFlag8.B5))
{
vettPath[idxPath].mPathExeMode.Value = "READY";
}
// switch su run mode...
/*
* MODO_X V[74].W --> byte (6)
* 0 = Modo NESSUNO 
* 1 = Modo MANUALE 
* 2 = Modo AUTOMATICO 
* 3 = Modo POM 
* 4 = Modo MDI 
* 5 = Modo SEMIAUTOMATICO 
* 6 = Modo RAP 
* 7 = Modo TES
* */
uint V74 = ncDevice.PLC_MemoryAreaV[6];
switch (V74)
{
case 1:
vettPath[idxPath].mPathRunMode.Value = "EDIT";
break;
case 2:
vettPath[idxPath].mPathRunMode.Value = "AUTO";
break;
case 3:
vettPath[idxPath].mPathRunMode.Value = "REF";
break;
case 4:
vettPath[idxPath].mPathRunMode.Value = "MDI";
break;
case 5:
vettPath[idxPath].mPathRunMode.Value = "SEMIAUTO"; // JOG/JOGINC/HANDLE ?
break;
case 6:
vettPath[idxPath].mPathRunMode.Value = "RAP"; // JOG/JOGINC/HANDLE ?
break;
case 7:
vettPath[idxPath].mPathRunMode.Value = "TES"; // JOG/JOGINC/HANDLE ?
break;
case 0:
default:
vettPath[idxPath].mPathRunMode.Value = "ND"; // JOG/JOGINC/HANDLE ?
break;
}
}
public override void getUnOp()
{
base.getUnOp();
// cicl su UnOp
for (int i = 0; i < currAdpConf.nUnOp; i++)
{
vettUnOp[i].mUnOpToolId.Value = (int)ncDevice.PLC_MemoryAreaEOK[31];
}
}
public override void getPath()
{
base.getPath();
}
public override void getAxis()
{
base.getAxis();
// mostro assi in DataMonitor......
StringBuilder sb = new StringBuilder();
// nuova posizione (per calcoli)
double newPos = 0;
double distPerc = 0;
int newDir = 0;
// leggo in modo "cablato" i dati dei vari assi...
for (int i = 0; i < currAdpConf.nAxis; i++)
{
// in base a indice scelgo valore posizione e load
switch (i)
{
case 0:
newPos = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryRead[240]), 0);
break;
case 1:
newPos = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryRead[241]), 0);
break;
case 2:
newPos = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryRead[242]), 0);
break;
case 3:
newPos = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryRead[243]), 0);
break;
case 4:
newPos = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryRead[244]), 0);
break;
case 5:
newPos = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryRead[245]), 0);
break;
default:
// valPos = posAssi.p1;
// valLoad = loadAssi.svload1;
break;
}
// popolo valori...
//vettAxis[i].mAxLoad.Value = (double)(valLoad.data) / Math.Pow(10, valLoad.dec);
vettAxis[i].mAxPosAct.Value = newPos;
//vettAxis[i].mAxPosTgt.Value = newPos + (double)(valPos.dist.data) / Math.Pow(10, valPos.dist.dec);
if (utils.CRB("verbose"))
{
sb.AppendLine(string.Format("Asse {0}: PosAct:{1:N3}, ToGo:{2:N3}{3}", i, (double)(newPos) / utils.CRI("fattdecimale"), i, 0));
}
vettAxis[i].mAxFeedAct.Value = FeedRate;
// calcolo distanza e salvo valore...
distPerc = newPos - prevPosAxis[i];
// sistemo direzione +/- (POS/NEG se lineari, CCW/CW se rotativi)
if (distPerc != 0)
{
newDir = Convert.ToInt32(distPerc / Math.Abs(distPerc));
}
else
{
newDir = prevDirAxis[i];
}
vettAxis[i].mAxDir.Value = newDir;
// se la direzione è variata salvo il cambio direzione...
if (newDir != prevDirAxis[i])
{
// salvo "+1" come cambi direzione
istNumInvAssi[i]++;
}
// salvo valori vettore prec...
prevPosAxis[i] = newPos;
prevDirAxis[i] = newDir;
//vettAxis[i].mAxMainProc.Value = AxData.AxisMainProc;
//vettAxis[i].mAxIsMaster.Value = AxData.AxisIsMaster;
//vettAxis[i].mAxMastId.Value = AxData.AxisMastId;
//vettAxis[i].mAxFeedOver.Value = AxData.AxisFeedOver;
//vettAxis[i].mAxAccelAct.Value = AxData.AxisAccel;
//vettAxis[i].mAxBattery.Value = AxData.AxisBattery;
}
parentForm.dataMonitor += sb.ToString();
}
}
}