using System; using System.Collections.Generic; using System.Linq; namespace IOB_WIN_NEXT { public class IobSiemensFape : IobSiemens { /* -------------------------------------------------------------------------------- * Controlli SIEMENS FAPE (es punzonatrice Tecnomeccanica di LVF) * - basasto su SIEMENS * - S7 vers 1200 * - abilitata 1 area in lettura DB15 ed 1 in scrittura DB16 (NON la usano) * - x poter funzionare --> protezione: meccanismi di collegamento / consenti put/get * - lettura/scrittura primi 48 byte (240 max x le due DB) * * LETTURA seguenti byte: * - B0, WORD, Stato Macchina Generale * - B2, WORD, Posizione sequenza contatore * - B4, WORD, contatore cicli eseguiti per lubrifica * - B40, DWORD, contapezzi azzerabile da operatore * - B44, DWORD, contapezzi ASSOLUTO * * -------------------------------------------------------------------------------- */ #region Public Constructors /// /// Classe base con i metodi x Siemens /// /// /// public IobSiemensFape(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { // dovebbe fare init della classe base, VERIFICARE... lgInfo("NEW IOB SIEMENS versione FAPE"); } #endregion Public Constructors #region Public Enums /// /// Posizione sequenza ciclo standard punzonatrice /// public enum posizioneSequenza { CICLO_AUTOMATICO_FERMO = 0, CONTROLLO_MODO_OPERATIVO = 5, MODO_ATTIVO_CON_ROBOT = 8, SBLOCCAGGIO_PEZZO = 10, APERTURA_PORTELLO_ROBOT = 11, CONSENSO_ACCESSO_AL_ROBOT = 12, CARICO_ROBOT_IN_CORSO = 14, CARICO_ROBOT_CONCLUSO = 16, CHIUSURA_PORTELLO_ROBOT = 18, VERIFICA_POSIZIONE_CARRI = 20, BLOCCAGGIO_PEZZO = 22, ATTESA_CARRO_A_DESTRA = 24, DISCESA_RAPIDO_BROCCIATURA = 25, CICLO_DI_BROCCIATURA = 26, RITORNO_BROCCIATRICE = 28, COMANDO_CARRO_A_SINISTRA = 30, CICLO_DI_ALESATURA = 32, RITORNO_CARRO_ALESATURA = 34, COMANDO_CARRO_A_DESTRA = 36, INCREMENTO_CONTAPEZZI = 38, CONTROLLO_TIME_OUT_CICLO = 40, RILANCIO_CICLO_F42 = 42, ATTESA_FINE_CICLO = 45 } /// /// Enum degli stati macchina (B0) /// public enum statoMacchina { COMUNICAZIONE_ASSENTE = 0, EMERGENZA_INSERITA = 1, AVARIA_ARIA = 2, AVARIA_PRESSIONE_OLIO = 3, AVARIA_LIVELLO_OLIO = 4, AVARIA_TEMPERATURA_OLIO = 5, AVARIA_MOTORE_POMPA_IDRAULICA = 6, AVARIA_MOTORE_RAFFREDDO_IDRAULICA = 7, AVARIA_SINCRONISMO_PORTE = 8, AVARIA_LIBERA = 9, ATTIVAZIONE_IN_CORSO = 10, MODO_MANUALE_ATTREZZAGGIO = 11, MODO_AUTOMATICO_LOCALE = 12, MODO_AUTOMATICO_ROBOT = 13, CICLO_IN_CORSO = 14, LIBERO = 15 } #endregion Public Enums #region Protected Methods /// /// Effettua decodifica aree memoria alla bitmap usata x MAPO /// protected override void decodeToBaseBitmap() { // init a zero... B_input = 0; // FAPE: leggo i primi 2 WORD x decodifica stato e posizione... ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); statoMacchina _stMacch = ((statoMacchina)valStatus); posizioneSequenza _posSeq = ((posizioneSequenza)valPosit); /* ----------------------------------------------------- * bitmap MAPO * B0: POWER_ON * B1: RUN * B2: pzCount * B3: allarme * B4: manuale * B5: emergenza ----------------------------------------------------- */ // bit 0 (poweron) imposto a 1 SE connected... B_input = currPLC.IsConnected ? 1 : 0; // controllo stato macchina x impostare altri bit... switch (_stMacch) { case statoMacchina.EMERGENZA_INSERITA: B_input += (1 << 5); break; case statoMacchina.AVARIA_ARIA: case statoMacchina.AVARIA_PRESSIONE_OLIO: case statoMacchina.AVARIA_LIVELLO_OLIO: case statoMacchina.AVARIA_TEMPERATURA_OLIO: B_input += (1 << 3); B_input += (1 << 6); break; case statoMacchina.AVARIA_MOTORE_POMPA_IDRAULICA: case statoMacchina.AVARIA_MOTORE_RAFFREDDO_IDRAULICA: case statoMacchina.COMUNICAZIONE_ASSENTE: case statoMacchina.AVARIA_SINCRONISMO_PORTE: case statoMacchina.AVARIA_LIBERA: case statoMacchina.ATTIVAZIONE_IN_CORSO: B_input += (1 << 3); break; case statoMacchina.MODO_MANUALE_ATTREZZAGGIO: B_input += (1 << 4); break; case statoMacchina.CICLO_IN_CORSO: B_input += (1 << 1); break; case statoMacchina.MODO_AUTOMATICO_LOCALE: case statoMacchina.MODO_AUTOMATICO_ROBOT: B_input += (1 << 7); break; case statoMacchina.LIBERO: default: break; } // procedo SOLO SE è enabled IOB if (IobOnline) { try { currODL = utils.callUrl(urlGetCurrODL); // solo SE HO un ODL... if (string.IsNullOrWhiteSpace(currODL) || currODL == "0") { if (periodicLog) { lgInfo(string.Format("SiemensFape | Lettura ODL andata a vuoto: currODL: {0}", currODL)); } } else { // se variato o scaduto timeout log... if (periodicLog || (currIdxODL.ToString() != currODL)) { lgInfo(string.Format("SiemensFape | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); } // provo a salvare nuovo ODL int.TryParse(currODL, out currIdxODL); } } catch (Exception exc) { if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) { lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); lastWarnODL = DateTime.Now; } } } else { // imposto currODL a vuoto! currODL = ""; if (periodicLog) { lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); } } if (!string.IsNullOrWhiteSpace(currODL) && currODL != "0") { // ora processo il contapezzi... // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) { // se sono differenti MOSTRO... if (contapezziPLC != contapezziIOB) { // registro contapezzi lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); } // verifico se variato contapezzi... e se passato ritardo minimo... if (contapezziPLC > contapezziIOB) { // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio contapezziIOB++; needRefreshPzCount = true; // salvo in semaforo! B_input += (1 << 2); // registro contapezzi lgInfo($"contapezziPLC SIEMENS: {contapezziPLC} | contapezziIOB {contapezziIOB}"); } // invio a server contapezzi (aggiornato) string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); // verifica se tutto OK if (retVal != contapezziIOB.ToString()) { // errore salvataggio contapezzi lgInfo($"Errore salvataggio Contapezzi SIEMENS: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); // rileggo il counter pezzi da server pzCntReload(true); } // resetto timer... lastPzCountSend = DateTime.Now; } } else { if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) { lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENS {contapezziPLC} | contapezziIOB {contapezziIOB}"); // resetto timer... lastPzCountSend = DateTime.Now; } } // log opzionale! if (verboseLog) { lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); } } #endregion Protected Methods #region Public Methods /// /// Recupero dati override in formato dictionary /// /// public override Dictionary getDynData() { Dictionary outVal = new Dictionary(); ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); outVal.Add("CURR_STATO", ((statoMacchina)valStatus).ToString()); outVal.Add("CURR_POSIT", ((posizioneSequenza)valPosit).ToString()); return outVal; } /// /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) /// public override void processOverride() { } #endregion Public Methods } }