Início / Blogs / Blog Automatas / Cómo crear una media horaria, sin que el PLC pida la baja

Cómo crear una media horaria, sin que el PLC pida la baja

Iñigo Gútiez nos muestra como programar en un PLC en lenguaje SCL para calcular la media continua de una variable de la última hora

Cómo crear una media horaria, sin que el PLC pida la baja

Recientemente, en el foro ha habido una duda de cómo hacer una media horaria, es decir, cómo calcular la media continua de la última hora. Es una aplicación y duda bastante común, por lo que vamos a intentar resolverla de una vez por todas.

Evidentemente si solo habláramos de calcular la media de un valor durante una hora, no habría mucha discusión ya que sería cuestión de sumar los valores de cada segundo y dividir entre 3600.

La cosa se complica si lo que quieres hacer es calcular la media de forma continua, es decir, que cada segundo obtengamos la media de los últimos 3600 segundos.

Y no se complica por el cálculo, que no es más que hacer un FIFO, sino porque realizar un FIFO de 3600 posiciones, sumar sus valores, y realizar la media de estos 3600 valores, no es moco de pavo para el PLC ya que estarás castigando de forma innecesaria el tiempo de ciclo del bicho.

Piensa que el tiempo de procesamiento de una operación aritmética en coma fija es muy variado. Por ejemplo, tenemos los 0,12us de un 325 2DP (6ES7315-2AH14-0AB0) o los 1,7us de un 1200 (6ES7212-1BE40-0XB0). Como ves, no se parecen en nada.

Esto se va a traducir en que sumar 3600 valores enteros en tiempos de procesamiento de 0,43us del primer caso, pero tendríamos unos no despreciable 6,1us para el pequeño 1200 solamente para realizar una media.

En caso de valores reales, la cosa se complica desde los 1,6us en el 315 hasta ¡9us en el caso del 1200!

Por tanto, tenemos que estrujarnos las meninges para hacerlo de una forma más eficiente.

Este ejemplo se podría hacer en muchos lenguajes, pero creo que se ajusta mejor usando lenguaje estructurado SCL.

 

Un FIFO y un poco de imaginación para calcular la media horaria.

Tenemos que almacenar de un modo u otro, las 3600 últimas medidas para poder generar la media.

En este caso, vamos a construir un ARRAY [0..59,0..59] para guardar nuestras medidas. Siendo los índices de ambas dimensiones, los minutos y los segundos, es decir, una tabla de 60x60.

Como la captura de datos es cada segundo, vamos a andar listos, y vamos a usar el reloj del sistema para generar nuestros punteros, y así nos evitamos mayores complicaciones.

Tiene además el interés adicional de poder acceder a los datos si hiciera falta de un momento en concreto de la última hora (a las en punto, a las y media etc.)

Así pues:

// Obtenemos la hora local

#Retorno := RD_LOC_T(#Reloj);

Vamos a necesitar un contador de segundos para saber cuánto tiempo ha transcurrido y si estamos en la primera hora o en las siguientes.

Además, como el bloque puede que se ejecute más de una vez cada segundo (imaginemos si lo cargamos desde el OB1), necesitaremos realizar un pulso solo cada segundo.

Para ello, nos apoyamos en una variable auxiliar: primero comparamos el segundo del reloj con esta variable, decidimos qué hacer con el contador, y luego igualamos la variable auxiliar al segundero del contador. Así nos aseguramos que se ejecuta una sola vez por segundo.

//Sumamos una unidad al contador de segundos

IF #SegundoAnterior #Reloj.SECOND THEN

    #Contador := #Contador + 1;

END_IF;

// Actualizamos el segundo

#SegundoAnterior := #Reloj.SECOND;

Ya tenemos nuestro contador. Lo que vamos a hacer es determinar si estamos en la primera vuelta (la primera hora) o estamos ya en segundas y sucesivas.

Si hemos sobrepasado la hora, pondremos este contador a su valor máximo, ya que estaremos sobre escribiendo los valores de hace una hora.

Por tanto, tenemos que leer y guardar este valor viejo antes de sobre escribirlo y por otro lado, decir que el contador no puede superar los 3600 segundos.

Si por el contrario, aún estamos en la primera hora (el contador3600), entonces diremos que el valor antiguo (el de hace una hor), es cero para no falsear las medidas posteriores.

//Evaluamos si el contador ha llegado a la hora, si es así, lo fijamos en una hora.

IF #Contador > 3600 THEN

    #Contador := 3600;

    //Si ya hemos dado la primera vuelta, Recuperamos el valor que vamos a eliminar sobreescribiendo sobre él.

    #Valor_Antiguo := #Datos[#Reloj.MINUTE, #Reloj.SECOND];

ELSE

    //Si estamos aún en la primera vuelta, ponemos el valor antiguo a cero.

    #Valor_Antiguo := 0;

END_IF;

Ahora ya podemos sobre escribir en nuestra tabla sin miedo:

//Sobreescribimos el nuevo valor

#Datos[#Reloj.MINUTE, #Reloj.SECOND] := #Señal_Analogica;

Para realizar la media, lo que haremos será ir añadiendo a un sumador los valores nuevos y restando los valores viejos.

Como puedes ver tras el código visto, durante los primeros 3600 segundos, la medida no hará mas que sumar ya que restaremos 0.

Una vez alcanzado los 3600 segundos, sumaremos el valor nuevo de la medida, pero restaremos el valor que tenía hace exactamente una hora, por lo que nuestro sumador estará siempre actualizado.

//Actualizamos el nuevo valor del sumador, sumando el nuevo valor, y restando el valor antiguo saliente

#Sumador := #Sumador + #Señal_Analogica - #Valor_Antiguo;

Finalmente, toca hacer la división. Si estamos en la primera hora, el contador aún no sumará 3600 y estaremos ofreciendo la media actualizada del arranque hasta que se cumpla la hora.

Una vez cumplida la hora, tanto el sumador solo tendrá los datos de la última hora, y el contador valdrá siempre 3600 segundos.

//Realizamos la media y redondeamos a un número entero

#Media := REAL_TO_INT(#Sumador / #Contador);

La media horaria calculada en SCL.

Aquí os dejamos un vídeo explicando este ejemplo por si no ha quedado claro. Siempre es más práctico verlo que leerlo ¿verdad?

Autor: Iñigo Gútiez

http://programacionsiemens.com

Más información

/blogs-automatizacion/marcas/223-blog-automatas

Blog Automatas

Blog dedicado a comentar experiencias, tendencias, tecnologías y mercados relacionados  
con la Automatización Industrial