Vai al contenuto
PLC Forum


Ottimizzazione PID


Project75

Messaggi consigliati

Quote

anche se parliamo di due grandezze completamente diverse

Appunto, parliamo di due grandezze completamente diverse.

Non puoi pretendere che un flusso ed una temperatura si comportino nello stesso modo.
A questo punto, se vuoi rendere la lettura ancora più stabile, filtra il valore da visualizzare sul display.
Io sono sempre dell'idea che sia un'operazione inutile, perché il valore mi sembra già sufficientemente stabile, e perché non andrai a migliorare realmente la stabilità del flusso, ma solo il valore visualizzato.

Poi, anche se qualcuno dice che è sbagliato filtrare il segnale in ingresso al PID, io non sono di quest'idea, soprattutto se il processo è relativamente lento e si dà priorità alla stabilità piuttosto che alla rapidità di risposta.

Una cosa è un PID per il posizionamento di un asse (e qui di filtri neanche a parlarne), altra regolare una portata.
Ovviamente, bisogna valutare i parametri del PID e l'entità del filtro.

Link al commento
Condividi su altri siti


  • Risposte 73
  • Created
  • Ultima risposta

Top Posters In This Topic

  • Project75

    31

  • Livio Orsini

    16

  • incus

    13

  • batta

    11

Top Posters In This Topic

Posted Images

35 minuti fa, batta scrisse:

Poi, anche se qualcuno dice che è sbagliato filtrare il segnale in ingresso al PID, io non sono di quest'idea, soprattutto se il processo è relativamente lento e si dà priorità alla stabilità piuttosto che alla rapidità di risposta

 

Se il regolatore è ben ottimizzato e il sistema ben progettato, non hai bisogno di filtrare l'ingresso per stabilizzare il processo.

Filtrando l'ingresso non lo stabilizzi, mascheri la variazione che è una cosa differente.

 

Differente è il ragionamento se non si tratta di variazioni reali ma di rumore del trasduttore.

Un esempio classico è l'integratore posto all'ingresso di tachimetrica dei convertitori analogici.

Si deve metterlo per abbattere il ripple della tachimetrica. 

Però bisogna considerare le differenti frequenze: quella del rumore è molto maggiore della massima frequenza della banda di risposta dell'azionamento.

I sistemi reazionati hanno tutti delle oscillazioni, è un fatto fisiologico.

In alcuni sistemi sono avvertibili "ad occhio" in altri sono solo misurabili con strumentazione adeguata.

Quello che a mio parere è sbagliato è "truccare" la misura per fare apparire un sistema più stabile.

Un tempo, ad esempio, si usava costruire dei "ballerini" molto inerti così che sembravano inchiodati al centro della corsa. Però misurando la tensione del materiale si registravano variazioni anche notevoli. Un ballerino che oscilla un poco attorno al suo centro sembra meno stabile, ma la tensione sul materiale è praticamente costante.

Costruire un ballerino ad elevata inerzia è assimilabile ad un volano, è come mettere un integratore, che è un filtro passa basso, sull'ingresso di reazione.

 

Link al commento
Condividi su altri siti

il 7/7/2018 at 19:42 , incus scrisse:

Anche io ignoro il motivo per cui tu, @Project75, debba filtrare l'ingresso analogico.

Comunque sia, se non hai dimistichezza con l'scl puoi farlo anche in kop...in pratica: col fronte di salita di un clock1hz muovi nel seguente ordine

Valore9 nel valore10

Valore8 nel valore9

Valore7 nel valore8

Cosi fino a 

Valore1 nel valore2

NuovoValore nel valore1

 

Cosi, campionando ogni secondo,hai dieci variabili con le ultime dieci letture

 

Poi non devi fare altro che sommare tutti e 10 i valori e dividerli per dieci

 

Questo è il concetto di base, numero di campionamenti e frequenza di campionamento sta a te deciderli

 

Se vuoi il sorgente scl posso inviartelo lunedi

Ciao incus se ti è possibile mi puoi mandare il sorgente. Grazie mille

il 7/7/2018 at 19:42 , incus scrisse:

Anche io ignoro il motivo per cui tu, @Project75, debba filtrare l'ingresso analogico.

Comunque sia, se non hai dimistichezza con l'scl puoi farlo anche in kop...in pratica: col fronte di salita di un clock1hz muovi nel seguente ordine

Valore9 nel valore10

Valore8 nel valore9

Valore7 nel valore8

Cosi fino a 

Valore1 nel valore2

NuovoValore nel valore1

 

Cosi, campionando ogni secondo,hai dieci variabili con le ultime dieci letture

 

Poi non devi fare altro che sommare tutti e 10 i valori e dividerli per dieci

 

Questo è il concetto di base, numero di campionamenti e frequenza di campionamento sta a te deciderli

 

Se vuoi il sorgente scl posso inviartelo lunedi

Ciao incus se ti è possibile mi puoi mandare il sorgente. Grazie mille

Link al commento
Condividi su altri siti

Quote

Se il regolatore è ben ottimizzato e il sistema ben progettato, non hai bisogno di filtrare l'ingresso per stabilizzare il processo.

Filtrando l'ingresso non lo stabilizzi, mascheri la variazione che è una cosa differente. 

 

Differente è il ragionamento se non si tratta di variazioni reali ma di rumore del trasduttore.

Appunto, qui siamo nel secondo caso, con segnale che varia anche con riferimento fisso della pompa. Non si tratta quindi di filtrare instabilità creata dal PID stesso, ma di dare in pasto al PID un segnale più pulito, che non risenta di pulsazioni causate da turbolenze o da rumore in genere. Con frequenze diverse, ma è esattamente come filtrare il segnale della tachimetrica per eliminare il ripple.

 

Project75, perché ti sei fissato con il FIFO? Perché non provi prima a vedere il risultato che ottieni con la semplice formuletta

Out = Out + (In - Out) / k

Ti assicuro che funziona.

 

E, se vuoi proprio fare una media aritmetica di N valori, piuttosto che un FIFO che ad ogni ciclo sposta tutte le variabili, potresti procedere come segue:

- crea un array di N variabili (per esempio 10 variabili, da miaVar[0] a miaVar[9]).

- utilizza un indice "id" (per seguire l'esempio, anche l'indice deve assumere valori da 0 a 9)

- ad ogni campionamento, scrivi il dato nella variabile puntata dall'indice (miaVar[id]) ed incrementi l'indice.

- se l'indice supera il valore massimo, azzeri l'indice.

- Per fare la media, sommi tutti i valori dell'array e dividi per il numero di elementi dell'array (in SCL lo fai con un banale ciclo FOR).

 

In questo modo ad ogni campionamento vai a scrivere una sola variabile nell'array. Se si parla di array di piccole dimensioni, la differenza tra scrivere una sola variabile o fare lo scroll di tutto l'array è di natura puramente filosofica. Se hai un array con qualche migliaio di elementi, la differenza si sente.

Link al commento
Condividi su altri siti

1 ora fa, batta scrisse:

Out = Out + (In - Out) / k

Quindi out è l'uscita del pid, in è l'ingresso del pid, cioè il valore misurato dal flussimeyro, k invece cos'è?

Link al commento
Condividi su altri siti

Mentre per quanto riguarda la media aritmetica, ho creato un array real da 1 a 5, e l'ho chiamata dati, ho inserto un contatore avanti, dopo di che ho messo il contatto del contatore al primo 'move' all'ingresso di questultimo ho messo il valore del flussimetro ed all'uscita del move ho messo 'dati [1]', poi ho messo il contatto del contatore al secondo 'move' all'ingresso di questultimo ho messo il valore del flussimetro ed all'uscita del move ho messo 'dati [2]', poi ancora ho messo il contatto del contatore al terzo 'move' all'ingresso di questultimo ho messo il valore del flussimetro ed all'uscita del move ho messo 'dati [3]', ho fatto così fino a 'dati [5], a questo punto ho sommato i valori dellarray, 'dati [1]' fino a 'dati [5], e ho diviso per 5, potrebbe andare bene così? 

Link al commento
Condividi su altri siti

1 ora fa, Project75 scrisse:

Quindi out è l'uscita del pid, in è l'ingresso del pid, cioè il valore misurato dal flussimeyro, k invece cos'è?

no, out sarebbe il valore del flussimetro dopo aver eseguito il calcolo, per capire meglio la formula interpretala così:

 

ValoreFiltrato = ValoreFiltrato + (ValoreIngresso - ValoreFiltrato) / Kostante

 

-Il ValoreFiltrato è quello che metterai come ingresso al PID

-La Kostante è un valore fisso che imposti tu, in principio mettilo a 1, poi varialo e scopri i suoi effetti 😝

 

Ricorda che la formula di cui sopra devi farla esclusivamente con variabili di tipo REAL

 

 

 

Link al commento
Condividi su altri siti

3 ore fa, batta scrisse:

Appunto, qui siamo nel secondo caso, con segnale che varia anche con riferimento fisso della pompa.

 

E chi ti assicura che la pompa ruoti a velocità costante? E' azionata da un un inverter e non è stato specificato che sia reazionato in velocità, anzi i credo che sia in normale V/f.

Non credo nemmeno che una variazione di 800 l/h, nell'intorno di 13000 l/h di portata, sia da addebitarsi al trasduttore vista la qualità dello stesso (a meno che sia difettoso).

Poi come ho scritto prima, il problema non è mio ed ognuno è libero di comportarsi come preferisce. Però questo, a mio giudizio, è un caso in cui il filtraggio della reazione è un trucco.

 

 

Link al commento
Condividi su altri siti

Ciao incus la media aritmetica che ho postato prima potrebbe andare bene? Mi potresti mandare gentilmente l'eseguibile che mi avevi detto?

 

Link al commento
Condividi su altri siti

Quote

Quindi out è l'uscita del pid, in è l'ingresso del pid, cioè il valore misurato dal flussimeyro, k invece cos'è?

Ti ha risposto "incus".

Come utilizzare la formula era spiegato in un precedente post che, probabilmente, non hai letto.

Comunque:

- devi assolutamente utilizzare variabili di tipo REAL

- il calcolo va eseguito ad intervalli di tempo regolari (mettilo in un OB a tempo). Per il tuo caso, penso potrebbero andar bene da 10 a 100 ms.

- K la potremmo impropriamente chiamare "costante di smorzamento". Se ha valore 1, è come non ci fosse il filtro. Aumentando il valore di K aumenti lo smorzamento, ma aumenti anche il ritardo a variazioni del segnale. Devi trovare un giusto compromesso.

 

Quote

Mentre per quanto riguarda la media aritmetica, ho creato un array real da 1 a 5, e l'ho chiamata dati, ho inserto un contatore avanti, dopo di che ho messo il contatto del contatore al primo 'move' all'ingresso di questultimo ho messo il valore del flussimetro ed all'uscita del move ho messo 'dati [1]', poi ho messo il contatto del contatore al secondo 'move' all'ingresso di questultimo ho messo il valore del flussimetro ed all'uscita del move ho messo 'dati [2]', poi ancora ho messo il contatto del contatore al terzo 'move' all'ingresso di questultimo ho messo il valore del flussimetro ed all'uscita del move ho messo 'dati [3]', ho fatto così fino a 'dati [5], a questo punto ho sommato i valori dellarray, 'dati [1]' fino a 'dati [5], e ho diviso per 5, potrebbe andare bene così? 

Ma ti piace così tanto complicare le cose semplici?

 

Vediamo, questo è il sorgente di una funzione in SCL, buttata giù in modo piuttosto barbaro, tanto per fare un esempio.
La funzione va richiamata ad intervalli regolari.

FUNCTION_BLOCK "Media"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      inValue : Real;
      dim : Int;   // Min 1, Max 100
   END_VAR

   VAR_OUTPUT 
      average : Real;
   END_VAR

   VAR 
      id : Int;
      data : Array[1..100] of Real;
   END_VAR

   VAR_TEMP 
      tmpDim : Int;
      i : Int;
      tot : Real;
   END_VAR


BEGIN
	#tmpDim := #dim;
	
	IF #tmpDim < 1 THEN
	    #tmpDim := 1;
	ELSIF #tmpDim > 100 THEN
	    #tmpDim := 100;
	END_IF;
	
	IF #id < 1 OR #id > #tmpDim THEN
	    #id := 1;
	END_IF;
	
	#data[#id] := #inValue;
	#id := #id + 1;
	
	#tot := 0.0;
	FOR #i := 1 TO #tmpDim DO
	    #tot := #tot + #data[#i];
	END_FOR;
	
	#average := #tot / INT_TO_REAL(#tmpDim);
	
END_FUNCTION_BLOCK

 

Link al commento
Condividi su altri siti

7 minuti fa, batta scrisse:

Ti ha risposto "incus".

Come utilizzare la formula era spiegato in un precedente post che, probabilmente, non hai letto.

Comunque:

- devi assolutamente utilizzare variabili di tipo REAL

- il calcolo va eseguito ad intervalli di tempo regolari (mettilo in un OB a tempo). Per il tuo caso, penso potrebbero andar bene da 10 a 100 ms.

- K la potremmo impropriamente chiamare "costante di smorzamento". Se ha valore 1, è come non ci fosse il filtro. Aumentando il valore di K aumenti lo smorzamento, ma aumenti anche il ritardo a variazioni del segnale. Devi trovare un giusto compromesso.

 

Ma ti piace così tanto complicare le cose semplici?

 

Vediamo, questo è il sorgente di una funzione in SCL, buttata giù in modo piuttosto barbaro, tanto per fare un esempio.
La funzione va richiamata ad intervalli regolari.


FUNCTION_BLOCK "Media"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      inValue : Real;
      dim : Int;   // Min 1, Max 100
   END_VAR

   VAR_OUTPUT 
      average : Real;
   END_VAR

   VAR 
      id : Int;
      data : Array[1..100] of Real;
   END_VAR

   VAR_TEMP 
      tmpDim : Int;
      i : Int;
      tot : Real;
   END_VAR


BEGIN
	#tmpDim := #dim;
	
	IF #tmpDim < 1 THEN
	    #tmpDim := 1;
	ELSIF #tmpDim > 100 THEN
	    #tmpDim := 100;
	END_IF;
	
	IF #id < 1 OR #id > #tmpDim THEN
	    #id := 1;
	END_IF;
	
	#data[#id] := #inValue;
	#id := #id + 1;
	
	#tot := 0.0;
	FOR #i := 1 TO #tmpDim DO
	    #tot := #tot + #data[#i];
	END_FOR;
	
	#average := #tot / INT_TO_REAL(#tmpDim);
	
END_FUNCTION_BLOCK

 

Non ho mai utilizzato SCL, devo mettere questo codice dentro un blocco?

Link al commento
Condividi su altri siti

Quote

Non credo nemmeno che una variazione di 800 l/h, nell'intorno di 13000 l/h di portata, sia da addebitarsi al trasduttore vista la qualità dello stesso


800 l/h di variazione su 13000 non possono nemmeno essere imputati alla pompa, nemmeno se l'inverter è impostato V/f.

Link al commento
Condividi su altri siti

Out=out+(in-out)/k, allora 'in' è il valore letto dal flussimetro, k è la costante e la decido io, e out cos'è? È il vaLore filtrato?ma il valore filtrato non è quello che mi dovrei ricavare dalla formula? Quindi potrebbe essere

Valore filtrato ( che voglio ottenere)= out+(in-out)/k , a questo punto out sarebbe il valore in uscita del pid?

Link al commento
Condividi su altri siti

1 ora fa, Project75 scrisse:

Ciao incus la media aritmetica che ho postato prima potrebbe andare bene? Mi potresti mandare gentilmente l'eseguibile che mi avevi detto?

 

 

non sono riuscito a caricare il file, comunque:

  • copia tutto il testo
  • incollalo dentro un file di testo
  • dopo di che modifica l'estensione da .txt a .scl

 

  • poi nel tia portal nel menu ad albero del plc apri la cartella sorgenti esterne
  • clicca su aggiungi nuovo file esterno selezionando il file scl che ti ho passato
  • dopo averlo caricato nel tia portal, fai tasto destro sulla sorgente e clicca genera sorgente dai blocchi 

 

 

 

FUNCTION_BLOCK "FB137_FILTRO_VALORE_BY_MEDIA_ARITMETICA"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      START : Bool;   // 1=start
      CLR : Bool;   // 1=pulisci buffer di lettura
      CLK { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
      VALUE { ExternalWritable := 'False'} : Real;   // valore da filtrare
      DIM_BUFFER { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int := 5;   // dimensione buffer di lettura [1..99]
   END_VAR

   VAR_OUTPUT 
      Q_VALUE { ExternalWritable := 'False'} : Real;
      Q_ERR { ExternalWritable := 'False'} : Word;   // %X0=outrange dimensioni buffer
   END_VAR

   VAR 
      CLK_OLD { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // vecchio valore di clock
      CLK_TP { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // trig positivo clock
      DIM_BUFFER_OLD { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // vecchio valore buffer di lettura
      CNG_DIM_BUFFER { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // trig positivo cambio dimensioni buffer di lettura
      BUFFER { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[0..99] of Real;   // buffer valori letti
      J { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // indice
   END_VAR


BEGIN
    //************ TRIG POSITIVO CLOCK ************
    IF #CLK AND NOT #CLK_OLD THEN
        #CLK_TP := TRUE;
    ELSE
        #CLK_TP := FALSE;
    END_IF;
    #CLK_OLD := #CLK;
    
    //************ TRIG CAMBIO DIMENSIONI BUFFER DI LETTURA ************
    IF #DIM_BUFFER <> #DIM_BUFFER_OLD THEN
        #CNG_DIM_BUFFER := TRUE;
    ELSE
        #CNG_DIM_BUFFER := FALSE;
    END_IF;
    #DIM_BUFFER_OLD := #DIM_BUFFER;
    
    
    //************ PULIZIA BUFFER DI LETTURA ************
    IF #CLR OR #CNG_DIM_BUFFER OR #Q_ERR.%X0 THEN
        FOR #J := 0 TO 99 BY 1 DO
            #BUFFER[#J] := 0.0;
        END_FOR;
    END_IF;
    
    
    //************ TRASFERIMENTO VALORE LETTO NEL BUFFER DI LETTURA ************
    IF #START AND #CLK_TP THEN
        FOR #J := #DIM_BUFFER TO 0 BY -1 DO
            IF #J > 0 THEN
                #BUFFER[#J] := #BUFFER[#J - 1];
            ELSIF #J = 0 THEN
                #BUFFER[#J] := #VALUE;
            END_IF;
        END_FOR;
    END_IF;
    
    
    //************ CALCOLO LA MEDIA ARITMETICA ************
    #Q_VALUE := 0.0;
    FOR #J := 0 TO #DIM_BUFFER DO
        #Q_VALUE := #Q_VALUE + #BUFFER[#J];
    END_FOR;
    #Q_VALUE := #Q_VALUE / (#DIM_BUFFER + 1.0);
    
    
    //************ ERRORI ************
    
    //controllo inrange dimensioni buffer
    IF (#DIM_BUFFER < 1) OR (#DIM_BUFFER > 99) THEN
        #Q_ERR.%X0 := TRUE;
    ELSE
        #Q_ERR.%X0 := FALSE;
    END_IF;
    
END_FUNCTION_BLOCK

Link al commento
Condividi su altri siti

1 ora fa, Project75 scrisse:

Out=out+(in-out)/k, allora 'in' è il valore letto dal flussimetro, k è la costante e la decido io, e out cos'è? È il vaLore filtrato?ma il valore filtrato non è quello che mi dovrei ricavare dalla formula? Quindi potrebbe essere

Valore filtrato ( che voglio ottenere)= out+(in-out)/k , a questo punto out sarebbe il valore in uscita del pid?

Ma le leggi le risposte che ti stiamo dando?????? 

 

ti riquoto le risposte

 

2 ore fa, incus scrisse:

no, out sarebbe il valore del flussimetro dopo aver eseguito il calcolo, per capire meglio la formula interpretala così:

 

ValoreFiltrato = ValoreFiltrato + (ValoreIngresso - ValoreFiltrato) / Kostante

 

-Il ValoreFiltrato è quello che metterai come ingresso al PID

-La Kostante è un valore fisso che imposti tu, in principio mettilo a 1, poi varialo e scopri i suoi effetti 😝

 

Ricorda che la formula di cui sopra devi farla esclusivamente con variabili di tipo REAL

 

 

 

 

1 ora fa, batta scrisse:

Ti ha risposto "incus".

Come utilizzare la formula era spiegato in un precedente post che, probabilmente, non hai letto.

Comunque:

- devi assolutamente utilizzare variabili di tipo REAL

- il calcolo va eseguito ad intervalli di tempo regolari (mettilo in un OB a tempo). Per il tuo caso, penso potrebbero andar bene da 10 a 100 ms.

- K la potremmo impropriamente chiamare "costante di smorzamento". Se ha valore 1, è come non ci fosse il filtro. Aumentando il valore di K aumenti lo smorzamento, ma aumenti anche il ritardo a variazioni del segnale. Devi trovare un giusto compromesso.

 

Link al commento
Condividi su altri siti

Scusa ma io non ho capito come funziona questa formula, se out è il valore filtrato cioè il valore che devo ricavare, come si esegue questa formula con un valore che ancora devo calcolare?

Link al commento
Condividi su altri siti

39 minuti fa, Project75 scrisse:

Scusa ma io non ho capito come funziona questa formula, se out è il valore filtrato cioè il valore che devo ricavare, come si esegue questa formula con un valore che ancora devo calcolare?

 

Ad ogni ciclo di scansio e il valore filtrato si aggiorna, provala, cosi ti rendi conto

Link al commento
Condividi su altri siti

E se scrivo:

a = a + 1

ti pare una cosa impossibile? Il valore attuale di "a" viene incrementato di una unità ed il risultato viene scritto nuovamente in "a".

Se in KOP richiami l'istruzione ADD, su IN1 metti "a", su IN2 metti "1" e su OUT metti ancora "a", ti sembra normale, giusto?
È la stessa cosa.

 

"ValoreFiltrato", che devi ricavare, all'inizio, avrà pure un valore, o no?
Se non hai assegnato nessun valore, avrà valore zero, che è pur sempre un valore!
Poi, ad ogni calcolo, si modifica.

 

In quella banalissima formula prendi il valore filtrato (che è il risultato dei precedenti calcoli). A questo valore filtrato sommi una parte della differenza che c'è tra il valore attuale e il valore filtrato. Alla fine dell'operazione il valore filtrato sarà diverso da come era prima di eseguire l'operazione.

 

Se ancora non sei convinto, prova a fare una semplice prova con dei numeri.

Partiamo con "valoreFiltrato" = 0, "ValoreGrezzo" = 100, e k = 2.

quindi:
"valoreFiltrato" = 0 + (100 - 0) / 2 = 50.

Al ciclo successivo avrai:

"valoreFiltrato" = 50 + (100 - 50) / 2 = 75

e ancora:

"valoreFiltrato" = 75 + (100 - 75) / 2 = 87.5

 

 

Link al commento
Condividi su altri siti

11 minuti fa, batta scrisse:

E se scrivo:

a = a + 1

ti pare una cosa impossibile? Il valore attuale di "a" viene incrementato di una unità ed il risultato viene scritto nuovamente in "a".

Se in KOP richiami l'istruzione ADD, su IN1 metti "a", su IN2 metti "1" e su OUT metti ancora "a", ti sembra normale, giusto?
È la stessa cosa.

 

"ValoreFiltrato", che devi ricavare, all'inizio, avrà pure un valore, o no?
Se non hai assegnato nessun valore, avrà valore zero, che è pur sempre un valore!
Poi, ad ogni calcolo, si modifica.

 

In quella banalissima formula prendi il valore filtrato (che è il risultato dei precedenti calcoli). A questo valore filtrato sommi una parte della differenza che c'è tra il valore attuale e il valore filtrato. Alla fine dell'operazione il valore filtrato sarà diverso da come era prima di eseguire l'operazione.

 

Se ancora non sei convinto, prova a fare una semplice prova con dei numeri.

Partiamo con "valoreFiltrato" = 0, "ValoreGrezzo" = 100, e k = 2.

quindi:
"valoreFiltrato" = 0 + (100 - 0) / 2 = 50.

Al ciclo successivo avrai:

"valoreFiltrato" = 50 + (100 - 50) / 2 = 75

e ancora:

"valoreFiltrato" = 75 + (100 - 75) / 2 = 87.5

 

 

Si avevo provato a far un calcolo con numeri e ne volevo essere sicuro. A questo punto si potrebbe pensare che la media aritmetica sia più efficace....

Link al commento
Condividi su altri siti

3 ore fa, incus scrisse:

 

non sono riuscito a caricare il file, comunque:

  • copia tutto il testo
  • incollalo dentro un file di testo
  • dopo di che modifica l'estensione da .txt a .scl

 

  • poi nel tia portal nel menu ad albero del plc apri la cartella sorgenti esterne
  • clicca su aggiungi nuovo file esterno selezionando il file scl che ti ho passato
  • dopo averlo caricato nel tia portal, fai tasto destro sulla sorgente e clicca genera sorgente dai blocchi 

 

 

 

FUNCTION_BLOCK "FB137_FILTRO_VALORE_BY_MEDIA_ARITMETICA"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      START : Bool;   // 1=start
      CLR : Bool;   // 1=pulisci buffer di lettura
      CLK { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
      VALUE { ExternalWritable := 'False'} : Real;   // valore da filtrare
      DIM_BUFFER { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int := 5;   // dimensione buffer di lettura [1..99]
   END_VAR

   VAR_OUTPUT 
      Q_VALUE { ExternalWritable := 'False'} : Real;
      Q_ERR { ExternalWritable := 'False'} : Word;   // %X0=outrange dimensioni buffer
   END_VAR

   VAR 
      CLK_OLD { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // vecchio valore di clock
      CLK_TP { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // trig positivo clock
      DIM_BUFFER_OLD { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // vecchio valore buffer di lettura
      CNG_DIM_BUFFER { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // trig positivo cambio dimensioni buffer di lettura
      BUFFER { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[0..99] of Real;   // buffer valori letti
      J { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // indice
   END_VAR


BEGIN
    //************ TRIG POSITIVO CLOCK ************
    IF #CLK AND NOT #CLK_OLD THEN
        #CLK_TP := TRUE;
    ELSE
        #CLK_TP := FALSE;
    END_IF;
    #CLK_OLD := #CLK;
    
    //************ TRIG CAMBIO DIMENSIONI BUFFER DI LETTURA ************
    IF #DIM_BUFFER <> #DIM_BUFFER_OLD THEN
        #CNG_DIM_BUFFER := TRUE;
    ELSE
        #CNG_DIM_BUFFER := FALSE;
    END_IF;
    #DIM_BUFFER_OLD := #DIM_BUFFER;
    
    
    //************ PULIZIA BUFFER DI LETTURA ************
    IF #CLR OR #CNG_DIM_BUFFER OR #Q_ERR.%X0 THEN
        FOR #J := 0 TO 99 BY 1 DO
            #BUFFER[#J] := 0.0;
        END_FOR;
    END_IF;
    
    
    //************ TRASFERIMENTO VALORE LETTO NEL BUFFER DI LETTURA ************
    IF #START AND #CLK_TP THEN
        FOR #J := #DIM_BUFFER TO 0 BY -1 DO
            IF #J > 0 THEN
                #BUFFER[#J] := #BUFFER[#J - 1];
            ELSIF #J = 0 THEN
                #BUFFER[#J] := #VALUE;
            END_IF;
        END_FOR;
    END_IF;
    
    
    //************ CALCOLO LA MEDIA ARITMETICA ************
    #Q_VALUE := 0.0;
    FOR #J := 0 TO #DIM_BUFFER DO
        #Q_VALUE := #Q_VALUE + #BUFFER[#J];
    END_FOR;
    #Q_VALUE := #Q_VALUE / (#DIM_BUFFER + 1.0);
    
    
    //************ ERRORI ************
    
    //controllo inrange dimensioni buffer
    IF (#DIM_BUFFER < 1) OR (#DIM_BUFFER > 99) THEN
        #Q_ERR.%X0 := TRUE;
    ELSE
        #Q_ERR.%X0 := FALSE;
    END_IF;
    
END_FUNCTION_BLOCK

Grazie mille per il file sorgente incus, ho creato il blocco ora devo capire bene come funziona, allora l'ingresso start avvia il blocco quindi la campionatura, l'ingresso clr credo che cancelli i dati salvati, quando bisogna cancellarli?, l'ingresso clk cos'è?, value è  il valore da stabilizzare, dimm_buffer sarebbero il numero di campioni, che va da 1 a 99, Q_value credo sia il valore filtrato, e Q_err cos'è? 

Link al commento
Condividi su altri siti

11 ore fa, batta scrisse:

800 l/h di variazione su 13000 non possono nemmeno essere imputati alla pompa, nemmeno se l'inverter è impostato V/f.

 

E' una variazione del 6.15% non credo sia rumore di fondo, ma proprio variazione di portata.

Link al commento
Condividi su altri siti

7 ore fa, Project75 scrisse:

Grazie mille per il file sorgente incus, ho creato il blocco ora devo capire bene come funziona, allora l'ingresso start avvia il blocco quindi la campionatura, l'ingresso clr credo che cancelli i dati salvati, quando bisogna cancellarli?, l'ingresso clk cos'è?, value è  il valore da stabilizzare, dimm_buffer sarebbero il numero di campioni, che va da 1 a 99, Q_value credo sia il valore filtrato, e Q_err cos'è? 

Incus ho capito chè l'ingresso clk è il fronte in salita, cioè la frequenza di campionatura, Q_err potrebbe essere l'indicazione di errore (come deduco i valori di errore?), mentre l'ingresso clr posso avviarlo quando ho bisogno di cancellare i dati salvati.

Link al commento
Condividi su altri siti

1 ora fa, Project75 scrisse:

Incus ho capito chè l'ingresso clk è il fronte in salita, cioè la frequenza di campionatura, Q_err potrebbe essere l'indicazione di errore (come deduco i valori di errore?), mentre l'ingresso clr posso avviarlo quando ho bisogno di cancellare i dati salvati.

nei commenti delle variabili c'è la descrizione da cui puoi capire a cosa servono, comunque di seguito inserisco dei commenti aggiuntivi per facilitarti:

 

START : 1=start, avvia il blocco
CLR 1=pulisci buffer di lettura, serve per azzerare il buffer di lettura
CLK : frequenza di campionamento, nel TIA puoi abilitare le Merker di clock nelle proprietà della CPU e collegarci una di esse
VALUE : valore da filtrare , valore di cui devi fare la media aritmetica
DIM_BUFFER : dimensione buffer di lettura [1..99], indica quanti valori vuoi caricare nel buffer di lettura, puoi impostare un valore da 1 a 99, se devi fare 10 campionamenti devi impostare DIM_BUFFER=9 poiche il conteggio parte da 0
 
Q_VALUE :
valore filtrato
Q_ERR : %X0=outrange dimensioni buffer, se il primo bit della word è TRUE allora significa che le dimensioni del buffer sono errate

 

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...