Ejemplo 1 - Cálculo de potencia, contador de energía, valores diarios
Ejemplo 1a - Cálculo de potencia
Tarea:
Se debe calcular la potencia eléctrica de un consumidor a partir de las señales de tensión (LINEVOLT_1, LINEVOLT_2 en voltios) y de corriente (LINECURRENT en amperios) medidas. La tensión se mide de forma redundante, y un punto de medición puede estar desconectado. La salida debe expresarse en la unidad "kW". Determinación de la energía absorbida y de la energía cedida en "kWh".
Solución:
// 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
Funciones utilizadas
Explicación:
-
uConv_Ws2kWh: En primer lugar se define un factor para la conversión de unidades de Ws a kWh. Esto mejora la legibilidad del código siguiente. Conviene colocar estas definiciones de forma centralizada al principio del conjunto de fórmulas. -
LINEVOLT: de las dos tensiones de red medidas se toma el máximo. Si una de ellas falla y pasa a valer 0.0, la otra sigue proporcionando un valor plausible. -
POWERyPOWER_KW: el cálculo de la potencia eléctrica se realiza primero en W (vatios) y, por separado, enkW(kilovatios). Esta separación es necesaria porque la función de integración posterior debe alimentarse siempre con unidades básicas del SI del sistema "MKS", es decir, aquí con la potencia en W. -
WAUF_KWH, WABG_KWH: la potencia calculada se separa según su signo, y con ello según el sentido del flujo de potencia, mediante las funcionesmin()ymax(), y se dirige a los dos integradoresintegrate(). Ambos integradores mantienen su lectura actual del contador (¡en unidades básicas del SI!) en las posiciones de memoria indicadas. Mediante la integración se añade al integrando la dimensión tiempo como s (segundo). El valor integrado tiene, por tanto, la unidad de energía "Ws" (vatio-segundo). Esta se convierte a kWh (kilovatio-hora) con el factor de escala calculado arriba. -
Si más adelante cambian las unidades de las señales de medición que se integran (kV, kA, mA) o del valor integrado (kJ, MWh, etc.), el valor almacenado en el integrador puede seguir utilizándose fácilmente, siempre que esté expresado en unidades básicas del SI. Entonces solo es necesario un escalado sencillo y comprensible de la magnitud de entrada o de salida, pero no un reescalado permanente del valor almacenado en el integrador ni un reinicio forzado por ello.
Ejemplo 1b - Valores intermedios diarios actualizados
Tarea:
Ahora el cálculo se debe ampliar de modo que se obtengan las lecturas de contador del día en el momento del cierre de la jornada, el consumo de los últimos 7 días y el consumo en curso del día actual.
Solución:
Como complemento al texto de fórmulas del Ejemplo 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];
Funciones utilizadas
Explicación:
-
Las variables de uso interno se identifican con un
_como primer carácter. Esto mejora la legibilidad. -
newDay: con la funcióntimer()se genera una señal de impulsos que, con la configuración dada, produce un impulso breve cada mañana a las 3:15 hora local de "Berlín". Con este impulso se guardan a continuación las lecturas de los contadores. -
_hist_WAUF_KWH, _hist_WABG_KWH: con ayuda de la funciónbuffer()se transfieren los valores de los contadores de energía a una memoria circular de longitud 8. Siempre que hay un flanco positivo en la señalnewDay, los valores de la memoria circular se desplazan una posición hacia atrás y en la posición [0] se guarda el valor actualWAUF_KWHoWABG_KWH. Estas memorias también guardan su contenido en una ubicación persistente, para seguir calculando tras un reinicio con las lecturas de contador determinadas hasta entonces. -
WEEK_*: el consumo de energía de los últimos 7 días resulta de la diferencia entre el valor registrado la última noche y el de 8 noches antes [7]. -
YDAY_*: el consumo de energía del último día (yesterday) resulta de la diferencia entre el valor registrado la última noche [0] y el de la penúltima [1]. -
TDAY_*: el consumo de energía del día en curso (today) es la diferencia entre el valor absoluto y el valor guardado la última noche.
Como los valores históricos almacenados solo cambian una vez al día, la transmisión de datos a la nube o a archivos OSF puede realizarse de forma muy eficiente.
Ejemplo 1c - Valores de consumo por días de la semana o meses
Tarea:
El Ejemplo 1b) requiere que el smartCORE esté permanentemente en línea y pueda generar también los impulsos de disparo. A partir de la versión 13 del catálogo puede utilizarse la función memory() para evitar este problema.
Solución:
Como complemento al texto de fórmulas del Ejemplo 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];
Funciones utilizadas:
Explicación:
-
En primer lugar se obtiene, mediante la función
decodeTime(), el día de la semana_weekDaycorrespondiente a la hora UTC actual_now. Este es un valor entero en el intervalo , comenzando con 0 para el domingo. -
El día de la semana anterior
_yesterDayse determina con una operación módulo en el mismo intervalo de valores. -
La memoria
_memECLatchlleva permanentemente la lectura actual del contador a la posición de memoria indexada por_weekDay(= elemento del vector). Para ello está inicializada con 7 posiciones de memoria y una memoria persistente en modo latch. De este modo, para cada día de la semana se guarda siempre la última lectura del contador del día correspondiente. Para ello, la entrada de control control es siempre false.
En principio, el consumo diario resulta de la diferencia entre las lecturas del contador respecto al día anterior. Sin embargo, si se formara la diferencia directamente, el valor del sexto día anterior (es decir, p. ej., el jueves si el día actual es miércoles) sería erróneo. El valor final del miércoles (de hace una semana) es precisamente el que se sobrescribe continuamente.
-
Por ello, una segunda memoria
_memStart, con la misma estructura, mantiene siempre los valores del día anterior_memECLatch[_yesterday]como valor inicial para el día en curso. -
La diferencia de ambos vectores (memorias) da el consumo diario por días de la semana como vector
Consumption, o desglosado por día de la semanaConsume_Sun,Consume_Mon, etc.
Una ventaja respecto al método de avanzar una memoria circular buffer() mediante impulsos de la función trigger() es que el dispositivo no tiene que estar encendido en el momento del disparo. Condición en este caso: al menos un cálculo el día anterior.