163f58fec9
NON completo, non va ma appuntato codice come DOVREBBE ragionare...
505 lines
18 KiB
C#
505 lines
18 KiB
C#
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?!?)
|
||
if (v87 != 0)
|
||
{
|
||
sb.AppendLine(string.Format("v87: {0}", v87));
|
||
}
|
||
|
||
// -------------------------------------------
|
||
// 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));
|
||
// -------------------------------------------
|
||
|
||
// -------------------------------------------
|
||
// 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);
|
||
|
||
// 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>
|
||
protected override void loadOtherFile()
|
||
{
|
||
base.loadOtherFile();
|
||
|
||
// carico dati x Maintenance
|
||
if (utils.CRB("verbose")) lg.Info(string.Format("Inizio caricamento file dati produzione ({0})", ScmProdFileName));
|
||
int totRighe = 0;
|
||
string linea;
|
||
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);
|
||
|
||
// !!!FARE!!! (ri-fare)
|
||
|
||
// ora devo verificare il contenuto rispetto ai "vecchi" valori... conto numero righe (devono essere diverse o uguali e ultima riga con qta differente e pari cod PRG...)
|
||
int nRecCur = 0;
|
||
if (elencoDatiProd != null)
|
||
{
|
||
try
|
||
{
|
||
nRecCur = elencoDatiProd.Length;
|
||
}
|
||
catch
|
||
{ }
|
||
}
|
||
int nRecIst = 0;
|
||
if (elencoDatiProdNew != null)
|
||
{
|
||
try
|
||
{
|
||
nRecCur = elencoDatiProdNew.Length;
|
||
}
|
||
catch
|
||
{ }
|
||
}
|
||
|
||
// in primis devo verificare che sia > 0 num oggetti su entrambi i vettori
|
||
|
||
// se vett curr è nullo --> devo inizializzare
|
||
|
||
// se NONE' nullo devo confrontare ULTIMO record Curr con equivalente record NEW x verificare se sia variato
|
||
|
||
// se ultimo curr === corrispondente new DEVO aggiungere 1 riga
|
||
|
||
// riporto comunque ultima riga del vettore CURR (sia perché variato sia perché aggiunto)
|
||
#if false
|
||
|
||
|
||
|
||
bool checkNumRow = nRecCur != nRecIst;
|
||
bool checkPart = elencoDatiProd[nRecCur - 1].fileName != elencoDatiProdNew[nRecIst - 1].fileName;
|
||
bool checkQta = elencoDatiProd[nRecCur - 1].qta != elencoDatiProdNew[nRecIst - 1].qta;
|
||
// se differiscono processo
|
||
if (checkNumRow || checkPart || (!checkPart && checkQta))
|
||
{
|
||
// CARICO IN vettore IST il primo dei NUOVI particolari coi suoi pezzi prodotti
|
||
istPathPartId[0] = elencoDatiProdNew[nRecIst - 1].fileName;
|
||
istPathPartCount[0] = Convert.ToUInt32(elencoDatiProdNew[nRecIst - 1].qta);
|
||
// aggiorno ultima riga (son diverse x numeri righe...)
|
||
if (checkNumRow)
|
||
{
|
||
Array.Resize<datiProdSCM>(ref elencoDatiProd, nRecCur + 1);
|
||
elencoDatiProd[nRecCur + 1] = elencoDatiProdNew[nRecCur + 1];
|
||
}
|
||
//... aggiorno ultima riga dati...
|
||
else
|
||
{
|
||
elencoDatiProd[nRecCur] = elencoDatiProdNew[nRecCur];
|
||
}
|
||
// al prossimo giro caricherà altro particolare...
|
||
}
|
||
#endif
|
||
}
|
||
/// <summary>
|
||
/// Processo stti macchina...
|
||
/// </summary>
|
||
public override void processStatus()
|
||
{
|
||
base.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();
|
||
|
||
int numUnOp = 1;
|
||
// cicl su path
|
||
for (int i = 0; i < numUnOp; 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];
|
||
#if false
|
||
vettAxis[i].mAxDistDone.Value = Math.Abs(distPerc);
|
||
#endif
|
||
|
||
// 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].mAxAccTime.Value = AxData.AxisAccTime;
|
||
//vettAxis[i].mAxBattery.Value = AxData.AxisBattery;
|
||
}
|
||
|
||
parentForm.dataMonitor += sb.ToString();
|
||
}
|
||
}
|
||
}
|