Vai al contenuto
PLC Forum


Cpu Impazzita? - Tutte le prove fatte, mi portano a tale conclusione.


mubeta

Messaggi consigliati

L'applicazione che mi ha portato a questo post è poco importante, mentre sono rilevanti i risultati che ho trovato a seguito di prove varie fatte in seguito al probleva avuto.

Per inciso, ho avuto problemi nel calcolare la derivata di una grandezza e quindi sono arrivato alla prove che descrivo qui di seguito:

Cpu S7-314, completamente svuotata di tutto, con solo due FB, le due relative DB di istanza ed in OB1 il solo richiamo alla due FB che descriverò. Nulla di più, nulla d'altro; tempo ciclo medio di 1 ms.

Ecco la prima funzione: FB1

FUNCTION_BLOCK "fbkSine"

VAR
  ltc : TIME;
  lct : TIME;
  ct : TIME;
  t : TIME;
END_VAR
VAR_outPUT
  Result : REAL;
END_VAR
BEGIN

// last cycle time (ms)
lct := TIME_TCK();
IF lct >= ltc THEN
  ct := lct - ltc;
ELSE
  ct := t#2147483647ms - ltc + lct;
END_IF;
ltc := lct;

t := t + ct;
IF t >= t#200000ms THEN
  t := t#0ms;
END_IF;

Result := SIN(0.0001*3.141578*DINT_TO_REAL(TIME_TO_DINT(t))) * reaL#1000.0;             

OK := TRUE;
END_FUNCTION_BLOCK
Tale funzione genera ne più ne meno che una sinusoide, molto lenta, per poterne fare il relativo grafico. (Immagine allegata, curva nera). Fin qui tutto bene. Nella variabile di destinazione viene fuori la sinusoide e fine. Il problea viene dopo, con la funzione che segue, FB2, origine di tutti i miei problemi:
FUNCTION_BLOCK "fbkDerivate"

VAR_INPUT
  Value : REAL;
end_var
VAR
  ltc : TIME;
  lct : TIME;
  ct : TIME;
  LastValue : REAL;
  LastResult : REAL;
END_VAR
VAR_outPUT
  Result : REAL;
END_VAR
VAR_TEMP
  Ts : REAL;
end_var
BEGIN

// last cycle time (ms)
lct := TIME_TCK();
IF lct >= ltc THEN
  ct := lct - ltc;
ELSE
  ct := t#2147483647ms - ltc + lct;
END_IF;

Ts := DINT_TO_REAL(TIME_TO_DINT(ct));

IF Ts >= 1.0 THEN
  ltc := lct;
  Result := ((Value - LastValue) * real#1000.0) / Ts;
  LastValue := Value;
  LastResult := Result;
END_IF;

OK := TRUE;
END_FUNCTION_BLOCK

Questa funzione, molto vicina a cosa avevo programmato, non fa altro che calcolare la derivata di una curva, in relazione al vole istantaneo passato nel parametro di ingresso "Value".

Ho collegato il tutto alla prima funzione FB1, (tramite OB1), ed ecco che sul grafico si vede bene il mio problema originario: la derivata della curva in ingresso, ha continui ed anomali picchi o verso lo zero, od a valori pseudo-casuali.

(Notate che le due funzioni tengono conto del tempo, in relazione al Tick counter della CPU).

Ebbene, ho fatto moltissime prove, con molte varianti al codice che ho postato, ma nulla, il calcolo della derivata da stranissimi picchi. Gli stessi picchi li ottengo anche se semplicemente misuro la differenza tra i due valori reali: (Result := Value - LastValue) dà sempre dei picchi.

Ogni volta che ho provato ad imputare gli errori ai compilatori ed alle CPU mi sono sempre dovuto rimangare tutto ed osservare la bontà dei prodotti Siemens, ma questo invece mi sta facendo impazzire, e non ne trovo spiegazione logica.

Sembra che per una qualche ragione, Value e LastValue si trovino allo stesso valore, che, almeno in questo test, è praticamente impossibile.

Se non avete di meglio da fare, provate anche voi, che vi prenderà poco tempo e mi potrete dire cosa osservate, ammesso che non abbiate già una risposta.

mubeta.

Link al commento
Condividi su altri siti


Ho provato al plcsim e il grafico mi viene corretto.

Ho usato il driver MPI del pc adapter collegato al winccflexible via memoria del PC.

Se hai una connessione fisica per acquisire i dati della derivata e' normale che arrivino non in real time e sballino la curva.

Link al commento
Condividi su altri siti

Mi rendo conto che il post originario era scarno di informazioni. Giungevo alla conclusione che il problema fosse in CPU, proprio perché ero certo che il codice funzionasse. Anche io avevo preventivamente usato il PLCSIM;

Facendo ancora una serie di prove, ho trovato che, modificando il codice della FB2 come segue:

FUNCTION_BLOCK "fbkDerivate"

VAR_INPUT
  Value : REAL;
end_var
VAR
  ltc : TIME;
  lct : TIME;
  ct : TIME;
  LastValue : REAL;
  LastResult : REAL;
END_VAR
VAR_outPUT
  Result : REAL;
END_VAR
VAR_TEMP
  Ts : REAL;
end_var
BEGIN

// last cycle time (ms)
lct := TIME_TCK();
IF lct >= ltc THEN
  ct := lct - ltc;
ELSE
  ct := t#2147483647ms - ltc + lct;
END_IF;

Ts := DINT_TO_REAL(TIME_TO_DINT(ct));

IF Ts >= 1.0  AND Value <> LastValue THEN
  ltc := lct;
  Result := ((Value - LastValue) * real#1000.0) / Ts;
  LastValue := Value;
  LastResult := Result;
ELSE
  Result := LastResult;
END_IF;

OK := TRUE;
END_FUNCTION_BLOCK

La diffrenza stà nel fatto che verifico se "Value" e "LastValue" sono diverse tra loro e, qualora non lo siano, il risultato "Result" viene comunque riscritto con un valore di appoggio "LastResult". Così tutto funziona anche su questa CPU desueta.

Ho riportato il know-how sul progetto che mi interessava e sembra andare bene.

Forse ha qualche problema nel firmware con le variabili di istanza. (E' veramente vecchiotta).

mubeta.

Link al commento
Condividi su altri siti

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 account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...