using CMSCncLib.CNC; using MTC; using SCMA.AdapterCom; using System; using System.Collections.Generic; using System.Text; namespace SCMA { public class AdapterOsai : AdapterGeneric { /// /// Oggetto MAIN x connessione OSAI /// protected OSAI OSAI_ref; /// /// wrapper chiamata lettura/scrittura OSAI x BYTE... /// /// /// /// /// 0/1 orimo o secondo byte della word... /// /// public bool OsaiMemRW_Byte(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, Int32 memOrderStart, ref byte[] Value) { bool answ = false; if (OSAI_ref.Connected) { try { parentForm.commPlcActive = true; answ = OSAI_ref.O_RW_Byte(bWrite, MemType, memIndex, memOrderStart, ref Value); } catch (Exception exc) { lg.Error(exc, "Eccezione in OsaiMemRW_Byte"); } } parentForm.commPlcActive = false; return answ; } /// /// wrapper chiamata lettura/scrittura x WORD... /// /// /// /// /// /// public bool OsaiMemRW_Word(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref ushort[] Value) { bool answ = false; if (OSAI_ref.Connected) { try { parentForm.commPlcActive = true; answ = OSAI_ref.O_RW_Word(bWrite, MemType, memIndex, ref Value); } catch (Exception exc) { lg.Error(exc, "Eccezione in OsaiMemRW_Word"); } } parentForm.commPlcActive = false; return answ; } /// /// wrapper chiamata lettura/scrittura x DOUBLE-WORD... /// /// /// /// /// /// public bool OsaiMemRW_DWord(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref uint[] Value) { bool answ = false; if (OSAI_ref.Connected) { try { parentForm.commPlcActive = true; answ = OSAI_ref.O_RW_DWord(bWrite, MemType, memIndex, ref Value); } catch (Exception exc) { lg.Error(exc, "Eccezione in OsaiMemRW_DWord"); } } parentForm.commPlcActive = false; return answ; } /// /// wrapper chiamata lettura/scrittura x Short... /// /// /// /// /// /// public bool OsaiMemRW_Short(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref short[] Value) { bool answ = false; if (OSAI_ref.Connected) { try { parentForm.commPlcActive = true; answ = OSAI_ref.O_RW_Short(bWrite, MemType, memIndex, ref Value); } catch (Exception exc) { lg.Error(exc, "Eccezione in OsaiMemRW_Short"); } } parentForm.commPlcActive = false; return answ; } /// /// wrapper chiamata lettura/scrittura x INT... /// /// /// /// /// /// public bool OsaiMemRW_Integer(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref int[] Value) { bool answ = false; if (OSAI_ref.Connected) { try { parentForm.commPlcActive = true; answ = OSAI_ref.O_RW_Integer(bWrite, MemType, memIndex, ref Value); } catch (Exception exc) { lg.Error(exc, "Eccezione in OsaiMemRW_Integer"); } } parentForm.commPlcActive = false; return answ; } /// /// wrapper chiamata lettura/scrittura x Double... /// /// /// /// /// /// public bool OsaiMemRW_Double(bool bWrite, OSAI.MemTypeDouble MemType, Int32 memIndex, ref double[] Value) { bool answ = false; if (OSAI_ref.Connected) { try { parentForm.commPlcActive = true; answ = OSAI_ref.O_RW_Double(bWrite, MemType, memIndex, ref Value); } catch (Exception exc) { lg.Error(exc, "Eccezione in OsaiMemRW_Double"); } } parentForm.commPlcActive = false; return answ; } /// /// variabile contatore cicli prima di rileggere codici G di un path inattivo... /// public int contChkGCod; /// /// Vettore codici G attivi x PATH 1... /// ushort[] vettGCodes_01; /// /// Vettore codici G attivi x PATH 2... /// ushort[] vettGCodes_02; /// /// struttura dati OSAI x dati NC (pag 148) /// protected CMSCncLib.OPENcontrol.GETINFO1DATA allNcData; /// /// Vettore degli allarmi CNC attivi /// public Dictionary allarmiCNC = new Dictionary(); /// /// estende l'init della classe base... /// /// FORM chaimante /// CONFIGURAZIONE adapter /// OGGETTO gestione comunicazione OUT (tipologia e metodi) public AdapterOsai(MainForm caller, AdapterConf adpConf, Gateway gatewayObj) : base(caller, adpConf, gatewayObj) { // !!!HARD CODED!!! aggiunto banco STATUS del 2 processo IN CODA... (4+1)DW=20byte x strobes...!!! Strobes = new byte[20]; // fix dimensione memorie MST: 52 Byte = 26 short(16bit) x (12+7+7) aree (attenzione: secondo set di 2 bit è VUOTO...) MemBlock_MST = new byte[52]; // salto necessario! saltoMST = 1; // GCodes! vettGCodes_01 = new ushort[14]; vettGCodes_02 = new ushort[14]; contChkGCod = utils.CRI("contChkGCod"); // è little endian (NON serve conversione) hasBigEndian = false; 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]; parentForm.commPlcActive = true; 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)); } parentForm.commPlcActive = false; // disconnetto e connetto... if (utils.CRB("verbose")) { lg.Info("OSAI: tryDisconnect"); } tryDisconnect(); lg.Info("OSAI: tryConnect"); tryConnect(); lg.Info("End init Adapter OSAI"); } /// /// Override disconnessione /// public override void tryDisconnect() { if (connectionOk) { string szStatusConnection = ""; try { parentForm.commPlcActive = true; 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"); } parentForm.commPlcActive = false; } else { lg.Error("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile..."); } } /// /// Override connessione /// public override void tryConnect() { if (!connectionOk) { string szStatusConnection = ""; try { parentForm.commPlcActive = true; 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(string.Format("Errore nella connessione all'adapter OSAI: {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"))); } parentForm.commPlcActive = false; } } /// /// Verifico connessione OSAI... /// /// public override bool connectionOk { get { return OSAI_ref.Connected; } } /// /// Effettuo lettura dei 16 byte di strobe/status /// 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!!! // 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"); } } /// /// processing strobe! /// public override void processStrobe() { // inizializzo userAction string UserAction = ""; // oggetti "accessori" x processing (1 byte di strobe x ogni path) StFlag8 currStrobe; StFlag8 currAck; // processo ora i dati dei path... di sicuro il primo currStrobe = (StFlag8)(Strobes[4]); // 5° byte currAck = (StFlag8)(Acknowl[4]); // 5° byte procPathStrobes(0, currStrobe, currAck, 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() != "") { currGateway.updateItemNodeValue("USER_ACTION", UserAction.Trim()); } // verifico strobe dell'auto-test currStrobe = (StFlag8)(Strobes[7]); // 8° byte currAck = (StFlag8)(Acknowl[7]); // 8° byte processTestStrobe(currStrobe, currAck, 19021, 1); // gestione bit di watchdog... sulal DWord successiva sendWatchDog(); } /// /// Scrive ACK x dati MST /// /// /// /// /// public override bool writeMST_ACK(int memIndexAck, ref byte[] currACK_DW) { bool fatto = false; try { inizio = DateTime.Now; fatto = OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndexAck, 0, ref currACK_DW); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("W{0}-ACK_DW0", currACK_DW.Length), DateTime.Now.Subtract(inizio).Ticks); } } catch (Exception exc) { lg.Error(string.Format("Errore in scrittura dati ACK MST:{0}{1}", Environment.NewLine, exc)); } return fatto; } /// /// Legge area memoria dati MST /// /// /// /// /// public override bool readMST_data(int idxPath, int memIndexMST, ref byte[] MemBlock_MST) { bool fatto = false; try { // leggo tutto!!! inizio = DateTime.Now; fatto = OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndexMST, 0, ref MemBlock_MST); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-STRB_DW1-P{1:00}", MemBlock_MST.Length, idxPath), DateTime.Now.Subtract(inizio).Ticks); } } catch (Exception exc) { lg.Error(string.Format("Errore in lettura dati MST:{0}{1}", Environment.NewLine, exc)); } return fatto; } /// /// Scrive watchdog /// /// /// public override bool writeWatchDog(ref byte[] retACK_DW) { int memIndex = 19022; return OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref retACK_DW); } /// /// Effettua lettura dati TESTING /// /// /// public override bool readTestData(ref uint[] MemBlockTestData) { bool fatto = false; try { // 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); } fatto = true; } catch (Exception exc) { lg.Error(string.Format("Errore in lettura dati TEST:{0}{1}", Environment.NewLine, exc)); } return fatto; } /// /// Scrive vettore ACK degli allarmi /// /// /// public override bool writeAlarmAck(ref byte[] retACK_DW0) { int memIndexAck = 19018; return OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndexAck, 0, ref retACK_DW0); } /// /// Legge vettore di TUTTE memorie tipo DWord dato vettore memorie (completo) /// /// /// public override bool readAllAlarms(ref uint[] MemBlock) { int memIndex = 19036; return OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref MemBlock); } /// /// Legge vettore di TUTTE memorie tipo DWord dato indice di partenza e vettore memorie /// /// /// /// public override bool readAlarmBlock(ref uint[] MemBlock, int blockIndex) { int memIndex = 19036; return OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex + blockIndex * 2, ref MemBlock); } #region implementazione processing GlobalData /// /// Legge dati globali... /// public override void readGlobalData() { // leggo dati globali... parentForm.commPlcActive = true; inizio = DateTime.Now; OSAI_ref.O_GetNcInfo1(ref allNcData); if (utils.CRB("recTime")) { TimingData.addResult("R-NcInfo", DateTime.Now.Subtract(inizio).Ticks); } parentForm.commPlcActive = false; // recupero speed e feed... FeedRate = Convert.ToInt32(allNcData.realfeed); SpeedRate = Convert.ToInt32(allNcData.realspeed); } /// /// legge dati override... /// /// /// public override bool readOverrides(ref StringBuilder sb1) { bool fatto = false; try { // 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... sb1.AppendLine(string.Format("FeedRate: {0} mm/min", FeedRate)); sb1.AppendLine(string.Format("SpeedRate: {0} mm/min", SpeedRate)); // 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 sb1); //...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 sb1); } fatto = true; } catch (Exception exc) { lg.Error(exc, "Eccezione in readOverrides"); } return fatto; } /// /// processa allarmi CNC... /// public override bool procCncAlarm() { bool fatto = false; try { // se ho allarmi li accodo... if (allNcData.lastncerror != 0) { if (utils.CRI("loglevel") > 5) { lg.Info(string.Format("Allarmi CNC: {0} ", allNcData.lastncerror)); } string alarmText = string.Format("CNC Alarm - Cod: {0}", allNcData.lastncerror); // tolgo eventuali allarmi CNC... allarmiCNC.Clear(); allarmiCNC.Add(allNcData.lastncerror.ToString(), alarmText); // 2017.05.09 gestione allarmi commentata #if false //----------------------------------------------------- // PROMO BLOCCO TEST //----------------------------------------------------- mAlarmCNC.Add(MTConnect.Condition.Level.FAULT, alarmText, allNcData.lastncerror.ToString(), "", ""); // mostro in form! sb1.AppendLine(alarmText); parentForm.dataMonitor_1 += sb1.ToString(); //----------------------------------------------------- // SECONDO BLOCCO TEST //----------------------------------------------------- // il codice è corretto (manca prima aprte codice + traduzione), se cerco di trovare oggett completo NON c'è, verificare con Andrea... sb1.AppendLine(string.Format("Allarmi CNC: {0}", allNcData.lastncerror)); parentForm.commPlcActive = true; inizio = DateTime.Now; OSAI_ref.O_ReadCurrentErrorMsg(ref allarmiCNC); if (utils.CRB("recTime")) TimingData.addResult("R-CNC-ERROR-MSG", DateTime.Now.Subtract(inizio).Ticks); parentForm.commPlcActive = false; checkCNCAlarms(); //----------------------------------------------------- // TERZO BLOCCO TEST //----------------------------------------------------- // provo altri metodi... parentForm.commPlcActive = true; CMSCncLib.OPENcontrol.MSGEMERGENCY emergCNC = new CMSCncLib.OPENcontrol.MSGEMERGENCY(); OSAI_ref.O_ReadCurrentEmergMsg(ref emergCNC); CMSCncLib.OPENcontrol.MSGANOMALY anomCNC = new CMSCncLib.OPENcontrol.MSGANOMALY(); OSAI_ref.O_ReadCurrentAnomalyMsg(ref anomCNC); parentForm.commPlcActive = false; #endif } else { allarmiCNC.Clear(); allarmiCNC = new Dictionary(); // 2017.05.09 gestione allarmi commentata //allarmiCNC = new CMSCncLib.OPENcontrol.MSGERROR(); } fatto = true; } catch (Exception exc) { lg.Error(exc, "Eccezione in procCncAlarm"); } return fatto; } /// /// 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 = 1000; // calcolo indice max scorrendo... uint[] tabDatiMtz = new uint[maintDataMaxNum]; 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); } fatto = true; } catch (Exception exc) { lg.Error(string.Format("{0}", exc)); } 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 = 19434; uint[] tabDatiAnalog = new uint[analogDataMaxNum]; inizio = DateTime.Now; OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref tabDatiAnalog); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-DatiAnalog", tabDatiAnalog.Length * 4), DateTime.Now.Subtract(inizio).Ticks); } // decodifico aree memoria secondo tab configurazione processAnalogData(tabDatiAnalog, analogData); } fatto = true; } catch (Exception exc) { lg.Error(string.Format("{0}", exc)); } return fatto; } /// /// Gestione lettura dati status da PLC /// public override bool getStatusDataFromPlc() { bool fatto = false; try { if (statusDataMaxNum > 0) { // recupero i dati di manutenzione dall'area di memoria IN BLOCCO int memIndex = 19426; int numByte = 1 + (statusDataMaxNum / 8); byte[] tabDatiStatus = new byte[numByte]; inizio = DateTime.Now; OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, 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 (Exception exc) { lg.Error(string.Format("{0}", exc)); } return fatto; } #endregion /// /// Carico file conf dati CMS /// protected override void loadOtherFile() { base.loadOtherFile(); //loadMaintData("MW", 19166, 2); loadMaintData("GL", 500, 1); loadStatusData("M", 19426, 1); //loadAnalogData("ML", 19434, 2); loadAnalogData("ML", 9717, 1); } /// /// Processing allarmi CNC /// public override void processAlarm() { base.processAlarm(); // aggiungo gestione allarmi CNC checkCNCAlarms(); } /// /// Verifica i 10 allarmi CNC SE presenti /// private void checkCNCAlarms() { if (allarmiCNC != null) { sendAlarmIfPresent(allarmiCNC); } } /// /// Invia singolo allarme CNC se presente (da dictionary) /// /// protected void sendAlarmIfPresent(Dictionary allarmi) { // controllo valore... if (allarmi != null && allarmi.Count > 0) { try { StringBuilder sb = new StringBuilder(); foreach (KeyValuePair item in allarmi) { string alarmText = string.Format("{0} - {1}", item.Key, item.Value); if (utils.CRI("loglevel") > 5) { lg.Info(string.Format("Allarme CNC: {0}", alarmText)); } // predispongo allarme allarme currAllarm = new allarme(item.Key, currGateway.nCncConditions, "FAULT", alarmText); currGateway.addAlarm(currAllarm); // mostro in form! sb.AppendLine(alarmText); } 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 = 2950; // buffer memoria 60 byte... speed (16bit 2 * 20) + load (8bit 1 * 20) visto che sono 20 teste max byte[] unOpSpeedMem = new byte[60]; ushort[] unOpSpeedMemW = new ushort[30]; inizio = DateTime.Now; OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref unOpSpeedMemW); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-SPEED_UNOP", unOpSpeedMem.Length), DateTime.Now.Subtract(inizio).Ticks); } // travaso in modalità byte... Buffer.BlockCopy(unOpSpeedMemW, 0, unOpSpeedMem, 0, unOpSpeedMem.Length); procUnOp(unOpSpeedMem); } /// /// Procedura di processing lettura memoria x DatiUt - Step 4 /// /// /// /// public override int getDatiUt_step4(ref byte[] int32Mem, int j) { int memIndex = 6200 + 2 * j; inizio = DateTime.Now; OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, 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 = 5000 + 1 * j / 2; // dovrebeb leggere correttamente solo 1 byte... byte[] byteMtrx = new byte[1]; int resto = 0; Math.DivRem(j, 2, out resto); inizio = DateTime.Now; OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, resto, ref byteMtrx); int8Mem = byteMtrx[0]; 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 = 4100; inizio = DateTime.Now; OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, 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 = 5500 + j; inizio = DateTime.Now; OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, 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 = 5300; inizio = DateTime.Now; OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, 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 = 3020; inizio = DateTime.Now; OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, 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() { // NON ci sono nella documentazione metodi x recuperare posizione PuntaUtensile, in attesa news da OSAI/Andrea... // ciclo su path StringBuilder sb_2; StringBuilder sb_3; ushort[] vettGCodes; // faccio VERA lettura SOLO ogni TOT cicli... if (contChkGCod <= 0) { // reimposto contatore contChkGCod = utils.CRI("contChkGCod"); // recupero vettore generale G MODE parentForm.commPlcActive = true; inizio = DateTime.Now; OSAI_ref.getPathGCodeMod(1, ref vettGCodes_01); if (currAdpConf.nPath > 1) { OSAI_ref.getPathGCodeMod(2, ref vettGCodes_02); } if (utils.CRB("recTime")) { TimingData.addResult("R-GCodModal", DateTime.Now.Subtract(inizio).Ticks); } parentForm.commPlcActive = false; } else { contChkGCod--; } for (int i = 0; i < currAdpConf.nPath; i++) { // accodo dati path in DataMonitor... sb_2 = new StringBuilder(); sb_3 = new StringBuilder(); // attenzione: il vettore contiene come campi "vuoti" il valore MAX di USHort (16bit) ovvero 2^16 -1 (base 0) --> 65535 string GCodAttivi = ""; vettGCodes = i == 0 ? vettGCodes_01 : vettGCodes_02; for (int j = 0; j < vettGCodes.Length; j++) { // se il valore è < di UShort.max (65535)... if (vettGCodes[j] < ushort.MaxValue) { GCodAttivi += string.Format("[G{0}]", vettGCodes[j]); } } currGateway.updateItemNodeValue(vettPath[i].gCodeAct_Key, GCodAttivi); if (currGateway.protocollo != gwProtocol.SOURS) { // 2017.01.16 da rivedere currGateway.updateItemNodeValue(vettPath[i].currProgRowNumKey, ""); currGateway.updateItemNodeValue(vettPath[i].activeAxesKey, ""); sb_2.AppendLine(string.Format("Path {0}, PROG: {1}", i + 1, currGateway.getItemNode(vettPath[i].currProgKey))); } sb_3.AppendLine(string.Format("Path {0}, GCodes: {1}", i + 1, GCodAttivi)); parentForm.dataMonitor_2 += sb_2.ToString(); parentForm.dataMonitor_3 += sb_3.ToString(); } } public override void getAxis() { // mostro assi in DataMonitor...... StringBuilder sb = new StringBuilder(); parentForm.commPlcActive = true; inizio = DateTime.Now; /*------------------------------------------------------------------------ * 2018.01.16 modifica per gestione doppio processo e nome assi duplicato * ------------------------------------------------------------------------ * * E' risultato (marco.negri, amcchian OSAI con 2 processi in cui glia ssi di ogni processoa vevano lo stesso nome) ceh OSAI NON restituisce ID univoco asse ma nome etichetta asegnato * in questo modo glia ssi verso agent (e seguenti) si sovrappongono/sovrascrivono * * E' quindi necessario procedere in + step * - verificare numero processia ttivi * - chiedere x ogni processo quali assi ci siano (AsixTable (con Id UNIVOCO e consistente e NOME) * - chiedere x ogni processo le posizioni assi in modo che processo + nome --> Id Univoco --> possiamo popolare la tabella da invaire poi all'agent */ // inizializzo x numero assi... CMSCncLib.OPENcontrol.GETINTDATA[] tmpPosAssiTgt = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis]; CMSCncLib.OPENcontrol.GETINTDATA[] tmpPosAssi = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis]; CMSCncLib.OPENcontrol.GETINTDATA[] posAssiTgt = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis]; CMSCncLib.OPENcontrol.GETINTDATA[] posAssi = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis]; Dictionary axisDict = new Dictionary(); char[] axisTable = new char[currAdpConf.nAxis]; short[] axisIdTable = new short[currAdpConf.nAxis]; int currId = 0; // verifico quanti path ho... e recupero le info sugli assi (se id > 0 è PRESENTE...) for (short i = 1; i <= currAdpConf.nPath; i++) { axisTable = new char[currAdpConf.nAxis]; axisIdTable = new short[currAdpConf.nAxis]; // chiamo lettura tab assi OSAI_ref.O_GetAxisTab(i, ref axisTable, ref axisIdTable); //...e popolo i dati... for (int j = 0; j < currAdpConf.nAxis; j++) { // recupero Id... currId = axisIdTable[j]; // controllo se id > 0... if (currId > 0) { // salvo!!! come path#nome axisDict.Add(string.Format("{0}#{1}", i, axisTable[j]), currId); // se conf di leggere nome/path asse.. if (utils.CRB("enableAxNamePath")) { // solo se HO UN NOME valido x asse... if (axisTable[j] != '-' && axisTable[j] != '\0') { try { // salvo (per ID) descr asse e processo corrente! currGateway.updateItemNodeValue(vettAxis[currId - 1].descriptionKey, axisTable[j]); currGateway.updateItemNodeValue(vettAxis[currId - 1].mainProcKey, i); } catch (Exception exc) { lg.Error(exc, string.Format("Eccezione in salvataggio nome/path asse num {0}", currId)); } } } } } } char axName; int reIdx = 0; // ora processo i dati PER PATH delle posizioni assi... for (short i = 1; i <= currAdpConf.nPath; i++) { tmpPosAssiTgt = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis]; tmpPosAssi = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis]; OSAI_ref.getAllAxisPos(1, i, ref tmpPosAssiTgt); OSAI_ref.getAllAxisPos(2, i, ref tmpPosAssi); // decodifico e salvo in posizione corretta... for (int j = 0; j < currAdpConf.nAxis; j++) { // per sicurezza try-catch try { if (tmpPosAssiTgt[j].AxisName == 0) { axName = '-'; } else { axName = Convert.ToChar(tmpPosAssiTgt[j].AxisName); } // salvo nella posizione DECODIFICATA da dictionary x path/nome... if (axName != '\0' && axName != '-') { // calcolo ID REALE reIdx = axisDict[string.Format("{0}#{1}", i, axName)]; posAssiTgt[reIdx - 1] = tmpPosAssiTgt[j]; posAssi[reIdx - 1] = tmpPosAssi[j]; } } catch { } } } // nuova posizione (per calcoli) double newPos = 0; double newPosTgt = 0; double distPerc = 0; int newDir = 0; string direzione = ""; // ORA ho tutto in posizione corretta, PROCESSO!!! for (int i = 0; i < currAdpConf.nAxis; i++) { // per sicurezza try-catch try { //string axName = System.Text.Encoding.ASCII.GetString(posAssi[i].AxisName); if (posAssiTgt[i] == null || posAssiTgt[i].AxisName == 0) { axName = '-'; } else { axName = Convert.ToChar(posAssiTgt[i].AxisName); } // controllo nome asse: se vuoto NON PROCESSARE if (axName != '\0' && axName != '-') { newPos = posAssi[i].position; newPosTgt = posAssiTgt[i].position; } else { newPos = 0; newPosTgt = 0; } // popolo valori... LOAD gestito da vettore letto con area memoria AnalogData.map currGateway.updateItemNodeValue(vettAxis[i].loadKey, Convert.ToUInt32(istLoadAssi[i].vcMedian)); currGateway.updateItemNodeValue(vettAxis[i].posActKey, newPos); currGateway.updateItemNodeValue(vettAxis[i].posTgtKey, newPosTgt); 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]; } // calcolo direzione direzione = calculateDirection(newDir, i); // imposto direzione currGateway.updateItemNodeValue(vettAxis[i].directionKey, direzione); if (utils.CRB("verbose")) { sb.AppendLine(string.Format("Asse {0}: PosAct:{1:N3} | Prg:{2:N3} | Load:{3:N1} | {4}", axName, newPos, newPosTgt, currGateway.getItemNode(vettAxis[i].loadKey), direzione)); } // salvo valori vettore prec... prevPosAxis[i] = newPos; prevDirAxis[i] = newDir; currGateway.updateItemNodeValue(vettAxis[i].feedOverKey, FeedRateOver); } catch { lg.Error(string.Format("Errore in lettura asse {0}", i)); } } // salvo timing! if (utils.CRB("recTime")) { TimingData.addResult("R-AXIS_POS", DateTime.Now.Subtract(inizio).Ticks); } parentForm.commPlcActive = false; parentForm.dataMonitor_3 += sb.ToString(); } } }