diff --git a/IOB-WIN/IobSiemensComur.cs b/IOB-WIN/IobSiemensComur.cs index c9cdd2c9..06554444 100644 --- a/IOB-WIN/IobSiemensComur.cs +++ b/IOB-WIN/IobSiemensComur.cs @@ -4,240 +4,249 @@ using System.Collections.Generic; namespace IOB_WIN { - /// - /// Controllo Siemens specifico x impianti COMUR - /// - public class IobSiemensComur : IobSiemens - { - /* -------------------------------------------------------------------------------- - * Controlli SIEMENS COMUR - * - basasto su SIEMENS - * - S7 vers 1500 - * - * STRUTTURA MEMORIA DB150: 56 byte lettura, di cui 4 byte scrittura (4..7), vedere doc allegato - * G:\Drive condivisi\30_Clienti\Valvital\Comunicazione PLC\COMUR Dentatrice - * - * Si intende tutto con DB150.DBxx - * - * - parametri processo PLC --> MES - * - DBX0.0 - Macchina On: Segnale pulito di informazione sullo stato della macchina. 0->Aux OFF, 1->Aux ON - * - DBX0.1 – Macchina in Allarme: Segnale pulito di macchina in allarme. 0->Nessun Allarme, 1->E’ presente almeno un allarme/anomalia - * - DBX0.2 – Macchina in Ciclo: Segnale pulito sullo stato di funzionamento. 0->La macchina NON sta eseguendo un ciclo automatico, 1->La macchina sta * - eseguendo un ciclo automatico. - * - DBX0.3 – Macchina Non in Produzione: Segnale pulito sullo stato della macchina. 0->Macchina accesa e in lavorazione automatica, 1->Macchina accesa * - ma NON sta eseguendo un ciclo automatico. - * - DBX0.4 – Macchina In Ciclo Continuità: Segnale pulito sullo stato di funzionamento. 1->La macchina sta eseguendo un ciclo automatico con carico/ * - scarico pezzo autonomo, 0->Altrimenti. - * - DBX0.7 – Assi In Moto: Segnale pulito sullo stato di movimento Assi. 0->Tutti gli assi della macchina sono fermi, 1->Almeno un asse si sta * - muovendo. - * - DBX1.0 – Impulso Start Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Start Ciclo. - * - DBX1.1 – Impulso Fine Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Fine Ciclo. Attenzione! Questo * - impulso viene generato solo se il Ciclo Automatico finisce correttamente. Non viene generato nel caso in cui il Ciclo Automatico venga interrotto da * - allarmi. - * - DBX1.3 – Impulso Conta Pezzi: Impulso a fronte positivo (0->1) della durata di 1’’ generato al completamento di ogni programma pezzo. - * - DBX2.0 – Preallarmi Pezzi: Segnale pulito di segnalazione Preallarme Pezzi impostabile su CN. 0->Preallarme Disattivo, 1->Preallarme Attivo - * - DBX2.1 – Allarme Pezzi: Segnale pulito di segnalazione Allarme Pezzi impostabile su CN. 0->Allarme Disattivo, 1->Allarme Attivo. - * - DBX2.3 – Fine Vita Utensile: Segnale pulito di segnalazione Allarme Fine Vita Creatore. 0->Allarme Disattivo, 1->Allarme Attivo. - * - DBX2.7 – Ciclo In Attesa: Segnale pulito sullo stato di funzionamento. 1->Ciclo Automatico attivo ma tutti assi fermi, 0->Altrimenti. - * - * - DBD52 - Codice Pezzo In Lavorazione (4byte, REAL) - * - DBD56 - Codice Utensile In Uso (4byte, REAL) - * - * - * - parametri processo MES --> PLC - * - DBX4.0 – Reset Contapezzi Parziale: Segnale per resettare il valore del contatore “Contapezzi parziale”. Impostare il bit a 1 per attivare la funzione (il PLC riporterà a 0 il valore quando completa l’operazione). - * - * - DB150.DBD8 - Numero di Pezzi da produrre per il lotto (4byte, DInt) - * - DB150.[12.0 .. 31.7] - Codice articolo (stringa da 18 char) - * - DB150.[32.0 .. 51.7] - Codice commessa (stringa da 18 char) - * - * - * - DB111.DBD2: PartCounter INT 2.0 Conteggio Parziale di pezzi prodotti dalla macchina - * -------------------------------------------------------------------------------- */ - /// - /// Classe base con i metodi x Siemens + /// Controllo Siemens specifico x impianti COMUR /// - /// - /// - public IobSiemensComur(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + public class IobSiemensComur : IobSiemens { - lgInfo("NEW IOB SIEMENS versione COMUR"); - } + /* -------------------------------------------------------------------------------- + * Controlli SIEMENS COMUR + * - basasto su SIEMENS + * - S7 vers 1500 + * + * STRUTTURA MEMORIA DB150: 56 byte lettura, di cui 4 byte scrittura (4..7), vedere doc allegato + * G:\Drive condivisi\30_Clienti\Valvital\Comunicazione PLC\COMUR Dentatrice + * + * Si intende tutto con DB150.DBxx + * + * - parametri processo PLC --> MES + * - DBX0.0 - Macchina On: Segnale pulito di informazione sullo stato della macchina. 0->Aux OFF, 1->Aux ON + * - DBX0.1 – Macchina in Allarme: Segnale pulito di macchina in allarme. 0->Nessun Allarme, 1->E’ presente almeno un allarme/anomalia + * - DBX0.2 – Macchina in Ciclo: Segnale pulito sullo stato di funzionamento. 0->La macchina NON sta eseguendo un ciclo automatico, 1->La macchina sta * - eseguendo un ciclo automatico. + * - DBX0.3 – Macchina Non in Produzione: Segnale pulito sullo stato della macchina. 0->Macchina accesa e in lavorazione automatica, 1->Macchina accesa * - ma NON sta eseguendo un ciclo automatico. + * - DBX0.4 – Macchina In Ciclo Continuità: Segnale pulito sullo stato di funzionamento. 1->La macchina sta eseguendo un ciclo automatico con carico/ * - scarico pezzo autonomo, 0->Altrimenti. + * - DBX0.7 – Assi In Moto: Segnale pulito sullo stato di movimento Assi. 0->Tutti gli assi della macchina sono fermi, 1->Almeno un asse si sta * - muovendo. + * - DBX1.0 – Impulso Start Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Start Ciclo. + * - DBX1.1 – Impulso Fine Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Fine Ciclo. Attenzione! Questo * - impulso viene generato solo se il Ciclo Automatico finisce correttamente. Non viene generato nel caso in cui il Ciclo Automatico venga interrotto da * - allarmi. + * - DBX1.3 – Impulso Conta Pezzi: Impulso a fronte positivo (0->1) della durata di 1’’ generato al completamento di ogni programma pezzo. + * - DBX2.0 – Preallarmi Pezzi: Segnale pulito di segnalazione Preallarme Pezzi impostabile su CN. 0->Preallarme Disattivo, 1->Preallarme Attivo + * - DBX2.1 – Allarme Pezzi: Segnale pulito di segnalazione Allarme Pezzi impostabile su CN. 0->Allarme Disattivo, 1->Allarme Attivo. + * - DBX2.3 – Fine Vita Utensile: Segnale pulito di segnalazione Allarme Fine Vita Creatore. 0->Allarme Disattivo, 1->Allarme Attivo. + * - DBX2.7 – Ciclo In Attesa: Segnale pulito sullo stato di funzionamento. 1->Ciclo Automatico attivo ma tutti assi fermi, 0->Altrimenti. + * + * - DBD52 - Codice Pezzo In Lavorazione (4byte, REAL) + * - DBD56 - Codice Utensile In Uso (4byte, REAL) + * + * + * - parametri processo MES --> PLC + * - DBX4.0 – Reset Contapezzi Parziale: Segnale per resettare il valore del contatore “Contapezzi parziale”. Impostare il bit a 1 per attivare la funzione (il PLC riporterà a 0 il valore quando completa l’operazione). + * + * - DB150.DBD8 - Numero di Pezzi da produrre per il lotto (4byte, DInt) + * - DB150.[12.0 .. 31.7] - Codice articolo (stringa da 18 char) + * - DB150.[32.0 .. 51.7] - Codice commessa (stringa da 18 char) + * + * + * - DB111.DBD2: PartCounter INT 2.0 Conteggio Parziale di pezzi prodotti dalla macchina + * -------------------------------------------------------------------------------- */ - #region Metodi specifici (da verificare/completare in implementazione) - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - bool taskOk = false; - string taskVal = ""; - // inizio con 1 byte di default - byte[] MemBlock = new byte[1]; - string memAddrWrite = ""; - if (task2exe != null) - { - // cerco task specifici - foreach (var item in task2exe) + /// + /// Classe base con i metodi x Siemens + /// + /// + /// + public IobSiemensComur(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - // controllo sulla KEY - switch (tName) - { - case taskType.nihil: - case taskType.fixStopSetup: - case taskType.forceResetPzCount: - case taskType.forceSetPzCount: - case taskType.setProg: - case taskType.sendWatchDogMes2Plc: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - break; - case taskType.setArt: - case taskType.setComm: - case taskType.setPzComm: - saveProdData(item); - int byteSize = 0; - // recupero dati da memMap... altrimenti NULLA - if (memMap.mMapWrite.ContainsKey(item.Key)) - { - dataConf currMem = memMap.mMapWrite[item.Key]; - byteSize = currMem.size; - memAddrWrite = currMem.memAddr; - MemBlock = new byte[byteSize]; - if (currMem.tipoMem == plcDataType.String) - { - saveStringOnMemBlock(ref MemBlock, item.Key, 0, byteSize); - } - else if (currMem.tipoMem == plcDataType.DInt) - { - int valDInt = 0; - int.TryParse(item.Value, out valDInt); - MemBlock = S7.Net.Types.DInt.ToByteArray(valDInt); - } - else if (currMem.tipoMem == plcDataType.Int) - { - short valDInt = 0; - short.TryParse(item.Value, out valDInt); - MemBlock = S7.Net.Types.Int.ToByteArray(valDInt); - } - } - taskVal = item.Value; - break; - case taskType.startSetup: - // processo scrittura BIT su DB150.DBX4.0 - MemBlock = new byte[1]; - MemBlock[0] = (byte)1; - memAddrWrite = "DB150.DBB4"; - break; - case taskType.stopSetup: - // processo scrittura BIT su DB150.DBX4.0 - MemBlock = new byte[1]; - MemBlock[0] = (byte)0; - memAddrWrite = "DB150.DBB4"; - break; - case taskType.setParameter: - // richiedo da URL i parametri WRITE da popolare - lgInfo("Chiamata processMemWriteRequests"); - taskVal = processMemWriteRequests(); - // se restituiscce "" faccio altra prova... - if (string.IsNullOrEmpty(taskVal)) - { - // i parametri me li aspetto come stringa composta paramName|paramvalue - if (item.Value.Contains("|")) - { - string[] paramsJob = item.Value.Split('|'); - taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; - } - else - { - taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; - } - } - break; - default: - taskVal = "SKIPPED | NO EXEC"; - break; - } - // aggiungo task! - taskDone.Add(item.Key, taskVal); - if (string.IsNullOrEmpty(memAddrWrite)) - { - // scrivo comunque! - taskOk = S7WriteBB(ref MemBlock, memAddrWrite); - } - if (!taskOk) - { - lgError($"Errore in S7WriteBB durante executeTasks: {item.Key} | {item.Value}"); - } + lgInfo("NEW IOB SIEMENS versione COMUR"); } - } - return taskDone; + + #region Metodi specifici (da verificare/completare in implementazione) + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti... + Dictionary taskDone = new Dictionary(); + bool taskOk = false; + string taskVal = ""; + // inizio con 1 byte di default + byte[] MemBlock = new byte[1]; + string memAddrWrite = ""; + if (task2exe != null) + { + // cerco task specifici + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + // controllo sulla KEY + switch (tName) + { + case taskType.nihil: + case taskType.fixStopSetup: + case taskType.forceResetPzCount: + case taskType.forceSetPzCount: + case taskType.setProg: + case taskType.sendWatchDogMes2Plc: + taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + break; + case taskType.setArt: + case taskType.setComm: + case taskType.setPzComm: + saveProdData(item); + int byteSize = 0; + // recupero dati da memMap... altrimenti NULLA + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + byteSize = currMem.size; + memAddrWrite = currMem.memAddr; + MemBlock = new byte[byteSize]; + if (currMem.tipoMem == plcDataType.String) + { + saveStringOnMemBlock(ref MemBlock, item.Key, 0, byteSize); + } + else if (currMem.tipoMem == plcDataType.DInt) + { + int valDInt = 0; + int.TryParse(item.Value, out valDInt); + MemBlock = S7.Net.Types.DInt.ToByteArray(valDInt); + } + else if (currMem.tipoMem == plcDataType.Int) + { + short valDInt = 0; + short.TryParse(item.Value, out valDInt); + MemBlock = S7.Net.Types.Int.ToByteArray(valDInt); + } + } + taskVal = item.Value; + break; + case taskType.startSetup: + // processo scrittura BIT su DB150.DBX4.0 + MemBlock = new byte[1]; + MemBlock[0] = (byte)1; + memAddrWrite = "DB150.DBB4"; + break; + case taskType.stopSetup: + // processo scrittura BIT su DB150.DBX4.0 + MemBlock = new byte[1]; + MemBlock[0] = (byte)0; + memAddrWrite = "DB150.DBB4"; + break; + case taskType.setParameter: + // richiedo da URL i parametri WRITE da popolare + lgInfo("Chiamata processMemWriteRequests"); + taskVal = processMemWriteRequests(); + // se restituiscce "" faccio altra prova... + if (string.IsNullOrEmpty(taskVal)) + { + // i parametri me li aspetto come stringa composta paramName|paramvalue + if (item.Value.Contains("|")) + { + string[] paramsJob = item.Value.Split('|'); + taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; + } + else + { + taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; + } + } + break; + default: + taskVal = "SKIPPED | NO EXEC"; + break; + } + // aggiungo task! + taskDone.Add(item.Key, taskVal); + if (string.IsNullOrEmpty(memAddrWrite)) + { + // scrivo comunque! + taskOk = S7WriteBB(ref MemBlock, memAddrWrite); + } + if (!taskOk) + { + lgError($"Errore in S7WriteBB durante executeTasks: {item.Key} | {item.Value}"); + } + } + } + return taskDone; + } + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + protected override void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + + /* ----------------------------------------------------- + * bitmap MAPO STANDARD + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: allarme creatore + * + * + * - BIT di stato + * - DBX0.0 - Macchina On: Segnale pulito di informazione sullo stato della macchina. 0->Aux OFF, 1->Aux ON + * - DBX0.1 – Macchina in Allarme: Segnale pulito di macchina in allarme. 0->Nessun Allarme, 1->E’ presente almeno un allarme/anomalia + * - DBX0.2 – Macchina in Ciclo: Segnale pulito sullo stato di funzionamento. 0->La macchina NON sta eseguendo un ciclo automatico, 1->La macchina sta eseguendo un ciclo automatico. + * - DBX0.3 – Macchina Non in Produzione: Segnale pulito sullo stato della macchina. 0->Macchina accesa e in lavorazione automatica, 1->Macchina accesa ma NON sta eseguendo un ciclo automatico. + * - DBX0.4 – Macchina In Ciclo Continuità: Segnale pulito sullo stato di funzionamento. 1->La macchina sta eseguendo un ciclo automatico con carico/scarico pezzo autonomo, 0-> Altrimenti. NON HA SENSO perché NON HANNO il robot... + * DB150.DBX0.7 – Assi In Moto: Segnale pulito sullo stato di movimento Assi. 0->Tutti gli assi della macchina sono fermi, 1->Almeno un asse si sta muovendo. + * DB150.DBX1.0 – Impulso Start Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Start Ciclo. + * DB150.DBX1.1 – Impulso Fine Ciclo: Impulso a fronte positivo (0->1) della durata di 1’’ che rappresenta l’evento di Fine Ciclo. Attenzione! Questo impulso viene generato solo se il Ciclo Automatico finisce correttamente. Non viene generato nel caso in cui il Ciclo Automatico venga interrotto da allarmi. + * DB150.DBX1.3 – Impulso Conta Pezzi: Impulso a fronte positivo (0->1) della durata di 1’’ generato al completamento di ogni programma pezzo. + * DB150.DBX2.0 – Preallarmi Pezzi: Segnale pulito di segnalazione Preallarme Pezzi impostabile su CN. 0->Preallarme Disattivo, 1->Preallarme Attivo + * DB150.DBX2.1 – Allarme Pezzi: Segnale pulito di segnalazione Allarme Pezzi impostabile su CN. 0->Allarme Disattivo, 1->Allarme Attivo. + * DB150.DBX2.3 – Fine Vita Utensile: Segnale pulito di segnalazione Allarme Fine Vita Creatore. 0->Allarme Disattivo, 1->Allarme Attivo. + * DB150.DBX2.7 – Ciclo In Attesa: Segnale pulito sullo stato di funzionamento. 1->Ciclo Automatico attivo ma tutti assi fermi, 0->Altrimenti. + * + ----------------------------------------------------- */ + + byte mainData = RawInput[0]; + + int byteSignals = 0; + // bit 0 (poweron) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSignals += (1 << 0); + } + if ((mainData & (1 << 2)) != 0) + { + byteSignals += (1 << 1); + } + + // controllo il bit MAIN dello status + if ((mainData & (1 << 1)) != 0) + { + byteSignals += (1 << 3); + } + + // considero come MANUALE NON ciclo in continuo... + if ((mainData & (1 << 3)) != 0) + { + byteSignals += (1 << 4); + } + + // salvo! + B_input = byteSignals; + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); + } + } + + #endregion } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - protected override void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - - /* ----------------------------------------------------- - * bitmap MAPO STANDARD - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * - * - * - BIT di stato - * - DBX0.0 - Macchina On: Segnale pulito di informazione sullo stato della macchina. 0->Aux OFF, 1->Aux ON - * - DBX0.1 – Macchina in Allarme: Segnale pulito di macchina in allarme. 0->Nessun Allarme, 1->E’ presente almeno un allarme/anomalia - * - DBX0.2 – Macchina in Ciclo: Segnale pulito sullo stato di funzionamento. 0->La macchina NON sta eseguendo un ciclo automatico, 1->La macchina sta eseguendo un ciclo automatico. - * - DBX0.3 – Macchina Non in Produzione: Segnale pulito sullo stato della macchina. 0->Macchina accesa e in lavorazione automatica, 1->Macchina accesa ma NON sta eseguendo un ciclo automatico. - * - DBX0.4 – Macchina In Ciclo Continuità: Segnale pulito sullo stato di funzionamento. 1->La macchina sta eseguendo un ciclo automatico con carico/scarico pezzo autonomo, 0->Altrimenti. - * - ----------------------------------------------------- */ - - byte mainData = RawInput[0]; - - int byteSignals = 0; - // bit 0 (poweron) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSignals += (1 << 0); - } - if ((mainData & (1 << 2)) == 1) - { - byteSignals += (1 << 1); - } - - // controllo il bit MAIN dello status - if ((mainData & (1 << 1)) == 1) - { - byteSignals += (1 << 3); - } - - // considero come MANUALE NON ciclo in continuo... - if ((mainData & (1 << 4)) == 0 || (mainData & (1 << 3)) == 1) - { - byteSignals += (1 << 4); - } - - // salvo! - B_input = byteSignals; - - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione dati: RawInput:{RawInput[0]} --> B_input: {B_input}"); - } - } - - #endregion - } }