using CMSCncLib.CNC; using MTC; using SCMA.AdapterCom; using System; using System.Text; namespace SCMA { public class AdapterFanuc : AdapterGeneric { /// /// Oggetto MAIN x connessione FANUC /// protected FANUC FANUC_ref; /// /// wrapper chiamata lettura/scrittura SINGOLO BYTE... /// /// /// /// /// /// public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte Value) { bool answ = false; if (FANUC_ref.Connected) { try { parentForm.commPlcActive = true; answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); } catch { } } parentForm.commPlcActive = false; return answ; } /// /// wrapper chiamata lettura/scrittura MULTI BYTE... /// /// /// /// /// /// public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte[] Value) { bool answ = false; if (FANUC_ref.Connected) { try { parentForm.commPlcActive = true; answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); } catch { } } parentForm.commPlcActive = false; return answ; } /// /// struttura dati fanuc x ALL DYN DATA /// C:\Users\samuele\Documents\FOCAS A02B-0207-K737_04.20\Document\SpecE\Position\cnc_rddynamic2.htm /// protected CMSCncLib.Focas1.ODBDY2_1 allDynData; /// /// Vettore degli allarmi CNC attivi /// public CMSCncLib.Focas1.ODBALMMSG2 allarmiCNC; /// /// estende l'init della classe base... /// /// FORM chaimante /// CONFIGURAZIONE adapter /// OGGETTO gestione comunicazione OUT (tipologia e metodi) public AdapterFanuc(MainForm caller, AdapterConf adpConf, Gateway gatewayObj) : base(caller, adpConf, gatewayObj) { // è little endian (NON serve conversione) hasBigEndian = false; lg.Info("Start init Adapter FANUC all'IP {0}", utils.CRS("ipPLC")); parentForm.commPlcActive = true; Runtime.CreateNC(CNC.NcType.FANUC, utils.CRS("ipPLC")); parentForm.commPlcActive = false; // inizializzo posizioni assi... prevPosAxis = new double[adpConf.nAxis]; prevDirAxis = new int[adpConf.nAxis]; FANUC_ref = (FANUC)Runtime.NC; if (utils.CRB("verbose")) { lg.Info("FANUC_ref da CMSCncLib"); } // disconnetto e connetto... if (utils.CRB("verbose")) { lg.Info("FANUC: tryDisconnect"); } tryDisconnect(); lg.Info("FANUC: tryConnect"); tryConnect(); lg.Info("End init Adapter FANUC"); } /// /// Override disconnessione /// public override void tryDisconnect() { if (connectionOk) { string szStatusConnection = ""; try { FANUC_ref.Disconnect(ref szStatusConnection); connectionOk = false; lg.Info(szStatusConnection); lg.Info("Effettuata disconnessione adapter FANUC!"); } catch (Exception exc) { lg.Fatal(exc, "Errore nella disconnessione dall'adapter FANUC"); } } else { lg.Error("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile..."); } } /// /// Override connessione /// public override void tryConnect() { if (!connectionOk) { string szStatusConnection = ""; try { parentForm.commPlcActive = true; FANUC_ref.Connect(ref szStatusConnection); parentForm.commPlcActive = false; 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(string.Format("Errore nella connessione all'adapter FANUC: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); connectionOk = false; lg.Info(string.Format("Segnalo Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); } } } /// /// Verifico connessione FANUC... /// /// public override bool connectionOk { get { return FANUC_ref.Connected; } } /// /// Effettuo lettura dei 16 byte di strobe/status /// public override void getStrobeAndAckStatus() { base.getStrobeAndAckStatus(); if (connectionOk) { // leggo TUTTO ack e strobe, byte[] MemBlock = new byte[Strobes.Length + Acknowl.Length]; int memIndex = 10500; inizio = DateTime.Now; FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlock); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-STROBES", MemBlock.Length), DateTime.Now.Subtract(inizio).Ticks); } // suddivido! Buffer.BlockCopy(MemBlock, 0, Acknowl, 0, Acknowl.Length); Buffer.BlockCopy(MemBlock, Acknowl.Length, Strobes, 0, Strobes.Length); } else { lg.Error("Errore connessione mancante in getStrobeAndAckStatus"); } } /// /// processing strobe! /// public override void processStrobe() { // inizializzo userAction string UserAction = ""; string TestingData = ""; string UnkStrobe = ""; // !!!FARE!!! multipath... // verifico i vari strobe x recuperare i dati... PER ORA SOLO DW1 per path1 (indice 0)... int idxPath = 0; int memIndex = 0; int bitNum = 0; inizio = DateTime.Now; // byte di acknowledge... byte[] retACK_DW1 = new byte[4]; try { // controllo TUTTI i flag: se ce ne sono di alzati DEVO processare... if (STRB_DW1 != StFlag32.NONE) { // blocco memoria x lettura TUTTI i dati di buffer M/S/T: 46 byte: 2byte (16bit) x (11+6+6) aree byte[] MemBlock = new byte[46]; // leggo tutto!!! memIndex = 10660; inizio = DateTime.Now; FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlock); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-STRB_DW1", MemBlock.Length), DateTime.Now.Subtract(inizio).Ticks); } // check COD_M bitNum = 0; gestStrobeCodMST(bitNum, ref retACK_DW1, 0, MemBlock, "M"); // check COD_S bitNum = 1; gestStrobeCodMST(bitNum, ref retACK_DW1, 11, MemBlock, "S"); // check COD_T bitNum = 2; gestStrobeCodMST(bitNum, ref retACK_DW1, 17, 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.... retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum); } catch { lg.Info("Errore lettura dati da file"); } } // AREA strobe USER ACTION // chiamato Start... bitNum = 4; gestStrobeUserAction(idxPath, bitNum, ref retACK_DW1, ref UserAction, " (START) "); // chiamato Stop... bitNum = 5; gestStrobeUserAction(idxPath, bitNum, ref retACK_DW1, ref UserAction, " (STOP) "); // chiamato Reset... bitNum = 6; gestStrobeUserAction(idxPath, bitNum, ref retACK_DW1, ref UserAction, " (RESET) "); // processo tutti gli strobe x i BIT 7-29 NON gestiti in modo da dare comunque ACK e event... for (int i = 7; i < 30; i++) { gestStrobeUserAction(idxPath, i, ref retACK_DW1, ref UnkStrobe, string.Format(" [STROBE_{0:00}] ", i)); } // AREA strobe x TEST // INIZIO TEST... bitNum = 30; if (STRB_DW1.HasFlag((StFlag32)Math.Pow(2, bitNum))) { // formatto stringa risultato TestingData = string.Format("START TEST{0}", getTestData(utils.CRS("testCharSep"))); // memorizzo allarme nel vettore ack.... retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum); } // FINE TEST... bitNum = 31; if (STRB_DW1.HasFlag((StFlag32)Math.Pow(2, bitNum))) { // formatto stringa risultato TestingData = string.Format("STOP TEST{0}", getTestData(utils.CRS("testCharSep"))); // memorizzo allarme nel vettore ack.... retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum); } } else { // se mi sono rimasti degli strobe di lettura allarmi alzati li abbasso if (ACK_DW1 != StFlag32.NONE) { // inizializzo 4 byte a zero!!! retACK_DW1 = new byte[4]; } } } catch { lg.Info("Errore in strobe"); } // 2017.01.16 INVIO vettore azioni (1 o +)... SE CE NE SONO! if (UserAction.Trim() != "") { currGateway.updateItemNodeValue("USER_ACTION", UserAction.Trim()); } // Invio comunque strobe non riconosciuti if (currGateway.getItemNode("UNK_STROBE").ToString() != UnkStrobe.Trim()) { currGateway.updateItemNodeValue("UNK_STROBE", UnkStrobe.Trim()); } // INVIO COMUNQUE stato test... currGateway.updateItemNodeValue("TESTING_DATA", TestingData.Trim()); memIndex = 10504; // scrivo update ad ack SE VARIATO!!! if (ACK_DW1 != (StFlag32)BitConverter.ToUInt32(retACK_DW1, 0)) { inizio = DateTime.Now; FanucMemRW(W, FANUC.MemType.R, memIndex, ref retACK_DW1); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("W{0}-DW1", retACK_DW1.Length), DateTime.Now.Subtract(inizio).Ticks); } } sendWatchDog(); } /// /// Scrive watchdog /// /// /// public override bool writeWatchDog(ref byte[] retACK_DW) { int memIndex = 10508; return FanucMemRW(W, FANUC.MemType.R, memIndex, ref retACK_DW); } /// /// Recupero info su test: numero + elenco parametri IN/OUT /// /// /// private new string getTestData(string charSep) { string answ = ""; // Area di memoria x test... 64 byte byte[] MemBlockTestData = new byte[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 = 11000; inizio = DateTime.Now; FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlockTestData); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-TEST_DATA_DW1", MemBlockTestData.Length), DateTime.Now.Subtract(inizio).Ticks); } // recupero cod univoco test e numero parametri impiegati testNum = BitConverter.ToUInt16(MemBlockTestData, 0); numPar = BitConverter.ToUInt16(MemBlockTestData, 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 = BitConverter.ToUInt32(MemBlockTestData, 4 * (1 + i)); answ += string.Format("{0}{1}", charSep, testParam); } } return answ; } /// /// Gestione STROBE --> ACK per codici M/S/T /// /// 0/1/2 /// vettore da restituire di ACK /// shift memoria x buffer dati da leggere /// Vettore completo dei valori + buffer code M/S/T /// Quale coda: M/S/T private void gestStrobeCodMST(int bitNum, ref byte[] retACK_DW1, int memShift, byte[] MemBlock, string Coda) { int numEv = 0; int codEv = 0; int idxPath = 0; // Hard coded path 0 soltanto... if (STRB_DW1.HasFlag((StFlag32)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 + 1 + memShift)); // accodo evento Codice appendCodeMST(Coda, codEv.ToString(), idxPath); } } // memorizzo allarme nel vettore ack.... retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum); } } /// /// recupera allarmi ed aggiorna strobe (privato) degli allarmi /// /// 32bit mask degli allarmi da aggiornare /// boolean: se si debba tornare ACK 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("RAS | 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; byte[] MemBlock; // primo blocco memoria allarmi int memIndex = 10532; // 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 byte[128]; // recupero tutti i 32 bit del blocco inizio = DateTime.Now; FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlock); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-STRB_DW0", MemBlock.Length), DateTime.Now.Subtract(inizio).Ticks); } if (currGateway.AlarmFlags != null) { try { // aggiorno vettore allarmi x intero! size del vettore di destinazione (in byte!!!!) Buffer.BlockCopy(MemBlock, 0, currGateway.AlarmFlags, 0, currGateway.AlarmFlags.Length); } catch (Exception exc) { lg.Error(string.Format("RAS | Errore in BLOCKCOPY{0}{1}", Environment.NewLine, exc)); } } } else { if (Alarm2Refresh != StFlag32.NONE) { // blocco memoria x lettura dati MemBlock = new byte[4]; // 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; FanucMemRW(R, FANUC.MemType.R, memIndex + i * 4, ref MemBlock); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-STRB_DW0", MemBlock.Length), DateTime.Now.Subtract(inizio).Ticks); } // da testare metodo copia alternativo, condizionato a web.config if (!utils.CRB("fastCopy")) { // aggiorno nel vettore allarmi i byte interessati for (int j = 0; j < 4; j++) { // copy array a blocchi currGateway.AlarmFlags[i * 4 + j] = MemBlock[j]; } } else { Buffer.BlockCopy(MemBlock, 0, currGateway.AlarmFlags, i * 4, MemBlock.Length); } if (utils.CRB("verbose")) { UInt32 valore = BitConverter.ToUInt32(MemBlock, 0); lg.Info("RAS | Bit allarme rilevato dalla posizione {0} | {1}", i * 32, utils.binaryForm((int)valore)); } // 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 = 10500; // scrivo update ad ack!!! inizio = DateTime.Now; FanucMemRW(W, FANUC.MemType.R, memIndex, 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 = 10500; // invio INTERO set ACK_DW0 con bit abbassati... retACK_DW0 = BitConverter.GetBytes(Convert.ToUInt32(STRB_DW0 & ACK_DW0)); inizio = DateTime.Now; FanucMemRW(W, FANUC.MemType.R, memIndex, ref retACK_DW0); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("W{0}-ACK_DW0", retACK_DW0.Length), DateTime.Now.Subtract(inizio).Ticks); } } } } /// /// processing! /// public override void processStatus() { // update status da DW2/ DW3 // EMstop: verifico BIT e di conseguenza imposto if (STRB_DW2.HasFlag(StFlag32.B00)) { currGateway.updateItemNodeValue("E_STOP", emStatus.TRIGGERED.ToString()); } else { currGateway.updateItemNodeValue("E_STOP", emStatus.ARMED.ToString()); } // verifico POWER ON... if (STRB_DW2.HasFlag(StFlag32.B01)) { currGateway.updateItemNodeValue("POWER", onOffStatus.ON.ToString()); } else { currGateway.updateItemNodeValue("POWER", onOffStatus.OFF.ToString()); } // Processo selezionato 0=P1, 1=P2 string procSel = ""; if (STRB_DW2.HasFlag(StFlag32.B02)) { procSel = "P2"; } else { procSel = "P1"; } if (currGateway.getItemNode("PROC_SEL").ToString() != procSel) { currGateway.updateItemNodeValue("PROC_SEL", procSel); } // HARD CODE: forzo path 1 (indice 0...) int idxPath = 0; // verifico tipo processo path... if (STRB_DW2.HasFlag(StFlag32.B03)) { currGateway.updateItemNodeValue(vettPath[idxPath].pathTypeKey, pathType.LAVORO.ToString()); } else { currGateway.updateItemNodeValue(vettPath[idxPath].pathTypeKey, pathType.ASSERV.ToString()); } // 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"; } // salvo valore selezionato if (currGateway.getItemNode(vettPath[idxPath].runModeKey).ToString() != runMode) { currGateway.updateItemNodeValue(vettPath[idxPath].runModeKey, runMode); } // 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"; } // salvo valore selezionato if (currGateway.getItemNode(vettPath[idxPath].exeModeKey).ToString() != exeMode) { currGateway.updateItemNodeValue(vettPath[idxPath].exeModeKey, exeMode); } // processo eventuali altri bit status non noti... string UnkStatus = ""; // cerco i bit alzati --> aggiungo in stringa! TRANNE 31 e 32 che sono watchdog... for (int i = 14; i < 30; i++) { // converto! e aggiungo allarmi sollevati al corretto controller allarmi... if (STRB_DW2.HasFlag((StFlag32)Math.Pow(2, i))) { UnkStatus += string.Format(" [STATUS_{0:00}] ", i); } } // invio comunque... currGateway.updateItemNodeValue("UNK_STATUS", UnkStatus.Trim()); // 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(" [{0}]", elencoSubMode[i.ToString()]); } } } // 2017.01.16 INVIO SOLO SE CAMBIA:.. if (currGateway.getItemNode(vettPath[idxPath].subModeKey).ToString() != SubMode.Trim()) { currGateway.updateItemNodeValue(vettPath[idxPath].subModeKey, SubMode.Trim()); } } /// /// Gestione lettura dati manutenzione /// public override bool getMtzDataFromPlc() { bool fatto = false; try { if (maintData.Length > 0) { // recupero i dati di manutenzione dall'area di memoria IN BLOCCO int memIndex = 14000; byte[] tabDatiMtzByte = new byte[4 * maintData.Length]; uint[] tabDatiMtz = new uint[maintData.Length]; inizio = DateTime.Now; FanucMemRW(R, FANUC.MemType.R, memIndex, ref tabDatiMtzByte); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-DatiMtz", tabDatiMtzByte.Length), DateTime.Now.Subtract(inizio).Ticks); } // copio byte --> word! Buffer.BlockCopy(tabDatiMtzByte, 0, tabDatiMtz, 0, tabDatiMtzByte.Length); // decodifico aree memoria secondo tab configurazione processMaintData(tabDatiMtz, maintData); } fatto = true; } catch { } return fatto; } /// /// Gestione lettura dati analogici /// public override bool getAnalogDataFromPlc() { bool fatto = false; try { if (analogData.Length > 0) { // recupero i dati di manutenzione dall'area di memoria IN BLOCCO int memIndex = 15000; byte[] tabDatiAnalogByte = new byte[4 * analogData.Length]; uint[] tabDatiAnalog = new uint[analogData.Length]; inizio = DateTime.Now; FanucMemRW(R, FANUC.MemType.R, memIndex, ref tabDatiAnalogByte); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-DatiAnalog", tabDatiAnalogByte.Length * 4), DateTime.Now.Subtract(inizio).Ticks); } // copio byte --> word! Buffer.BlockCopy(tabDatiAnalogByte, 0, tabDatiAnalog, 0, tabDatiAnalogByte.Length); // decodifico aree memoria secondo tab configurazione processAnalogData(tabDatiAnalog, analogData); } fatto = true; } catch { } return fatto; } /// /// Gestione lettura dati status da PLC /// public override bool getStatusDataFromPlc() { bool fatto = false; try { if (statusData.Length > 0) { // recupero i dati di manutenzione dall'area di memoria IN BLOCCO int memIndex = 14512; int numByte = 1 + (statusData.Length / 8); byte[] tabDatiStatus = new byte[numByte]; inizio = DateTime.Now; FanucMemRW(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); } // decodifico aree memoria secondo tab configurazione processStatusData(tabDatiStatus, statusData); } fatto = true; } catch { } return fatto; } /// /// Leggo dati globali comuni (x path, assi...) /// public override void getGlobalData() { // svuoto... resetDebugConsole(); // accodo dati path in DataMonitor...... StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(); // dati base... sb1.AppendLine(string.Format("POWER {0}: | EmStop:{1} | ProcSel: {2}", currGateway.getItemNode("POWER"), currGateway.getItemNode("E_STOP"), currGateway.getItemNode("PROC_SEL"))); // leggo dati globali... parentForm.commPlcActive = true; inizio = DateTime.Now; allDynData = FANUC_ref.getAllDynData(); if (utils.CRB("recTime")) { TimingData.addResult("R-ALL-DYN-DATA", DateTime.Now.Subtract(inizio).Ticks); } parentForm.commPlcActive = false; FeedRate = allDynData.actf; int memIndex = 12000; byte[] PathData_mem = new byte[4]; inizio = DateTime.Now; FanucMemRW(R, FANUC.MemType.R, memIndex, ref PathData_mem); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-PathData", PathData_mem.Length), DateTime.Now.Subtract(inizio).Ticks); } // 2016.07.19 mod con Fabio //JogRateOver = PathData_mem[0]; FeedRateOver = PathData_mem[1]; RapidOver = PathData_mem[2]; SpeedRateOver = PathData_mem[3]; sb1.AppendLine(string.Format("FeedRate: {0} mm/min", FeedRate)); sb1.AppendLine(string.Format("FeedRateOver: {0} %", FeedRateOver)); sb1.AppendLine(string.Format("RapidOver: {0} %", RapidOver)); sb1.AppendLine(string.Format("SpeedRateOver: {0} %", SpeedRateOver)); // se ho allarmi li accodo... if (allDynData.alarm != 0) { sb1.AppendLine(string.Format("Allarmi CNC: {0}", allDynData.alarm)); parentForm.commPlcActive = true; inizio = DateTime.Now; if (!utils.CRB("disableAdvRead")) { try { allarmiCNC = FANUC_ref.getCncAlarm(); if (utils.CRB("recTime")) { TimingData.addResult("R-CNC-ALARMS", DateTime.Now.Subtract(inizio).Ticks); } checkCNCAlarms(); } catch (Exception exc) { lg.Error(string.Format("Errore in recupero Allarmi CNC{0}{1}", Environment.NewLine, exc)); } } parentForm.commPlcActive = false; } else { allarmiCNC = new CMSCncLib.Focas1.ODBALMMSG2(); } // accodo dati base! parentForm.dataMonitor_1 = sb1.ToString(); // accodo dati UT... for (int i = 0; i < currAdpConf.nUnOp; i++) { sb2.AppendLine(string.Format("UT: ToolId {0} | VitaRes {1} | TipoVita {2} ", currGateway.getItemNode(vettUnOp[i].toolIdKey), currGateway.getItemNode(vettUnOp[i].vitaResKey), currGateway.getItemNode(vettUnOp[i].vitaResTypeKey))); } parentForm.dataMonitor_2 = sb2.ToString(); // gestisco lettura dati manutenzione da PLC... getMtzDataFromPlc(); // gestisco lettura dati analogici da PLC... getAnalogDataFromPlc(); // gestisco lettura dati status da PLC... getStatusDataFromPlc(); } /// /// Carico file conf dati CMS /// protected override void loadOtherFile() { base.loadOtherFile(); loadMaintData("R", 14000, 4); loadStatusData("R", 14512, 1); loadAnalogData("R", 15000, 4); } /// /// Processing allarmi CNC /// public override void processAlarm() { base.processAlarm(); // aggiungo gestione allarmi CNC checkCNCAlarms(); } /// /// Verifica i 10 allarmi CNC SE presenti /// private void checkCNCAlarms() { // faccio parse allarmi: se ci sono invio e presento sendAlarmIfPresent(allarmiCNC.msg1); sendAlarmIfPresent(allarmiCNC.msg2); sendAlarmIfPresent(allarmiCNC.msg3); sendAlarmIfPresent(allarmiCNC.msg4); sendAlarmIfPresent(allarmiCNC.msg5); sendAlarmIfPresent(allarmiCNC.msg6); sendAlarmIfPresent(allarmiCNC.msg7); sendAlarmIfPresent(allarmiCNC.msg8); sendAlarmIfPresent(allarmiCNC.msg9); sendAlarmIfPresent(allarmiCNC.msg10); } /// /// Invia singolo allarme CNC se presente /// /// protected void sendAlarmIfPresent(CMSCncLib.Focas1.ODBALMMSG2_data allarmiFanuc) { // controllo valore... if (allarmiFanuc.alm_no > 0) { allarme newAlarm; try { StringBuilder sb = new StringBuilder(); if (utils.CRI("loglevel") > 5) { lg.Info(string.Format("Allarmi CNC: NUM {0} | MESS: {1} | ASSE: {2} | TYPE: {3}", allarmiFanuc.alm_no, allarmiFanuc.alm_msg, allarmiFanuc.axis, allarmiFanuc.type)); } // se ho asse accodo ad asse altrimenti no... string codAllarme = string.Format("T{0}-N{1}", allarmiFanuc.type, allarmiFanuc.alm_no); if (allarmiFanuc.axis == 0) { allarme currAllarm = new allarme(codAllarme, "CNC", "FAULT", allarmiFanuc.alm_msg); currGateway.addAlarm(currAllarm); } else { newAlarm = new allarme(codAllarme, vettAxis[allarmiFanuc.axis - 1].alarmCncKey, "FAULT", allarmiFanuc.alm_msg); currGateway.addAlarm(currGateway.conditionNodes[vettAxis[allarmiFanuc.axis - 1].alarmCncKey], newAlarm); } // mostro in form! sb.AppendLine(codAllarme); parentForm.dataMonitor_1 += sb.ToString(); } catch (Exception exc) { lg.Error(string.Format("{0}", exc)); } } } /// /// Recupero dati x UnOp /// public override void getUnOp() { // 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; FanucMemRW(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); } procUnOp(unOpSpeedMem); } /// /// Procedura di processing lettura memoria x DatiUt - Step 4 /// /// /// /// public override int getDatiUt_step4(ref byte[] int32Mem, int j) { int memIndex = 13100 + 4 * j; inizio = DateTime.Now; FanucMemRW(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); } return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 3b /// /// /// /// public override int getDatiUt_step3b(ref byte int8Mem, int j) { int memIndex = 10700 + 1 * j; inizio = DateTime.Now; FanucMemRW(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); } return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 3a /// /// /// public override int getDatiUt_step3a(ref byte[] tabFam_FamUt) { int memIndex = 8900; inizio = DateTime.Now; FanucMemRW(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); } return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 2b /// /// /// /// public override int getDatiUt_step2b(ref byte[] int16Mem, int j) { int memIndex = 11700 + 2 * j; inizio = DateTime.Now; FanucMemRW(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); } return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 2a /// /// /// public override int getDatiUt_step2a(ref byte[] tabUt_UT) { int memIndex = 11300; inizio = DateTime.Now; FanucMemRW(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); } return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 1 /// /// /// public override int getDatiUt_step1(ref byte[] elencoUtMem) { int memIndex = 2960; inizio = DateTime.Now; FanucMemRW(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); } return memIndex; } public override void getPath() { base.getPath(); // recupero vettore generale G MODE parentForm.commPlcActive = true; inizio = DateTime.Now; CMSCncLib.Focas1.ODBGCD vettGCodes = FANUC_ref.getPathGCodeMod(); if (utils.CRB("recTime")) { TimingData.addResult("R-GCodModal", DateTime.Now.Subtract(inizio).Ticks); } parentForm.commPlcActive = false; 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); parentForm.commPlcActive = true; inizio = DateTime.Now; vettGCodes = FANUC_ref.getPathGCode1Shot(); parentForm.commPlcActive = false; 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); } // 2017.12.27 gestione assi limitati --> non sono abilitate le funzioni £D, quindi DISABILITO da conf... CMSCncLib.Focas1.ODB5AXMAN vettTTCoord = new CMSCncLib.Focas1.ODB5AXMAN(); if (!utils.CRB("FanucLimit3D")) { parentForm.commPlcActive = true; inizio = DateTime.Now; vettTTCoord = FANUC_ref.getPathTTCoord(); if (utils.CRB("recTime")) { TimingData.addResult("R-TTCoord", DateTime.Now.Subtract(inizio).Ticks); } parentForm.commPlcActive = false; } // ciclo su path StringBuilder sb_2; StringBuilder sb_3; for (int i = 0; i < currAdpConf.nPath; i++) { // accodo dati path in DataMonitor... sb_2 = new StringBuilder(); sb_3 = new StringBuilder(); currGateway.updateItemNodeValue(vettPath[i].gCodeAct_Key, GCodAttivi); if (!utils.CRB("FanucLimit3D")) { currGateway.updateItemNodeValue(vettPath[i].posAct_X_Key, ((decimal)vettTTCoord.data1) / utils.CRI("fattdecimale")); currGateway.updateItemNodeValue(vettPath[i].posAct_Y_Key, ((decimal)vettTTCoord.data2) / utils.CRI("fattdecimale")); currGateway.updateItemNodeValue(vettPath[i].posAct_Z_Key, ((decimal)vettTTCoord.data3) / utils.CRI("fattdecimale")); currGateway.updateItemNodeValue(vettPath[i].posAct_I_Key, ((decimal)vettTTCoord.c1) / utils.CRI("fattdecimale")); currGateway.updateItemNodeValue(vettPath[i].posAct_J_Key, ((decimal)vettTTCoord.c2) / utils.CRI("fattdecimale")); currGateway.updateItemNodeValue(vettPath[i].posAct_K_Key, "0"); // è 5 assi...nullo... } // 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)); sb_3.AppendLine(string.Format("Path {0}, Asse 1: {1:N3}", i + 1, ((decimal)vettTTCoord.data1) / utils.CRI("fattdecimale"))); sb_3.AppendLine(string.Format("Path {0}, Asse 2: {1:N3}", i + 1, ((decimal)vettTTCoord.data2) / utils.CRI("fattdecimale"))); sb_3.AppendLine(string.Format("Path {0}, Asse 3: {1:N3}", i + 1, ((decimal)vettTTCoord.data3) / utils.CRI("fattdecimale"))); sb_3.AppendLine(string.Format("Path {0}, Cent 1: {1:N3}", i + 1, ((decimal)vettTTCoord.c1) / utils.CRI("fattdecimale"))); sb_3.AppendLine(string.Format("Path {0}, Cent 2: {1:N3}", i + 1, ((decimal)vettTTCoord.c2) / utils.CRI("fattdecimale"))); parentForm.dataMonitor_2 += sb_2.ToString(); parentForm.dataMonitor_3 += sb_3.ToString(); } } public override void getAxis() { // mostro assi in DataMonitor...... StringBuilder sb = new StringBuilder(); parentForm.commPlcActive = true; inizio = DateTime.Now; CMSCncLib.Focas1.ODBPOS posAssi = FANUC_ref.getAllAxisPos(); if (utils.CRB("recTime")) { TimingData.addResult("R-AXIS_POS", DateTime.Now.Subtract(inizio).Ticks); } inizio = DateTime.Now; CMSCncLib.Focas1.ODBSVLOAD loadAssi = FANUC_ref.getAllAxisLoad(); if (utils.CRB("recTime")) { TimingData.addResult("R-AXIS_LOAD", DateTime.Now.Subtract(inizio).Ticks); } parentForm.commPlcActive = false; 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... currGateway.updateItemNodeValue(vettAxis[i].loadKey, valLoad.data / Math.Pow(10, valLoad.dec)); newPos = valPos.abs.data / Math.Pow(10, valPos.abs.dec); currGateway.updateItemNodeValue(vettAxis[i].posActKey, newPos); currGateway.updateItemNodeValue(vettAxis[i].posTgtKey, newPos + valPos.dist.data / Math.Pow(10, valPos.dist.dec)); currGateway.updateItemNodeValue(vettAxis[i].feedrateKey, 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 = currGateway.getItemNode(vettAxis[i].typeKey).ToString(); if (tipoAsse == "LINEAR") { // ?: conditional operator. direzione = (newDir > 0) ? "POSITIVE" : "NEGATIVE"; } else if (tipoAsse == "ROTARY") { direzione = (newDir > 0) ? "CLOCKWISE" : "COUNTER_CLOCKWISE"; } currGateway.updateItemNodeValue(vettAxis[i].directionKey, direzione); if (utils.CRB("verbose")) { sb.AppendLine(string.Format("Asse {0}: PosAct:{1:N3}, ToGo:{2:N3}{3} | {4}", valPos.abs.name, valPos.abs.data / Math.Pow(10, valPos.abs.dec), valPos.dist.name, 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; currGateway.updateItemNodeValue(vettAxis[i].feedOverKey, 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_3 += sb.ToString(); } } }