mubeta Inserito: 28 marzo 2010 Segnala Share Inserito: 28 marzo 2010 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: FB1FUNCTION_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_BLOCKQuesta 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 More sharing options...
rguaresc Inserita: 30 marzo 2010 Segnala Share Inserita: 30 marzo 2010 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 More sharing options...
mubeta Inserita: 30 marzo 2010 Autore Segnala Share Inserita: 30 marzo 2010 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_BLOCKLa 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 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