Documentos de Académico
Documentos de Profesional
Documentos de Cultura
infoPLC Net S7 SCL v1 0 PDF
infoPLC Net S7 SCL v1 0 PDF
SCL
Introducción a la programación
Electricitat/Electrònica
PLC S7-300
PROGRAMACIÓN ESTRUCTURADA
S7-SCL
PRÓLOGO
Esta documentación forma parte de una serie de manuales que un grupo de profesores de tres institutos de
educación secundaria de Catalunya, como son:
han estado experimentando con diferentes materiales incluidos dentro de la temática de la automatización,
el control y las comunicaciones industriales.
Este grupo de trabajo continúa trabajando en cada uno de los temas para poder ir actualizando día a día
esta documentación, es por ello, que nos podéis enviar vuestras sugerencias a través de la información que
encontrareis en la web dedicada a este grupo de trabajo y que desde aquí os invitamos a participar.
www.iespalauausit.com/edcai/edcai.php
Esperamos que el esfuerzo y dedicación que hemos realizado pueda ayudar a mejorar vuestra labor
educativa.
ÍNDICE
1. Introducción.
6. Ejercicios propuestos.
7. Soluciones.
1.- Introducción.
SCL “ structured control language “ es el lenguaje de texto estructurado para PLCs de Siemens
y está basado en el lenguaje de alto nivel PASCAL. Permite una fácil integración en el
contexto de una solución global para un problema de automatización ya que un bloque
programado en SCL puede ser llamado desde un bloque escrito en KOP, en grafcet, en AWL o
en FUP y a la inversa, un bloque escrito, por ejemplo en KOP puede ser llamado desde un
bloque escrito en SCL. Al mismo tiempo SCL trata todas las áreas de memoria del PLC como
variables globales, lo que permite, como en el resto de lenguajes, intercalar una dirección
absoluta de memoria (entrada, salida, marca, DB, periferia, etc.) en el área de instrucciones
del bloque como si se tratara de una variable del bloque.
SCL está especialmente indicado para la resolución de los siguientes tipos de problemas:
1. Problemas matemáticos complejos como los siguientes ejemplos:
• Función de normalizado de variables analógicas.
• Cálculo de volúmenes y pesos de depósitos cónico-cilíndricos.
• Cálculo de tiempos de activación o funcionamiento de dispositivos.
En el presente documento se pretende, a la par que ir explicando los detalles del trabajo con la
herramienta de programación en SCL ( editor y compilador), diseñar funciones que resuelvan
todos los problemas tipo planteados, forzando al alumno a leer programas diseñados por otros
programadores cosa que necesariamente forma parte del aprendizaje de todo buen
programador. Al final de cada capítulo se van a dar también una colección de ejercicios
propuestos.
Para terminar con la introducción quisiera hacer unas recomendaciones acerca de la ubicación
de estos contenidos en el ciclo superior de Sistemas de Regulación y Control, de los
conocimientos previos que debe tener los alumnos para sacar el máximo aprovechamiento de
estos contenidos, de las herramientas necesarias para trabajar en SCL y del uso más racional
a mi modo de entender de SCL en una aplicación general de automatización.
Respecto al primer punto, mi opinión es que hay que enseñar diseño, antes que codificación
por lo que habría que seguir el camino clásico consistente, en enseñar las estructuras básicas
de control, las estructuras de datos y la programación en pseudo código de los algoritmos tipo,
antes que entrar en la codificación a cualquier tipo de lenguaje. De otro lado es necesario
tener un buen nivel de autómatas, antes de programar en SCL. Desde mi punto de vista, estos
dos factores hacen que la ubicación más deseable para estos contenidos, sea la de los
módulos de Desarrollo de sistemas secuenciales o de Desarrollo de sistemas de medida y
regulación o de Informática industrial pero siempre que se impartan después de haber dado
conocimientos generales sobre PLCs, que ya está así recomendado en los documentos sobre la
planificación del ciclo formativo.
Sobre las herramientas necesarias para trabajar con SCL mencionar que con disponer del
STEP-7 y de las herramientas SCL y PLCSIM es suficiente puesto que PLCSIM nos permite
depurar todas las funciones que desarrollemos con SCL.
Sobre el último punto y después de escuchar alguna recomendación de técnicos que trabajan
en este campo mi opinión es la siguiente. Ocurre sobretodo en alumnos que provienen de
formación informática, que tienen dificultad relativa en trabajar con diagrama de contactos
KOP, que al conocer SCL quieren resolverlo todo en SCL cosa realmente inadecuada por la
razón que la mayoría de personas (técnicos de mantenimiento, de puesta en marcha, etc.) que
tienen que leer programas de PLC, cambiarlos, depurarlos, etc. Entienden perfectamente KOP
pero pocos de ellos son capaces de entender y menos depurar y testear programas en SCL.
Por ello mi recomendación es que se destine SCL a resolver problemas concretos, muy bien
definidos y que esté muy bien documentado como tienen que funcionar y que se siga
utilizando KOP o FUP para enlazar todas las funciones y para programar la parte básica de la
aplicación.
Supongamos que queremos consultar el estado de la entrada E124.0 para activar o desactivar
la salida A124.0. En KOP o diagrama de contactos es tan simple como esto:
si (E124.0 = 1) entonces
A124.0 := 1;
sino
A124.0 := 0;
fsi
Este trozo de código, incorporado a una función concreta como FC51, tiene traducción directa
a SCL como:
Dejando aparte la traducción precisa de las distintas estructuras y operadores, del lenguaje
algorítmico a SCL, cuestión que abordaremos progresivamente, esta función deberá llamarse,
por ejemplo desde el OB1, para que sea ejecutada. El aspecto de la llamada será el siguiente:
Supongamos ahora, que queremos hacer lo mismo con la entrada E124.1 para activar la salida
A124.1 Evidentemente habrá que modificar el código fuente de la FC51, para incorporar esa
modificación, que pasará a ser:
Con esta modificación la llamada a la función no sufrirá ningún cambio, pero es obvio que
hemos obligado al programador a cambiar el código de una función escrita en SCL. Si quisieran
añadirse mas entradas y salidas que debieran recibir el mismo tratamiento, debería
modificarse de nuevo el código de la función SCL.
Veamos el ejemplo inicial reescrito usando dos parámetros, primero en lenguaje algorítmico.
si (entrada = 1) entonces
salida := 1;
sino
salida := 0;
fsi
facción
Es ahí en la llamada cuando asignamos un valor al parámetro formal entrada y una dirección
“puntero” al parámetro formal salida. Trabajando de esta forma no será necesario modificar el
código de la función para actuar sobre una salida adicional, sino que efectuaremos una
segunda llamada asignando nuevos valores actuales a los parámetros. La última versión de la
FC51 en el que actuábamos sobre dos salidas, quedará resuelto con dos llamadas a la FC52,
tal como se muestra a continuación:
Es obvio que pueden realizarse llamadas adicionales, de hecho pueden hacerse tantas como
sean necesarias.
Esta forma de trabajar tiene dos ventajas claras: La primera es que reducimos la memoria
ocupada por el programa al duplicar la llamada de la función en vez del código de la misma.
Las ventajas son más evidentes cuantas más veces tengamos que ejecutar la función y cuanto
más código tenga la función. La segunda ventaja hace referencia a la transparencia de la
función en el sentido de que es mucho mas clara una función con parámetros que sin ellos.
Una función con parámetros nos permite observar su funcionamiento viendo los valores de
respuesta, y además la introducción de un parámetro nos permite evitar la modificación del
código de una función para por ejemplo cambiar una dirección de memoria.
2.1.- Función para indicar si una variable está o no dentro de márgenes o fuera de
control.
Se trata de una función de vigilancia de una variable de proceso o de una variable interna del
control, de manera que si su valor está por encima de un máximo, introducido como
parámetro de entrada o por debajo de un mínimo también introducido como parámetro de
entrada nos activa una salida para aviso, alarma o indicación de fuera de control.
Podemos plantear una función que nos retorne alarma teniendo como entradas los tres
parámetros o variables mencionados. Escrita en lenguaje algorítmico tendremos:
var
alarma: bool;
fvar
retorna alarma;
ffuncion;
Vamos a continuación a explicar por pasos, como programar y probar esta función en SCL.
En primer lugar, hay que crear un proyecto en STEP 7 asociándole únicamente un programa
S7 puesto que no es necesario asignarle un hardware si no trabajamos con una aplicación
concreta. En segundo lugar hay que escribir el código fuente de nuestra función (existe una
traducción precisa de lenguaje algorítmico a SCL), usando para ello el contenedor fuentes de
nuestro proyecto, insertando dentro del mismo una fuente SCL. Por último, hay que compilar
nuestra fuente SCL para traducirla a lenguaje ejecutable por el PLC.
Insertamos dentro de la carpeta fuentes, una fuente SCL con el nombre “fueraDeControl”. Una
fuente SCL puede contener varias funciones así como otros tipos de bloques como OB y DB.
Abrimos la herramienta SCL haciendo doble clic sobre el objeto que acabamos de insertar para
pasar a la edición de nuestra función. Debemos plantearnos con que tipo de bloque S7,
básicamente FC o FB vamos a trabajar para introducir nuestra función, y como traducir la
declaración de variables, las estructuras de control y el resto de elementos contemplados en la
notación algorítmica.
En primer lugar hay que decir que tanto las funciones como las acciones de la notación
algorítmica se corresponden con FCs o FBs al traducirlos a SCL. SCL por tanto, no distingue
Realizado por: Fecha: 12/01/2007 Página: 11/56
Josep Cañigueral i Barnes IES SEP LA GARROTXA Versión: 1.1 Fichero: S7_SCL
Departament d’Educació
SCL
Introducción a la programación
Electricitat/Electrònica
Para facilitar la edición disponemos de plantillas, tanto de bloques como de parámetros como
de estructuras de control, por lo que empezamos insertando una plantilla de bloque FC.
De las líneas 3 a 8 hay que introducir la declaración de todos los objetos necesarios para la
correcta ejecución de la función.
En la figura pueden
observarse todos los tipos de
objetos que pueden
declararse, la sintaxis de la
declaración y el tipo de
módulo de programa S7 que
lo soporta.
Finalmente las líneas 9 y 10 de la plantilla de la FC y por supuesto todas las que fueran
necesarias, albergarían el código de la función con todas las estructuras de control necesarias.
La línea 11 asigna a la función el valor constante 100, para que sea su valor de retorno y con
la línea 12 finaliza la función.
Como solo debemos declarar parámetros de entrada y una variable temporal que se
corresponderá con la variable de retorno de la función, eliminamos el resto de apartados de la
declaración. Observar que la función se ha declarado con nombre simbólico. Esto nos obligará
a declarar una FC con el mismo nombre simbólico en la tabla de símbolos. A la tabla de
símbolos puede accederse directamente desde el menú herramientas. Indicamos FC120.
Nos queda compilar la función, programar su llamada en OB1 por ejemplo, y probarla.
Que nos indica que no existe ningún error y que nuestro bloque está listo para ser probado.
Antes hay que programar la llamada a la función. Para ello, desde el contenedor bloques
abrimos el OB1 en KOP e insertamos la FC120 en un segmento.
Para completar la llamada a una función (FC) hay forzosamente que asignar valores a los
parámetros de la función.
En el ejemplo, usamos la
función para controlar una
variable de proceso, cuyo
valor está en MD50 y sobre
la que hay que indicar una
alarma si su valor es menor
de 30 o mayor que 50,5. La
marca M100.0 estará a 1 si
hay alarma y a 0 en caso
contrario.
Arrancamos el simulador
desde el administrador
simatic y cargamos todos los
bloques en la CPU, para a
continuación colocar en RUN
el conmutador de estado del PLC.
Para probar la función insertamos en el simulador una variable general y le indicamos MD0,
con el formato regulación real, lo que nos permite cambiar su valor entre un mínimo y un
máximo como si fuera un potenciómetro.
En las figuras siguientes podemos observar la respuesta de la función para tres valores en
MD0.
En este caso, el valor de MD0 está entre 30 y 50.5 y por lo tanto, M100.0 está en 0 indicando
que la variable se encuentra dentro de márgenes.
En este segundo caso, la variable ha sobrepasado a valorMaximo por lo que el valor de retorno
de la función es 1, indicando alarma de proceso.
La misma situación se da cuando el valor en MD0 es inferior a 30, tal como muestra la
siguiente figura.
Con esto podemos hemos comprobado que la función se comporta tal como deseábamos por lo
que la damos por buena.
Supongamos que tenemos un sistema de control de una máquina o proceso donde intervienen
un PLC y una pantalla para la interfase de usuario, conectados por MPI, tal como muestra la
siguiente figura.
En la interfase de usuario
del sistema descrito se ha
previsto una pantalla de
configuración, donde se
desea poder cambiar el
valor de preselección de
varios temporizadores del
proceso.
Los temporizadores de la
gama del S7-300/400
utilizan el tipo S5TIME que
no es un tipo de datos
estándar y que tiene el
inconveniente de cambiar
la base de tiempo de manera automática, según el valor de preselección propuesto. Esto
quiere decir que según el intervalo de tiempo deseado para preseleccionar el temporizador
deberíamos cambiar el formato de preselección. Para facilitar la tarea del operador de planta
hemos diseñado la interfase para permitir la entrada directa de tiempos en segundos, en
formato real con dos decimales, por lo que podemos apreciar centésimas de segundo.
Con esto facilitamos la tarea por parte del usuario pero hemos de diseñar una función de
conversión para convertir el tiempo, introducido en formato real a formato S5TIME.
Escrita en lenguaje algorítmico la función tiene el aspecto que sigue. En ella utilizamos varias
funciones de conversión de tipos. En primer lugar disponemos, en la librería estándar de
funciones S7, de la función de conversión timeToS5time, que vamos a utilizar. Con ello
hemos reducido el problema a realizar una conversión realATime que en el ejemplo lo
realizamos del siguiente modo:
• Pasamos entrada de segundos a milisegundos (entrada*1000.0)
• Convertimos el resultado anterior (real) a entero 32 bits (realAEnter)
• Convertimos el resultado del paso anterior a time (entero 32 bits en mseg) con
(enterATime)
var
aS5T: s5time;
fvar
Para probar la función hemos diseñado una pequeña interfase en la pantalla TP270, que
describimos a continuación.
En la columna preselección
hemos incluido tres campos
de entrada con el valor de
preselección en segundos,
en formato real, de tres
temporizadores.
Los tres campos de salida situados bajo la columna Valor actual permitirán observar el valor
actual de cada uno de los temporizadores después de programar la correspondiente función.
De momento vamos a probar que la introducción de un valor real en cada uno de los
mencionados campos de preselección se traduce en el correspondiente valor S5TIME de
arranque del temporizador. Para ello programamos los tres temporizadores en el OB1. Debido
a que tanto la preselección como el BIT de arranque se modifican desde la pantalla hemos
definido los siguientes valores en DB10.
Con estas variables la programación de los temporizadores nos queda como sigue:
En primer lugar llamamos a la función REAL_TO_S5TIME a la que damos como entrada el valor
de preselección introducido en el correspondiente campo de entrada de la pantalla comentado
anteriormente. La respuesta de la función la descargamos en “D_TP”.T1_S5T_SP en formato
S5TIME. Este mismo valor, es el que introducimos como preselección del temporizador.
El arranque del temporizador lo realizamos con “D_TP”.T1_ON que se activa o desactiva desde
la pantalla. Cuando el temporizador finaliza el tiempo desactiva también el BIT de arranque. En
la siguiente diapositiva vemos el resultado de la función de conversión.
Los proyectos descritos en esta práctica y en el resto de prácticas de este manual están
incluidos en el CD que lo acompaña.
Como puede fácilmente intuirse, a menudo se hace necesaria la función contraria para
convertir a real el tiempo transcurrido en el temporizador. Esto podría usarse para visualizar
los tiempos actuales de temporizadores cuando están activados.
Para construir esta segunda función que vamos a denominar S5TIME_TO_REAL vamos a usar
la función S5TIME_TIME (FC33) del apartado funciones IEC de la librería estándar que
acompaña al paquete STEP 7.
Es una función muy parecida a la anterior pero quiero resaltar dos cosas:
• entrada es el parámetro que va a recibir al valor actual del temporizador del parámetro
DEZ del mismo, que esta declarado como WORD. Sin embargo SCL no dispone de la
conversión WORD_TO_S5TIME, por lo que no podemos traspasar la salida de DEZ a la
entrada de S5TI_TIM. Aunque hay otras soluciones, en nuestro caso lo hemos resuelto,
declarando lo que se denomina una vista sobre una variable. Si observamos el apartado
de variables de entrada vemos la declaración de entrada_S5T AT entrada: S5TIME.
Esto significa exactamente que entrada_S5T contiene lo mismo que entrada pero que
su contenido será interpretado como S5TIME, con lo que podemos pasar entrada_S5T
a S5TI_TIM sin ningún problema. Sin embargo, en la interfase de la función solo nos
aparecerá, entrada.
• Las conversiones aplicadas son: entrada_S5T pasa a formato TIME (miliseg), el
resultado se pasa a DINT y a su vez, este último a REAL. Este resultado se divide por
1000.0 para pasar a segundos y finalmente restamos este resultado del valor
preseleccionado para obtener el tiempo transcurrido en vez del tiempo restante.
Para probar la función solo nos queda llamarla en el OB1 colocando como salida de la misma
la dirección de DB10 asignada a los campos de salida de la pantalla.
La llamada de la función queda como sigue:
Gráficamente:
HI_LIM
VAR_PV
El gráfico corresponde a una entrada unipolar. Para un valor “INPUT” cualquiera entre 0 y
27648 la función nos responde con VAR_PV, que se correspondería con el valor de la variable
del proceso. Nótese que la función podría perfectamente dar valores por encima de HI_LIM
cuando INPUT varía de 27648 a 32767.
La formula que hay que aplicar se deduce de la ecuación de una recta que pasa por dos puntos
(x1, y1), (x2, Y2)
y = ((Y2-y1)/(x2-x1))*(x-x1) + y1
Aplicado a nuestro problema los puntos de la recta son (0, LO_LIM), (27648, HI_LIM)
Y la formula para el caso de rangos unipolares es:
Si el rango es bipolar los puntos son (-27648, LO_LIM), (+27648, HI_LIM) y la formula cambia
a la siguiente expresión
En primer lugar hay que tener un PC con STEP7 y las herramientas PLCSIM y por supuesto
SCL. Si se dispone de STEP7 Professional ambas herramientas de ingeniería vienen incluidas
en el mismo CD del STEP7.
Creamos el proyecto SCL001 e insertamos un programa S7, tal como muestra la figura
contigua.
A continuación hemos de crear la fuente SCL de nuestra función. Esto significa que cuando
trabajamos con SCL hay que primero escribir el código y luego compilarlo para generar el
bloque ejecutable por el PLC. Así que abrimos la carpeta fuentes y bien con el menú insertar,
bien con el botón derecho del ratón creamos una fuenteSCL(1), a la cual denominaremos
funcionEscalar. En nuestro proyecto existe ya otra fuente denominada volumenDeposito.
Tanto de una forma como de otra es posible insertar dos tipos de objetos relacionados con
SCL, fuente SCL y archivo de control de compilación de SCL. Optaremos por Fuente SCL y más
adelante ya trabajaremos con archivos de control de compilación.
A continuación abrimos la fuente que acabamos de insertar haciendo doble clic sobre ella. Se
nos abre la herramienta de trabajo en SCL, que tiene el aspecto de la siguiente figura. Abrimos
directamente el menú Herramientas, Preferencias
El menú insertar tiene un apartado interesante, destinado a facilitar la tarea del programador,
denominado insertar plantilla de bloque que vamos a usar inmediatamente. Al seleccionar
insertar, plantilla de bloque, FC aparecen las siguientes líneas en el editor.
VAR_OUTPUT La función entrega valores de salida sobre estos parámetros, pero no puede
consultar su valor mientras se ejecuta.
VAR_IN_OUT La función entrega valores de salida sobre estos parámetros pero además puede
consultar su estado o valor en cualquier momento.
Por ultimo deja espacio para el área de instrucciones y acaba con un valor constante de
retorno para la función y la palabra clave END_FUNCTION.
Para concretar nuestra función escalar debemos antes identificar los parámetros o variables
que necesitamos. Pueden deducirse de la propia expresión que antes hemos descrito. Se
tendrán los siguientes parámetros de entrada.
IN: Valor de entrada de la función. Es el valor que nos proporciona la tarjeta
analógica del PLC. Será un valor entero entre 0 - +32767 si el rango es unipolar y –32767 a
+32767 si el rango es bipolar.
HI_LIM: Valor máximo del margen del captador en unidades de ingeniería. Se
corresponde con el valor de la variable del proceso para la máxima señal proporcionada por el
captador: 10v, 20mA, etc. Será un valor real.
LO_LIM: Valor mínimo del margen del captador en unidades de ingeniería. Se
corresponde con el valor de la variable del proceso para la mínima señal proporcionada por el
captador: 0v, 4mA, etc. Será También un valor real.
Bipolar: Bit que indicará a la función que se trata de rangos bipolares si está en 1 o
unipolares si está en 0.
Botón compilar
fuente
En la siguiente figura ya
podemos observar el código de
la función. Una pequeña
aclaración antes de ver las
instrucciones. La variable IN es
entera y por tanto hay que
convertirla a real antes de poder
operar con el resto de variables.
En KOP habría que usar las
instrucciones de conversión.
Asignando el valor correcto a AR1 usar la misma expresión tanto para rango unipolar como
bipolar, simplificando la función.
Nos falta programar la llamada a la función y probarla. La llamamos desde el OB1 por ejemplo,
como un segmento en KOP. Observar como en la carpeta bloques de nuestro proyecto aparece
la función FC55.
Para comparar nuestra función con la estándar de Siemens vamos a llamar a las dos
simultáneamente comparando resultados con PLCSIM.
Después de
transferir el
programa al
simulador
visualizamos en el
propio simulador:
PEW256 para
forzar la entrada y
MD0 y MD4 para
ver los resultados.
En las siguientes
figuras tenemos
resultados para
entrada “0” para
entrada “27648” y
para entrada
“30000”.
En un silo de forma cónico cilíndrica se mide el nivel de carga con un sensor de ultrasonidos
que nos proporciona una señal proporcional a la altura entre la superficie del líquido o sólido
que contiene y el borde superior del silo hs. Se dan también las medidas del silo que se indican
en el gráfico siguiente.
hci = R2*h2/(R1-R2)
Vci = 1/3*(∏*R22)*hci
El volumen total del cono final del silo Vc será el volumen del cono con base de radio R1,
menos el volumen del cono con base, de radio R2
Vc = 1/3*(∏*R12)*(h2+hci) - Vci
Caso 1: h > h2
Caso 2: h < h2
En este caso hay que determinar el radio R correspondiente al círculo donde está la superficie
del producto almacenado. Por trigonometría
R = R2*(h + hci)/hci
Con esta introducción podemos ya plantear el diseño de la función que queremos desarrollar.
Para facilitar los cálculos definiremos también unas variables temporales que usaremos para
almacenar resultados intermedios.
Variables temporales
hci, h, R, Vci, AR1 Reales
Hemos añadido una variable temporal denominada error que vamos a usar para la llamada de
la función scale, y hemos declarado h como variable de salida en vez de temporal por
considerarla útil para determinadas aplicaciones.
Para llamar a la función scale lo más fácil es acudir al menú insertar, cogiendo la opción
llamada de bloque. Esto produce los resultados que se observan en las siguientes diapositivas.
Si hay valores de
entrada incorrectos
pone a cero las
salidas e indica
error en RetValue.
Si los valores de
entrada están en el
rango correcto, da
un cero en RetValue
y escalamos la
entrada del sensor
entre 0 y la altura
total del tanque,
h1+h2.
Determinamos los
valores auxiliares
que hemos
comentado en el
planteamiento.
Aplicamos dos
fórmulas según que
el nivel esté por
encima o por debajo
del cono.
Calculamos el peso,
el volumen total y el
porcentaje de
llenado.
Vemos las variables de entrada a las cuales asignamos valores de prueba para comprobar la
función. A la variable InSensor le asignamos el canal analógico PEW256. Por último a las
variables de salida les asignamos registros del área de marcas para observar su valor en el
simulador.
Resultados de la prueba para depósito lleno, depósito vacío y con dos valores intermedios.
Tener en consideración que el volumen está en m3, la altura en metros y el peso en Kg.
Con valores intermedios: 4,78 metros de altura de producto, que representa un 54,82% de
capacidad y con 1,5 metros lo que se traduce en un 5,09% de capacidad.
Cualquiera de los dos ejercicios anteriores puede programarse en KOP aunque el código a
escribir es bastante más extenso.
No seria adecuado actualizar el tiempo solo al finalizar el ciclo ya que el valor visualizado
tendría siempre el error del tiempo correspondiente al último ciclo.
La función medirTiempo que se va a desarrollar va a tener como entrada la señal on off del
dispositivo o proceso y otra señal para poder poner a cero los acumuladores cuando se desee.
Esta última podría provenir del terminal de operador o scada y su actuación estar protegida
con un password para evitar que pudieran borrarse los acumuladores de manera accidental.
El formato fecha y hora CPU, (DT date and time) es un formato de datos complejo que ocupa 8
bytes en memoria y por lo tanto deberemos emplear funciones incluidas en la librería estándar
del Step 7 para tratarlo. Como el volumen de datos involucrado en la función va a ser grande
comparado con las dos funciones anteriores, y como además será una función que se podrá
utilizar bastantes veces en un mismo proyecto vamos a desarrollar la función como un FB. Con
ello los parámetros que no se quieran incluir en la interfase se declaran como estáticas y sus
valores actuales van a quedar almacenados en el correspondiente DB de instancia del FB.
Con todo esto, en este ejercicio vamos a practicar con formatos DT, llamadas de funciones en
SCL, llamadas de FB y multiinstancias.
Entrada Salida:
DP_NC_ACC Número de ciclos acumulado en dispositivo o proceso
DP_T_ACC Tiempo acumulado de funcionamiento en dispositivo o proceso
DP_T_UC Tiempo último ciclo en dispositivo o proceso
Salida:
DP_DT_IUC Fecha y hora inicio último ciclo en dispositivo o proceso
DP_DT_FUC Fecha y hora finalización último ciclo en dispositivo o proceso
Estáticos
DP_FUP Flanco de subida para la señal on off del dispositivo o proceso
DP_A_FUP Auxiliar para la obtención del flanco anterior
DP_FDOWN Flanco de bajada para la señal on off del dispositivo o proceso
DP_A_FDOWN Auxiliar para la obtención del flanco anterior
DT_UMIN Fecha y hora del último registro
Empezamos editando nuestra función insertando en la carpeta fuentes del proyecto SCL001 la
fuente SCL medirTiempo. Vamos al editor de SCL e insertamos plantilla para bloque FB y
realizamos la declaración de variables especificada anteriormente.
En este ejemplo he declarado las dos variables DP_DT_IUC y DP_DT_FUC como parámetros de
salida si bien podrían muy bien ser consideradas como variables estáticas. Mi opinión es la
siguiente: Si esas dos variables tienen que visualizarse en el sistema HMI, si son declaradas
como parámetros de salida será posible enlazarlas con otras variables de un DB específico para
el sistema HMI. Si por el contrario son declaradas como variables estáticas, el sistema HMI
deberá leerlas del propio DB de instancia del FB. Ambas soluciones son posibles aunque por
estilo de programación prefiero la primera de ellas. Además el hecho de incluirlas como
parámetros de salida nos va a permitir practicar con el formato DT.
Respecto a las tareas en las que podemos dividir nuestra función podemos enumerarlas como
sigue:
• Elaborar flancos de subida y bajada de la señal de marcha del proceso.
• Anotar fecha y hora de inicio de ciclo cuando aparece el flanco de subida, poner a cero
el contador de horas del último ciclo e incrementar el acumulador de maniobras o
ciclos.
• Mientras esté en ON la señal del proceso leer el reloj de la CPU y comparar la fecha y
hora actual con la del último registro para detectar el paso de un minuto. Cuando eso
ocurra incrementar acumuladores y actualizar registro.
En el flanco de
subida
Incrementamos el
contador de ciclos o
maniobras. Leemos
la hora del sistema
con SFC1 y la
registramos como la
fecha y hora de inicio del último ciclo o maniobra (DP_DT_IUC). Guardamos esta fecha y hora
en DT_UMIN para comparaciones posteriores. Ponemos a cero el contador de horas del último
ciclo.
Leemos el reloj de la CPU con SFC1 y comparamos el DT (date and time) correspondiente, con
el registrado en el inicio del ciclo. Esto último lo hacemos de la siguiente forma: Usamos la FC
34 del apartado funciones IEC de la librería estándar del Step7 para restar dos DT y encontrar
el tiempo transcurrido entre los dos DT. Si el tiempo transcurrido es igual o superior a un
minuto incrementamos los acumuladores de tiempo. Dos aclaraciones: Para la comparación
debemos convertir el formato time a entero y como en realidad contiene el tiempo en
milisegundos comparamos con los milisegundos que tiene un minuto. Para sumar a los
acumuladores pasamos a real el tiempo en milisegundos y lo dividimos por el número de
milisegundos que tiene 1 hora antes de realizar la suma con el acumulador correspondiente.
Por último actualizamos DT_UMIN para posteriores comparaciones.
En el flanco de bajada.
Como en los casos anteriores lo llamamos desde el OB1 y lo probamos con el simulador.
Al llamar al FB hay alguna diferencia con respecto las llamadas a FCs. En primer lugar la
asignación de valores a los parámetros puede dejarse en blanco. En este caso el FB trabajará
con los valores del DB de instancia, el número del cual se nos pide en la cabecera de la
llamada. Si el número de DB no existe nos pide si queremos generarlo. Finalmente la llamada
quedará como sigue:
La señal que nos llega de un captador lleva un rizado incorporado que puede tener diversas
causas a veces difíciles de eliminar, que nos provoca que el valor numérico de la conversión de
la variable sufra continuas variaciones, que por ejemplo, si la variable es visualizada en una
pantalla provoque un efecto molesto. Para solucionar el problema introducimos un filtro entre
el valor que nos llega directamente de la tarjeta analógica y el valor que damos para la
variable, que finalmente será el que se va a visualizar.
El filtro que se propone consiste en almacenar una determinada cantidad de valores que se va
a entrar como parámetro, calcular la media de estos valores y dar esta media como valor de la
variable.
En este caso dado que necesitamos un array para almacenar los valores que nos van llegando
por la entrada, vamos a usar un FB. De esta forma los parámetros van a quedar en el DB de
instancia del FB.
Se trata del siguiente problema: Un robot cartesiano ha de almacenar tres tipos distintos de
piezas cilíndricas que se distinguen básicamente por su color, pueden ser negras, naranjas o
de color gris claro, y por que estas últimas son metálicas mientras que las negras y naranjas
son de materiales plásticos.
Las piezas son almacenadas según el tipo, en tres filas de 13 piezas cada fila distanciadas
entre ellas 60mm, según el eje x. El origen se encuentra situado en el extremo superior
derecho del sinóptico que se muestra a continuación y la primera pieza de cada fila está
situada en las coordenadas (100, 250) para las piezas negras, (100, 350) para las piezas
metálicas y (100, 450) para las piezas naranjas.
El tipo de pieza se detecta antes de la entrada al almacén por medio de tres detectores, uno
de capacitivo (detecta cualquier tipo de pieza), otro de inductivo (detecta solo las metálicas) y
otro de reflexión directa que detecta las naranjas y las metálicas pero no las negras. Los tres
detectores se encuentran conectados a las entradas:
E0.0 inductivo
E0.1 capacitivo
E0.2 reflex
La presencia o no de pieza en cada una de las posiciones del almacén se guarda en un array
de bits, almacenado en el DB10, de manera que un 1 en el índice [11, 2] del array significa
que hay una pieza metálica en la posición 11.
Se pide una función que teniendo como entradas las señales de los tres detectores y la tabla
de posiciones del DB nos de cómo salidas el tipo de pieza (negra =1, metálica =2 y naranja
=3) y las coordenadas de la posición de descarga para las funciones de posicionamiento de los
ejes.
const
delta_x: real = 60.0;
inici_x: real = 100.0;
fconst
var
j: int;
trobat: bool;
coordy tabla[3] de real;
fvar
si (capacitivo = 1) entonces
si (inductivo = 1) entonces
tipoPieza := 2;
sino
si (reflex =1) entonces
tipoPieza := 3;
sino
tipoPieza := 1;
fsi
fsi
fsi
{Determinar posiciones}
si tipoPieza <> 0 entonces
j:= 1;
filaLlena := 0;
trobat := tablaPosiciones[j, tipoPieza] = 0;
mentre trobat = 0 i j <= 13 fer
trobat := tablaPosiciones[j, tipoPieza] = 0;
j := j+1;
fmentre
si j>13 entonces
filaLlena := 1;
sino
posx := inici_x + desta_x * (j-1);
posy := coordy[tipoPieza];
fsi
fsi
facción
Para probar la función trabajaremos con el proyecto SCL_004, en el cuál hemos insertado la
fuente SCL buscarPosicionesCarga. La traducción de esta función a SCL se muestra a
continuación.
Nos falta como siempre, llamar a la función desde por ejemplo el OB1 i probar su
funcionamiento. En este caso, será necesario también crear la correspondiente estructura de
datos en el DB10.
En primer lugar probamos los tres tipos de pieza con el almacén vacío. Los resultados pueden
verse en las siguientes figuras.
Para pieza metálica nos da el tipo de pieza correcto y la posición de la primera pieza en la fila
correspondiente es también correcta.
Para ello insertamos en nuestro proyecto una tabla de datos con los valores de la tabla de
posiciones para poder ocupar posiciones a voluntad.
Para dar definitivamente como buena a la función vamos a probarla para la situación de fila
llena. Para ello modificamos la tabla de posiciones como sigue: