Problemi con memorie ritentive PLC SlimLine MPS5054C110
Home › Forum › Controllori SlimLine e Netsyst (LogicLab) › Problemi con memorie ritentive PLC SlimLine MPS5054C110
Taggato: memorie a ritenzione
- Questo topic ha 4 risposte, 2 partecipanti ed è stato aggiornato l'ultima volta 13 ore, 30 minuti fa da
PLP.
-
AutorePost
-
Luglio 12, 2025 alle 12:26 pm #83403
PLP
PartecipanteFacendo delle prove ho notato che le variabili che ho utilizzato per registrare le ore di funzionamento di alcuni dispositivi, allo spegnimento e riavvio del PLC si azzerano, come mai?
La dichiarazione delle variabili in linguaggio ST che ho usato:
HMI_ORE_ASP1 AT %MW100.2048: INT; (* Word di registrazione ore funzionamento aspiratore 1*) HMI_ORE_ASP2 AT %MW100.2050: INT; (* Word di registrazione ore funzionamento aspiratore 2*) HMI_IMP_ORE_A1 AT %MW100.2052: INT:=3600; (* Word di impostazione ore max funzionamento aspiratore 1*) HMI_IMP_ORE_A2 AT %MW100.2054: INT:=3600; (* Word di impostazione ore max funzionamento aspiratore 1*) HMI_num_cest AT %MW100.2056: INT; (* Word di registrazione numero max di cestelli utilizzati *)
Luglio 14, 2025 alle 8:36 am #83408Sergio Bertana
Amministratore del forumIl backup dei dati è effettuato in una memoria FRAM che non necessita di batterie. Alla accensione viene eseguita una verifica sul CRC dei valori memorizzati allo spegnimento, se il controllo è in errore tutte la variabili sono azzerate e viene settata la variabile SysRestoreFault.
Se il controllo è corretto le variabili vengono valorizzate con i valori allo spegnimento poi viene eseguita la funzione che assegna alle variabili i valori di inizializzazione. Nel tuo caso vedo che hai inizializzato alcune variabili in area ritentiva, queste naturalmente assumeranno sempre il valore definito nella inizializzazione.
Il fatto che le variabili ritentive si azzerino è molto strano, per evitare che sia il programma a sporcarle, ti consiglio di realizzare un nuovo programma LogicLab con solo il programma MyProgram, poi definire le variabili ritentive così come hai indicato e da debug impostare valori casuali nelle variabili. Spegnere ed accendere il sistema e verificare se il valore viene mantenuto.
Nel caso siano azzerate puoi collegarti verificare da debug lo stato della variabile SysRestoreFault, ed eventualmente collegarti in telnet, eseguire il comando SysLog e postare il risultato del comando.
Luglio 14, 2025 alle 7:47 pm #83440PLP
PartecipanteLe memorie cosi dichiarate funzionano bene, è il “CounterUp” che ho usato che deve essere a ritenzione.
Ho fatto delle prove e ho assegnato all’oggetto CTU che mi serviva l’area di memoria DB100.2048 e il tutto funziona bene.
Luglio 15, 2025 alle 9:33 am #83467Sergio Bertana
Amministratore del forumColgo l’occasione della discussione per trattare lo spinoso argomento del rendere ritentivi i blocchi funzione. I FB utilizzano al loro interno svariate variabili e non è noto il loro impegno di memoria, quindi sconsiglio la loro allocazione in area indirizzabile come la DB100. Perchè dovendo definire gli indirizzi di allocazione non è possibile sapere a priori a che indirizzo allocare la variabile successiva alla allocazione del FB. Quindi se proprio si desidera rendere ritentivo un FB è preferibile definirlo in area automatica con l’attributo RETAIN.
Rendere retain un FB potrebbe nascondere insidie, chi sviluppa i FB solitamente non li struttura per essere tamponati, per esempio potrebbe alllocare al loro interno memoria rilocabile ed in questo caso il mantenere retain l’indirizzo di allocazione potrebbe portare a gravi errori di funzionamento del programma. Nel tuo caso quindi puoi allocare il tuo FB CTU in area automatica con l’attributo RETAIN.
Nel caso ti occorra accedere da Modbus il valore di conteggio, non utilizzare più il FB CTU ma alloca ad esempio in DB100.2048 una variabili UINT o UDINT e gestisci il conteggio da programma, ecco un esempio:
VAR Pulse : BOOL; (* Clock pulse *) Di00CPU AT %IX255.0 : BOOL; (* Digital input *) Counter AT %MD100.2048 : UDINT; (* Counter value *) END_VAR IF (Di00CPU <> Pulse) THEN Pulse:=Di00CPU; //Clock pulse IF (Di00CPU) THEN Counter:=Counter+1; END_IF; END_IF;
Luglio 15, 2025 alle 3:17 pm #83475PLP
PartecipanteGrazie dell’informazione, in effetti mi era sorto questo dubbio, ora ho modificato il codice secondo il tuo ultimo esempio, ecco il programma di test:
PROGRAM MyProgram
VAR
Start AT %IX255.0 : BOOL; (* Pulsante di marcia motore *)
Stop AT %IX255.1 : BOOL; (* Pulsante di stop motore *)
Km AT %QX255.0 : BOOL; (* Comando di avvio e stop motore *)
N_AVVII AT %MW100.2048 : INT; (* Numero di avvi motore *)
Reset AT %MX100.0 : BOOL;
Seg AT %MX100.1 : BOOL; (* segnalazione max numero avvii raggiunto*)
TP_Trig : R_TRIG;
END_VAR
Km:= (Start OR Km) AND NOT Stop;
TP_Trig(CLK := Km);
IF (TP_Trig.Q) THEN
N_AVVII := N_AVVII+1;
END_IF;
IF(N_AVVII >= 15)THEN
Seg:=TRUE;
END_IF;
IF(Reset= TRUE)THEN
N_AVVII:=0;
Seg:= FALSE;
END_IF;
cosi ho tutte le variabili sotto controllo.
-
AutorePost
- Devi essere connesso per rispondere a questo topic.