1943 lines
80 KiB
C#
1943 lines
80 KiB
C#
using CMSCncLib.CNC;
|
|
using MTC;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace MTC_Adapter
|
|
{
|
|
public class AdapterOsai : AdapterGeneric
|
|
{
|
|
// vettore valori in file interscambio
|
|
public Dictionary<string, string> generalStatus;
|
|
/// <summary>
|
|
/// Contenuto valori maintenance data da PLC
|
|
/// </summary>
|
|
public otherData[] maintData;
|
|
/// <summary>
|
|
/// Contenuto valori status data da PLC
|
|
/// </summary>
|
|
public otherData[] statusData;
|
|
|
|
/// <summary>
|
|
/// Oggetto MAIN x connessione OSAI
|
|
/// </summary>
|
|
protected OSAI OSAI_ref;
|
|
|
|
/// <summary>
|
|
/// wrapper chiamata lettura/scrittura fanuc x BYTE...
|
|
/// </summary>
|
|
/// <param name="bWrite"></param>
|
|
/// <param name="MemType"></param>
|
|
/// <param name="memIndex"></param>
|
|
/// <param name="memOrderStart">0/1 orimo o secondo byte della word...</param>
|
|
/// <param name="MATRICE Value"></param>
|
|
/// <returns></returns>
|
|
public bool OsaiMemRW_Byte(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, Int32 memOrderStart, ref byte[] Value)
|
|
{
|
|
bool answ = false;
|
|
if (OSAI_ref.Connected)
|
|
{
|
|
try
|
|
{
|
|
answ = OSAI_ref.O_RW_Byte(bWrite, MemType, memIndex, memOrderStart, ref Value);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
return answ;
|
|
}
|
|
/// <summary>
|
|
/// wrapper chiamata lettura/scrittura fanuc x WORD...
|
|
/// </summary>
|
|
/// <param name="bWrite"></param>
|
|
/// <param name="MemType"></param>
|
|
/// <param name="memIndex"></param>
|
|
/// <param name="MATRICE Value"></param>
|
|
/// <returns></returns>
|
|
public bool OsaiMemRW_Word(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref ushort[] Value)
|
|
{
|
|
bool answ = false;
|
|
if (OSAI_ref.Connected)
|
|
{
|
|
try
|
|
{
|
|
answ = OSAI_ref.O_RW_Word(bWrite, MemType, memIndex, ref Value);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
return answ;
|
|
}
|
|
/// <summary>
|
|
/// wrapper chiamata lettura/scrittura fanuc x DOUBLE-WORD...
|
|
/// </summary>
|
|
/// <param name="bWrite"></param>
|
|
/// <param name="MemType"></param>
|
|
/// <param name="memIndex"></param>
|
|
/// <param name="MATRICE Value"></param>
|
|
/// <returns></returns>
|
|
public bool OsaiMemRW_DWord(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref uint[] Value)
|
|
{
|
|
bool answ = false;
|
|
if (OSAI_ref.Connected)
|
|
{
|
|
try
|
|
{
|
|
answ = OSAI_ref.O_RW_DWord(bWrite, MemType, memIndex, ref Value);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
return answ;
|
|
}
|
|
/// <summary>
|
|
/// wrapper chiamata lettura/scrittura fanuc x Short...
|
|
/// </summary>
|
|
/// <param name="bWrite"></param>
|
|
/// <param name="MemType"></param>
|
|
/// <param name="memIndex"></param>
|
|
/// <param name="MATRICE Value"></param>
|
|
/// <returns></returns>
|
|
public bool OsaiMemRW_Short(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref short[] Value)
|
|
{
|
|
bool answ = false;
|
|
if (OSAI_ref.Connected)
|
|
{
|
|
try
|
|
{
|
|
answ = OSAI_ref.O_RW_Short(bWrite, MemType, memIndex, ref Value);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
return answ;
|
|
}
|
|
/// <summary>
|
|
/// wrapper chiamata lettura/scrittura fanuc x Short...
|
|
/// </summary>
|
|
/// <param name="bWrite"></param>
|
|
/// <param name="MemType"></param>
|
|
/// <param name="memIndex"></param>
|
|
/// <param name="MATRICE Value"></param>
|
|
/// <returns></returns>
|
|
public bool OsaiMemRW_Integer(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref int[] Value)
|
|
{
|
|
bool answ = false;
|
|
if (OSAI_ref.Connected)
|
|
{
|
|
try
|
|
{
|
|
answ = OSAI_ref.O_RW_Integer(bWrite, MemType, memIndex, ref Value);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
return answ;
|
|
}
|
|
/// <summary>
|
|
/// wrapper chiamata lettura/scrittura fanuc x Double...
|
|
/// </summary>
|
|
/// <param name="bWrite"></param>
|
|
/// <param name="MemType"></param>
|
|
/// <param name="memIndex"></param>
|
|
/// <param name="MATRICE Value"></param>
|
|
/// <returns></returns>
|
|
public bool OsaiMemRW_Double(bool bWrite, OSAI.MemTypeDouble MemType, Int32 memIndex, ref double[] Value)
|
|
{
|
|
bool answ = false;
|
|
if (OSAI_ref.Connected)
|
|
{
|
|
try
|
|
{
|
|
answ = OSAI_ref.O_RW_Double(bWrite, MemType, memIndex, ref Value);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// struttura dati OSAI x dati NC (pag 148)
|
|
/// </summary>
|
|
protected CMSCncLib.OPENcontrol.GETINFO1DATA allNcData;
|
|
/// <summary>
|
|
/// Vettore degli allarmi CNC attivi
|
|
/// </summary>
|
|
public CMSCncLib.OPENcontrol.MSGERROR allarmiCNC;
|
|
|
|
/// <summary>
|
|
/// estende l'init della classe base...
|
|
/// </summary>
|
|
/// <param name="caller"></param>
|
|
/// <param name="adpConf"></param>
|
|
public AdapterOsai(MainForm caller, AdapterConf adpConf) : base(caller, adpConf)
|
|
{
|
|
// !!!HARD CODED!!! aggiunto banco STATUS del 2 processo IN CODA... (4+1)DW=20byte x strobes...!!!
|
|
Strobes = new byte[20];
|
|
|
|
lg.Info("Start init Adapter OSAI all'IP {0}", utils.CRS("ipPLC"));
|
|
|
|
Runtime.CreateNC(CNC.NcType.OSAI, utils.CRS("ipPLC"));
|
|
|
|
// inizializzo posizioni assi...
|
|
prevPosAxis = new double[adpConf.nAxis];
|
|
prevDirAxis = new int[adpConf.nAxis];
|
|
|
|
OSAI_ref = (OSAI)Runtime.NC;
|
|
if (utils.CRB("verbose")) lg.Info(string.Format("Generato oggetto OSAI_ref da CMSCncLib:{0}{1}", Environment.NewLine, OSAI_ref.Descrizione));
|
|
|
|
// disconnetto e connetto...
|
|
if (utils.CRB("verbose")) lg.Info("OSAI: tryDisconnect");
|
|
tryDisconnect();
|
|
lg.Info("OSAI: tryConnect");
|
|
tryConnect();
|
|
lg.Info("End init Adapter OSAI");
|
|
}
|
|
/// <summary>
|
|
/// Override disconnessione
|
|
/// </summary>
|
|
public override void tryDisconnect()
|
|
{
|
|
if (connectionOk)
|
|
{
|
|
string szStatusConnection = "";
|
|
try
|
|
{
|
|
OSAI_ref.Disconnect(ref szStatusConnection);
|
|
connectionOk = false;
|
|
lg.Info(szStatusConnection);
|
|
lg.Info("Effettuata disconnessione adapter OSAI!");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Fatal(exc, "Errore nella disconnessione dall'adapter OSAI");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lg.Error("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile...");
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Override connessione
|
|
/// </summary>
|
|
public override void tryConnect()
|
|
{
|
|
if (!connectionOk)
|
|
{
|
|
string szStatusConnection = "";
|
|
try
|
|
{
|
|
OSAI_ref.Connect(ref szStatusConnection);
|
|
lg.Info("szStatusConnection: " + szStatusConnection);
|
|
connectionOk = true;
|
|
// refresh stato allarmi!!!
|
|
if (connectionOk)
|
|
{
|
|
if (adpRunning)
|
|
{
|
|
// carico status allarmi (completo)
|
|
lg.Info("Inizio refresh completo stato allarmi...");
|
|
forceAlarmCheck();
|
|
lg.Info("Completato refresh completo stato allarmi!");
|
|
}
|
|
else
|
|
{
|
|
lg.Info("Connessione OK");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lg.Error("Impossibile procedere, connessione mancante...");
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Fatal(exc, "Errore nella connessione all'adapter OSAI", szStatusConnection);
|
|
connectionOk = false;
|
|
lg.Info(string.Format("Segnalo Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec")));
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Verifico connessione OSAI...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override bool connectionOk
|
|
{
|
|
get
|
|
{
|
|
return OSAI_ref.Connected;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Effettuo lettura dei 16 byte di strobe/status
|
|
/// </summary>
|
|
public override void getStrobeAndAckStatus()
|
|
{
|
|
base.getStrobeAndAckStatus();
|
|
if (connectionOk)
|
|
{
|
|
// leggo TUTTO ack e strobe... in blocco di 16 WORD (32 byte) + altre 2 in coda...
|
|
ushort[] MemBlock_A = new ushort[16];
|
|
ushort[] MemBlock_B = new ushort[2];
|
|
|
|
int memIndexA = 19018;
|
|
int memIndexB = 19698;
|
|
|
|
// NB: LEGGO SEMPRE a WORD 16bit (+ veloce...)
|
|
|
|
// leggo blocco dati + grande...
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndexA, ref MemBlock_A);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R-{0}-W4", MemBlock_A.Length * 2), DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
// leggo blocco dati + piccolo
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndexB, ref MemBlock_B);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R-{0}-W1", MemBlock_B.Length * 2), DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
// suddivido blocco a blocco... da file di conf x OSAI!!!
|
|
|
|
//Buffer.BlockCopy(MemBlock_A, 0, Acknowl, 0, Acknowl.Length);
|
|
//Buffer.BlockCopy(MemBlock_A, Acknowl.Length, Strobes, 0, Strobes.Length);
|
|
|
|
// primi 12 byte ad ACK
|
|
Buffer.BlockCopy(MemBlock_A, 0, Acknowl, 0, Acknowl.Length - 4);
|
|
// altri 4 byte ad ACK blocco secondario
|
|
Buffer.BlockCopy(MemBlock_B, 0, Acknowl, Acknowl.Length - 4, 4);
|
|
// tutti i 16+4 byte a strobe/status
|
|
Buffer.BlockCopy(MemBlock_A, Acknowl.Length - 4, Strobes, 0, Strobes.Length);
|
|
}
|
|
else
|
|
{
|
|
lg.Error("Errore connessione mancante in getStrobeAndAckStatus");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// processing strobe!
|
|
/// </summary>
|
|
public override void processStrobe()
|
|
{
|
|
base.processStrobe();
|
|
|
|
// reset dello SB parent...
|
|
|
|
// oggetti "accessori" x processing (1 byte di strobe x ogni path)
|
|
StFlag8 currStrobe;
|
|
StFlag8 currAck;
|
|
string UserAction = "";
|
|
|
|
// 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, 19100, 19020, ref UserAction);
|
|
|
|
//...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, 19126, 19021, ref UserAction);
|
|
}
|
|
|
|
// 2017.01.16 INVIO vettore azioni (1 o +)... SE CE NE SONO!
|
|
if (UserAction.Trim() != "")
|
|
{
|
|
mUserAction.ForceChanged();
|
|
mUserAction.Value = UserAction.Trim();
|
|
}
|
|
|
|
// verifico strobe dell'auto-test
|
|
currStrobe = (StFlag8)(Strobes[7]); // 8° byte
|
|
currAck = (StFlag8)(Acknowl[7]); // 8° byte
|
|
processTestStrobe(currStrobe, currAck, 19021, 1);
|
|
|
|
// gestione bit di watchdog... sulal DWord successiva
|
|
sendWatchDog();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processa strobe x un dato path
|
|
/// </summary>
|
|
/// <param name="idxPath">path corrente</param>
|
|
/// <param name="currStrobe">Byte di strobe del path corrente</param>
|
|
/// <param name="currAck">Byte di strobe del path corrente</param>
|
|
/// <param name="memIndexMST">indice x lettura memoria MST del path</param>
|
|
/// <param name="memIndexAck">indice x scrittura ACK x path</param>
|
|
/// <param name="UserAction">stringa COMPLESSIVA azioni utente</param>
|
|
private void procPathStrobes(int idxPath, StFlag8 currStrobe, StFlag8 currAck, int memIndexMST, int memIndexAck, ref string UserAction)
|
|
{
|
|
// byte di strobe e di acknowledge... inizializzo!!!
|
|
byte[] currACK_DW = new byte[1];
|
|
// altre variabili
|
|
int bitNum = 0;
|
|
inizio = DateTime.Now;
|
|
// incomincio vera e propria gestione...
|
|
try
|
|
{
|
|
// controllo TUTTI i flag: se ce ne sono di alzati DEVO processare...
|
|
if (currStrobe != StFlag8.NONE)
|
|
{
|
|
// se ho un M/S/T leggo area...
|
|
if (currStrobe.HasFlag(StFlag8.B0) || currStrobe.HasFlag(StFlag8.B1) || currStrobe.HasFlag(StFlag8.B2))
|
|
{
|
|
|
|
// blocco memoria x lettura TUTTI i dati di buffer M/S/T: 26 short(16bit) x (12+7+7) aree (attenzione: secondo set di 2 bit è VUOTO...)
|
|
ushort[] MemBlock_W = new ushort[26];
|
|
|
|
// leggo tutto!!!
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndexMST, ref MemBlock_W);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-STRB_DW1-P{1:00}", MemBlock_W.Length, idxPath), DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
// converto a byte x compatibilità...
|
|
byte[] MemBlock = new byte[MemBlock_W.Length * 2];
|
|
Buffer.BlockCopy(MemBlock_W, 0, MemBlock, 0, MemBlock.Length);
|
|
|
|
// check COD_M
|
|
bitNum = 0;
|
|
gestStrobeCodMST(currStrobe, bitNum, ref currACK_DW, 0, MemBlock, "M");
|
|
|
|
// check COD_S
|
|
bitNum = 1;
|
|
gestStrobeCodMST(currStrobe, bitNum, ref currACK_DW, 12, MemBlock, "S");
|
|
|
|
// check COD_T
|
|
bitNum = 2;
|
|
gestStrobeCodMST(currStrobe, bitNum, ref currACK_DW, 19, MemBlock, "T");
|
|
|
|
}
|
|
|
|
// check FILE DATI MODIFICATO: ricaricare...
|
|
bitNum = 3;
|
|
if (STRB_DW1.HasFlag((StFlag32)Math.Pow(2, bitNum)))
|
|
{
|
|
lg.Info("Notifica file modificato");
|
|
try
|
|
{
|
|
// reload dati da file...
|
|
reloadDataFromFile();
|
|
|
|
// memorizzo allarme nel vettore ack....
|
|
currACK_DW = utils.setBitOnStFlag(currACK_DW, true, bitNum);
|
|
}
|
|
catch
|
|
{
|
|
lg.Info("Errore lettura dati da file");
|
|
}
|
|
}
|
|
|
|
// AREA strobe USER ACTION
|
|
// chiamato Start...
|
|
bitNum = 4;
|
|
gestStrobeUserAction(bitNum, ref currACK_DW, ref UserAction, string.Format(" (P{0:00} START) ", idxPath));
|
|
// chiamato Stop...
|
|
bitNum = 5;
|
|
gestStrobeUserAction(bitNum, ref currACK_DW, ref UserAction, string.Format(" (P{0:00} STOP) ", idxPath));
|
|
// chiamato Reset...
|
|
bitNum = 6;
|
|
gestStrobeUserAction(bitNum, ref currACK_DW, ref UserAction, string.Format(" (P{0:00} RESET) ", idxPath));
|
|
|
|
}
|
|
else
|
|
{
|
|
// inizializzo 4 byte a zero!!!
|
|
currACK_DW = new byte[1];
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("Errore in strobe:{0}{1}", Environment.NewLine, exc));
|
|
}
|
|
|
|
// scrivo update ad ack SE VARIATO!!!
|
|
if (currAck != (StFlag8)currACK_DW[0])
|
|
{
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndexAck, 0, ref currACK_DW);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("W{0}-B", currACK_DW.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Verifica strobe autotest
|
|
/// </summary>
|
|
/// <param name="currStrobe"></param>
|
|
/// <param name="currAck"></param>
|
|
/// <param name="memIndexAck"></param>
|
|
private void processTestStrobe(StFlag8 currStrobe, StFlag8 currAck, int memIndexAck, int memOrderStart)
|
|
{
|
|
// byte di strobe e di acknowledge... inizializzo!!!
|
|
byte[] currACK_DW = new byte[1];
|
|
string TestingData = "";
|
|
// INIZIO TEST...
|
|
int bitNum = 6;
|
|
if (currStrobe.HasFlag((StFlag8)Math.Pow(2, bitNum)))
|
|
{
|
|
// formatto stringa risultato
|
|
TestingData = string.Format("START TEST{0}", getTestData(utils.CRS("testCharSep")));
|
|
|
|
// memorizzo allarme nel vettore ack....
|
|
currACK_DW = utils.setBitOnStFlag(currACK_DW, true, bitNum);
|
|
}
|
|
// FINE TEST...
|
|
bitNum = 7;
|
|
if (currStrobe.HasFlag((StFlag8)Math.Pow(2, bitNum)))
|
|
{
|
|
// formatto stringa risultato
|
|
TestingData = string.Format("STOP TEST{0}", getTestData(utils.CRS("testCharSep")));
|
|
|
|
// memorizzo allarme nel vettore ack....
|
|
currACK_DW = utils.setBitOnStFlag(currACK_DW, true, bitNum);
|
|
}
|
|
|
|
// INVIO stato test...
|
|
if (mTestingData.Value.ToString() != TestingData.Trim())
|
|
{
|
|
mTestingData.Value = TestingData.Trim();
|
|
}
|
|
|
|
// scrivo update ad ack SE VARIATO!!!
|
|
if (currAck != (StFlag8)currACK_DW[0])
|
|
{
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndexAck, memOrderStart, ref currACK_DW);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("W{0}-B", currACK_DW.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Invia (se necessario) il watchdog di stato in vita... blink 0/1 ogni secondo
|
|
/// </summary>
|
|
private void sendWatchDog()
|
|
{
|
|
int memIndex = 0;
|
|
byte[] retACK_DW = new byte[1];
|
|
// 2016.10.18 aggiungo scrittura del bit di "watchdog" al primo bit della DW2... come resto tra secondi / 2
|
|
if (utils.CRB("sendWatchDog"))
|
|
{
|
|
int resto = 0;
|
|
Math.DivRem(DateTime.Now.Second, 2, out resto);
|
|
bool setFlag = resto == 0;
|
|
retACK_DW = utils.setBitOnStFlag(retACK_DW, setFlag, 0); // imposto primo bit!!!
|
|
// scrivo su area PLC
|
|
memIndex = 19022;
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref retACK_DW);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("W{0}-B", retACK_DW.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero info su test: numero + elenco parametri IN/OUT
|
|
/// </summary>
|
|
/// <param name="charSep"></param>
|
|
/// <returns></returns>
|
|
private string getTestData(string charSep)
|
|
{
|
|
string answ = "";
|
|
// Area di memoria x test... (64 DWord) (la prima va splittata)
|
|
UInt32[] MemBlockTestData = new UInt32[64];
|
|
// variabili numero test e num parametri impiegati
|
|
int testNum = 0;
|
|
int numPar = 0;
|
|
// variabile dove parcheggiare conversione codici dei parametri del test (IN o OUT)
|
|
UInt32 testParam = 0;
|
|
|
|
// leggo tutto!!!
|
|
int memIndex = 19700;
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref MemBlockTestData);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TEST_DATA", MemBlockTestData.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
// recupero cod univoco test e numero parametri impiegati
|
|
testNum = BitConverter.ToUInt16(BitConverter.GetBytes(MemBlockTestData[0]), 0);
|
|
numPar = BitConverter.ToUInt16(BitConverter.GetBytes(MemBlockTestData[0]), 2);
|
|
|
|
|
|
// riporto separatore + numero test + num parametri
|
|
answ = string.Format("{0}TN:{1}{0}NP:{2}", charSep, testNum, numPar);
|
|
// se ci sono parametri da accodare li recupero!
|
|
if (numPar > 0)
|
|
{
|
|
for (int i = 0; i < numPar; i++)
|
|
{
|
|
testParam = MemBlockTestData[1 + i];
|
|
answ += string.Format("{0}{1}", charSep, testParam);
|
|
}
|
|
}
|
|
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione STROBE --> ACK per codici M/S/T
|
|
/// </summary>
|
|
/// <param name="currStrobe">byte di strobe corrente</param>
|
|
/// <param name="bitNum">0/1/2</param>
|
|
/// <param name="retACK_DW1">vettore da restituire di ACK</param>
|
|
/// <param name="memShift">shift memoria x buffer dati da leggere</param>
|
|
/// <param name="MemBlock">Vettore completo dei valori + buffer code M/S/T</param>
|
|
/// <param name="Coda">Quale coda: M/S/T</param>
|
|
private void gestStrobeCodMST(StFlag8 currStrobe, int bitNum, ref byte[] retACK_DW1, int memShift, byte[] MemBlock, string Coda)
|
|
{
|
|
int numEv = 0;
|
|
int codEv = 0;
|
|
if (currStrobe.HasFlag((StFlag8)Math.Pow(2, bitNum)))
|
|
{
|
|
// verifico sia > 0 il numero di valori da leggere - indice 0 sull'area...
|
|
numEv = BitConverter.ToUInt16(MemBlock, 2 * memShift);
|
|
if (numEv > 0)
|
|
{
|
|
// il num ev rappresenta quanti slot 16bit (da 2 byte) sono stati valorizzati, VA FATTO CICLO E LETTI TUTTI
|
|
for (int i = 0; i < numEv; i++)
|
|
{
|
|
// leggo valore Codice
|
|
codEv = BitConverter.ToUInt16(MemBlock, 2 * (i + 2 + memShift));
|
|
// accodo evento Codice
|
|
appendCodeMST(Coda, codEv.ToString());
|
|
}
|
|
}
|
|
// memorizzo allarme nel vettore ack....
|
|
retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Ricarica dati da file di scambio con CMSConnect
|
|
/// </summary>
|
|
private void reloadDataFromFile()
|
|
{
|
|
if (utils.CRB("verbose")) lg.Info("Inizio lettura dati da file");
|
|
int totRighe = 0;
|
|
// da rivedere: se sono N+1 file (N=path + generale) deve essere ad esempio nomeComune_*.mtc --> ciclo per leggerne N
|
|
string fileName = string.Format(@"{0}\{1}", utils.dataDir, utils.CRS("GeneralStatusFilePath"));
|
|
string linea;
|
|
// creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
|
|
generalStatus = new Dictionary<string, string>();
|
|
try
|
|
{
|
|
totRighe = File.ReadLines(fileName).Count();
|
|
// carica da file...
|
|
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
|
|
if (file != null)
|
|
{
|
|
// leggo 1 linea alla volta...
|
|
string[] valori;
|
|
while ((linea = file.ReadLine()) != null)
|
|
{
|
|
// SE non è un commento...
|
|
if (linea.Substring(0, 1) != "#")
|
|
{
|
|
valori = linea.Split(utils.CRC("testCharSep"));
|
|
generalStatus.Add(valori[0], valori[1]);
|
|
}
|
|
}
|
|
// chiudo file
|
|
file.Close();
|
|
if (utils.CRB("verbose")) lg.Info("Fine lettura dati da file");
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
lg.Info("Errore in lettura dati da file");
|
|
}
|
|
|
|
|
|
// ora salvo valori letti...
|
|
foreach (KeyValuePair<string, string> item in generalStatus)
|
|
{
|
|
// verifico la chiave e nel caso aggiorno...
|
|
switch (item.Key)
|
|
{
|
|
case "OperatorId":
|
|
mOperator.Value = item.Value;
|
|
break;
|
|
case "Path_01_CurrProg":
|
|
istPathProgrName[0] = item.Value;
|
|
break;
|
|
case "Path_02_CurrProg":
|
|
istPathProgrName[1] = item.Value;
|
|
break;
|
|
case "Path_03_CurrProg":
|
|
istPathProgrName[2] = item.Value;
|
|
break;
|
|
case "Path_04_CurrProg":
|
|
istPathProgrName[3] = item.Value;
|
|
break;
|
|
case "Path_05_CurrProg":
|
|
istPathProgrName[4] = item.Value;
|
|
break;
|
|
case "Path_06_CurrProg":
|
|
istPathProgrName[5] = item.Value;
|
|
break;
|
|
case "Path_01_PartId":
|
|
istPathPartId[0] = item.Value;
|
|
break;
|
|
case "Path_02_PartId":
|
|
istPathPartId[1] = item.Value;
|
|
break;
|
|
case "Path_03_PartId":
|
|
istPathPartId[2] = item.Value;
|
|
break;
|
|
case "Path_04_PartId":
|
|
istPathPartId[3] = item.Value;
|
|
break;
|
|
case "Path_05_PartId":
|
|
istPathPartId[4] = item.Value;
|
|
break;
|
|
case "Path_06_PartId":
|
|
istPathPartId[5] = item.Value;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione strobe UserAction: salva dati e gestione ACK
|
|
/// </summary>
|
|
/// <param name="bitNum"></param>
|
|
/// <param name="retACK_DW1"></param>
|
|
/// <param name="UserAction"></param>
|
|
/// <param name="azione"></param>
|
|
private void gestStrobeUserAction(int bitNum, ref byte[] retACK_DW1, ref string UserAction, string azione)
|
|
{
|
|
if (STRB_DW1.HasFlag((StFlag32)Math.Pow(2, bitNum)))
|
|
{
|
|
// salvo evento UserAction in variabile...
|
|
UserAction += azione;
|
|
// memorizzo allarme nel vettore ack....
|
|
retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// recupera allarmi ed aggiorna strobe (privato) degli allarmi
|
|
/// </summary>
|
|
/// <param name="Alarm2Refresh">32bit mask degli allarmi da aggiornare</param>
|
|
/// <param name="giveAck">boolean: se si debba tornare ACK</param>
|
|
public override void refreshAlarmState(StFlag32 Alarm2Refresh, bool giveAck)
|
|
{
|
|
// log bitmap se verboso attivo + ho allarmi da refreshare
|
|
if ((Alarm2Refresh != StFlag32.NONE) && utils.CRB("verbose"))
|
|
{
|
|
lg.Info("Richiesto refresh allarmi x bitmask: {0}", utils.binaryForm((int)Alarm2Refresh));
|
|
}
|
|
|
|
bool ackReturned = false;
|
|
// byte di acknowledge...
|
|
byte[] retACK_DW0 = new byte[4];
|
|
// inizio impostando una bitmap x ACK che abbia i bit abbassati se lo strobe è disattivo: AND logico tra STR e ACK
|
|
retACK_DW0 = BitConverter.GetBytes(Convert.ToUInt32(STRB_DW0 & ACK_DW0));
|
|
|
|
inizio = DateTime.Now;
|
|
uint[] MemBlock;
|
|
// primo blocco memoria allarmi
|
|
int memIndex = 19036;
|
|
// controllo, SE devo leggere tutto uso un unico accesso ai 128byte, altrimenti leggo a blocchi di 32bit...
|
|
if (Alarm2Refresh == (StFlag32)unchecked((int)UInt32.MaxValue))
|
|
{
|
|
// blocco memoria x lettura dati COMPLETO (4Byte*32 = 128Byte)
|
|
MemBlock = new uint[32];
|
|
// recupero tutti i 32 bit del blocco
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref MemBlock);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-STRB_DW0", MemBlock.Length * 4), DateTime.Now.Subtract(inizio).Ticks);
|
|
if (AlarmFlags != null)
|
|
{
|
|
try
|
|
{
|
|
// aggiorno vettore allarmi x intero! size del vettore di destinazione (in byte!!!!)
|
|
Buffer.BlockCopy(MemBlock, 0, AlarmFlags, 0, AlarmFlags.Length);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("Errore in BLOCKCOPY{0}{1}", Environment.NewLine, exc));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Alarm2Refresh != StFlag32.NONE)
|
|
{
|
|
// blocco memoria x lettura dati
|
|
MemBlock = new uint[1];
|
|
// verifico gli allarmi di tutti i bit alzati...
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
if (Alarm2Refresh.HasFlag((StFlag32)Math.Pow(2, i)))
|
|
{
|
|
// recupero tutti i 32 bit del blocco
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex + i * 2, ref MemBlock);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-STRB_DW0", MemBlock.Length * 4), DateTime.Now.Subtract(inizio).Ticks);
|
|
try
|
|
{
|
|
// aggiorno vettore allarmi x intero!
|
|
Buffer.BlockCopy(MemBlock, 0, AlarmFlags, i * 4, 4);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("Errore in BLOCKCOPY per indice i = {2},{0}{1}", Environment.NewLine, exc, i));
|
|
}
|
|
if (utils.CRI("loglevel") > 5)
|
|
{
|
|
lg.Info("Bit {0}, MemBlock: {1}", i, MemBlock[0]);
|
|
}
|
|
// segnalo allarme letto! memorizzo allarme nel vettore ack....
|
|
retACK_DW0 = utils.setBitOnStFlag(retACK_DW0, true, i);
|
|
}
|
|
}
|
|
// scrivo ack se richiesto!!!
|
|
if (giveAck)
|
|
{
|
|
// mi preparo a scrivere ACK
|
|
memIndex = 19018;
|
|
// scrivo update ad ack!!!
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref retACK_DW0);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("W{0}-ACK_DW0", retACK_DW0.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
ackReturned = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// SE non ho già tornato un ACK...
|
|
if (!ackReturned)
|
|
{
|
|
// se è diverso il vettori degli ACK in memoria da quello PLC...
|
|
if (ACK_DW0 != (StFlag32)BitConverter.ToUInt32(retACK_DW0, 0))
|
|
{
|
|
memIndex = 19018;
|
|
// invio INTERO set ACK_DW0 con bit abbassati...
|
|
retACK_DW0 = BitConverter.GetBytes(Convert.ToUInt32(STRB_DW0 & ACK_DW0));
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref retACK_DW0);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("W{0}-ACK_DW0", retACK_DW0.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// processing!
|
|
/// </summary>
|
|
public override void processStatus()
|
|
{
|
|
// update status da DW2/ DW3
|
|
|
|
// EMstop: verifico BIT e di conseguenza imposto
|
|
if (STRB_DW2.HasFlag(StFlag32.B00))
|
|
{
|
|
mEStop.Value = "TRIGGERED";
|
|
}
|
|
else
|
|
{
|
|
mEStop.Value = "ARMED";
|
|
}
|
|
|
|
// verifico POWER ON...
|
|
if (STRB_DW2.HasFlag(StFlag32.B01))
|
|
{
|
|
mPower.Value = "ON";
|
|
}
|
|
else
|
|
{
|
|
mPower.Value = "OFF";
|
|
}
|
|
|
|
// Processo selezionato 0=P1, 1=P2
|
|
string procSel = "";
|
|
if (STRB_DW2.HasFlag(StFlag32.B02))
|
|
{
|
|
procSel = "P2";
|
|
}
|
|
else
|
|
{
|
|
procSel = "P1";
|
|
}
|
|
if (mProcSel.Value.ToString() != procSel)
|
|
{
|
|
mProcSel.Value = procSel;
|
|
}
|
|
|
|
// processo ora i dai dei path... di sicuro il primo
|
|
procPath01_Status();
|
|
//...e se c'è pure il secondo...
|
|
if (currAdpConf.nPath > 1)
|
|
{
|
|
// anche il secondo!
|
|
procPath02_Status();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Processa status del path 01...
|
|
/// </summary>
|
|
private void procPath01_Status()
|
|
{
|
|
// HARD CODE: forzo path 1 (indice 0...) x iniziare...
|
|
int idxPath = 0;
|
|
string pathType = "";
|
|
// verifico tipo processo path...
|
|
if (STRB_DW2.HasFlag(StFlag32.B03))
|
|
{
|
|
pathType = "LAVORO";
|
|
}
|
|
else
|
|
{
|
|
pathType = "ASSERV";
|
|
}
|
|
|
|
// switch su RUN mode...
|
|
string runMode = "";
|
|
if (STRB_DW2.HasFlag(StFlag32.B04))
|
|
{
|
|
runMode = "AUTOMATIC";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B05))
|
|
{
|
|
runMode = "EDIT";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B06))
|
|
{
|
|
runMode = "MANUAL_DATA_INPUT";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B07))
|
|
{
|
|
runMode = "MANUAL";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B08))
|
|
{
|
|
runMode = "SEMI_AUTO";
|
|
}
|
|
|
|
// switch su EXE mode...
|
|
string exeMode = "";
|
|
if (STRB_DW2.HasFlag(StFlag32.B09))
|
|
{
|
|
exeMode = "ACTIVE";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B10))
|
|
{
|
|
exeMode = "READY";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B11))
|
|
{
|
|
exeMode = "STOPPED";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B12))
|
|
{
|
|
exeMode = "FEED_HOLD";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B13))
|
|
{
|
|
exeMode = "OPTIONAL_STOP";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B14))
|
|
{
|
|
exeMode = "PROGRAM_STOPPED";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B15))
|
|
{
|
|
exeMode = "PROGRAM_COMPLETED";
|
|
}
|
|
|
|
// inizializzo SEMPRE a vuoto...
|
|
string SubMode = "";
|
|
// verifico sulla STRB_DW3 i submode che POTREBBERO tutti sovrapposti...
|
|
if (STRB_DW3 != StFlag32.NONE)
|
|
{
|
|
// cerco i bit alzati --> aggiungo relativo submode!
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
// converto! e aggiungo allarmi sollevati al corretto controller allarmi...
|
|
if (STRB_DW3.HasFlag((StFlag32)Math.Pow(2, i)))
|
|
{
|
|
SubMode += string.Format(" [P{0:00}_{1}]", idxPath, elencoSubMode[i.ToString()]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// salvo in blocco le info ricostruite x path!
|
|
savePathData(idxPath, pathType, runMode, exeMode, SubMode.Trim());
|
|
}
|
|
/// <summary>
|
|
/// Processa status del path 02...
|
|
/// </summary>
|
|
private void procPath02_Status()
|
|
{
|
|
// HARD CODE: forzo path 2 (indice 1)...
|
|
int idxPath = 1;
|
|
string pathType = "";
|
|
// verifico tipo processo path...
|
|
if (STRB_DW2.HasFlag(StFlag32.B16))
|
|
{
|
|
pathType = "LAVORO";
|
|
}
|
|
else
|
|
{
|
|
pathType = "ASSERV";
|
|
}
|
|
|
|
// switch su RUN mode...
|
|
string runMode = "";
|
|
if (STRB_DW2.HasFlag(StFlag32.B17))
|
|
{
|
|
runMode = "AUTOMATIC";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B18))
|
|
{
|
|
runMode = "EDIT";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B19))
|
|
{
|
|
runMode = "MANUAL_DATA_INPUT";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B20))
|
|
{
|
|
runMode = "MANUAL";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B21))
|
|
{
|
|
runMode = "SEMI_AUTO";
|
|
}
|
|
|
|
// switch su EXE mode...
|
|
string exeMode = "";
|
|
if (STRB_DW2.HasFlag(StFlag32.B22))
|
|
{
|
|
exeMode = "ACTIVE";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B23))
|
|
{
|
|
exeMode = "READY";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B24))
|
|
{
|
|
exeMode = "STOPPED";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B25))
|
|
{
|
|
exeMode = "FEED_HOLD";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B26))
|
|
{
|
|
exeMode = "OPTIONAL_STOP";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B27))
|
|
{
|
|
exeMode = "PROGRAM_STOPPED";
|
|
}
|
|
else if (STRB_DW2.HasFlag(StFlag32.B28))
|
|
{
|
|
exeMode = "PROGRAM_COMPLETED";
|
|
}
|
|
|
|
// inizializzo SEMPRE a vuoto...
|
|
string SubMode = "";
|
|
// verifico sulla STRB_DW3 i submode che POTREBBERO tutti sovrapposti...
|
|
if (STRB_DW4 != StFlag32.NONE)
|
|
{
|
|
// cerco i bit alzati --> aggiungo relativo submode!
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
// converto! e aggiungo allarmi sollevati al corretto controller allarmi...
|
|
if (STRB_DW4.HasFlag((StFlag32)Math.Pow(2, i)))
|
|
{
|
|
SubMode += string.Format(" [P{0:00}_{1}]", idxPath, elencoSubMode[i.ToString()]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// salvo in blocco le info ricostruite x path!
|
|
savePathData(idxPath, pathType, runMode, exeMode, SubMode.Trim());
|
|
}
|
|
/// <summary>
|
|
/// Salva i valori per il path indicato SE variati...
|
|
/// </summary>
|
|
/// <param name="idxPath"></param>
|
|
/// <param name="pathType"></param>
|
|
/// <param name="pathRunMode"></param>
|
|
/// <param name="pathExeMode"></param>
|
|
/// <param name="pathSubMode"></param>
|
|
protected void savePathData(int idxPath, string pathType, string pathRunMode, string pathExeMode, string pathSubMode)
|
|
{
|
|
// salvo type
|
|
if (vettPath[idxPath].mPathType.Value.ToString() != pathType)
|
|
{
|
|
vettPath[idxPath].mPathType.Value = pathType;
|
|
}
|
|
// salvo RUN mode
|
|
if (vettPath[idxPath].mPathRunMode.Value.ToString() != pathRunMode)
|
|
{
|
|
vettPath[idxPath].mPathRunMode.Value = pathRunMode;
|
|
}
|
|
// salvo EXE mode
|
|
if (vettPath[idxPath].mPathExeMode.Value.ToString() != pathExeMode)
|
|
{
|
|
vettPath[idxPath].mPathExeMode.Value = pathExeMode;
|
|
}
|
|
// salvo i submode..
|
|
if (vettPath[idxPath].mPathSubMode.Value.ToString() != pathSubMode)
|
|
{
|
|
vettPath[idxPath].mPathSubMode.Value = pathSubMode;
|
|
}
|
|
}
|
|
|
|
public override void getConfigParam()
|
|
{
|
|
base.getConfigParam();
|
|
}
|
|
|
|
public override void getSlowChangingData()
|
|
{
|
|
base.getSlowChangingData();
|
|
|
|
// reload dati da file...
|
|
reloadDataFromFile();
|
|
|
|
// area gestione dati utensili... in base al num max di UnOp recupero i dati utensile... PROCEDURA AD HOC!!!
|
|
getDatiUt_Fanuc(currAdpConf.nUnOp);
|
|
|
|
}
|
|
/// <summary>
|
|
/// Gestione lettura dati manutenzione
|
|
/// </summary>
|
|
private void getMtzDataFromPlc()
|
|
{
|
|
// recupero i dati di manutenzione dall'area di memoria IN BLOCCO
|
|
int memIndex = 1000;
|
|
uint[] tabDatiMtz = new uint[maintData.Length];
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_DWord(R, OSAI.MemTypeWord.GW_CODE, memIndex, ref tabDatiMtz);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-DatiMtz", tabDatiMtz.Length * 4), DateTime.Now.Subtract(inizio).Ticks);
|
|
// decodifico aree memoria secondo tab configurazione
|
|
processMaintData(tabDatiMtz, maintData);
|
|
// verifica se debba salvare e mostrare dati
|
|
checkSavePersDataLayer();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione lettura dati status da PLC
|
|
/// </summary>
|
|
private void getStatusDataFromPlc()
|
|
{
|
|
// recupero i dati di manutenzione dall'area di memoria IN BLOCCO
|
|
#if false
|
|
int memIndex = 14512;
|
|
int bitNum = 0;
|
|
int byteNum = 0;
|
|
byte byteVal;
|
|
int numByte = 1 + (statusData.Length / 8);
|
|
byte[] tabDatiStatus = new byte[numByte];
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.R, memIndex, ref tabDatiStatus);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-DatiStatus", tabDatiStatus.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
// uno ad uno vado a inserirli nella mappa dei dati dell'adapter...
|
|
int numero = 0;
|
|
string status = "";
|
|
for (int i = 0; i < statusData.Length; i++)
|
|
{
|
|
numero = 0;
|
|
status = "";
|
|
|
|
// calcolo quale byte e quale bit devo leggere..
|
|
byteNum = i / 8;
|
|
bitNum = i - (8 * byteNum); // indice zero dei bit nel byte ( da cui -1 )
|
|
// faccio vera lettura
|
|
byteVal = tabDatiStatus[byteNum];
|
|
// leggo bit come ACTIVE/INACTIVE
|
|
if (((StFlag8)byteVal).HasFlag((StFlag8)Math.Pow(2, bitNum)))
|
|
{
|
|
status = "ACTIVE";
|
|
}
|
|
else
|
|
{
|
|
status = "INACTIVE";
|
|
}
|
|
|
|
if (statusData[i].varName == "PROTECTION_STATUS")
|
|
{
|
|
mProtectionStatus.Value = status;
|
|
}
|
|
else if (statusData[i].varName.StartsWith("VacPump_"))
|
|
{
|
|
if (statusData[i].varName.EndsWith("_Status"))
|
|
{
|
|
try
|
|
{
|
|
numero = Convert.ToInt32(statusData[i].varName.Replace("VacPump_", "").Replace("_Status", ""));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
if (numero > 0)
|
|
{
|
|
vettVacPump[numero - 1].mVacPumpStatus.Value = status;
|
|
}
|
|
}
|
|
}
|
|
else if (statusData[i].varName.StartsWith("Cooler_"))
|
|
{
|
|
if (statusData[i].varName.EndsWith("_Status"))
|
|
{
|
|
try
|
|
{
|
|
numero = Convert.ToInt32(statusData[i].varName.Replace("Cooler_", "").Replace("_Status", ""));
|
|
}
|
|
catch
|
|
{ }
|
|
if (numero > 0)
|
|
{
|
|
vettCooler[numero - 1].mCoolStatus.Value = status;
|
|
}
|
|
}
|
|
}
|
|
else if (statusData[i].varName.StartsWith("UnOp_"))
|
|
{
|
|
if (statusData[i].varName.EndsWith("_Status"))
|
|
{
|
|
try
|
|
{
|
|
numero = Convert.ToInt32(statusData[i].varName.Replace("UnOp_", "").Replace("_Status", ""));
|
|
}
|
|
catch
|
|
{ }
|
|
if (numero > 0)
|
|
{
|
|
vettUnOp[numero - 1].mUnOpStatus.Value = status;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
/// <summary>
|
|
/// Leggo dati globali comuni (x path, assi...)
|
|
/// </summary>
|
|
public override void getGlobalData()
|
|
{
|
|
base.getGlobalData();
|
|
|
|
// accodo dati path in DataMonitor......
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
// dati base...
|
|
sb.AppendLine(string.Format("POWER {0}: | EmStop:{1:N3} | ProcSel: {2}", mPower.Value, mEStop.Value, mProcSel.Value));
|
|
|
|
// leggo dati globali...
|
|
inizio = DateTime.Now;
|
|
OSAI_ref.O_GetNcInfo1(ref allNcData);
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-NcInfo", DateTime.Now.Subtract(inizio).Ticks);
|
|
// recupero feed...
|
|
FeedRate = Convert.ToInt32(allNcData.realfeed);
|
|
|
|
// area path1/2: 7 WORD x ogni path...
|
|
int memIndex = 19151;
|
|
ushort[] PathData_mem = new ushort[14];
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref PathData_mem);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PathData", PathData_mem.Length * 2), DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
// inizio indicando feed...
|
|
sb.AppendLine(string.Format("FeedRate: {0} mm/min", FeedRate));
|
|
|
|
// 2017.04.20: recupero OVER per Jog/Feed/Rapid/Spindle x i path multipli (qui cablati 1-2)
|
|
ushort[] currPathData = new ushort[7];
|
|
// processo ora i dai dei path... di sicuro il primo
|
|
Array.Copy(PathData_mem, 0, currPathData, 0, 7);
|
|
procPathOverride(0, currPathData, ref sb);
|
|
//...e se c'è pure il secondo...
|
|
if (currAdpConf.nPath > 1)
|
|
{
|
|
Array.Copy(PathData_mem, 7, currPathData, 0, 7);
|
|
// anche il secondo!
|
|
procPathOverride(1, currPathData, ref sb);
|
|
}
|
|
|
|
// se ho allarmi li accodo...
|
|
if (allNcData.lastncerror != 0)
|
|
{
|
|
sb.AppendLine(string.Format("Allarmi CNC: {0}", allNcData.lastncerror));
|
|
|
|
inizio = DateTime.Now;
|
|
OSAI_ref.O_ReadCurrentErrorMsg(ref allarmiCNC);
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-CNC-ALARMS", DateTime.Now.Subtract(inizio).Ticks);
|
|
checkCNCAlarms();
|
|
}
|
|
else
|
|
{
|
|
allarmiCNC = new CMSCncLib.OPENcontrol.MSGERROR();
|
|
}
|
|
|
|
parentForm.dataMonitor = sb.ToString();
|
|
|
|
// gestisco lettura dati manutenzione da PLC...
|
|
getMtzDataFromPlc();
|
|
|
|
// gestisco lettura dati status da PLC...
|
|
getStatusDataFromPlc();
|
|
}
|
|
/// <summary>
|
|
/// Processa i dati di override di un path
|
|
/// </summary>
|
|
/// <param name="currIdx">idx path (zero based)</param>
|
|
/// <param name="dataVector">vettore 7 valori dei dati (valori int16 jog/feed/rapid/spindle[1..4])</param>
|
|
/// <param name="sb">StringBuilder da aggiornare</param>
|
|
private void procPathOverride(int currIdx, ushort[] dataVector, ref StringBuilder sb)
|
|
{
|
|
// prendo quella GLOBALE...
|
|
vettPath[currIdx].mPathFeed.Value = FeedRate;
|
|
// leggo da vettore... CABLATO DIVISO PER 100!!!
|
|
vettPath[currIdx].mPathJogOver.Value = dataVector[0] / 100;
|
|
vettPath[currIdx].mPathFeedOver.Value = dataVector[1] / 100;
|
|
vettPath[currIdx].mPathRapidOver.Value = dataVector[2] / 100;
|
|
vettPath[currIdx].mPathSpindleOver_01.Value = dataVector[3] / 100;
|
|
vettPath[currIdx].mPathSpindleOver_02.Value = dataVector[4] / 100;
|
|
vettPath[currIdx].mPathSpindleOver_03.Value = dataVector[5] / 100;
|
|
vettPath[currIdx].mPathSpindleOver_04.Value = dataVector[6] / 100;
|
|
|
|
// salvo stringa!
|
|
sb.AppendLine(string.Format("P{0} - Override % Jog | Feed | Rapid: {1} | {2} | {3}", currIdx + 1, dataVector[0] / 100, dataVector[1] / 100, dataVector[2] / 100));
|
|
sb.AppendLine(string.Format("P{0} - Override % Spindle 1 | 2 | 3 | 4: {1} | {2} | {3} | {4}", currIdx + 1, dataVector[3] / 100, dataVector[4] / 100, dataVector[5] / 100, dataVector[6] / 100));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Carico file conf dati CMS
|
|
/// </summary>
|
|
protected override void loadOtherFile()
|
|
{
|
|
base.loadOtherFile();
|
|
loadMaintData();
|
|
loadStatusData();
|
|
}
|
|
/// <summary>
|
|
/// Lettura file gestione dati manutenzione da PLC
|
|
/// </summary>
|
|
private void loadMaintData()
|
|
{
|
|
// carico dati x Maintenance
|
|
if (utils.CRB("verbose")) lg.Info("Inizio caricamento vettore variabili manutenzione gestite");
|
|
int totRighe = 0;
|
|
string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("CounterListFilePath"));
|
|
string linea;
|
|
totRighe = File.ReadLines(fileName).Count();
|
|
// creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
|
|
maintData = new otherData[File.ReadLines(fileName).Count()];
|
|
// 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) != "#")
|
|
{
|
|
//elencoAllarmi[rumRiga] = decodeAlarmLine(linea, ':');
|
|
maintData[numRiga] = decodeOtherData(linea, utils.CRC("testCharSep"), "MW", 19166, 2);
|
|
numRiga++;
|
|
}
|
|
}
|
|
// chiudo file
|
|
file.Close();
|
|
// ora trimmo vettore al solo numero VERO dei valori caricati...
|
|
Array.Resize<otherData>(ref maintData, numRiga);
|
|
|
|
if (utils.CRB("verbose")) lg.Info(string.Format("Fine caricamento vettore di {0} variabili manutenzione gestite", numRiga));
|
|
}
|
|
/// <summary>
|
|
/// Lettura file gestione dati status da PLC
|
|
/// </summary>
|
|
private void loadStatusData()
|
|
{
|
|
// problema blocco file dati persistenti che diventa binario/illeggibile: cambiare metodo accesso file? using{}?!?
|
|
#if false
|
|
// carico dati x Maintenance
|
|
if (utils.CRB("verbose")) lg.Info("Inizio caricamento vettore variabili status gestite");
|
|
int totRighe = 0;
|
|
string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("StatusListFilePath"));
|
|
string linea;
|
|
totRighe = File.ReadLines(fileName).Count();
|
|
// creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
|
|
statusData = new otherData[File.ReadLines(fileName).Count()];
|
|
// 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) != "#")
|
|
{
|
|
//elencoAllarmi[rumRiga] = decodeAlarmLine(linea, ':');
|
|
statusData[numRiga] = decodeBitData(linea, utils.CRC("testCharSep"), "R", 14512, 1, numRiga);
|
|
numRiga++;
|
|
}
|
|
}
|
|
// chiudo file
|
|
file.Close();
|
|
// ora trimmo vettore al solo numero VERO dei valori caricati...
|
|
Array.Resize<otherData>(ref statusData, numRiga);
|
|
|
|
if (utils.CRB("verbose")) lg.Info(string.Format("Fine caricamento vettore di {0} variabili status gestite", numRiga));
|
|
#endif
|
|
}
|
|
|
|
public override void processAlarm()
|
|
{
|
|
base.processAlarm();
|
|
|
|
// aggiungo gestione allarmi CNC
|
|
checkCNCAlarms();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica i 10 allarmi CNC SE presenti
|
|
/// </summary>
|
|
private void checkCNCAlarms()
|
|
{
|
|
if (allarmiCNC != null)
|
|
{
|
|
sendAlarmIfPresent(allarmiCNC);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invia singolo allarme CNC se presente
|
|
/// </summary>
|
|
/// <param name="allarme"></param>
|
|
protected void sendAlarmIfPresent(CMSCncLib.OPENcontrol.MSGERROR allarme)
|
|
{
|
|
// controllo valore...
|
|
if (allarme != null)
|
|
{
|
|
try
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
if (utils.CRI("loglevel") > 5)
|
|
{
|
|
lg.Info(string.Format("Allarmi CNC: {0} ", allarme.CodeErr));
|
|
}
|
|
string alarmText = string.Format("Cod: {0} | Proc: {1} | Comm: {2} | SubCom: {3} | {4}", allarme.CodeErr, allarme.Process, allarme.Comando, allarme.SubCom, allarme.FormatTxt);
|
|
mAlarmCNC.Add(MTConnect.Condition.Level.FAULT, alarmText, allarme.CodeErr.ToString(), "", "");
|
|
// mostro in form!
|
|
sb.AppendLine(alarmText);
|
|
parentForm.dataMonitor += sb.ToString();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error(string.Format("{0}", exc));
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void getUnOp()
|
|
{
|
|
base.getUnOp();
|
|
#if false
|
|
|
|
// leggo in blocco tutte le speed da memoria...
|
|
int memIndex = 3140;
|
|
// buffer memoria 60 byte... speed (16bit 2 * 20) + load (8bit 1 * 20) visto che sono 20 teste max
|
|
byte[] unOpSpeedMem = new byte[60];
|
|
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.D, memIndex, ref unOpSpeedMem);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-SPEED_UNOP", unOpSpeedMem.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
// NON VA: RICHIEDE OPZIONE... The extended driver/library function is necessary.
|
|
#if false
|
|
// recupero vettore load spindle...
|
|
inizio = DateTime.Now;
|
|
CMSCncLib.Focas1.ODBSPN spindleVect = FANUC_ref.getSpindleLoad();
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-SpindleLoad", DateTime.Now.Subtract(inizio).Ticks);
|
|
#endif
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
int numUnOp = currAdpConf.nUnOp;
|
|
// cicl su path x leggere le velocità dell'UnOp
|
|
for (int i = 0; i < numUnOp; i++)
|
|
{
|
|
// leggo valore Codice
|
|
SpeedRate = BitConverter.ToUInt16(unOpSpeedMem, 2 * i);
|
|
|
|
// leggo 41° byte = indice 40 + 2*i x le var del carico UnOp
|
|
UnOpLoad = unOpSpeedMem[40 + i];
|
|
|
|
//vettUnOp[i].mUnOpNumCU.Value = uoData.UnOpNumCU;
|
|
//vettUnOp[i].mUnOpStatus.Value = uoData.UnOpStatus;
|
|
//vettUnOp[i].mUnOpAccTime.Value = uoData.UnOpAccTime;
|
|
|
|
sb.AppendLine(string.Format("SpeedRate UnOp_{0}: {1} rpm", i + 1, SpeedRate));
|
|
sb.AppendLine(string.Format("Load UnOp_{0}: {1}", i + 1, UnOpLoad));
|
|
}
|
|
|
|
|
|
parentForm.dataMonitor += sb.ToString();
|
|
#endif
|
|
}
|
|
/// <summary>
|
|
/// procedura di lettura (Multipla) dati da memoria x caricare dati utensile
|
|
/// </summary>
|
|
/// <param name="maxNumOp">num max di teste da recuperare</param>
|
|
private void getDatiUt_Fanuc(int maxNumOp)
|
|
{
|
|
#if false
|
|
// variabili "Indice" utensile e famiglia da decodificare + utils
|
|
int maxMemAddr = 200;
|
|
int[] idUtMontato = new int[maxNumOp];
|
|
int[] idFamUt = new int[maxNumOp];
|
|
int[] idTipoVitaUt = new int[maxNumOp];
|
|
int[] valVitaUtRes = new int[maxNumOp];
|
|
int[] tabUt = new int[maxMemAddr];
|
|
int[] tabFamUt = new int[maxMemAddr];
|
|
int memIndex = 0;
|
|
byte[] int32Mem = new byte[4];
|
|
byte[] int16Mem = new byte[2];
|
|
byte int8Mem = new byte();
|
|
|
|
// step 1: lettura ID dell'utensile x ogni testa...
|
|
byte[] elencoUtMem = new byte[2 * maxNumOp];
|
|
// leggo area memoria degli UT montati
|
|
memIndex = 2960;
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.D, memIndex, ref elencoUtMem);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-NUMUT", elencoUtMem.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
// decodifica da byte a int16 dell'ID Utensile
|
|
for (int i = 0; i < maxNumOp; i++)
|
|
{
|
|
idUtMontato[i] = BitConverter.ToUInt16(elencoUtMem, 2 * i);
|
|
}
|
|
|
|
// step 2a: leggo vettore memoria dei maxMemAddr(200) UT in Tabella Utensili
|
|
memIndex = 11300;
|
|
byte[] tabUt_UT = new byte[2 * maxMemAddr];
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.D, memIndex, ref tabUt_UT);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-UT", tabUt_UT.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
// decodifico TUTTI i maxMemAddr utensili
|
|
for (int i = 0; i < maxMemAddr; i++)
|
|
{
|
|
tabUt[i] = BitConverter.ToUInt16(tabUt_UT, 2 * i);
|
|
}
|
|
// step 2a: devo cercare l'UT di ogni UnOp nella Tabella Utensili
|
|
for (int i = 0; i < maxNumOp; i++)
|
|
{
|
|
// spazzo la tab Utensili x cercare quelli delle UnOp...
|
|
for (int j = 0; j < maxMemAddr; j++)
|
|
{
|
|
// controllo, se l'id utensile è quello dell'attuale UnOp...
|
|
if (tabUt[j] == idUtMontato[i])
|
|
{
|
|
// leggo FamUt puntuale..
|
|
memIndex = 11700 + 2 * j;
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int16Mem);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", int16Mem.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
// step 2b: leggo puntualmente la FamUt dal suo indice...
|
|
idFamUt[i] = BitConverter.ToUInt16(int16Mem, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// step 3: leggo vettore memoria dei maxMemAddr(200) FamUT in Tabella Famiglie Utensili (x ricavare unità misura vita)
|
|
memIndex = 8900;
|
|
byte[] tabFam_FamUt = new byte[2 * maxMemAddr];
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.D, memIndex, ref tabFam_FamUt);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabFamUT-FamUT", tabFam_FamUt.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
// decodifico TUTTI i maxMemAddr utensili
|
|
for (int i = 0; i < maxMemAddr; i++)
|
|
{
|
|
tabFamUt[i] = BitConverter.ToUInt16(tabFam_FamUt, 2 * i);
|
|
}
|
|
// step 3a: devo cercare la famiglia dell'UT di ogni UnOp nella Tabella Famiglie
|
|
for (int i = 0; i < maxNumOp; i++)
|
|
{
|
|
// poiché potrei trovarlo replicato dopo la prima volta che lo trovo evito di ricontrollare...
|
|
bool found = false;
|
|
// spazzo la tab Utensili x cercare quelli delle UnOp...
|
|
for (int j = 0; j < maxMemAddr; j++)
|
|
{
|
|
// controllo, se l'id utensile è quello dell'attuale UnOp...
|
|
if (tabFamUt[j] == idFamUt[i] && !found)
|
|
{
|
|
// leggo FamUt puntuale..
|
|
memIndex = 10700 + 1 * j;
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int8Mem);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", 8), DateTime.Now.Subtract(inizio).Ticks);
|
|
// step 3b: leggo puntualmente il TIPO DI vita UT dal suo indice...
|
|
idTipoVitaUt[i] = int8Mem;
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// step 4: recupero la vita residua dell'utente
|
|
for (int i = 0; i < maxNumOp; i++)
|
|
{
|
|
// spazzo la tab Utensili x cercare quelli delle UnOp...
|
|
for (int j = 0; j < maxMemAddr; j++)
|
|
{
|
|
// controllo, se l'id utensile è quello dell'attuale UnOp...
|
|
if (tabUt[j] == idUtMontato[i])
|
|
{
|
|
// leggo FamUt puntuale..
|
|
memIndex = 13100 + 4 * j;
|
|
inizio = DateTime.Now;
|
|
OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int32Mem);
|
|
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-VitaRes", int32Mem.Length), DateTime.Now.Subtract(inizio).Ticks);
|
|
// leggo puntualmente valore della vita ut residua da indice utensile...
|
|
valVitaUtRes[i] = BitConverter.ToInt32(int32Mem, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// salvo in adapter vita UT residua...
|
|
for (int i = 0; i < maxNumOp; i++)
|
|
{
|
|
vettUnOp[i].mUnOpToolId.Value = idUtMontato[i];
|
|
vettUnOp[i].mUnOpVitaRes.Value = valVitaUtRes[i];
|
|
// decodifico valore tipo VitaRes...
|
|
string tipoVitaRes = "ND";
|
|
switch (idTipoVitaUt[i])
|
|
{
|
|
case 1:
|
|
tipoVitaRes = "Time";
|
|
break;
|
|
case 2:
|
|
tipoVitaRes = "Stroke";
|
|
break;
|
|
case 3:
|
|
tipoVitaRes = "Distance";
|
|
break;
|
|
default: break;
|
|
}
|
|
vettUnOp[i].mUnOpVitaResType.Value = tipoVitaRes;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public override void getPath()
|
|
{
|
|
//NON richiamo metodo base... ma faccio override qui (e altrove...)
|
|
checkPath();
|
|
|
|
#if false
|
|
|
|
// recupero vettore generale G MODE
|
|
inizio = DateTime.Now;
|
|
CMSCncLib.Focas1.ODBGCD vettGCodes = OSAI_ref.getPathGCodeMod();
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-GCodModal", DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
string GCodAttivi = "";
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd0.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd1.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd2.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd3.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd4.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd5.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd6.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd7.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd8.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd9.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd10.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd11.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd12.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd13.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd14.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd15.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd16.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd17.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd18.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd19.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd20.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd21.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd22.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd23.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd24.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd25.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd26.code);
|
|
GCodAttivi += string.Format("[{0}]", vettGCodes.gcd27.code);
|
|
|
|
inizio = DateTime.Now;
|
|
vettGCodes = OSAI_ref.getPathGCode1Shot();
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-GCodOneShot", DateTime.Now.Subtract(inizio).Ticks);
|
|
if (vettGCodes.gcd0.flag > 0) GCodAttivi += string.Format("[{0}]", vettGCodes.gcd0.code);
|
|
if (vettGCodes.gcd1.flag > 0) GCodAttivi += string.Format("[{0}]", vettGCodes.gcd1.code);
|
|
if (vettGCodes.gcd2.flag > 0) GCodAttivi += string.Format("[{0}]", vettGCodes.gcd2.code);
|
|
if (vettGCodes.gcd3.flag > 0) GCodAttivi += string.Format("[{0}]", vettGCodes.gcd3.code);
|
|
|
|
inizio = DateTime.Now;
|
|
CMSCncLib.Focas1.ODB5AXMAN vettTTCoord = OSAI_ref.getPathTTCoord();
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-TTCoord", DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
// cicl su path
|
|
for (int i = 0; i < currAdpConf.nPath; i++)
|
|
{
|
|
// accodo dati path in DataMonitor......
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
vettPath[i].mPathCodG_Act.Value = GCodAttivi;
|
|
|
|
vettPath[i].mPathPosActX.Value = ((decimal)vettTTCoord.data1) / utils.CRI("fattdecimale");
|
|
vettPath[i].mPathPosActY.Value = ((decimal)vettTTCoord.data2) / utils.CRI("fattdecimale");
|
|
vettPath[i].mPathPosActZ.Value = ((decimal)vettTTCoord.data3) / utils.CRI("fattdecimale");
|
|
vettPath[i].mPathPosActI.Value = ((decimal)vettTTCoord.c1) / utils.CRI("fattdecimale");
|
|
vettPath[i].mPathPosActJ.Value = ((decimal)vettTTCoord.c2) / utils.CRI("fattdecimale");
|
|
vettPath[i].mPathPosActK.Value = "0"; // è 5 assi...nullo...
|
|
|
|
// 2017.01.16 da rivedere
|
|
vettPath[i].mPathCurrProgRowNum.Value = "";
|
|
vettPath[i].mPathActiveAxes.Value = "";
|
|
|
|
sb.AppendLine(string.Format("Path {0}, PROG: {1}", i + 1, vettPath[i].mPathCurrProg.Value));
|
|
|
|
sb.AppendLine(string.Format("Path {0}, Asse 1: {1:N3}", i + 1, ((decimal)vettTTCoord.data1) / utils.CRI("fattdecimale")));
|
|
sb.AppendLine(string.Format("Path {0}, Asse 2: {1:N3}", i + 1, ((decimal)vettTTCoord.data2) / utils.CRI("fattdecimale")));
|
|
sb.AppendLine(string.Format("Path {0}, Asse 3: {1:N3}", i + 1, ((decimal)vettTTCoord.data3) / utils.CRI("fattdecimale")));
|
|
sb.AppendLine(string.Format("Path {0}, Cent 1: {1:N3}", i + 1, ((decimal)vettTTCoord.c1) / utils.CRI("fattdecimale")));
|
|
sb.AppendLine(string.Format("Path {0}, Cent 2: {1:N3}", i + 1, ((decimal)vettTTCoord.c2) / utils.CRI("fattdecimale")));
|
|
|
|
parentForm.dataMonitor += sb.ToString();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public override void getAxis()
|
|
{
|
|
// mostro assi in DataMonitor......
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
inizio = DateTime.Now;
|
|
#if false
|
|
CMSCncLib.Focas1.ODBPOS posAssi = OSAI_ref.getAllAxisPos();
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-AXIS_POS", DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
inizio = DateTime.Now;
|
|
CMSCncLib.Focas1.ODBSVLOAD loadAssi = OSAI_ref.getAllAxisLoad();
|
|
if (utils.CRB("recTime")) TimingData.addResult("R-AXIS_LOAD", DateTime.Now.Subtract(inizio).Ticks);
|
|
|
|
CMSCncLib.Focas1.LOADELM valLoad = new CMSCncLib.Focas1.LOADELM();
|
|
CMSCncLib.Focas1.POSELMALL valPos = new CMSCncLib.Focas1.POSELMALL();
|
|
|
|
// nuova posizione (per calcoli)
|
|
double newPos = 0;
|
|
double distPerc = 0;
|
|
int newDir = 0;
|
|
string tipoAsse = "";
|
|
string direzione = "";
|
|
|
|
for (int i = 0; i < currAdpConf.nAxis; i++)
|
|
{
|
|
// per sicurezza try-catch
|
|
try
|
|
{
|
|
// in base a indice scelgo valore posizione e load
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
valPos = posAssi.p1;
|
|
valLoad = loadAssi.svload1;
|
|
break;
|
|
case 1:
|
|
valPos = posAssi.p2;
|
|
valLoad = loadAssi.svload2;
|
|
break;
|
|
case 2:
|
|
valPos = posAssi.p3;
|
|
valLoad = loadAssi.svload3;
|
|
break;
|
|
case 3:
|
|
valPos = posAssi.p4;
|
|
valLoad = loadAssi.svload4;
|
|
break;
|
|
case 4:
|
|
valPos = posAssi.p5;
|
|
valLoad = loadAssi.svload5;
|
|
break;
|
|
case 5:
|
|
valPos = posAssi.p6;
|
|
valLoad = loadAssi.svload6;
|
|
break;
|
|
case 6:
|
|
valPos = posAssi.p7;
|
|
valLoad = loadAssi.svload7;
|
|
break;
|
|
case 7:
|
|
valPos = posAssi.p8;
|
|
valLoad = loadAssi.svload8;
|
|
break;
|
|
case 8:
|
|
valPos = posAssi.p9;
|
|
valLoad = loadAssi.svload9;
|
|
break;
|
|
case 9:
|
|
valPos = posAssi.p10;
|
|
valLoad = loadAssi.svload10;
|
|
break;
|
|
case 10:
|
|
valPos = posAssi.p11;
|
|
valLoad = loadAssi.svload11;
|
|
break;
|
|
case 11:
|
|
valPos = posAssi.p12;
|
|
valLoad = loadAssi.svload12;
|
|
break;
|
|
case 12:
|
|
valPos = posAssi.p13;
|
|
valLoad = loadAssi.svload13;
|
|
break;
|
|
case 13:
|
|
valPos = posAssi.p14;
|
|
valLoad = loadAssi.svload14;
|
|
break;
|
|
case 14:
|
|
valPos = posAssi.p15;
|
|
valLoad = loadAssi.svload15;
|
|
break;
|
|
case 15:
|
|
valPos = posAssi.p16;
|
|
valLoad = loadAssi.svload16;
|
|
break;
|
|
case 16:
|
|
valPos = posAssi.p17;
|
|
valLoad = loadAssi.svload17;
|
|
break;
|
|
case 17:
|
|
valPos = posAssi.p18;
|
|
valLoad = loadAssi.svload18;
|
|
break;
|
|
case 18:
|
|
valPos = posAssi.p19;
|
|
valLoad = loadAssi.svload19;
|
|
break;
|
|
case 19:
|
|
valPos = posAssi.p20;
|
|
valLoad = loadAssi.svload20;
|
|
break;
|
|
case 20:
|
|
valPos = posAssi.p21;
|
|
valLoad = loadAssi.svload21;
|
|
break;
|
|
case 21:
|
|
valPos = posAssi.p22;
|
|
valLoad = loadAssi.svload22;
|
|
break;
|
|
case 22:
|
|
valPos = posAssi.p23;
|
|
valLoad = loadAssi.svload23;
|
|
break;
|
|
case 23:
|
|
valPos = posAssi.p24;
|
|
valLoad = loadAssi.svload24;
|
|
break;
|
|
case 24:
|
|
valPos = posAssi.p25;
|
|
valLoad = loadAssi.svload25;
|
|
break;
|
|
case 25:
|
|
valPos = posAssi.p26;
|
|
valLoad = loadAssi.svload26;
|
|
break;
|
|
case 26:
|
|
valPos = posAssi.p27;
|
|
valLoad = loadAssi.svload27;
|
|
break;
|
|
case 27:
|
|
valPos = posAssi.p28;
|
|
valLoad = loadAssi.svload28;
|
|
break;
|
|
case 28:
|
|
valPos = posAssi.p29;
|
|
valLoad = loadAssi.svload29;
|
|
break;
|
|
case 29:
|
|
valPos = posAssi.p30;
|
|
valLoad = loadAssi.svload30;
|
|
break;
|
|
case 30:
|
|
valPos = posAssi.p31;
|
|
valLoad = loadAssi.svload31;
|
|
break;
|
|
case 31:
|
|
valPos = posAssi.p32;
|
|
valLoad = loadAssi.svload32;
|
|
break;
|
|
default:
|
|
// 2017.03.01 suggerimento Fabio: in CMS_FANUC in advanced compiler options mettere FS30D=1,SIEMENS=1 x leggere + assi?!?
|
|
valPos = posAssi.p1;
|
|
valLoad = loadAssi.svload1;
|
|
break;
|
|
}
|
|
|
|
// popolo valori...
|
|
vettAxis[i].mAxLoad.Value = (double)(valLoad.data) / Math.Pow(10, valLoad.dec);
|
|
newPos = (double)(valPos.abs.data) / Math.Pow(10, valPos.abs.dec);
|
|
vettAxis[i].mAxPosAct.Value = newPos;
|
|
vettAxis[i].mAxPosTgt.Value = newPos + (double)(valPos.dist.data) / Math.Pow(10, valPos.dist.dec);
|
|
|
|
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];
|
|
}
|
|
|
|
// verifico tipo direzione da tipo asse...
|
|
tipoAsse = vettAxis[i].mAxType.Value.ToString();
|
|
if (tipoAsse == "LINEAR")
|
|
{
|
|
// ?: conditional operator.
|
|
direzione = (newDir > 0) ? "POSITIVE" : "NEGATIVE";
|
|
}
|
|
else if (tipoAsse == "ROTARY")
|
|
{
|
|
direzione = (newDir > 0) ? "CLOCKWISE" : "COUNTER_CLOCKWISE";
|
|
}
|
|
|
|
vettAxis[i].mAxDir.Value = direzione;
|
|
|
|
|
|
if (utils.CRB("verbose"))
|
|
{
|
|
|
|
sb.AppendLine(string.Format("Asse {0}: PosAct:{1:N3}, ToGo:{2:N3}{3} | {4}", valPos.abs.name, (double)(valPos.abs.data) / Math.Pow(10, valPos.abs.dec), valPos.dist.name, (double)(valPos.dist.data) / Math.Pow(10, valPos.dist.dec), direzione));
|
|
}
|
|
|
|
// 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 = FeedRateOver;
|
|
//vettAxis[i].mAxAccelAct.Value = AxData.AxisAccel;
|
|
//vettAxis[i].mAxBattery.Value = AxData.AxisBattery;
|
|
}
|
|
catch
|
|
{
|
|
lg.Error(string.Format("Errore in lettura asse {0}", i));
|
|
}
|
|
}
|
|
|
|
parentForm.dataMonitor += sb.ToString();
|
|
#endif
|
|
}
|
|
}
|
|
}
|