step-80 Inserito: 25 marzo 2019 Segnala Share Inserito: 25 marzo 2019 Buongiorno a tutti come da titolo, volevo sapere se qualcuno di voi ha eletto ST come linguaggio universale, usandolo anche con pura logica Booleana per esempio. Credo che ognuno di noi abbia il suo linguaggio preferito, al di là di quanto è effettivamente 'efficace' per fare ciò che ci siamo prefissati. Anzi, credo che ognuno di noi sia mentalmente 'predisposto' ad usare un linguaggio piuttosto che l'altro, il motivo non lo so spiegare. Io per esempio per quanto mi sforzi ad usare il Ladder, non riesco ad avere l'immediata idea di come si svolga il flusso. Non so se questo dipenda dal fatto che visivamente una operazione in ladder occupi più spazio dell'equivalente in ST ,ma comunque sia questo non mi aiuta. Detto questo, tempo fa consultando un manuale di ST del plc che stavo usando, sono incappato in questo: e cioè il tempo impiegato dalla cpu per eseguire la STESSA operazione in 2 linguaggi: IL(lista istruzioni) ed-appunto-ST. La differenza mi ha lasciato sconcertato: immaginavo una differenza sostanziale, ma qui si parla del 7-800% in più per eseguire la STESSA cosa. Mi chiedo a questo punto a che livelli di programmazione sia necessario arrivare perchè ciò rappresenti un problema. Voglio dire: su una macchinetta media che costruisco io(3-4 assi brushless + una 20ina di ev pneumatiche, circa 50-60 i/o in tutto) potrei vedere la differenza secondo voi scrivendo tutto in un linguaggio piuttosto che l'altro? Oppure a questi livelli ST gli fa il solletico? Se riesco, vorrei fare una prova: testare 2 program block che eseguono esattamente la stessa operazione(su un asse per esempio, diciamo una serie di posizionamenti in sequenza con qualche pausa in mezzo), e vedere che differenza in termini di tempo di scansione riscontrerei. Voi cosa ne pensate? P.s: vorrei evitare i discorsi del tipo che ST è meglio per fare certe cose e Ladder è meglio per fare altre cose😊 Link al commento Condividi su altri siti More sharing options...
pigroplc Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 Io faccio largo uso di ST e mi sono dato delle regole di sintassi e posizionamento del codice in modo da agevolare il debug e la visualizzazione on-line. La condizione di uguale la gestisco così: // Cumulativo delle condizioni che provocano l'arresto delle pompe Ok_pompe :=(NOT OverloadInverterMotorHydraulicPump AND NOT OverloadMotorCoolingOil AND NOT OverloadMotorCoolingFan AND NOT OverloadMotorPilotValve AND NOT OverloadMotorCoolingOil AND NOT OverloadMotorServiceValve AND NOT Inverter_Fault_HydrPump AND Powersupply24Vdc_inputPLC AND Powersupply24Vdc_outputPLC AND Powersupply24Vdc_outputPLC_actuators AND Powersupply24Vdc_maincontrolpanel AND Powersupply24Vdc_Sinamics AND Powersupply24Vdc_IM174 AND NOT rit_energy_saving.Q) OR boSimulazioneIO; La condizione di SET-RESET la gestisco così: IF TemperaturaOlioPrincipale/10 > iSetpointRaffreddamentoPrincipale_M01 AND SensorLeveLTankOil AND NOT Overloadmotorcoolingoil THEN START_Motorcooling := TRUE; END_IF; IF (TemperaturaOlioPrincipale/10 < iStopCoolingPrincipale_M01) OR ONsafetyrelaygeneralcycle OR ONSafetyRelayEmergency THEN START_Motorcooling := FALSE; END_IF; Notare bene che gli operandi sono su righe diverse per una visualizzazione chiara quanto la visualizzazione a contatti. Se si tratta di una cosa semplice allora metto tutto su una riga come per la condizione di RESET. Ovviamente qualora ci siano delle restrizioni sullo sviluppo software mi adeguo e scrivo a contatti, ma non mi piaceva in passato, non mi piace ora e non penso possa piacermi in futuro. Link al commento Condividi su altri siti More sharing options...
step-80 Inserita: 25 marzo 2019 Autore Segnala Share Inserita: 25 marzo 2019 (modificato) Yiogo: forse la mia domanda non era chiara. Io volevo sapere chi di voi fa uso di ST a prescindere dal compito. Cioè chi lo usa per tutto il programma , senza chiedersi se sarebbe stato piu semplice scrivere certe parti in altri linguaggi. PigroPlc: esattamente ciò che volevo sapere. Il codice che hai postato è il tipico compito che si eseguirebbe a contatti, ma che alcuni preferiscono scrivere in ST. Solitamente tendo ad usare costrutti CASE per molte cose. Mi aiutano ad avere la visione piu completa possibile del flusso macchina. Un esempio: //Servo Program K= (10*(NumeroAsse) + (i_wOpMode - 1)) //i_wOpMode: //0: NOT Enabled - Jog Available //1: Home //2: INC //3: ABS //4: PFSTART //...Fino a 499 per comando singolo asse //...... //1000: Sync Control Command - Advanced Mode ------------------------------------------------*) (***************************************************************************************) (*****************************_ENABLE_********************************************) IF i_xEn THEN IF NOT xExAct THEN (* If Loc_Ex_Act_X = FALSE it's the first entry *) wState := 10; xExAct := TRUE; END_IF; ELSE IF xExAct THEN wState := 1000; xExAct := FALSE; END_IF; END_IF; (**************************************************************************************) (*****************************_STATE_*********************************************) CASE wState OF 0: (* Not Enable *) xAxSVSTRq := FALSE; xRapidStop := FALSE; xAxCHGVRq := FALSE; xSpeedChgEn := FALSE; o_xActive := FALSE; o_xError := FALSE; o_xOpModeActive := FALSE; o_xOpModeDn := FALSE; o_wOpMode := 0; o_xSyncActive := FALSE; o_xSyncCtrlChgDn := FALSE; 10: (* Wait Start Servo Program Command *) o_xActive := TRUE; o_xOpModeActive := FALSE; o_xOpModeDn := FALSE; o_xSyncCtrlChgDn := FALSE; io_ServoCmd.dwSyncInitialParam := 0; (* Speed Change During Jog Command*) dwCHGVSpeedChange := io_ServoCmd.dwJogSpeed; (* Sync Ctrl Initial Position Parameter*) MOVE_E( NOT xSyncCtrlFirstStartDn , 1 , io_ServoCmd.dwSyncInitialParam ); IF NOT io_ServoCmd.xRapidStopCommand AND NOT io_ServoCmd.xStopCommand AND NOT io_ServoStatus.xStartAccept AND io_ServoStatus.xServoReady AND NOT io_ServoCmd.xForwardRotationJOG AND NOT io_ServoCmd.xReverseRotationJOG AND i_xStart THEN o_wOpMode := -1; (* OpMode Error *) IF (i_wOpMode > 0) AND (i_wOpMode < 499) THEN MOVE_E( (i_wOpMode = 1) , 0 , xSyncCtrlFirstStartDn ); wServoBlock := (10 * i_wAxNum) + (i_wOpMode - 1); (* Servo Program K= (10*(NumeroAsse) + (i_wOpMode - 1)) *) o_xOpModeActive := TRUE; o_wOpMode := i_wOpMode; wState := 20; ELSIF (i_wOpMode >= 1000) AND (i_wOpMode < 1999) THEN io_ServoCmd.xSyncControlStart := TRUE; (* Sync Control Command *) o_xOpModeActive := TRUE; o_wOpMode := i_wOpMode; wState := 200; END_IF; END_IF; 20: (* Servo Program Start Request *) xAxSVSTRq := TRUE; (* Wait Ax Busy *) IF io_ServoStatus.xStartAccept OR xMotionScanOn THEN wState := 30; END_IF; (* OpMode Change During Operation *) MOVE_E( o_wOpMode <>i_wOpMode , 900 , wState ); (* Check Stop Command *) MOVE_E( (io_ServoCmd.xRapidStopCommand OR io_ServoCmd.xStopCommand) , 600 , wState ); (* Error Detection *) MOVE_E( o_xError , 500 , wState ); 30: (* Servo Program Run *) (* Speed Change Servo Program Run *) dwCHGVSpeedChange := io_ServoCmd.dwSpeed; (* Wait Servo Program Done *) IF NOT io_ServoStatus.xStartAccept THEN o_xOpModeActive := FALSE; o_xOpModeDn := TRUE; wState := 100; END_IF; (* OpMode Change During Operation *) MOVE_E( o_wOpMode <>i_wOpMode , 900 , wState ); (* Check Stop Command *) MOVE_E( (io_ServoCmd.xRapidStopCommand OR io_ServoCmd.xStopCommand) , 600 , wState ); (* Error Detection *) MOVE_E( o_xError , 500 , wState ); 100: (* Servo Program Done - Wait For New Cycle *) IF NOT i_xStart THEN wState := 10; END_IF; (* Error Detection *) MOVE_E( o_xError , 500 , wState ); (************************************) (********* Sync Control ***********) (************************************) 200:(* Sync Control Check *) (* Sync Control Reset *) IF NOT i_xStart THEN io_ServoCmd.xSyncControlStart := FALSE; wState := 230; (* Wait Sync Control Active *) ELSIF io_ServoStatus.xSyncControlActive THEN xSyncCtrlFirstStartDn := TRUE; wState := 210; END_IF; (* Error Detection *) MOVE_E( o_xError , 500 , wState ); (* Check Stop Command *) MOVE_E( (io_ServoCmd.xRapidStopCommand OR io_ServoCmd.xStopCommand) , 400 , wState ); 210: (* Check Sync Control Change Value *) IF xMotionScanOn THEN dwPhaseOffset := io_ServoCmd.dwPhaseOffset; dwPhaseRem := ReminderDINT_FC((i_dwPhasePosition + dwPhaseOffset) ,io_ServoCmd.dwCamAxisLenghtPerCycle ); dwPhaseError := dwPhaseRem - io_ServoStatus.dwCamAxisCurrentValuePerCycle; IF dwPhaseError >= (io_ServoCmd.dwCamAxisLenghtPerCycle / 2)THEN dwPhaseError := dwPhaseError - io_ServoCmd.dwCamAxisLenghtPerCycle; ELSIF dwPhaseError <= -(io_ServoCmd.dwCamAxisLenghtPerCycle / 2) THEN dwPhaseError := dwPhaseError + io_ServoCmd.dwCamAxisLenghtPerCycle; END_IF; dwSyncControlChangeValue := dwPhaseError; wState := 220; END_IF; 220:(* Sync Control Active *) (* Sync Control Reset *) IF NOT i_xStart THEN io_ServoCmd.xSyncControlStart := FALSE; wState := 230; ELSE IF i_xSyncCtrlChgRq AND xMotionScanOn THEN (* Sync Control Change First Time *) IF NOT o_xSyncCtrlChgDn AND (dwSyncControlChangeValue <> 0) THEN io_ServoCmd.dwSyncControlChangeCommand := 4; io_ServoCmd.dwSyncControlChangeValue := dwSyncControlChangeValue; wState := 240;(* Sync Control Change Command Request *) (* Sync Control Change After First Sync Enable *) ELSIF o_xSyncCtrlChgDn AND (dwPhaseOffset <> io_ServoCmd.dwPhaseOffset) THEN io_ServoCmd.dwSyncControlChangeCommand := 4; io_ServoCmd.dwSyncControlChangeValue := io_ServoCmd.dwPhaseOffset - dwPhaseOffset ; o_xSyncCtrlChgDn := FALSE; dwPhaseOffset := io_ServoCmd.dwPhaseOffset; wState := 240;(* Sync Control Change Command Request *) ELSE o_xSyncCtrlChgDn := TRUE; END_IF; END_IF; END_IF; (* Error Detection *) MOVE_E( o_xError , 500 , wState ); (* Check Stop Command *) MOVE_E( (io_ServoCmd.xRapidStopCommand OR io_ServoCmd.xStopCommand) , 400 , wState ); 230: (* Sync Control NOT Active *) (* Wait Sync Control Active *) IF NOT io_ServoStatus.xSyncControlActive THEN wState := 10; END_IF; (* Error Detection *) MOVE_E( o_xError , 500 , wState ); (* Check Stop Command *) MOVE_E( (io_ServoCmd.xRapidStopCommand OR io_ServoCmd.xStopCommand) , 400 , wState ); 240: (* Sync Control Change Command Request *) io_ServoCmd.xSyncCtrlChgRq := xMotionScanOn ; IF io_ServoCmd.xSyncCtrlChgRq AND NOT io_ServoStatus.xSyncCtrlChgDn THEN wState := 250; END_IF; 250: (* Wait Sync Control Change Command Done *) (* Sync Control Reset *) IF NOT i_xStart THEN io_ServoCmd.xSyncControlStart := FALSE; io_ServoCmd.xSyncCtrlChgRq := FALSE; wState := 230; ELSIF io_ServoStatus.xSyncCtrlChgDn AND xMotionScanOn THEN io_ServoCmd.xSyncCtrlChgRq := FALSE; o_xSyncCtrlChgDn := TRUE; wState := 220; (* Sync Control Active *) END_IF; (* Error Detection *) MOVE_E( o_xError , 500 , wState ); (* Check Stop Command *) MOVE_E( (io_ServoCmd.xRapidStopCommand OR io_ServoCmd.xStopCommand) , 400 , wState ); 400: (* Check To Re-Stat Cycle *) io_ServoCmd.xSyncControlStart := FALSE; io_ServoCmd.xSyncCtrlChgRq := FALSE; IF NOT io_ServoStatus.xStartAccept AND NOT io_ServoStatus.xSyncControlActive THEN wState := 10; END_IF; 500: (* Axis Error *) io_ServoCmd.xSyncControlStart := FALSE; io_ServoCmd.xSyncCtrlChgRq := FALSE; o_xOpModeActive := FALSE; MOVE_E( NOT i_xStart AND NOT o_xError , 10 , wState ); 900: (* OpMode Change During Execution *) o_xOpModeActive := FALSE; xAxSVSTRq := FALSE; xRapidStop := TRUE; wState := 910; MOVE_E( (NOT io_ServoStatus.xStartAccept OR o_xError) AND xMotionScanOn , 910 , wState ); 910: (* Reset Rapid Stop Command *) xRapidStop := FALSE; MOVE_E( NOT io_ServoCmd.xRapidStopCommand AND NOT i_xStart , 10 , wState ); 600: (* Wait For Re-start Cycle *) MOVE_E( NOT i_xStart , 10 , wState ); 1000: (* Exit Action: Rapid Stop Command *) xRapidStop := TRUE; wState := 1010; 1010: (* Exit Action: Wait Axis Not Busy *) IF NOT io_ServoStatus.xStartAccept AND xMotionScanOn THEN xRapidStop := FALSE; wState := 1020; END_IF; 1020: (* Exit Action: Reset Servo Command *) o_xActive := FALSE; io_ServoCmd.xSyncControlStart := FALSE; io_ServoCmd.xServoOffCommand := FALSE; io_ServoCmd.xRapidStopCommand := FALSE; wState := 0; END_CASE; (* Change State Check *) IF wState <> wPrevState THEN wPrevState := wState; wScanCnt := 0; END_IF; (* FB Active *) IF o_xActive THEN (* First Sync Reset *) MOVE_E( i_xSyncCtrlFirstStartRst , 0 , xSyncCtrlFirstStartDn ); (* Speed Change Enable*) xSpeedChgEn := (o_xOpModeActive AND o_wOpMode > 1 AND o_wOpMode < 1000) OR (NOT o_xOpModeActive AND (io_ServoCmd.xForwardRotationJOG OR io_ServoCmd.xReverseRotationJOG)); IF xSpeedChgEn THEN xAxCHGVRq := dwCHGVSpeedChange <> dwCHGVSpeedChangeAux; dwCHGVSpeedChangeAux := dwCHGVSpeedChange; END_IF; (* ServoCmd - Axis Reset *) io_ServoCmd.xErrorReset := i_xRst; (* ServoCmd - Rapid Stop Command *) io_ServoCmd.xRapidStopCommand := xRapidStop OR i_xRapidStop; (* ServoCmd - Servo Off Command *) io_ServoCmd.xServoOffCommand := i_xServoOffRq; (* ServoStatus - Ax Error *) o_xError := io_ServoStatus.xErrorDetection OR io_ServoStatus.xServoErrorDetection; (* ServoStatus - Syn Control Active *) o_xSyncActive := io_ServoStatus.xSyncControlActive; (* First Sync Done *) o_xSyncCtrlFirstStartDn := xSyncCtrlFirstStartDn; (* Cycle Counter - 200 ms Delay *) wMinScanTime := MAXIMUM( 1 ,SD524); wScanNum := 200/wMinScanTime; INC(wScanCnt < 1000,wScanCnt); xMotionScanOn := WORD_TO_INT(wScanCnt) > wScanNum; END_IF; (**************************************************************************************) (*****************************_FB_CALL_*******************************************) (* Servo Program Command *) DP_SVST( xAxSVSTRq , i_wCpuNum, i_sAx , wServoBlock, aAxVSTCompleteDevice,wAxSVSTCompleteStatus); xAxSVSTRq := FALSE; (* Speed Change Command *) DP_CHGV( xAxCHGVRq , i_wCpuNum , i_sAx , dwCHGVSpeedChange , aAxCHGVCompleteDevice , wAxCHGVCompleteStatus); xAxCHGVRq := FALSE; Questa è una FB di gestione asse che mi sono creato. Gestisce Jog, posizionamenti assoluti, relativi, sincronismi..oltre a gestire errori eventuali dell'asse . Farla in Ladder sarebbe stato senza dubbio possibile, ma notevolmente più dispersivo. Modificato: 25 marzo 2019 da step-80 Link al commento Condividi su altri siti More sharing options...
batta Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 Io trovo una scelta da masochisti fare tutto il programma in un unico linguaggio. Per quanto riguarda i tempi di esecuzione, penso dipenda non tanto dal linguaggio, ma da come il PLC interpreta ogni linguaggio. Per esempio, con S7-300 tutto viene sempre tradotto in AWL e, i programmi scritti in SCL, richiedono molte più istruzioni per svolgere lo stesso compito scritto direttamente in AWL. Questo, ovviamente, incide sui tempi di esecuzione. Con le CPU 1500, il compilatore SCL (ST) non converte in AWL (che non corrisponde esattamente a IL), ma genera il suo compilato, molto più efficiente rispetto a quanto fatto con S7-300. Poi, a seconda del PLC ci saranno sicuramente differenze di tempi di esecuzione di un linguaggio rispetto ad un altro, ma le differenze dell'esempio le trovo alquanto inverosimili. Oppure potranno essere reali per un particolare PLC, ma non da assumere come regole generali. Link al commento Condividi su altri siti More sharing options...
batta Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 Quote // Cumulativo delle condizioni che provocano l'arresto delle pompe Ok_pompe :=(NOT OverloadInverterMotorHydraulicPump AND NOT OverloadMotorCoolingOil AND NOT OverloadMotorCoolingFan AND NOT OverloadMotorPilotValve AND NOT OverloadMotorCoolingOil AND NOT OverloadMotorServiceValve AND NOT Inverter_Fault_HydrPump AND Powersupply24Vdc_inputPLC AND Powersupply24Vdc_outputPLC AND Powersupply24Vdc_outputPLC_actuators AND Powersupply24Vdc_maincontrolpanel AND Powersupply24Vdc_Sinamics AND Powersupply24Vdc_IM174 AND NOT rit_energy_saving.Q) OR boSimulazioneIO; Anch'io quando mi trovo a scrivere in ST cose di questo tipo vado a capo ogni riga, per rendere tutto più leggibile. Con una sola differenza rispetto all'esempio di Pigroplc: gli operatori AND e OR li metto a capo: // Cumulativo delle condizioni che provocano l'arresto delle pompe Ok_pompe :=(NOT OverloadInverterMotorHydraulicPump AND NOT OverloadMotorCoolingOil AND NOT OverloadMotorCoolingFan AND NOT OverloadMotorPilotValve AND NOT OverloadMotorCoolingOil AND NOT OverloadMotorServiceValve AND NOT Inverter_Fault_HydrPump AND Powersupply24Vdc_inputPLC AND Powersupply24Vdc_outputPLC AND Powersupply24Vdc_outputPLC_actuators AND Powersupply24Vdc_maincontrolpanel AND Powersupply24Vdc_Sinamics AND Powersupply24Vdc_IM174 AND NOT rit_energy_saving.Q) OR boSimulazioneIO; Ma è solo una questione di abitudini. Link al commento Condividi su altri siti More sharing options...
Roberto Gioachin Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 6 ore fa, step-80 scrisse: ma qui si parla del 7-800% in più per eseguire la STESSA cosa A parte che una differenza del genere è già strana, ma questo differisce molto da costruttore a costruttore. Gli ambienti di sviluppo oggi compilano tutto quello che viene editato in un unico codice riconosciuto dalla CPU, questo significa che anche scrivendo in linguaggi diversi quello che entra realmente nel plc potrebbe essere la stessa cosa. 2 ore fa, step-80 scrisse: Farla in Ladder sarebbe stato senza dubbio possibile, ma notevolmente più dispersivo. Anche questo è molto discutibile, non è assolutamente detto che una volta compilato un programma sequenziale di questo tipo sia più "leggero" rispetto ad altri linguaggi, anche questo può variare molto da costruttore a costruttore. Facciamo un esempio: la compilazione di quanto hai rappresentato comporta al codice plc di eseguire una serie di comparazioni per verificare il codice "CASE" attivo ed eseguire quanto riferito a quel codice; alcuni costruttori hanno istruzioni specifiche per eseguire le stesse operazioni (ma anche più complesse se serve) utilizzando il linguaggio SFC, e questo linguaggio utilizza dei BIT di passo, non ha quindi bisogno di fare comparazioni, riducendo il tempo di esecuzione, se poi si considera che ogni passo non attivo diventa un salto di programma si capisce come il tempo di esecuzione diminuisca ancora di più. Quindi direi che le tue considerazioni possono essere corrette per un costruttore ma non per un altro. Link al commento Condividi su altri siti More sharing options...
step-80 Inserita: 25 marzo 2019 Autore Segnala Share Inserita: 25 marzo 2019 1 ora fa, Roberto Gioachin scrisse: A parte che una differenza del genere è già strana Lo screen inviato arriva direttamente da un manuale Mitsubishi, per la precisione il manuale Structured Text per serie L. Anche a me sembra tanta roba, al punto da spingermi ad aprire la discussione. Dico la verità: ho 'barato' perchè speravo che scrivendo in una sezione più generica il post avrebbe avuto più visibilità. 1 ora fa, Roberto Gioachin scrisse: Anche questo è molto discutibile, non è assolutamente detto che una volta compilato un programma sequenziale di questo tipo sia più "leggero" rispetto ad altri linguaggi, anche questo può variare molto da costruttore a costruttore. Aspetta, forse mi sono espresso male. Per me iil termine 'dispersivo' si riferisce solo ed esclusivamente al contesto grafico. Quando vedo una cosa del genere CASE wState OF 0: fai questo; 10; fai quest'altro; 20: alza pippo ...ecc Con un colpo d'occhio capisco perfettamente cosa succede quando la mia variabile di stato assume valore 0,10,20 ecc. In ladder(ma è sicuramente un mio limite) mi ci vuole di più. Questo in fase di stesura ma soprattutto in fase di debug. 2 ore fa, batta scrisse: Per esempio, con S7-300 tutto viene sempre tradotto in AWL e, i programmi scritti in SCL, richiedono molte più istruzioni per svolgere lo stesso compito scritto direttamente in AWL. Batta il manuale a cui faccio riferimento è della serie L Mitsubishi, paragonabile come fascia al 300. A questo punto o i jap si sono tenuti come al solito dalla parte della ragione(anche se cifre cosi accurate mi fanno pensare abbiano eseguito dei test approfonditi) oppure...non saprei. Riporto un altra pagina dove si prendono in considerazione altri costrutti: Link al commento Condividi su altri siti More sharing options...
lelos Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 Un programma semplice scritto in ST (poche righe) è più "pesante" di uno scritto in ladder e occupa più memoria. Questo vale per Mitsubishi , siemens non lo so. Link al commento Condividi su altri siti More sharing options...
ifachsoftware Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 (modificato) Ogni linguaggio ha un suo perchè , personalmente utilizzo Ladder per tutte le logiche Booleane , St per tutto quello che sono formule e calcoli. Parlando di Siemens , col nuovo TIA Portal ho trovato molto comodo partire con un programma in Ladder , dove posso inserire dei rami in ST. Facendo cosi' la parte booleana la scrivo in Ladder , il resto in St. Non conosco le differenze di tempi di esecuzione , ma ritengo che con le potenze di calcolo dei PLC attuali e della complessità crescente dei programmi sia una priorità guardare innanzitutto alla leggibilità del codice prima ancora di risparmiare qualche nanosecondo per scrivere delle istruzioni (a meno che non strettamente necessario , in quel caso rimane sempre l'AWL ....). Comunque con Siemens ci sono delle istruzioni per misurare i tempi ciclo ; per sfizio appena avrò del tempo faro' delle prove... Modificato: 25 marzo 2019 da ifachsoftware Link al commento Condividi su altri siti More sharing options...
pigroplc Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 4 ore fa, batta scrisse: Ma è solo una questione di abitudini. Eh si Batta. Devo dire che anche la tua soluzione risulta molto leggibile. Mi riservo di fare delle prove. Quello che conta è la facilità di comprensione quando si mette in visualizzazione dinamica per fare debug. L'editor di Simotion a contatti è a dir poco penoso rispetto all'editor del TIA, già io propendo per l'ST, figuriamoci su Simotion....... Quando la logica booleana si complica con più rami, tengo separate le singole condizioni racchiuse da parentesi, male che vada metto dei flag cumulativi. In fondo anche a contatti vale la pena di creare flag cumulativi piuttosto che complicare le cose creando mostri di incomprensione che necessiterebbero di un video bislungo. 37 minuti fa, ifachsoftware scrisse: ma ritengo che con le potenze di calcolo dei PLC attuali e della complessità crescente dei programmi sia una priorità guardare innanzitutto alla leggibilità del codice prima ancora di risparmiare qualche nanosecondo abbiamo creato linee di produzione con dei pedalò che giravano a 100 msec .... e parliamo di 35 anni fa! Si adottava addirittura la soluzione di utilizzare i micro switch a doppio contatto (uno NO che andava al plc come input da gestire nella logica e l'altro NC che interrompeva il movimento) altrimenti il pezzo si fermava con tolleranze mostruose. Adesso devi mettere le ganasce alla cpu per farla girare a 4 msec. 😁 Concordo sulla LEGGIBILITA', il resto è un di più. Link al commento Condividi su altri siti More sharing options...
pigroplc Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 6 ore fa, step-80 scrisse: esattamente ciò che volevo sapere. Il codice che hai postato è il tipico compito che si eseguirebbe a contatti, ma che alcuni preferiscono scrivere in ST Step-80, il CASE io lo uso solamente per le catene sequenziali, è la morte sua! Qualora la catena sequenziale abbia la necessità di sdoppiarsi non faccio altro che impostare altri indici di CASE esterni che al termine dello svolgimento retituiscono un flag di catena sequenziale conclusa. Il flag viene quindi interrogato nella catena sequenziale principale. Qualche anno fa facevo anche qualcosa di simile qui sotto esposto perché mi sembrava di evidenziare lo stato dell'uscita ma è durata poco, ho standardizzato il sistema postato in precedenza. Si è rivelato un inutile orpello a mio avviso. IF boAuxEVPressureON AND NOT EmergencyStop THEN AuxEVPressureON:= TRUE; ELSE AuxEVPressureON:= FALSE; END_IF; Link al commento Condividi su altri siti More sharing options...
Marco Fornaciari Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 Per esperienza dal 1985, le prestazioni e l'uso di memoria dei linguaggi dipende dal tipo di PLC e dalla sua architettura interna, processore compreso. Di Siemens 300 e 400 sappiamo tutti che il modo migliore di usare AWL. Il "letterale" (odierno ST) Telemecanique e Modicon ante 1990 occupava 1/3 di memoria e 1/5 di tempo di scansione: e lì mi sono sbizzarito allo spasimo. ST di Omron CX occupa 3 volte la stessa memoria e vale la pena usarlo solo per i calcoli, ma occhio alle troppe parentesi. I linguaggi ST di altri PLC non li utilizzo, anche perchè i clienti non vogliono che venga utilizzato: i miei sono clienti utenti finali con manutenzione interna che vuole l'accesso. Va da se che in abbinamento ai linguaggi bisogna anche fare anche buon uso di: task, subroutine, e blocchi funzione. Nel secolo scorso con l'uso appropriato in combinazione ho portato programmi da oltre 70 ms a 6, oppure forzato la scansione generale a 50 ms, ma con richiami di alcune task ogni 2 ms (Telemecanique e Siemen 115 CPU 945). Con i PLC di ultima generazione il problema velocità normalmente non si presenta, ma c'è il probelma di semplicità nell'edizione e nella comprensione nel tempo di un programma. Poi è inutile utilizzare un PLC nato per il Motion per far funzionare una impastatrice, ovvero uno per controllo di processo per una confezionatrice. Link al commento Condividi su altri siti More sharing options...
Nicola Carlotto Inserita: 25 marzo 2019 Segnala Share Inserita: 25 marzo 2019 (modificato) se uno proviene dalla pura elettromeccanica difficilmente usa ST, se uno proviene dalla pura informatica difficilmente usa il LADDER, Ciao Modificato: 25 marzo 2019 da Nicola Carlotto Link al commento Condividi su altri siti More sharing options...
pigroplc Inserita: 26 marzo 2019 Segnala Share Inserita: 26 marzo 2019 9 ore fa, Nicola Carlotto scrisse: se uno proviene dalla pura elettromeccanica difficilmente usa ST, se uno proviene dalla pura informatica difficilmente usa il LADDER pensa che io ho fatto meccanica ..... 😁😁😁 per me è stato un trauma Link al commento Condividi su altri siti More sharing options...
step-80 Inserita: 26 marzo 2019 Autore Segnala Share Inserita: 26 marzo 2019 Pensa che io non sono ne informatico ne elettrico, eppure preferisco St Link al commento Condividi su altri siti More sharing options...
batta Inserita: 26 marzo 2019 Segnala Share Inserita: 26 marzo 2019 Quote Batta il manuale a cui faccio riferimento è della serie L Mitsubishi, paragonabile come fascia al 300. A questo punto o i jap si sono tenuti come al solito dalla parte della ragione(anche se cifre cosi accurate mi fanno pensare abbiano eseguito dei test approfonditi) oppure...non saprei. Se i tempi riportati dal manuale Mitsubishi sono reali, significa una sola cosa: il Mitsubishi gestisce molto male il testo strutturato. Poi, a dirla tutta, io non sono d'accordo con il conteggio delle istruzioni riportato nelle tabelle. Seguiamo il primo esempio, che è il più semplice. Nella tabella scrivono che IF X0 THEN D0 := 100; END_IF; equivale a 7 passi, mentre LD X0 MOVE K100 D0 sono solo 3 passi. In entrambi i casi significa: - leggere lo stato di X0 - controllare se è vero o falso - se è vero: - caricare la costante 100 - scrivere il valore nella variabile D0 Come riescano a leggere 7 passi nel primo caso e 3 nel secondo, proprio non lo capisco. Il lavoro che dovrà fare il processore, se il compilatore lavora come si deve, è esattamente lo stesso. E poi, anche ammesso che il rapporto istruzioni sia 7/3, non si spiega lo stesso come il tempo di esecuzione diventi 12/1. Ripeto, l'unica spiegazione che posso trovare è una pessima gestione del testo strutturato. Link al commento Condividi su altri siti More sharing options...
step-80 Inserita: 26 marzo 2019 Autore Segnala Share Inserita: 26 marzo 2019 A dire il vero, questo è quello che viene generato dal compilatore. Non sono ne 3 passi ne 7. Questo invece quanto generato facendo la stessa cosa in ladder E anche vero che la prima immagine si può tradurre semplicemente: che diventa perfettamente uguale al ladder. Link al commento Condividi su altri siti More sharing options...
Roberto Gioachin Inserita: 26 marzo 2019 Segnala Share Inserita: 26 marzo 2019 (modificato) Attenzione, le due espressioni non sono la stessa cosa, per fare un confronto si devono utilizzare espressioni analoghe A parte il fatto che, come dice batta, l'ST è gestito male se compila in quel modo, chi ha realizzato il software avrà avuto le sue ragioni ma usare salti di programma per queste istruzioni mi sembra un eccesso. Detto questo, nel primo esempio si sono fatte delle impostazioni, sul secondo una assegnazione. Prova in ST a scrivere M1 = M0, vedrai che la compilazione è molto diversa. Io capisco che il plc ha tanta memoria ed un elevata velocità di elaborazione, ma non serve buttare via spazio in questo modo. Io sono dell'opinione (e non solo io) che quando un programma inizia troppo spesso con "IF" non si è fatto un buon lavoro. Vedo adesso che il terzo esempio è proprio quello che volevo dire io Modificato: 26 marzo 2019 da Roberto Gioachin Link al commento Condividi su altri siti More sharing options...
step-80 Inserita: 26 marzo 2019 Autore Segnala Share Inserita: 26 marzo 2019 @Roberto Gioachin io ho cominciato a programmare in un periodo recente, per cui non ero abituato a certe accortezze che permettono di ottimizzare le risorse. Ciò non toglie che scrivo e rompo le scatole perchè voglio imparare, avendo la fortuna di poterlo fare da Voi che siete Professionisti. Non mi è mai passato per la mente di usare bit al posto di word per sprecare meno risorse, ma da quando ho scoperto(grazie a voi) che il compilatore ed il tempo di scansione ringraziano cerco di stare attento a ciò che uso. Non sapevo nemmeno che ST, ladder, SFC ecc vengono tradotti tutti nel medesimo listato...da quando l'ho scoperto ho cercato di imparare a tradurre, vado a vedermi cosa 'digerisce' il mio plc del minestrone che gli scrivo e cerco di ottimizzare. Certo questo se si tratta di macchine complesse, se sono 10 righe non sto li a sbattermi tanto. Questa del programma che inizia troppo spesso con IF è un'altra perla che non conoscevo; starò attento anche a come uso i costrutti visto che , se usati in modo improprio, portano via un sacco di risorse. Che ST di Mitsubishi sia gestito male...qui non posso pronunciarmi. C'è da dire che uso una versione di software (GX Works2) che è palesemente superata , ormai è già qualche anno che è uscito il 3 ma non l'ho mai usato(anche perchè, solito mistero giapponese, lo puoi usare solo con determinati tipi di cpu che io non uso). Ringrazio comunque tutti per il contributo. Link al commento Condividi su altri siti More sharing options...
Roberto Gioachin Inserita: 26 marzo 2019 Segnala Share Inserita: 26 marzo 2019 Il motivo per cui dico che il compilatore a me sembra troppo dispersivo è perché mi aspetterei questo: Lascia perdere i primi 17 passi che si riferiscono alla firma digitale dell'intero programma, lascia perdere anche il passo 22 che è un END e viene messo alla fine dell'intero programma, rimangono 4 passi. Questo mi aspetterei. Comunque sia si tratta di istruzioni di impostazione (Set e Reset), scritta così è inutile nel 90 percento dei casi, meglio un istruzione di assegnazione. Se poi consideri che le istruzioni di Set e Reset sono fra i maggiori accusati quando si ha un programma che si ferma in maniera inaspettata, beh… io direi di utilizzarli solamente dove servono. Link al commento Condividi su altri siti More sharing options...
step-80 Inserita: 26 marzo 2019 Autore Segnala Share Inserita: 26 marzo 2019 13 minuti fa, Roberto Gioachin scrisse: Se poi consideri che le istruzioni di Set e Reset sono fra i maggiori accusati quando si ha un programma che si ferma in maniera inaspettata, beh… io direi di utilizzarli solamente dove servono. Se ho capito bene, preferisci usare istruzioni di assegnazione (OUT) piuttosto che impostazione? E impostare come fai? autoritenute? Link al commento Condividi su altri siti More sharing options...
Marco Fornaciari Inserita: 26 marzo 2019 Segnala Share Inserita: 26 marzo 2019 (modificato) Esempio di marcia arresto Variabili bool utilizzate Ingresso P_marcia = cablato NA Ingresso P_arresto = cablato NC uscita C_Motore C_Motore:= (P_marcia OR C_Motore) AND P_arresto Semplice! Modificato: 26 marzo 2019 da Marco Fornaciari invio errat Link al commento Condividi su altri siti More sharing options...
Marco Fornaciari Inserita: 26 marzo 2019 Segnala Share Inserita: 26 marzo 2019 Scrivere in ST presuppone dimestichezza con alcune basilari regole matematiche. Tra l'altro in diversi PLC l'uso delle istruzioni inizianti con IF non permette i fronti di salita e discesa delle variabili di uscita booleane, spesso per avere i fronti bisogna scivere: IF pollo Then SET uovo END IF uovo:= uovo // serve per avere i fronti. Poi se uno si vuole divertire Mela:= ((gatto * cane) >= (mucca / cavallo * pera)) AND martello (porta OR cipolla AND carota) AND ( (cipolla ANDWORD 6298) / 25) AND (pippo (Pluto)[123] <> Mario (luigi)[123]) ecc. ecc. alla fine c'erano circa 200 caretteri per dare il consenso generale ad un dosaggio di ingredienti. Pare non abbia senso, ma l'ho fatto, va da se c'erano anche: un cablaggio e una struttura di ricetta in sistonia con queste istruzioni create apposta per lasciare il programma sprotetto (come da capitolato) ma di fatto incomprensibile al 99,99 % dei programmatori, anche perchè dietro c'era la ricetta impostata sul PC e gestita da una sezione scritta in C e totalmente indicizzata. Per la cronaca, le variabili: gatto, cane, mucca, cavallo, pera, e cipolla, sono ingressi e uscite digitali che indicano lo stato dell'impianto. Solo in due sapevamo il significato. Link al commento Condividi su altri siti More sharing options...
Roberto Gioachin Inserita: 27 marzo 2019 Segnala Share Inserita: 27 marzo 2019 11 ore fa, step-80 scrisse: Se ho capito bene, preferisci usare istruzioni di assegnazione (OUT) piuttosto che impostazione? E impostare come fai? autoritenute? Non ho mai detto che non uso le impostazioni, ma le uso solo se servono e sto ben attento. 9 ore fa, Marco Fornaciari scrisse: C_Motore:= (P_marcia OR C_Motore) AND P_arresto Questo è il modo giusto. Più affidabile e meno impegnativo per il plc. Link al commento Condividi su altri siti More sharing options...
step-80 Inserita: 27 marzo 2019 Autore Segnala Share Inserita: 27 marzo 2019 (modificato) 9 ore fa, Marco Fornaciari scrisse: C_Motore:= (P_marcia OR C_Motore) AND P_arresto Sto ancora aspettando che mi capiti un problema del genere, dove ho 1 uscita motore, 1 pulsante di start ed 1 di stop. Ho provato anche questa strada (quindi niente SET e niente RST) sia in Ladder che in ST, è vero hai il vantaggio che la tua uscita è scritta in un posto solo ed hai chiare davanti le condizioni per le quali deve attivarsi e disattivarsi. Ma se le condizioni sono date da vari altri blocchi, i quali possono presentare diverse modalità operative ognuna delle quali deve poter scrivere su quell'uscita ..per quanto si tenti di rimanere puliti ed ordinati l'unica salvezza rimane commentare anche quello che li per li si ritiene superfluo secondo me. Commentare, commentare ed ancora commentare. Parlo per me sia chiaro. Non ho più la memoria che avevo 20 anni fa , a volte mi vengono idee che se non metto giù subito scritte da qualche parte svaniscono in fretta, sormontate da quella miriade di 'lampadine' che ci si accendono e spengono in testa continuamente(bit😃). 8 ore fa, Marco Fornaciari scrisse: uovo:= uovo // serve per avere i fronti. Qui non ci sono arrivato. Se fai SET uovo, uovo assume stato 1. Poi assegni lo stato di uovo(che dovrebbe essere 1) ad uovo..il quale dovrebbe rimanere ad 1. Cosa mi sono perso? Modificato: 27 marzo 2019 da step-80 Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
Crea un account o accedi per commentare
Devi essere un utente per poter lasciare un commento
Crea un account
Registrati per un nuovo account nella nostra comunità. è facile!
Registra un nuovo accountAccedi
Hai già un account? Accedi qui.
Accedi ora