Passa al contenuto principale

Esempio 1 - Calcolo della potenza, contatore di energia, valori giornalieri

Esempio 1a - Calcolo della potenza​

Compito:​

La potenza elettrica di un utilizzatore deve essere calcolata a partire dai segnali di tensione (LINEVOLT_1, LINEVOLT_2 in volt) e di corrente (LINECURRENT in ampere) misurati. La tensione viene misurata in modo ridondante e un punto di misura può essere disattivato. L'uscita deve avvenire nell'unità "kW". Determinazione dell'energia assorbita e di quella ceduta in "kWh".

Soluzione:​

// Konstanten zur Einheitenumrechnung
uConv_Ws2kWh = 1e-3 / 3600; // Ws -> kWh

LINEVOLT = max(LINEVOLT_1, LINEVOLT_2); // V
POWER = LINEVOLT * LINECURRENT; // W
POWER_KW = POWER / 1000.0; // kW
WAUF_KWH = integrate(max(POWER, 0.0), {storage: 'sto_WAUF'}) * uConv_Ws2kWh; // kWh
WABG_KWH = -integrate(min(POWER, 0.0), {storage: 'sto_WABG'}) * uConv_Ws2kWh; // kWh

Funzioni utilizzate​

Spiegazione:​

  • uConv_Ws2kWh: Per prima cosa viene definito un fattore per la conversione dell'unità da Ws a kWh. Ciò migliora la leggibilità del codice seguente. È opportuno collocare tali definizioni in modo centralizzato all'inizio del set di formule.

  • LINEVOLT: delle due tensioni di rete misurate viene preso il massimo. Se una delle due viene a mancare e vale 0.0, l'altra fornisce comunque un valore plausibile.

  • POWER e POWER_KW: Il calcolo della potenza elettrica avviene dapprima in W (watt) e separatamente in kW (kilowatt). Questa separazione è necessaria perché la successiva funzione di integrazione dovrebbe essere alimentata sempre con le unità di base SI del sistema "MKS", qui quindi con la potenza in W.

  • WAUF_KWH, WABG_KWH: La potenza calcolata viene inviata, tramite le funzioni min() e max(), ai due integratori integrate() separatamente in base al segno e quindi alla direzione del flusso di potenza. Entrambi gli integratori mantengono il proprio valore di contatore corrente (in unità di base SI!) nelle posizioni di memoria indicate. Con l'integrazione, all'integrando si aggiunge la dimensione tempo come s (secondo). Il valore integrato ha quindi l'unità di energia "Ws" (wattsecondo). Questa viene convertita in kWh (kilowattora) con il fattore di scala calcolato sopra.

  • Se in seguito dovessero cambiare le unità dei segnali di misura da integrare (kV, kA, mA) o del valore integrato (kJ, MWh, ecc.), il valore memorizzato nell'integratore può essere facilmente riutilizzato, purché sia espresso in unità di base SI. In tal caso è necessaria soltanto una scalatura semplice e comprensibile della grandezza di ingresso o di uscita, ma non una riscalatura permanente del valore memorizzato nell'integratore né un riavvio forzato per questo motivo.

Esempio 1b - Valori intermedi giornalieri​

Compito:​

Il calcolo deve ora essere esteso in modo da fornire in uscita le letture del contatore giornaliere al momento della chiusura dell'attività, il consumo degli ultimi 7 giorni e il consumo in corso del giorno attuale.

Soluzione:​

A integrazione del testo della formula dell'Esempio 1a):

#timezone Europe/Berlin
newDay = timer({ minute: 15, hour: 3, useTZ: true }); // Referenz-Zeit, Schichtwechsel

_hist_WAUF_KWH = buffer(WAUF_KWH, newDay, {size:8, storage:'sto_h_WAUF'});
WEEK_WAUF_KWH = _hist_WAUF_KWH[0] - _hist_WAUF_KWH[7];
YDAY_WAUF_KWH = _hist_WAUF_KWH[0] - _hist_WAUF_KWH[1];
TDAY_WAUF_KWH = WAUF_KWH - _hist_WAUF_KWH[0];

_hist_WABG_KWH = buffer(WABG_KWH, newDay, {size:8, storage:'sto_h_WABG'});
WEEK_WABG_KWH = _hist_WABG_KWH[0] - _hist_WABG_KWH[7];
YDAY_WABG_KWH = _hist_WABG_KWH[0] - _hist_WABG_KWH[1];
TDAY_WABG_KWH = WABG_KWH - _hist_WABG_KWH[0];

Funzioni utilizzate​

Spiegazione:​

  • Le variabili per uso interno sono contrassegnate da un _ come primo carattere. Ciò migliora la leggibilità.

  • newDay: Con la funzione timer() viene generato un segnale a impulsi che, con la configurazione indicata, produce ogni mattina alle 3:15 ora locale di "Berlino" un breve impulso. Con questo impulso vengono memorizzate le letture del contatore.

  • _hist_WAUF_KWH, _hist_WABG_KWH: Con l'aiuto della funzione buffer(), i valori dei contatori di energia vengono acquisiti in un buffer circolare di lunghezza 8. Ogni volta che sul segnale newDay è presente un fronte positivo, i valori nel buffer circolare vengono spostati di una posizione indietro e nella posizione [0] viene inserito il valore corrente WAUF_KWH o WABG_KWH. Anche queste memorie salvano il proprio contenuto in una posizione persistente, per poter proseguire il calcolo dopo un riavvio con le letture del contatore determinate fino a quel momento.

  • WEEK_*: Il consumo di energia degli ultimi 7 giorni risulta dalla differenza tra il valore rilevato nell'ultima notte e quello rilevato 8 notti prima [7].

  • YDAY_*: Il consumo di energia dell'ultimo giorno (yesterday) risulta dalla differenza tra i valori rilevati nell'ultima [0] e nella penultima [1] notte.

  • TDAY_*: Il consumo di energia del giorno in corso (today) è la differenza tra il valore assoluto e il valore memorizzato nell'ultima notte.

Poiché i valori storici memorizzati cambiano una sola volta al giorno, la trasmissione dei dati al cloud o in file OSF è possibile in modo molto efficiente.

Esempio 1c - Valori di consumo per giorni della settimana o mesi​

Compito:​

L'Esempio 1b) richiede che lo smartCORE sia permanentemente online e possa anche generare gli impulsi di trigger. A partire dalla versione di catalogo 13 è possibile utilizzare la funzione memory() per aggirare questo problema.

Soluzione:​

A integrazione del testo della formula dell'Esempio 1a):

_now = time();
_dateVec = decodeTime(_now);
_weekDay = int(_dateVec[7]);     // 0..6, starting on sunday
_yesterday = (_weekDay + 6) % 7;

_memECLatch = memory( false, _weekDay, WAUF_KWH
, {mode: latch, size:7
, storage: memECLatch_kWh});
_memStart = memory( false, _weekDay, _memECLatch[_yesterday]
, {mode: latch, size:7
, storage: memStart_kWh});
Consumption = _memECLatch - _memStart;

Consume_Sun = Consumption[0];
Consume_Mon = Consumption[1];
...
Consume_Sat = Consumption[6];

Funzioni utilizzate:​

Spiegazione:​

  • Per prima cosa, dalla funzione decodeTime() si ottiene il giorno della settimana _weekDay per l'ora UTC corrente _now. Questo è un valore intero nell'intervallo [0..6][0 .. 6], con 0 per la domenica.

  • Il giorno della settimana precedente _yesterDay viene determinato con un'operazione di modulo nello stesso intervallo di valori.

  • La memoria _memECLatch scrive in modo permanente la lettura corrente del contatore nella posizione di memoria (= elemento del vettore) indicizzata da _weekDay. A tale scopo è inizializzata con 7 posizioni di memoria e una memoria persistente in modalità latch. Per ogni giorno della settimana viene quindi sempre memorizzata l'ultima lettura del contatore del giorno corrispondente. Per questo l'ingresso di controllo control è sempre false.

In linea di principio, il consumo giornaliero risulta dalla differenza delle letture del contatore rispetto al giorno precedente. Se però si formasse la differenza direttamente, il valore del sesto giorno precedente (ad esempio giovedì quando il giorno attuale è mercoledì) sarebbe errato. Il valore finale di mercoledì (della settimana precedente) viene infatti sovrascritto proprio in continuazione.

  • Per questo una seconda memoria _memStart, con la stessa struttura, mantiene sempre i valori del giorno precedente _memECLatch[_yesterday] come valore iniziale per il giorno in corso.

  • La differenza dei due vettori (memorie) fornisce il consumo giornaliero per giorno della settimana come vettore Consumption, oppure suddiviso per giorno della settimana Consume_Sun, Consume_Mon, ecc.

Un vantaggio rispetto al metodo che fa avanzare un buffer circolare buffer() mediante impulsi della funzione trigger() è che il dispositivo non deve essere acceso nell'istante del trigger. Condizione in questo caso: almeno un calcolo nel giorno precedente.