869 lines
32 KiB
C#
869 lines
32 KiB
C#
using MTC;
|
|
using SCMA.AdapterCom;
|
|
using EsaCncLib;
|
|
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
|
|
namespace SCMA.AdapterPLC.CMS
|
|
{
|
|
public class EsaKosmos : Generic
|
|
{
|
|
/// <summary>
|
|
/// Configurazione valori da leggere IOT_Byte
|
|
/// </summary>
|
|
public otherData[] mapIOT_Byte;
|
|
/// <summary>
|
|
/// Configurazione valori da leggere IOT_Word
|
|
/// </summary>
|
|
public otherData[] mapIOT_Word;
|
|
/// <summary>
|
|
/// Configurazione valori da leggere IOT_DWord
|
|
/// </summary>
|
|
public otherData[] mapIOT_DWord;
|
|
/// <summary>
|
|
/// Configurazione valori da leggere IOT_String
|
|
/// </summary>
|
|
public otherData[] mapIOT_String;
|
|
|
|
/// <summary>
|
|
/// Oggetto elenco allarmi SOLO CNC (OCCHIO codice numerico = INDICE!!!)
|
|
/// </summary>
|
|
public allarme[] elencoAllarmiCNC;
|
|
/// <summary>
|
|
/// variabile contatore cicli prima di rileggere codici G di un path inattivo...
|
|
/// </summary>
|
|
public int contChkGCod;
|
|
/// <summary>
|
|
/// Vettore codici G attivi...
|
|
/// </summary>
|
|
int[] vettGCodesAct;
|
|
/// <summary>
|
|
/// Override asse Z (hard coded x ESA)
|
|
/// </summary>
|
|
int ZRateOver = 0;
|
|
|
|
/// <summary>
|
|
/// Carico file conf dati IOT
|
|
/// </summary>
|
|
protected override void loadOtherFile()
|
|
{
|
|
base.loadOtherFile();
|
|
loadMaintData("CNT", 0, 1);
|
|
loadStatusData("MNT", 0, 1);
|
|
loadAnalogData("ANALOG", 0, 1);
|
|
loadStringData("STR", 0, 1);
|
|
loadAllarmiCNC();
|
|
}
|
|
|
|
/// <summary>
|
|
/// caricamento allarmi da file (CON RIEMPIMENTO MANCANTI!!!!)
|
|
/// </summary>
|
|
protected void loadAllarmiCNC()
|
|
{
|
|
if (utils.CRB("verbose"))
|
|
{
|
|
lg.Info("Inizio caricamento vettore allarmi");
|
|
}
|
|
|
|
int totRighe = 0;
|
|
string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("AlarmListCNC"));
|
|
string linea;
|
|
try
|
|
{
|
|
string lastLine = File.ReadLines(fileName).Last();
|
|
totRighe = startNumb(lastLine, utils.CRC("testCharSep"));
|
|
}
|
|
catch
|
|
{
|
|
totRighe = File.ReadLines(fileName).Count();
|
|
}
|
|
// creo un vettore della dimensione corretta... PRENDO IL MASSIMO dei valori...
|
|
elencoAllarmiCNC = new allarme[totRighe];
|
|
// ora creo un vettore di allarmi VUOTI...
|
|
for (int i = 1; i <= totRighe; i++)
|
|
{
|
|
elencoAllarmiCNC[i - 1] = new allarme(i.ToString(), "CNC", "WARNING", string.Format("[{0}] MISSING", i), string.Format("[{0}] MISSING", i), string.Format("[{0}] MISSING", i));
|
|
}
|
|
// carica da file...
|
|
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
|
|
// leggo 1 linea alla volta...
|
|
int numRiga = 0;
|
|
while ((linea = file.ReadLine()) != null)
|
|
{
|
|
// SE non è un commento...
|
|
if (linea.Substring(0, 1) != "#")
|
|
{
|
|
// recupero numRiga da prima parte linea...
|
|
numRiga = startNumb(linea, utils.CRC("testCharSep"));
|
|
elencoAllarmiCNC[numRiga - 1] = decodeAlarmLine(linea, utils.CRC("testCharSep"));
|
|
}
|
|
}
|
|
// chiudo file
|
|
file.Close();
|
|
if (utils.CRB("verbose"))
|
|
{
|
|
lg.Info(string.Format("Fine caricamento vettore allarmi CNC: {0} allarmi caricati!", numRiga));
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Restituisce path completo file da chaive configurazione
|
|
/// </summary>
|
|
/// <param name="keyFile">chaive conf x file richiesto</param>
|
|
/// <returns></returns>
|
|
protected string filePath(string keyFile)
|
|
{
|
|
return string.Format(@"{0}\{1}", utils.confDir, utils.CRS(keyFile));
|
|
}
|
|
|
|
/// <summary>
|
|
/// oggetto onnessione ESA
|
|
/// </summary>
|
|
protected thdNcEsaKvara ncDevice;
|
|
/// <summary>
|
|
/// thread del processo comunicazione esa
|
|
/// </summary>
|
|
protected Thread thdDevice;
|
|
|
|
/// <summary>
|
|
/// estende l'init della classe base...
|
|
/// </summary>
|
|
/// <param name="caller">FORM chaimante</param>
|
|
/// <param name="adpConf">CONFIGURAZIONE adapter</param>
|
|
/// <param name="gatewayObj">OGGETTO gestione comunicazione OUT (tipologia e metodi)</param>
|
|
public EsaKosmos(MainForm caller, AdapterConf adpConf, Gateway gatewayObj) : base(caller, adpConf, gatewayObj)
|
|
{
|
|
// !!!HARD CODED!!! aggiunto banco STATUS del 2 processo IN CODA... (4+1)DW=20byte x strobes...!!!
|
|
Strobes = new byte[20];
|
|
|
|
//fix dimensione memorie MST: 26 short(16bit) x (11+6+6) aree (attenzione: secondo set di 2 bit è VUOTO...)
|
|
MemBlock_MST = new byte[46];
|
|
|
|
// GCodes!
|
|
vettGCodesAct = new int[10];
|
|
contChkGCod = utils.CRI("contChkGCod");
|
|
|
|
|
|
string iniPath = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("defaultEsaFile"));
|
|
|
|
lg.Info("Start init Adapter ESA dal file {0}", iniPath);
|
|
|
|
EsaCncLib.IniFile EsaIni = new EsaCncLib.IniFile(iniPath);
|
|
|
|
if (utils.CRB("verbose"))
|
|
{
|
|
lg.Info("step 01: impostato INI File {0}", iniPath);
|
|
}
|
|
|
|
loadOtherFile();
|
|
|
|
parentForm.commPlcActive = true;
|
|
// init classe comunicazione NC
|
|
ncDevice = new thdNcEsaKvara(EsaIni);
|
|
parentForm.commPlcActive = false;
|
|
|
|
if (utils.CRB("verbose"))
|
|
{
|
|
lg.Info("step 02: avviato thdNcEsaGvKvara da INI File {0}", iniPath);
|
|
}
|
|
|
|
// inizializzo posizioni assi...
|
|
prevPosAxis = new double[adpConf.nAxis];
|
|
prevDirAxis = new int[adpConf.nAxis];
|
|
|
|
// verifica avvio...
|
|
lg.Info("ESA: tryConnect");
|
|
tryConnect();
|
|
lg.Info("End init Adapter ESA");
|
|
|
|
// leggo dati "statici" dal PLC...
|
|
}
|
|
/// <summary>
|
|
/// Override disconnessione
|
|
/// </summary>
|
|
public override void tryDisconnect()
|
|
{
|
|
base.tryDisconnect();
|
|
// disconnetto
|
|
ncDevice.Disconnect();
|
|
connectionOk = false;
|
|
}
|
|
/// <summary>
|
|
/// Override connessione
|
|
/// </summary>
|
|
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();
|
|
connectionOk = false;
|
|
}
|
|
else
|
|
{
|
|
connectionOk = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifico connessione ESA...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override bool connectionOk
|
|
{
|
|
get
|
|
{
|
|
return ncDevice.Connected;
|
|
}
|
|
set
|
|
{
|
|
ncDevice.Connected = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Legge vettore di TUTTE memorie tipo DWord dato vettore memorie (completo)
|
|
/// </summary>
|
|
/// <param name="MemBlock"></param>
|
|
/// <returns></returns>
|
|
public override bool readAllAlarms(ref uint[] MemBlock)
|
|
{
|
|
ncDevice.ReadlAlarms();
|
|
MemBlock = ncDevice.SCMA_MMan_ALM.data;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettuo lettura dei 16 byte di strobe/status
|
|
/// </summary>
|
|
public override void getStrobeAndAckStatus()
|
|
{
|
|
base.getStrobeAndAckStatus();
|
|
if (connectionOk)
|
|
{
|
|
// leggo TUTTO il blocco di memoria
|
|
parentForm.commPlcActive = true;
|
|
inizio = DateTime.Now;
|
|
ncDevice.ReadStatus();
|
|
ncDevice.ReadAckStrobe();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult("R-PLC_SCMA-ACK-Strobe", DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
|
|
parentForm.commPlcActive = false;
|
|
|
|
// copio ACK
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_ACK.data, 0, Acknowl, 0, 16);
|
|
|
|
// copio strobes (all)
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_STROBE.data, 0, Strobes, 0, 16);
|
|
|
|
// status...
|
|
ouStatus = ncDevice.SCMA_MMan_status.data[0];
|
|
// copio su ack...
|
|
Acknowl[12] = (byte)ouStatus;
|
|
}
|
|
else
|
|
{
|
|
lg.Error("Errore connessione mancante in getStrobeAndAckStatus");
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// processing strobe!
|
|
/// </summary>
|
|
public override void processStrobe()
|
|
{
|
|
// inizializzo userAction
|
|
string UserAction = "";
|
|
// oggetti "accessori" x processing (1 byte di strobe x ogni path)
|
|
StFlag8 currStrobe;
|
|
StFlag8 currAck;
|
|
|
|
// processo ora i dati dei path... di sicuro il primo
|
|
currStrobe = (StFlag8)(Strobes[4]); // 5° byte
|
|
currAck = (StFlag8)(Acknowl[4]); // 5° byte
|
|
procPathStrobes(0, currStrobe, currAck, 1, 0, ref UserAction); // 0 --> primo byte della ACK MST
|
|
|
|
//...e se c'è pure il secondo...
|
|
if (currAdpConf.nPath > 1)
|
|
{
|
|
currStrobe = (StFlag8)(Strobes[6]); // 7° byte
|
|
currAck = (StFlag8)(Acknowl[6]); // 7° byte
|
|
procPathStrobes(1, currStrobe, currAck, 1, 2, ref UserAction); // 2 --> terzo byte della ACK MST
|
|
}
|
|
|
|
//2019.07.22 NON RIPORTO USER_ACTION x SOUR
|
|
if (currGateway.protocollo != gwProtocol.SOURS)
|
|
{
|
|
// 2017.01.16 INVIO vettore azioni (1 o +)... SE CE NE SONO!
|
|
if (UserAction.Trim() != "")
|
|
{
|
|
currGateway.updateItemNodeValue("USER_ACTION", UserAction.Trim());
|
|
}
|
|
}
|
|
|
|
// verifico strobe dell'auto-test
|
|
currStrobe = (StFlag8)(Strobes[7]); // 8° byte
|
|
currAck = (StFlag8)(Acknowl[7]); // 8° byte
|
|
processTestStrobe(currStrobe, currAck, 1, 30);
|
|
|
|
// gestione bit di watchdog... sulal DWord successiva
|
|
sendWatchDog();
|
|
}
|
|
/// <summary>
|
|
/// Scrive ACK x dati MST
|
|
/// </summary>
|
|
/// <param name="idxPath"></param>
|
|
/// <param name="memIndexMST"></param>
|
|
/// <param name="MemBlock_W"></param>
|
|
/// <returns></returns>
|
|
public override bool writeMST_ACK(int memIndexAck, ref byte[] currACK_DW)
|
|
{
|
|
bool fatto = false;
|
|
// converto DWord a byte, è la DW1 = ACK[1]...
|
|
byte[] actualAck = BitConverter.GetBytes(ncDevice.SCMA_MMan_ACK.data[1]);
|
|
// sistemo nella memoria dell'NC i valori di ack richiesti...
|
|
Buffer.BlockCopy(currACK_DW, 0, actualAck, memIndexAck, 1);
|
|
// riconverto a DWord
|
|
ncDevice.SCMA_MMan_ACK.data[1] = BitConverter.ToUInt32(actualAck, 0);
|
|
try
|
|
{
|
|
inizio = DateTime.Now;
|
|
// scrivo TUTTA la Hack
|
|
fatto = ncDevice.WriteAck();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult(string.Format("W{0}-ACK_DW1", currACK_DW.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("Errore in scrittura dati ACK MST:{0}{1}", Environment.NewLine, exc));
|
|
}
|
|
return fatto;
|
|
}
|
|
/// <summary>
|
|
/// Legge area memoria dati MST
|
|
/// </summary>
|
|
/// <param name="idxPath"></param>
|
|
/// <param name="memIndexMST"></param>
|
|
/// <param name="MemBlock_MST"></param>
|
|
/// <returns></returns>
|
|
public override bool readMST_data(int idxPath, int memIndexMST, ref byte[] MemBlock_MST)
|
|
{
|
|
bool fatto = false;
|
|
try
|
|
{
|
|
inizio = DateTime.Now;
|
|
// leggo memoria (TUTTA) e POI ricopio a byte x il resto delal gestione...
|
|
ncDevice.ReadMSTData();
|
|
// copio M
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_MNUM.data, idxPath, MemBlock_MST, 0, 2);
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_MF.data, idxPath * 10, MemBlock_MST, 2, 20);
|
|
// copio S
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_SNUM.data, idxPath, MemBlock_MST, 22, 2);
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_SF.data, idxPath * 5, MemBlock_MST, 24, 10);
|
|
// copio T
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_TNUM.data, idxPath, MemBlock_MST, 34, 2);
|
|
Buffer.BlockCopy(ncDevice.SCMA_MMan_TF.data, idxPath * 5, MemBlock_MST, 36, 10);
|
|
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult(string.Format("R{0}-STRB_DW1-P{1:00}", MemBlock_MST.Length, idxPath), DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("Errore in lettura dati MST:{0}{1}", Environment.NewLine, exc));
|
|
}
|
|
return fatto;
|
|
}
|
|
/// <summary>
|
|
/// Scrive watchdog
|
|
/// </summary>
|
|
/// <param name="retACK_DW"></param>
|
|
/// <returns></returns>
|
|
public override bool writeWatchDog(ref byte[] retACK_DW)
|
|
{
|
|
bool fatto = false;
|
|
// converto DWord a byte, è la DW2 = ACK[2]...
|
|
byte[] actualAck = BitConverter.GetBytes(ncDevice.SCMA_MMan_ACK.data[2]);
|
|
// sistemo nella memoria dell'NC i valori di ack richiesti...
|
|
Buffer.BlockCopy(retACK_DW, 0, actualAck, 0, 4);
|
|
// riconverto a DWord
|
|
ncDevice.SCMA_MMan_ACK.data[2] = BitConverter.ToUInt32(actualAck, 0);
|
|
|
|
// chiamo scrittura...
|
|
fatto = ncDevice.WriteAck();
|
|
|
|
return fatto;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Scrive vettore ACK degli allarmi
|
|
/// </summary>
|
|
/// <param name="retACK_DW0"></param>
|
|
/// <returns></returns>
|
|
public override bool writeAlarmAck(ref byte[] retACK_DW0)
|
|
{
|
|
bool fatto = false;
|
|
// converto DWord a byte, è la DW2 = ACK[2]...
|
|
byte[] actualAck = BitConverter.GetBytes(ncDevice.SCMA_MMan_ACK.data[0]);
|
|
// sistemo nella memoria dell'NC i valori di ack richiesti...
|
|
Buffer.BlockCopy(retACK_DW0, 0, actualAck, 0, 4);
|
|
// riconverto a DWord
|
|
ncDevice.SCMA_MMan_ACK.data[0] = BitConverter.ToUInt32(actualAck, 0);
|
|
// chiamo scrittura...
|
|
fatto = ncDevice.WriteAck();
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Legge vettore di TUTTE memorie tipo DWord dato indice di partenza e vettore memorie
|
|
/// </summary>
|
|
/// <param name="MemBlock"></param>
|
|
/// <param name="blockIndex"></param>
|
|
/// <returns></returns>
|
|
public override bool readAlarmBlock(ref uint[] MemBlock, int blockIndex)
|
|
{
|
|
// rileggo comunque tutto che faccio prima...
|
|
bool fatto = false;
|
|
try
|
|
{
|
|
ncDevice.ReadlAlarms();
|
|
var currMemBlock = ncDevice.SCMA_MMan_ALM.data;
|
|
MemBlock[0] = currMemBlock[blockIndex];
|
|
}
|
|
catch
|
|
{ }
|
|
return fatto;
|
|
}
|
|
|
|
|
|
#region implementazione processing GlobalData
|
|
|
|
/// <summary>
|
|
/// Legge dati globali...
|
|
/// </summary>
|
|
public override void readGlobalData()
|
|
{
|
|
// leggo dati globali...
|
|
parentForm.commPlcActive = true;
|
|
inizio = DateTime.Now;
|
|
|
|
ncDevice.ReadMSTData();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult("PLC-MST-Data", DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
parentForm.commPlcActive = false;
|
|
}
|
|
/// <summary>
|
|
/// legge dati override...
|
|
/// </summary>
|
|
/// <param name="sb1"></param>
|
|
/// <returns></returns>
|
|
public override bool readOverrides(ref StringBuilder sb1)
|
|
{
|
|
bool fatto = false;
|
|
try
|
|
{
|
|
// lettura override
|
|
inizio = DateTime.Now;
|
|
var allSpeedFeedData = ncDevice.getFeedSpeed();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult("PLC-R-overrides", DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
|
|
// inizio indicando feed...
|
|
sb1.AppendLine(string.Format("FeedRate: {0} mm/min", allSpeedFeedData.realFeed));
|
|
sb1.AppendLine(string.Format("SpeedRate: {0} mm/min", allSpeedFeedData.realSpeed));
|
|
|
|
fatto = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(exc, "Eccezione in readOverrides");
|
|
}
|
|
|
|
|
|
// HARD CODE: forzo path 1 (indice 0...)
|
|
int idxPath = 0;
|
|
// accodo dati path in DataMonitor......
|
|
StringBuilder sb = new StringBuilder();
|
|
// Processing area BYTE x OVERRIDE e status
|
|
ZRateOver = ncDevice.SCMA_MMan_OVR.data[0];
|
|
FeedRateOver = ncDevice.SCMA_MMan_OVR.data[1];
|
|
RapidOver = ncDevice.SCMA_MMan_OVR.data[2];
|
|
SpeedRateOver = ncDevice.SCMA_MMan_OVR.data[3];
|
|
|
|
// commentato x test sul campo da Gianandrea Grisetti + Marco Annese: si sovrascrivono status da PATH (processo) e generale, eliminato qui
|
|
#if false
|
|
string pathExeMode = $"{(macState)ouStatus}";
|
|
// copio exeMode sul path corrente
|
|
currGateway.updateItemNodeValue(vettPath[idxPath].exeModeKey, pathExeMode);
|
|
// sistemo le stringhe x display
|
|
sb.AppendLine(string.Format("ExeMode: {0}", pathExeMode));
|
|
#endif
|
|
sb.AppendLine(string.Format("ZRateOver: {0} %", ZRateOver));
|
|
sb.AppendLine(string.Format("FeedRateOver: {0} %", FeedRateOver));
|
|
sb.AppendLine(string.Format("RapidOver: {0} %", RapidOver));
|
|
sb.AppendLine(string.Format("SpeedRateOver: {0} %", SpeedRateOver));
|
|
// update form!
|
|
parentForm.dataMonitor_1 += sb.ToString();
|
|
|
|
return fatto;
|
|
}
|
|
/// <summary>
|
|
/// Gestione lettura dati manutenzione
|
|
/// </summary>
|
|
public override bool getMtzDataFromPlc()
|
|
{
|
|
bool fatto = false;
|
|
try
|
|
{
|
|
if (maintData != null)
|
|
{
|
|
if (maintData.Length > 0)
|
|
{
|
|
// recupero dati
|
|
uint[] tabDatiMtz = new uint[maintDataMaxNum];
|
|
inizio = DateTime.Now;
|
|
ncDevice.ReadCounterData();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult(string.Format("R{0}-DatiMtz", tabDatiMtz.Length * 4), DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
|
|
// copio maint data
|
|
tabDatiMtz = ncDevice.SCMA_MMan_CNT.data.Take(maintDataMaxNum).ToArray();
|
|
|
|
// decodifico aree memoria secondo tab configurazione
|
|
processMaintData(tabDatiMtz, maintData);
|
|
// se log verboso 10+ --> scrivo tutti!
|
|
if (utils.CRI("loglevel") > 9)
|
|
{
|
|
lg.Info($" Lettura di {maintDataMaxNum} variabili maintData");
|
|
}
|
|
}
|
|
fatto = true;
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("{0}", exc));
|
|
}
|
|
return fatto;
|
|
}
|
|
/// <summary>
|
|
/// Gestione lettura dati analogici
|
|
/// </summary>
|
|
public override bool getAnalogDataFromPlc()
|
|
{
|
|
bool fatto = false;
|
|
try
|
|
{
|
|
// leggo e salvo var analogiche ANALOG
|
|
if (analogDataMaxNum > 0)
|
|
{
|
|
// recupero dati
|
|
inizio = DateTime.Now;
|
|
ncDevice.ReadAnalogData();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult("R-AnalogData", DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
uint[] tabDatiAnalog = new uint[analogDataMaxNum];
|
|
tabDatiAnalog = ncDevice.SCMA_MMan_ANALOG.data.Take(analogDataMaxNum).ToArray();
|
|
// decodifico aree memoria secondo tab configurazione
|
|
processAnalogData(tabDatiAnalog, analogData);
|
|
}
|
|
fatto = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("{0}", exc));
|
|
}
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione lettura dati stringa
|
|
/// </summary>
|
|
public override bool getStringDataFromPlc()
|
|
{
|
|
bool fatto = false;
|
|
try
|
|
{
|
|
// leggo e salvo var analogiche ANALOG
|
|
if (stringDataMaxNum > 0)
|
|
{
|
|
// recupero dati
|
|
inizio = DateTime.Now;
|
|
ncDevice.ReadStringData();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult("R-StringData", DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
string[] tabDatiString = new string[stringDataMaxNum];
|
|
for (int i = 0; i < stringDataMaxNum; i++)
|
|
{
|
|
tabDatiString[i] = ncDevice.SCMA_MManCMS_Strings[i].data.Trim();
|
|
}
|
|
// decodifico aree memoria secondo tab configurazione
|
|
processStringData(tabDatiString, stringData);
|
|
}
|
|
fatto = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("{0}", exc));
|
|
}
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione lettura dati status da PLC
|
|
/// </summary>
|
|
public override bool getStatusDataFromPlc()
|
|
{
|
|
bool fatto = false;
|
|
try
|
|
{
|
|
// leggo e salvo status BIT STATUS MNT
|
|
if (statusDataMaxNum > 0)
|
|
{
|
|
// recupero dati
|
|
inizio = DateTime.Now;
|
|
ncDevice.ReadStatus();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult("R-Status", DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
int numByte = 1 + (statusDataMaxNum / 8);
|
|
// arrotondo ai 4 byte...
|
|
numByte = 4 * (int)Math.Ceiling((double)numByte / 4);
|
|
byte[] tabDatiStatus = new byte[numByte];
|
|
for (int i = 0; i < numByte / 4; i++)
|
|
{
|
|
Buffer.BlockCopy(BitConverter.GetBytes(ncDevice.SCMA_MMan_MNT.data[i]), 0, tabDatiStatus, i * 4, 4);
|
|
}
|
|
// decodifico aree memoria secondo tab configurazione
|
|
processStatusData(tabDatiStatus, statusData);
|
|
}
|
|
fatto = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("{0}", exc));
|
|
}
|
|
return fatto;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override void getPath()
|
|
{
|
|
var allSpeedFeedData = ncDevice.getFeedSpeed();
|
|
// cicl su path
|
|
for (int i = 0; i < currAdpConf.nPath; i++)
|
|
{
|
|
currGateway.updateItemNodeValue(vettPath[i].feedKey, allSpeedFeedData.realFeed);
|
|
currGateway.updateItemNodeValue(vettPath[i].feedOverKey, FeedRateOver);
|
|
currGateway.updateItemNodeValue(vettPath[i].rapidOverKey, RapidOver);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera la speed override x i mandrini (UnOp)
|
|
/// </summary>
|
|
public override void getUnOp()
|
|
{
|
|
var allSpeedFeedData = ncDevice.getFeedSpeed();
|
|
// cicl su UnOp
|
|
for (int i = 0; i < currAdpConf.nUnOp; i++)
|
|
{
|
|
currGateway.updateItemNodeValue(vettUnOp[i].speedOverKey, SpeedRateOver);
|
|
currGateway.updateItemNodeValue(vettUnOp[i].speedKey, allSpeedFeedData.realSpeed);
|
|
}
|
|
|
|
// ora recupero G Codes
|
|
StringBuilder sb_2;
|
|
StringBuilder sb_3;
|
|
|
|
// faccio VERA lettura SOLO ogni TOT cicli...
|
|
if (contChkGCod <= 0)
|
|
{
|
|
// reimposto contatore
|
|
contChkGCod = utils.CRI("contChkGCod");
|
|
// recupero vettore generale G MODE
|
|
parentForm.commPlcActive = true;
|
|
inizio = DateTime.Now;
|
|
vettGCodesAct = ncDevice.getGCodes();
|
|
if (utils.CRB("recTime"))
|
|
{
|
|
TimingData.addResult("R-GCodModal", DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
parentForm.commPlcActive = false;
|
|
}
|
|
else
|
|
{
|
|
contChkGCod--;
|
|
}
|
|
|
|
for (int i = 0; i < currAdpConf.nPath; i++)
|
|
{
|
|
// accodo dati path in DataMonitor...
|
|
sb_2 = new StringBuilder();
|
|
sb_3 = new StringBuilder();
|
|
|
|
// attenzione: il vettore contiene come campi "vuoti" il valore MAX di USHort (16bit) ovvero 2^16 -1 (base 0) --> 65535
|
|
string GCodAttivi = "";
|
|
for (int j = 0; j < vettGCodesAct.Length; j++)
|
|
{
|
|
// se il valore è < di UShort.max (65535)...
|
|
if (vettGCodesAct[j] < ushort.MaxValue && vettGCodesAct[j] >= 0)
|
|
{
|
|
GCodAttivi += string.Format("[G{0}]", vettGCodesAct[j]);
|
|
}
|
|
}
|
|
if (currGateway.getItemNode(vettPath[i].gCodeAct_Key).ToString() != $"{vettPath[i].gCodeAct_Key}||{GCodAttivi}")
|
|
{
|
|
currGateway.updateItemNodeValue(vettPath[i].gCodeAct_Key, GCodAttivi);
|
|
}
|
|
|
|
if (currGateway.protocollo != gwProtocol.SOURS)
|
|
{
|
|
// 2017.01.16 da rivedere
|
|
currGateway.updateItemNodeValue(vettPath[i].currProgRowNumKey, "");
|
|
currGateway.updateItemNodeValue(vettPath[i].activeAxesKey, "");
|
|
sb_2.AppendLine(string.Format("Path {0}, PROG: {1}", i + 1, currGateway.getItemNode(vettPath[i].currProgKey)));
|
|
}
|
|
|
|
sb_3.AppendLine(string.Format("Path {0}, GCodes: {1}", i + 1, GCodAttivi));
|
|
|
|
parentForm.dataMonitor_2 += sb_2.ToString();
|
|
parentForm.dataMonitor_3 += sb_3.ToString();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Carica info accessorie assi (direzione, feed, ...)
|
|
/// </summary>
|
|
public override void getAxis()
|
|
{
|
|
// mostro assi in DataMonitor......
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
// leggo in blocco dati dall'NC
|
|
var allAxisData = ncDevice.getAxisData();
|
|
|
|
var allSpeedFeedData = ncDevice.getFeedSpeed();
|
|
|
|
// nuova posizione (per calcoli)
|
|
double newPos = 0;
|
|
double distPerc = 0;
|
|
int newDir = 0;
|
|
string direzione = "";
|
|
int numInvAx = 0;
|
|
int currFeedOver = 0;
|
|
|
|
// leggo in modo "cablato" i dati dei vari assi...
|
|
for (int i = 0; i < currAdpConf.nAxis; i++)
|
|
{
|
|
// speed singolo asse
|
|
currGateway.updateItemNodeValue(vettAxis[i].feedrateKey, allAxisData[i].speed);
|
|
|
|
/*--------------------------------------------------------
|
|
* Override calcolata come segue:
|
|
* - asse Z: sempre "specifica"
|
|
* - altri assi:
|
|
* - se HO G0 (RAPID) --> OVR[2]
|
|
* - se HO G1 (FEED) --> OVR[1]
|
|
--------------------------------------------------------*/
|
|
if (!string.IsNullOrEmpty(allAxisData[i].name))
|
|
{
|
|
if (allAxisData[i].name == "Z")
|
|
{
|
|
currFeedOver = ZRateOver;
|
|
}
|
|
else
|
|
{
|
|
currFeedOver = FeedRateOver;
|
|
}
|
|
// imposto!
|
|
currGateway.updateItemNodeValue(vettAxis[i].feedOverKey, currFeedOver);
|
|
}
|
|
|
|
|
|
// load... divido per 10 x avere Ampere
|
|
currGateway.updateItemNodeValue(vettAxis[i].loadKey, allAxisData[i].load / 10);
|
|
|
|
// name
|
|
if (!string.IsNullOrEmpty(allAxisData[i].name))
|
|
{
|
|
currGateway.updateItemNodeValue(vettAxis[i].descriptionKey, allAxisData[i].name);
|
|
}
|
|
|
|
// calcolo distanza e salvo valore...
|
|
newPos = allAxisData[i].posMac;
|
|
currGateway.updateItemNodeValue(vettAxis[i].posActKey, newPos);
|
|
distPerc = newPos - prevPosAxis[i];
|
|
|
|
// posizione target = posizione atutale + sistance
|
|
currGateway.updateItemNodeValue(vettAxis[i].posTgtKey, newPos + allAxisData[i].distanceToGo);
|
|
|
|
// sistemo direzione +/- (POS/NEG se lineari, CCW/CW se rotativi)
|
|
if (distPerc != 0)
|
|
{
|
|
newDir = Convert.ToInt32(distPerc / Math.Abs(distPerc));
|
|
}
|
|
else
|
|
{
|
|
newDir = prevDirAxis[i];
|
|
}
|
|
|
|
// calcolo direzione
|
|
direzione = calculateDirection(newDir, i);
|
|
// imposto direzione
|
|
currGateway.updateItemNodeValue(vettAxis[i].directionKey, direzione);
|
|
|
|
// se la direzione è variata salvo il cambio direzione...
|
|
if (newDir != prevDirAxis[i])
|
|
{
|
|
// recupero num prec...
|
|
numInvAx = Convert.ToInt32(istNumInvAssi[i].vcMedian);
|
|
numInvAx++;
|
|
// salvo "+1" come cambi direzione.... ATTENZIONE servirà che la finestra sia "corta" (tipo 1 sec...) mentre io ne inserisco 3 distanziati di 1/5 sec
|
|
istNumInvAssi[i].addValue(DateTime.Now.AddMilliseconds(-400), numInvAx);
|
|
istNumInvAssi[i].addValue(DateTime.Now.AddMilliseconds(-200), numInvAx);
|
|
istNumInvAssi[i].addValue(DateTime.Now, numInvAx);
|
|
}
|
|
|
|
if (utils.CRB("verbose"))
|
|
{
|
|
sb.AppendLine($"Asse {i}: PosAct:{newPos:N3} | {direzione}");
|
|
sb.AppendLine($"Asse {i}: ESA speed {allAxisData[i].speed}");
|
|
}
|
|
|
|
// salvo valori vettore prec...
|
|
prevPosAxis[i] = newPos;
|
|
prevDirAxis[i] = newDir;
|
|
}
|
|
|
|
parentForm.dataMonitor_3 += sb.ToString();
|
|
}
|
|
}
|
|
}
|