Está en la página 1de 36

Cap.

03 Programación AWL

I. OBJETIVOS
Operaciones a nivel de bits, Bytes, Word, uso de punteros para el acceso de variables del tipo bit, Word,
DWord. Uso de comandos de saltos para el control del programa y de anidamiento. Rutinas típicas en AWL
(Ordenación de Burbuja, determinar el número menor, determinar el número mayor)

II. DESARROLLO

II.1.- ESTRUCTURA DE UN PROGRAMA EN AWL


Para empezar debemos de abrir un nuevo proyecto, deje el OB1 en KOP y todas las nuevas funciones creadas
póngalas en AWL

Definamos la siguiente tabla de variables.


Cap. 03 Programación AWL

AWL es el acrónimo de la palabra alemana AnWeisungsListe que define el lenguaje de programación


de PLC basado en instrucciones o secuencias de comandos, traducido al español quedaría como listado de
instrucciones, también se usa el acrónimo en inglés de STatement List (STL). Este es un lenguaje nativos para
los que aprendieron a programar en PLC’s siemens. Casi todas las maquinas que vienen de Europa, están
programada en su mayoría en este lenguaje. La estructura de un lenguaje de programación AWL es la
siguiente:

AWL se refiere exclusivamente al lenguaje de programación mediante secuencias de comandos, la


estructura del programa (OB, FC, FB, DB), sigue siendo la misma que se vio en el capítulo 02. Así como el
lenguaje LAD/KOP, es una forma natural para trabajar con lógica de relevadores y estos a su vez están
enfocados principalmente en resolver problemas a nivel de bits, el lenguaje AWL se usa para resolver
problemas en donde se trabaje con anidamientos, datos de más de un bits (byte, Word, DWord), saltos y
subrutinas. Juntos el KOP y AWL, resuelven la mayoría de los problemas de automatización. En algunas
circunstancias un lenguaje es más intuitivo que el otro. Por ejemplo el programa de escalera para el arranque y
paro de una bomba, resulta más conveniente para el técnico de servicio, porque ellos están más
acostumbrados a los diagramas eléctricos. También para el programador le es más simple programar esa
lógica en escalera que tenerlo que hacer en AWL. Sin embargo pensemos en un programa más complicado,
como por ejemplo el arranque de una bomba de entre diez bombas en donde se tiene que seleccionar arrancar
la bomba que tiene el menor número de horas trabajadas, resultaría muy laborioso si no que casi imposible
realizarlo en lenguaje de KOP, mientras que en AWL, este problema se limita a aplicar el método de la burbuja
para ordenación de números. Para este ejemplo, una buena práctica de programación sería crear dos
funciones, una para el arranque y paro de las bombas en LAD/KOP tal como se vio en el capítulo 02, y otra
función para aplicar la ordenación del número de horas trabajadas mediante el método de la burbuja.
Cap. 03 Programación AWL

II.2.- RLO, BR Y ACUMULADORES


Dentro de los aspectos de programación de AWL, hay tres tópicos de extrema importancia para poder
entenderlo: RLO, BR y ACCs.
RLO, Bit de resultado lógico (Result Logic Operation). Cuando se realizan operaciones lógicas a nivel
de bits, el resultado se pone en un bit llamado RLO (Result Logic Operation). En AWL una operación lógica a
nivel de bits (AND, OR, XOR, etc.) empieza con la primera consulta y termina con la última asignación. Por
ejemplo:

A I0.0 es una consulta


=Q0.0 es una asignación.

A I0.0 se lee: “¿Cuál es el valor de la entrada I0.0?”, una vez que se hizo esta consulta, el RLO se
modifica según el resultado de esta consulta, si el resultado de esa consulta es 1, el RLO se pone en 1. la
expresión =Q0.0, con el signo de igual, indica que se realiza una asignación, asignando el valor del RLO a
Q0.0.

S y R, también son sentencias de asignación. S asigna 1, R asigna cero. Estas asignaciones se ejecutan si el
RLO vale UNO.

A I0.1 //Primera y única consulta, modifica el RLO.


S Q0.3 //Asignación, pone a 1 a Q0.3 si RLO es igual a 1, aquí acaba la cadena lógica.

A I0.0 //Primera y única consulta, modifica el RLO


R Q0.3 //Asignación, pone a 0 a Q0.3 si RLO es igual a 1, aquí acaba la cadena lógica.

La primera consulta se puede hacer también con OR o XOR. Para iniciar la secuencia de operaciones
lógicas no importa que operación lógica se use en la primera consulta. La primera consulta se usa para
determinar el primer RLO, las siguientes operaciones lógicas (AND, OR, XOR) le irán dando el sentido al listado
de operaciones lógicas.

La siguiente figura ejemplifica este hecho.

Los comandos usados para operadores lógicos a nivel de bits, son:

A Operador lógico AND


O Operador lógico OR
X Operador de OR Exclusiva

AN Operador lógico NOT AND


ON Operador lógico NOT OR
XN Operador de NOT OR Exclusiva
Cap. 03 Programación AWL

Después de realizar la primera consulta, el RLO se combina lógicamente con la consulta siguiente.
Pudiera haber más consultas hasta encontrar la última expresión de asignación, con ello se da por terminado la
cadena de operaciones lógica que se inició con la primera consulta. De esta manera, se puede iniciar otra
secuencia de consultas lógicas con un nuevo RLO. Un ejemplo aclara este punto.

A I0.0 // Primera consulta, el RLO se modifica con esta primera consulta, NO IMPORTA CUAL ERA EL ANTERIOR RLO
A I0.1 //Segunda consulta. Aquí se toma en cuenta el RLO anterior y se hace un AND y el resultado se almacena en el RLO
=Q0.0 //El valor del RLO se asigna a Q0.0
=Q0.1 //El valor del RLO se asigna a Q0.1, y como ya no hay más asignaciones, con esto se da fin a la cadena de operaciones lógicas. .
. //A partir de aquí puede haber una primera consulta, para iniciar una nueva lista de instrucciones lógicas

A manera de ejemplificar la primera consulta y el fin de la secuencia de operaciones con la asignación,


observe las siguientes instrucciones. Aunque es una mala práctica poner una primera consulta con un operador
que no represente la idea de las instrucciones lógicas, nada impide que se pueda hacer, en este ejemplo se usa
X y A como primera consulta, sin embargo evite el uso de estas malas prácticas. Use paréntesis para agrupar la
precedencia de operadores lógicos. Si va a realizar operaciones a nivel se bits, se recomienda ampliamente el
uso del lenguaje de esquema de contactos (KOP), deje el AWL para situaciones más complicadas.

BR Resultado Binario (Binary Resut). Cuando el listado de operaciones lógicas se va haciendo extenso,
es necesario agrupar las operaciones lógicas con paréntesis. Las operaciones entre paréntesis arrojan un
resultado que es almacenado en un bit llamado BR el cual pertenece a la palabra del sistema llamado Status
Word (STW). No es necesario preocuparse por este bit BR, ya que el CPU se encarga de evaluar estas
expresiones y para el programador resulta transparente, sin embargo es necesario mencionarlo para entender
claramente cómo se ejecutan las operaciones lógicas entre paréntesis. Un ejemplo ayudará a clarificar este
tema.

Tanto el RLO y el BR pueden ser cambiados de valor, use las instrucciones SET y CLR para poner
respectivamente en uno o en cero al RLO; use la expresión SAVE para pasar el valor del RLO a BR. Un
ejemplo ayuda a aclarar estos temas.
Cap. 03 Programación AWL

El siguiente código en AWL, evalúa las entradas ED03 y ED04 y realiza una doble asignación del RLO a
las salidas SD01 y SD02. El resultado tal y como se ve con los valores de la columna “Valor”, es que SD01 y
SD02 tienen el valor de 1.

El mismo ejercicio anterior pero hemos introducido la instrucción CLR y SET antes de la instrucción
=”SD02”. Con ello mandamos el RLO a 0 o a 1. Como puede ver, SD01 no responde a las entradas ED03 y
ED04.

EL RLO también puede negarse, por lo que estas instrucciones serian equivalentes.
Cap. 03 Programación AWL

ACUMULADORES ACC1/ACC2: AWL usa dos registros de 32 bits y los denomina Acumulador Uno
(ACC1) y Acumulador Dos (ACC2). Todas las operaciones lógicas y aritméticas, funcionan alrededor de estos
dos acumuladores. Las instrucciones básicas sobre los ACC son las operaciones de carga (L) y transferencia
(T), estas instrucciones se hacen sin importar el contenido del RLO. El contenido de los acumuladores puede
intercambiarse, con las siguientes operaciones:

Estas operaciones se realizan sin consultar el RLO.

Hagamos un ejemplo de Carga (L) y Transferencia (T). Supongamos que queremos pasar el valor de la
Entrada Analógica 01 a la Salida Analógica 01. La instrucción L carga el contenido del operando EA01en ACC1
y la instrucción T, transfiere el contenido del ACC1 al operando SA01. Programe lo siguiente y observe:
Cap. 03 Programación AWL

Si a una instrucción de carga le sigue una nueva instrucción de carga, el contenido del ACC1 se pasa al
ACC2. Y el ACC1 tiene el valor de la última instrucción de carga. Vea el siguiente ejemplo donde en la línea 1,
se carga EA01 al ACC1, en la línea 2 hay una nueva instrucción de carga, cargando EA02 al ACC1, el
contenido de la primera carga se corre al ACC2, en la línea 3, se transfiere lo que hay en el ACC1 a la salida
SA02.

Modifiquemos el ejemplo usando la función TAK, que sirve para intercambiar el contenido de ACC1 y ACC2.

Modifiquemos el ejemplo usando la función POP, que sirve para mover el contenido de ACC2 y ACC1.

La operación +, sirve para sumar un valor constante al ACC1, sin modificar el ACC2, Observe el uso de la
operación +

Realice la siguiente instrucción y ponga en modo de visualización en DEC. Como podrá observar, el resultado
de dividir 721 por 195, no es el cociente esperado.
Cap. 03 Programación AWL

Ponga ahora la visualización en hexadecimal, verá que el resultado se pone en los dos Word del ACC1. En la
Word menos significativa pone el cociente y en la más significativa pone el residuo. Observe que
16#0088_0003, está en hexadecimal. Así que 88 es el 136 en decimal y 3 en hexadecimal es el 3 en decimal.
Compruebe que 721=3X195+136.

Ejercicios:

1. Practique las operaciones PUSH, CAW, CAD.

2. Practique las operaciones aritméticas y vea en la ayuda la descripción de cada instrucción aritmética,
observe sí el ACC2 es afectado. En versiones del Step 7 Clásico el ACC2 es afectado.

II.3.- INSTRUCCIONES DE SALTO.


A continuación se listan todas las instrucciones de saltos. Las más usadas son JU, JC y LOOP.
Cap. 03 Programación AWL

Los bloques de programa pueden terminarse en cualquier parte usando las instrucciones de BEC, BEU
y BE. La instrucción BEC termina un programa cuando el RLO=1, el control del programa se regresa a la
instrucción siguiente de donde fue llamada la función. La instrucción BEU termina el programa sin importar cuál
es el valor del RLO. BE hace lo mismo que BEU, pero BE solo se puede usar una sola vez al final del programa,
mientras que BEU se puede repetir en un programa. BE puede no ponerse al final del programa y no pasa
nada, es una instrucción opcional al final del programa.

A continuación haremos un programa simple usando JC. EL programa se usa para mover la IW256
selectivamente a la salida QW256 o QW258, dependiendo si se activa la entrada I0.2 Observe que también se
han programado la instrucción BEU, en caso que el RLO=0, el JC no se activa y se ejecuta la instrucción del
renglón 4 transfiriendo ACC1 a la Salida Analógica 1, luego de esto, la instrucción BEU, hace que el control del
programa regrese a la siguiente instrucción de donde fue llamada esta función. Si RLO=1, JC salta a la etiqueta
TSA, transfiriendo ACC1 a la Salida Analógica 2. El programa llega a su fin y se pone la instrucción BE, esta es
opcional y puede no ponerse, como quiera el programa termina y el control del programa regresa a la siguiente
instrucción de donde fue llamada esta función

Podemos cambiar BEU usando una JU para que brinque al final del programa, así como también
podemos quitar BE y el programa funcionara igual. Compruebe que hacen lo mismo estos dos programas.
Cap. 03 Programación AWL

Ahora usaremos la instrucción Loop a través de un ejemplo de programa que llena un arreglo de 5
Word del MW100 al MW108 con los número del 5 al 1.

Vea el siguiente arreglo de cómo debe quedar el resultado de la programación:

NOTA: #Counter es una variable local de tipo Temp declarada en la sección de parámetros de esta
función. Observe que la instrucción se realiza mientras el #Counter no es cero. Cuando el #Counter es
cero, ya no salta a LBL1, entonces se sale del LOOP.

Como podrá observar, en el ejercicio anterior, moverse por el arreglo no es la mejor manera, lo ideal sería
indexar los arreglos y moverse a través de un índice que se incremente con el #Counter, pero en Step 7 clásico
o TIA portal no hay esta solución. TIA portal tiene un tipo de dato tipo Array y las funciones WriteToArray y
ReadFromArrayDB, con estas funciones puede accederse a los DB de tipo arreglos. Sin embargo estas son
funciones bien definidos que aunque facilitan la programación para acceder a los DB de tipo Array, disminuyen
la potencia que tendría el uso del direccionamiento por puntero, con la cual puede accederse a todo tipo de
direcciones ya sea Entradas y Salidas, así como de tipo memoria interna M, veamos el siguiente ejemplo de uso
de los Array.
Cap. 03 Programación AWL

Agregue un nuevo tipo de Bloque de Datos de tipo Array, declárele diez elementos de tipo DInt (puede ser de
cualquier otro tipo, pero para este ejemplo y para que concuerde con los valores que se van a escribir, déjelos
de tipo DInt

Realice la siguiente programación y vea la tabla de observación de variable el comportamiento del DBArray.

Ponga en línea el DB1 y observe sus valores


Cap. 03 Programación AWL

II.4.- USO DE APUNTADORES


PUNTEROS
Un parámetro del tipo POINTER es un índice que puede señalar a una variable específica. Ocupa 4 bytes (32
bits) en la memoria. La variable declarada como puntero debe ser tipo DWord. La información de un puntero se
organiza de la siguiente manera:

Usa dos bytes + 3 bit, todo en una doble word


Byte n Byte n+1 Byte n+2 Byte n+3
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 y y y y y y y y y y y y y y y y x x x
Ejemplo p#128.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
16 bit = 2 Byte Address bit
addr
ess

Nota
En la tabla anterior el número binario 1000000 en rojo corresponde al número decimal 128 y en azul el numero
decimal 0.

Para formar el puntero se ocupa el siguiente formato. P#y.x, donde y son los bytes address y x es el bit
address. Tomando este ejemplo y usando estos datos formaríamos el puntero P#128.0

Al realizar el comando L P#128.0, hemos dado la instrucción que se cargue el ACC1 con los valores 128
cargados a partir del bit 3 y 0 en los primeros 3 bits, como se puede observar en el cuadro anterior. Al escribir
esta sintaxis, indicamos que esa carga es de tipo puntero. Una vez que tengamos cargado el ACC1, lo
transferimos a una variable de tipo Doble Word, de tipo M o variables locales, en este momento esta variable se
convierte en un índice. Ejemplo de la transferencia seria: T MD100. Esta instrucción inmediatamente después
de cargar el puntero, indica que MD100 va ser un índice que empieza en el byte 128 y en el bit 0. Pudiéndose
usar de las formas siguientes:

1. M[MD100] esta expresión usada de esa manera indica que es la dirección M128.0
2. MB[MD100] esta expresión usada de esa manera indica que es la dirección MB128
3. MW[MD100] esta expresión usada de esa manera indica que es la dirección MW128
4. MD[MD100] esta expresión usada de esa manera indica que es la dirección MD128

NOTA: observe que la memoria al que es transferido el apuntador debe ser tipo doble Word. Durante el
proceso de carga puede transferirlo a un tipo Word, pero al momento de usarlo como índice entre paréntesis le
va arrojar error de sintaxis.

Un ejemplo completo sería. Usar apuntadores para realizar las siguientes instrucciones:

A I0.0
=Q 0.0

Con apuntadores quedaría:

L P#0.0 //Carga en ACC1 el valor 0.0 (rellena el ACC1 con ceros)


T MD50 //MD50, contiene 0.0, el puntero o índice debe ser tipo doble word
A I [MD50] //es igual a I0.0, el índice toma el valor del puntero
= Q[MD50] //es igual a Q0.0, el índice toma el valor del puntero
Cap. 03 Programación AWL

Usar apuntadores para realizar las siguientes instrucciones:

A I0.7
=Q 0.3

Las señales I0.7, y Q0.3 tenemos que pasarlas al formato de puntero P#y.x. Debido que el formato de puntero
es similar a como se representan las memorias a nivel de bits (ejemplo M100.0, I0.5, Q5.5), la conversión es
inmediata sin hacer ningún tipo de cálculos a nivel de bits.

Para la entrada quedaría y=0, x=7


Para la salida quedaría y=0, x=3

L P#0.7 //carga el formato de puntero byte=0, bits=7


T MD54 //carga MD54 con el hexadecimal 16#0000_0007

L P#0.3 //carga el formato de puntero byte=0, bits=3


T MD58 //carga MD58 con el hexadecimal 16#0000_0003

A I[MD54] //consulta la entrada I0.7


= Q[MD58] //asigna el RLO en la salida Q0.3

Observe que la instrucción L P#0.8 arrojará un error de sintaxis. Esto sucede porque L P#0.8, no tiene sentido
ya que el formato P#y,x, permite solo tres bits en la parte x, entonces el número máximo que se puede formar
es el número 7.

Incrementar el índice del lado de los bits P#y,X. Una vez que se conoce el formato tipo puntero y la forma
en que usan, se pueden hacer cosas interesantes, como por ejemplo incrementar el índice de los bits. Esto se
hace simplemente sumando uno a la variable que se usa como puntero. La única precaución es que el
incremento tenga como limite el número 7. Programe el siguiente ejemplo:

L P#0.0 //carga el formato de puntero byte=0, bits=0, se carga en ACC1, todos los bits en 0

T MD62 //MD62 contiene el índice que apunta a 0.0

A I[MD62]

=Q0.3

+ 1 //suma 1 al contenido de ACC1. Ahora ACC1 vale 0.1

T MD62 //

A I[MD62]

=Q0.2

+ 1 //suma 1 al contenido de ACC1. Ahora ACC1 vale 0.2

T MD62 //

A I[MD62]

=Q0.1 //ultima asignación, termina la cadena lógica


Cap. 03 Programación AWL

+ 1 //suma 1 al contenido de ACC1. Ahora ACC1 vale 0.3

T MD62 //

A I[MD62] // primer scan no importa si es con A, O o X

+ 1 //suma 1 al contenido de ACC1. Ahora ACC1 vale 0.4

T MD62 //

O I[MD62]

+ 1 //suma 1 al contenido de ACC1. Ahora ACC1 vale 0.5

T MD62 //

O I[MD62]

+ 1 //suma 1 al contenido de ACC1. Ahora ACC1 vale 0.6

T MD62 //

O I[MD62]

+ 1 //suma 1 al contenido de ACC1. Ahora ACC1 vale 0.7

T MD62 //

O I[MD62]

= Q0.0 //ultima asignación, termina la cadena lógica

El ejercicio anterior es solo para ambientarse con los punteros, pero si va trabajar con bits, recurra a la
programación KOP/LAD.

Incrementar el índice del lado de los bytes P# y,x. A continuación vamos a incrementar el puntero del lado de
los bytes P#y.x, Observe que los bytes que se van incrementar están desplazados a la izquierda en 3 bits, ya
que los primeros 3 bits, son para la parte de “bits address”. Si esto no le queda claro regrese a la figura donde
se definió el patrón de bytes address y bits address. Tome en cuenta que sí se quiere mover a través de un
arreglo de bytes, el incremento es de 1, pero si se va a desplazar en un arreglo de palabras, el incremento es
en 2 bytes, de forma similar si el incremento es en un arreglo de doble palabra, el incremento es de 4 bytes.
Ejemplo:
Cap. 03 Programación AWL

Debido a que se requiere incrementar el índice que apunta a los bytes y este índice está desplazado 3 bits a la
izquierda, primero tenemos que correr el incremento 3 bits a la izquierda y luego hacer la suma del índice. Tome
en cuenta que se si incrementa el apuntador sin hacer el corrimiento, estaría sumando ese incremento de lado
de los 3 bits del bits address. Veamos un ejemplo, supongamos que queremos apuntar al byte 405 y luego
incrementarlo en uno hasta el 408, en cada caso vamos a cargar el byte con un valor constante:

L P#405.0 //apunta al byte 405 ACC1=2#00000000_00000000_00001100_1010_1000


T MD64 //carga el índice 405 en el MD64

L 1 // ACC1=2#00000000_00000000_00000000_00000001, ACC2=P#405.0
T MB[MD64] // transfiere el numero 1 a MB405. //MB405=1

SLD 3 // ACC1=2#00000000_00000000_00000000_00001000, ACC2= P#405.0


+D // Suma ACC1 y ACC2
T MD64

L 2 // ACC1=2
T MB[MD64] //MB406=2

L P#405.0 //apunta al byte 405 ACC1=2#00000000_00000000_00001100_1010_1000


T MD64 //carga el índice 405 en el MD64
L2 // ACC1=2#00000000_00000000_00000000_00000010, ACC2=P#405.0
SLD 3 // ACC1=2#00000000_00000000_00000000_00010000, ACC2= P#405.0
+D // Suma ACC1 y ACC2
T MD64

L 3 // ACC1=3
T MB[MD64] //MB407=3

L P#405.0 //apunta al byte 405 ACC1=2#00000000_00000000_00001100_1010_1000


T MD64 //carga el índice 405 en el MD64
L 3 // ACC1=2#00000000_00000000_00000000_00000011, ACC2=P#405.0
SLD 3 // ACC1=2#00000000_00000000_00000000_00011000, ACC2= P#405.0
+D // Suma ACC1 y ACC2
T MD64

L 4 // ACC1=4
T MB[MD64] //MB408=4

El ejercicio anterior se realizó solo para mostrar cómo se incrementa el índice del lado de los bytes address. Sin
embargo para que la programación sea eficiente, tiene que hacerse mediante un LOOP.
Cap. 03 Programación AWL

Esta tabla resume las operaciones que se hicieron anteriormente. Observe que se puede incrementar la
direccon tipo puntero, pero también se puede crear un índice e irlo incrementando y sumando al puntero. A
menos que se indique lo contrario siempre incrementaremos la dirección puntero.

LOOP usando punteros. Ahora que ya sabemos cómo movernos por los índices Address Bytes y Bits address,
podemos realizar un LOOP para movernos por los elementos de un arreglo. Vamos rellenar diez palabras
desde MW300 a MW318, con los valores consecutivos del 0 al 9. Haga una tabla de Observación y Forzado
con estas palabras para que vea el resultado. . A continuación cree una función FC8, declare como temporales
las siguientes variables

L P#300.0 // ACC1=P#300.0, carga un valor para que apunte al byte 300, bits 0
T #PointerMW // Transfiere ACC1 a la variable que será el índice puntero
L 0 //ACC1=0, inicializa el valor con que se rellenara las MW300
T #ValueMW // Como las MW admiten solo Word, se cargará como ejemplo 10 enteros (0 al 9)

L 10 // Indice para el LOOP


loop1: T #Counter // carga el Contador del bucle LOOP Inicia el LOOP

L #ValueMW // Carga el valor a meter a la primera MW


T MW [ #PointerMW] // Transfiere el ValueMW a la MW empezando con MW300

L #PointerMW // Carga el puntero para incrementarlo


L 2 // Se incrementa en dos, debido que una Word son bytes, para DW cambie aquí por 4
SLD 3 // El numero dos, se corre 3 bits a la izquierda para ponerlo del lado del Y bytes address.
+D // ACC1=ACC1+ACC2. ACC2 = #PointerMW
T #PointerMW //En esta línea #PointerMW a avanzado en dos bytes (1 palabra)

L #ValueMW // Esta tres líneas siguientes es solo para rellenar las MW


INC 1 // Rellenando desde la MW300 diez palabras
T #ValueMW // Desde la MW300 hasta la MW318

L #Counter //ACC1= #Counter


LOOP loop1 //ACC1= Decrementa el contador, si es cero se sale del LOOP
Cap. 03 Programación AWL

Hagamos una nueva función para que ahora se direccione dobles palabras desde MD320 a MD356, con los
valores consecutivos del 0 al 9, Esta es similar a la anterior pero opera sobre DWord. Haga una tabla de
Observación y Forzado con estas palabras para que vea el resultado. A continuación cree una función FC9,
declare las siguientes variables temporales.

L P#320.0 // ACC1=P#320.0, carga un valor para que apunte al byte 320, bits 0
T #PointerMD // Transfiere ACC1 a la variable que será el índice puntero
L 0 //ACC1=0, inicializa el valor con que se rellenara las MD320
T #ValueMW // se cargará como ejemplo 10 enteros (0 al 9)

L 10 // Índice para el LOOP


loop1: T #Counter // carga el Contador del bucle LOOP Inicia el LOOP

L #ValueMW // Carga el valor a meter a la primera MD


T MD [ #PointerMD] // Transfiere el ValueMW a la MD empezando con MD320

L #PointerMD // Carga el puntero para incrementarlo


L 4 // Se incrementa en 4, debido que una DWord son 4 bytes
SLD 3 // El número 4, se corre 3 bits a la izquierda para ponerlo del lado del Y bytes address.
+D // ACC1=ACC1+ACC2. ACC2 = #PointerMD
T #PointerMD //En esta línea #PointerMD a avanzado en 4 bytes (1 doble palabra)

L #ValueMW // Esta tres líneas siguientes es solo para rellenar las MD


INC 1 // Rellenando desde la MW320 diez dobles palabras
T #ValueMW // Desde la MD320 hasta la MD356

L #Counter //ACC1= #Counter


LOOP loop1 //ACC1= Decremento el contador, si es cero se sale del LOOP

Como podrá observar los dos ejemplos anteriores, casi son idénticos, con la única diferencia de que uno apunta
a la dirección MW300 (P#300.0) y otra a la MD320 (P#320.0). Otra diferencia es que para incrementar el
puntero en palabras, se suma 2 y para dobles palabras se suma 4. Un esquema general para trabajar con
punteros usando un LOOP sería la siguiente:
Cap. 03 Programación AWL

Hemos marcado con 1, la inicialización de variable del Apuntador. Aquí se inicializan todas las variables que se
usaran en el apuntador. En caso de que se aniden ciclos que contenga apuntador, es una buena práctica
inicializarla en donde se anida. La parte marcada con 2, se refiere al ciclo LOOP, siempre tiene la misma
estructura. En 3, se realizan las operaciones para las cuales se hizo este primer anidamiento. En caso de que
haya otro ciclo de anidamiento, es en este punto donde se pone. Hemos marcado con 4, la parte donde se
incrementa el puntero. Recuerde que si es para apuntar en bytes, se incrementa en 1, 2 para palabras y 4 para
doble palabras. Siempre se recorre 3 lugares a la izquierda.

En ocasiones será preferible incrementar un índice al apuntador e irlo incrementando y luego sumar a la
dirección puntero inicial, esto puede requerirse cuando se necesita el índice de la variable apuntada. Por
ejemplo el inicio de la variable apuntada en el ejemplo anterior es la 320, pudiendo referirse a M320.0, MB320,
MW320 y MD320, aunque en este ejemplo se refiere a la MD320. Vea que dentro del LOOP se carga el
número 4 y luego se incrementa el puntero en 4 (marcado con el circulo 4). Una opción es dejar fijo el inicio de
la palabra puntero e incrementar un índice que apunte a esa variable de inicio, de esa manera se podrá llevar el
conteo de los registro del arreglo, esto se requiere cuando importa saber la posición de un determinado
elemento del arreglo y no nos importa el contenido del arreglo.
Cap. 03 Programación AWL

Ejercicio de tabla de multiplicar: A continuación hagamos un ejercicio de anidamiento para multiplicar dos
Registros con 10 elementos cada registro. En la imagen se muestra una idea de lo que se intenta.

Inserte una FC10 y declare las siguientes variables de tipo temporal.

L P#500.0 // Línea obligatoria para marcar el inicio del puntero


T #PointOper01 // Línea obligatoria carga en un índice el puntero

L P#540.0 // Línea obligatoria para marcar el inicio del puntero del resultado
T #PointResult // Un puntero que se usa en los dos anidamiento se declara aquí

L 10 // Línea obligatoria inicio del LOOP1. Anidamiento externo


LOOP1: T #CountrLoop01 // Línea obligatoria pertenece al LOOP1
Cap. 03 Programación AWL

//////////////////INICIO Área de trabajo 01. Aquí debe poner toda la tarea del Loop01
//////////////////INICIO UN NUEVO LOOP, LOOP2
// aqui se debe declarar el puntero del segundo anidamiento
// para que cada que pase por aquí el loop1 lo inicialice de nuevo
L P#520.0 // Línea obligatoria para marcar el inicio del puntero 2
T #PointOper02 // Línea obligatoria carga en un índice el puntero 2

L 10 // Línea obligatoria inicio del LOOP2


LOOP2: T #CountrLoop02 // Línea obligatoria pertenece al LOOP2

//////////////////////inicia área de trabajo dos


// Aquí se ponen todas las operaciones del anidamiento
//esta es la razón del anidamiento

L MW [ #PointOper01]
L MW [#PointOper02]
*I
T MW [#PointResult]

/////////////////////Finaliza área de trabajo dos

L #PointOper02 // Carga el puntero 2 para incrementarlo


L 2 // Se incrementa en 2, debido que una Word son 2 bytes
SLD 3 // se corre 3 bits a la izquierda, lado del bytes address.
+D // ACC1=ACC1+ACC2. ACC2 = #PointOper02
T #PointOper02 //En esta línea #PointOper02 a avanzado en 2 bytes

L #PointResult // Carga el puntero de 100 datos para incrementarlo


L 2 // Se incrementa en 2, debido que una Word son 2 bytes
SLD 3 // se corre 3 bits a la izquierda, lado del bytes address.
+D // ACC1=ACC1+ACC2. ACC2 = #PointResult
T #PointResult //En esta línea #PointResult a avanzado en 2 bytes

L #CountrLoop02 //ACC1= ##CountrLoop02


LOOP LOOP2 //ACC1= Decremento el contador, si es cero se sale del LOOP2

//////////////////FIN de LOOP2
//////////////////FIN Área de trabajo 01

// Esta sección de código ya pertenece a LOOP1


L #PointOper01 // Carga el puntero para incrementarlo
L 2 // Se incrementa en 2, debido que una Word son 2 bytes
SLD 3 // se corre 3 bits a la izquierda, lado del bytes address.
+D // ACC1=ACC1+ACC2. ACC2 = #PointOper01
T #PointOper01 //En esta línea #PointOper01 a avanzado en 2 bytes

L #CountrLoop01 //ACC1= #CountrLoop01


LOOP LOOP1 //ACC1= Decremento el contador, si es cero se sale del LOOP1
Cap. 03 Programación AWL

Ordenación de números en un arreglo. Para continuar vamos abrir un nuevo proyecto y hacer una nueva
declaración de variables, tal como se indica abajo:

EL ejercicio tratará de ordenar un arreglo de 10 enteros que están en las variables MW100 al MW118. Para ello,
el primer dato del arreglo se compara con los siguientes 9 datos uno por uno y donde encuentre uno que es
menor, intercambia su posición. Esto lo hace hasta llegar al final del arreglo, en el siguiente ciclo, compara el
segundo dato del arreglo con los 8 siguientes datos y así sucesivamente hasta comparar todos los números e
intercambiar de posición cuando encuentre uno menor. La figura siguiente ilustra el hecho:
Cap. 03 Programación AWL

Un diagrama de flujo también puede ayudar a entender la idea.

Aquí tiene el programa, programelo en el PLC y vea sus resultados en la tabla de observacio de variables.
Cree una FC1 y las siguientes variables de tipo temporal.
Cap. 03 Programación AWL

//Esta rutina ordena de menor a mayor


L P#100.0 // marcar el inicio del puntero MW100
T #PointOper01 // carga en un índice el puntero

L 10 // inicio del LOOP1. Anidamiento externo


LOOP1: T #CountrLoop01 // pertenece al LOOP1

//////////////////INICIO Área de trabajo 01. Aquí debe poner toda la tarea del Loop01

//////////////////INICIO UN NUEVO LOOP, LOOP2


// aqui se debe declarar el puntero del segundo anidamiento
// para que cada que pase por aquí el loop1 lo inicialice de nuevo

L #PointOper01 // Puntero N
L 2 // Se incrementa en 2, debido que una Word son 2 bytes
SLD 3 // se corre 3 bits a la izquierda, lado del bytes address.
+D // ACC1=#PointOper01+1
T #PointOper02 //Puntero N+1; #PointOper02=#PointOper01+1

// Esta area de codigo, sirve para asignar el #CountrLoop02=#CountrLoop01-1


// y que si CountrLoop02=0, ya no realice el LOOP2, porque
//manda un error el PLC al evaluar el LOOP ultima linea
//decrementa el #CountrLoop02 y daria negativo si entra con cero
L #CountrLoop01 // Sirve para hacer que #CountrLoop02
DEC 1 // #CountrLoop02=CountrLoop01-1
T #CountrLoop02
L 0 // Si #CountrLoop02 cuida de no meterse al LOOP2
==D // porque lo que hace LOOP es restar uno a #CountrLoop02 y
JC finloop2 // Si #CountrLoop02=0, LOOP haria un -1
// FIN de fijar el #CountrLoop02=#CountrLoop01-1

L #CountrLoop02 //Inicia el nido dos LOOP2


LOOP2: T #CountrLoop02 // #CountrLoop02=#CountrLoop01-1

//////////////////////inicia área de trabajo loops dos


// Aquí se ponen todas las operaciones del anidamiento 2
//Area de trabajo de loop2
L MW [ #PointOper01]
L MW [ #PointOper02]
>=I // <=I Solo invierta el signo de
// comparacion para ordenar de Mayor a menor
JC swap

JU cont

swap: T MW [ #PointOper01]
TAK
T MW [ #PointOper02]

cont: NOP 0

/////////////////////Finaliza área de trabajo dos


Cap. 03 Programación AWL

L #PointOper02 // Carga el puntero 2 para incrementarlo


L 2 // Se incrementa en 2, debido que una Word son 2 bytes
SLD 3 // se corre 3 bits a la izquierda, lado del bytes address.
+D // ACC1=ACC1+ACC2. ACC2 = #PointOper02
T #PointOper02 //En esta línea #PointOper02 a avanzado en 2 bytes

L #CountrLoop02 //ACC1= ##CountrLoop02


LOOP LOOP2 //ACC1= Decremento el contador, si es cero se sale del LOOP2

//////////////////FIN de LOOP2

//////////////////FIN Área de trabajo 01

finloop2 : NOP 0

// Esta sección de código ya pertenece a LOOP1


L #PointOper01 // Carga el puntero para incrementarlo
L 2 // Se incrementa en 2, debido que una Word son 2 bytes
SLD 3 // se corre 3 bits a la izquierda, lado del bytes address.
+D // ACC1=ACC1+ACC2. ACC2 = #PointOper01
T #PointOper01 //En esta línea #PointOper01 a avanzado en 2 bytes

L #CountrLoop01 //ACC1= #CountrLoop01


LOOP LOOP1 //ACC1= Decremento el contador, si es cero se sale del LOOP1

Ahora ve el resultado en la tabla de observacion:

Este programa se puede arreglar para que los ordene de mayor a menor con tan solo cambiar la comparacion
menor igual por mayor igual.
Cap. 03 Programación AWL

Programa que indica la posición del número menor de un arreglo. Este ejercicio es similar al anterior, sin
embargo, se arregla para que ahora señale la posición del arreglo que contiene el menor de los números del
arreglo.
Cap. 03 Programación AWL

RUTINA PARA SELECCIONAR EL NUMERO MENOR

Se crean las siguientes variables en la tabla de variables PLC

Variable Dirección
"Numero_menor" MD24
Numero_1 MW4
Numero_2 MW6
Numero_3 MW8
Numero_4 MW10
Numero_5 MW12
Numero_6 MW14
Numero_7 MW16
Numero_8 MW18
Numero_9 MW20
Numero_10 MW22

Empezaremos por insertar un bloque FC llamado “Numero Menor” en el cual se declaran las siguientes
variables locales:

Posteriormente se procede a asignar los valores de inicialización de nuestros punteros, se inicia con el valor de
puntero P#4.0 a la variable local #puntero_indice_1, pues la primera área de memoria a leer es la MW4 que es
nuestra variable Numero_, la cual se compara con la variable adjunta MW6 o Numero_2, por lo cual se asigna
el valor de puntero P#6.0 a la variable local #puntero_indice_2
Cap. 03 Programación AWL

A continuación se carga el valor de nuestra primera área a leer en nuestra primera variable local
#memoria_temporal_1 y la segunda área a leer en la variable local #memoria_temporal_2 y posteriormente se
compara si #memoria_temporal_2 es menor que #memoria_temporal_1, si la condición es cierta se realiza un
salto hacia la etiqueta jmp1 sino se hace el salto a la etiqueta jmp2

Posteriormente se determina las acciones a realizar en el salto jmp1, en este caso como la comparación fue
cierta eso quiere decir que #memoria_temporal_2 es menor, por lo que se mueve el valor de la variable
#puntero_indice_2 hacia la variable PLC “Numero_Menor” antes de realizar la transferencia hay que mover el
valor del puntero 3 bits hacia la derecha (la razón de esta operación se examinara más profundidad en los
pasos siguientes) y además es necesario restarle 2 unidades y luego dividirla entre dos para asi indicar con
numero ordinario el número que es el menor
Cap. 03 Programación AWL

En caso contrario como la variable local #memoria_temporal_1 fue la mayor, entonces se incrementa el valor de
la variable #puntero_indice_1 en dos pues la siguiente área a leer seria MW8 (MW6 + 2 = MW8), para ello es
necesario recorre el valor del número 2, 3 bits a la izquierda, pues de acuerdo con designación de los punteros
los tres primeros bits son para determinar el número de bit del área a acceder ( el número 2 en formato puntero
sería igual a P#0.2 y se requiere acceder al valor P#2.0), posteriormente se compara el nuevo valor de la
variable #puntero_indice_1 con el valor 22, pues el área MW22 pues la última área a leer, si #puntero_indice_1
es menor o igual a 22 entonces se procede a saltar a la etiqueta Nst1 que esta al principio de nuestro programa
para que se realice de nuevo la evaluación, pero esta vez se comparan las áreas MW4 y MW8. Si la
comparación es falsa entonces se salta hacia la etiqueta EOF

En la etiqueta jmp2 se realizan las mismas acciones anteriores pero se intercambian las variables, el
puntero_indice_1 es el que se transfiere a la variable PLC “Numero_menor” y es la variable #puntero_indice_2
la que se incrementa. En la etiqueta EOF se finaliza el bloque.
Cap. 03 Programación AWL
Cap. 03 Programación AWL

RUTINA PARA SELECCIONAR EL NUMERO MAYOR

Variable Dirección
"Numero_mayor" MD72

Para determinar cuál de los tanques tiene el nivel mayor y se utilizara la misma lógica anterior, solamente que
con algunos cambios, primeramente se insertara un nuevo bloque FC llamado “Numero mayor”, se declaran las
mismas variables locales que el bloque anterior

La estructura es la misma que el bloque anterior, solamente se diferencian en la comparación que realizan, ya
que en este bloque se compara si es mayor la variable #memoria_temporal_2 que la variable
#memoria_temporal_1.

Además que la variable que se utiliza para guardar el valor del número mayor es “Numero_Mayor” en vez de
“Numero_Menor”
Cap. 03 Programación AWL

DESARROLLO DE RUTINA “ORDENACION DE BURBUJA”

Se realizara una rutina de ordenamiento del menor al mayor utilizando el método de la burbuja.Para ello se crea
un bloque FC llamado OrdenacionBurbuja y además, en la tabla de variables PLC se crea la siguiente variable.

Variable Dirección
"Puntero_numero_menor" MD0

Dentro del bloque FC se declaran las siguientes variables locales.

Primeramente se inicializan los valores de las variables #IndiceNesting y #BanderNesting con los valores 0 y 9
respectivamente, esto es para solamente leer 10 valores

De igual manera se inicializan las variables “Puntero_numero_menor” y #PunteroMenosUno con el valor


puntero P#4.0 con esto se indica que la primera área acceder es la variable MW4

Posteriormente se comparan los valores de las variables #IndiceNesting y #BanderaNesting si la primera es


mayor o igual que la segunda se salta a la etiqueta EOF de igual forma para configurar el Nesting es necesario
crear una etiqueta llamada Nst1 la cual se utilizara más adelante.

Posteriormente se carga el valor del área a comparar utilizando la variable “Puntero_numero_ menor” y se
carga a la variable #temporal, después el valor de la variable “Puntero_numero_ menor” se transfiere a la
variable #PunteroMenosUno.
Cap. 03 Programación AWL

Luego se incrementa el valor de “Puntero_numero_menor” en dos unidades.

Después se compara el valor de la variable #temporal y el valor del área que se accede con la variable
“Puntero_numero_menor”, si #temporal es mayor o igual que “Puntero_numero_menor” entonces se salta a la
etiqueta swap sino entonces se salta a la etiqueta Nesting.

En la etiqueta swap se transfiere el valor del área que se accede con la variable “puntero_numero_menor” hacia
la variable #swap, luego se utiliza el comando TAK para copiar el contenido del ACC2 en el ACC1, ahora el
ACC1 tiene el valor que poseía la variable #temporal y posteriormente se transfiere al área que se accede con
la variable “puntero_numero_menor”, por último se carga el valor de la variable #swap y se transfiere al área
que se accede con la variable #PunteroMenosUno.

En la etiqueta Nesting se incrementa en una unidad el valor de variable #IndiceNesting y se salta al principio del
programa con el salto hacia la etiqueta Nst1, para finalizar en la etiqueta EOF se finaliza el bloque
incondicionalmente.
Cap. 03 Programación AWL

EJERCICIO 1
Utilizar las operaciones lógicas con bits para programar un arranque y paro de una bomba de manera remota y
local, en el modo remoto el operador lo podrá accionar de manera manual o se lograra de manera automática
siguiendo una lógica predeterminada.

PROCEDIMIENTO

1. Cree un nuevo proyecto llamado Ejercicio 1 AWL

2. Configure el hardware

3. Inserte un bloque FC en lenguaje AWL llamado Arranque de una bomba

4. Declare las siguientes variables con sus respectivas direcciones

Variable Dirección
Paro_op I0.0
Arranque_op I0.1
Remoto I0.2
Local I0.3
Sistema/Operador I0.4
Bomba Q0.3
lógica M0.0

5. Recordando la lógica escalera donde dos ramas paralelas es la función O haga lo siguiente:

6. Posteriormente esta función O se ejecutará con una función AND con la entrada Paro_op negado

7. Luego todo el conjunto anterior se pondrá en AND con el permisivo Operador/Sistema


Cap. 03 Programación AWL

8. Después el conjunto resultante se ejecutará con una función O junto con una función AND del permisivo
lógica y el permisivo Operador/Sistema negado.

9. En seguida todo el conjunto anterior se pondrá a evaluar con una función AND de la evaluación AND entre
los permisivos Remoto y Local Negado

10. Para terminar se le asigna el valor del RLO a la salida Bomba (Q0.3)
Cap. 03 Programación AWL

EJERCICIO 2
Utilizar las operaciones de comparación para simular la activación de las alarmas de nivel máximo y mínimo del
nivel de un tanque, así mismo las alarmas accionaran la bomba del ejercicio anterior de la siguiente manera:

Cuando se detecte la alarma de nivel mínimo la bomba arrancara y se quedar activa hasta que se active la
alarma de nivel máximo

PROCEDIMIENTO

1. En el mismo ejercicio anterior inserte un bloque FC en lenguaje AWL llamado Nivel de tanque

2. Declare las siguientes variables con sus respectivas direcciones


Variable Dirección
Nivel_Tanq IW1
Nivel_tanq_Min Q0.0
Nivel_tanq_Max Q0.1
Nivel_aux I0.3

3. Primeramente se realizara la comparación del nivel con el nivel mínimo de 2000 unidades, para ello
cargamos primeramente 2000, luego cargamos la variable Nivel_tanq, y utilizamos el comando >=, por
último le asignamos el resultado a la salida Nivel_tanq_min

4. Luego se realizara la comparación del nivel con el nivel máximo de 20000 unidades, para ello cargamos
primeramente 20000, luego cargamos la variable Nivel_tanq_, y utilizamos el comando <=, por último le
asignamos el resultado a la salida Nivel_tanq_max

5. Posteriormente para que la bomba este activa entre los rangos de 2000 a 2000 es necesario activar una
variable auxiliar (Nivel_aux) utilizando operaciones lógicas con bits y comparaciones, primeramente para
asegurarnos que el nivel sea mayor a 2000 se realiza la siguiente comparación
Cap. 03 Programación AWL

6. A continuación el resultado de esta operación lógica se evaluara en una función AND junto con la
comparación del nivel del tanque y 20000 para asegurarse que sea menor, y el resultado de esta operación
se le asigna a la variable Nivel_aux.

7. Por último el permisivo Lógica solamente debe activarse cuando este activa la variable Nivel_tanq_min O
cuando este activado el Nivel_aux Y cuando no este activa la variable nivel_tanq_max

También podría gustarte