Discussion:
Dudas: Autómatas siemens. Software Step7
(demasiado antiguo para responder)
ByTePTr
2003-08-25 06:46:15 UTC
Permalink
Duda 1:
¿Se puede leer una variable de un bloque DB desde un OB?

llevo tiempo intentándolo y no lo consigo, he hecho esto:

AUF DB 1

o lo que es lo mismo en KOP:

DB1
----------------------(OPN)---

En el DB1 tengo declarado un array doble 10x10 del tipo INT con el nombre
"variable1"
y quiero acceder a él desde el OB1. Además, si fuera posible acceder a esta
tabla mediante otros 2 índices "j" y "k" desde el OB1 es decir algo como
DB1.variable1[j,k] la cuestión es

duda 2:
¿Se puede hacer esto?
en caso afirmativo, ¿Cómo?
¿Hay alguna manera mejor?

El objetivo en sí es poder leer/escribir en una tabla o vector y que sea
direccionado por unos indices, vamos, algo como
int tabla[10][10],j=0,k=0;
tabla[j][k] = valor;
sencillo de hacer en C o pascal, me resulta imposible hacerlo para el
autómata.
Tengo manuales etc... pero en ninguno veo una explicación clara y precisa a
esta cuestión.
Apatiko
2003-08-31 04:54:55 UTC
Permalink
Post by ByTePTr
¿Se puede leer una variable de un bloque DB desde un OB?
Sí. En AWL sería algo como...

L DB1.variable;

...o algo parecido.

Si se trata de un vector, pienso que esto debe funcionar:

L DB1.vector[3];

Para matrices no sé cual de las notaciones es la correcta si:

L DB1.matriz[3][4];

ó

L DB1.matriz[3,4];

Si usaras direccionamiento simbólico para el bloque de datos, harías

L "Nombre_del_bloque_de_datos".variable;
Post by ByTePTr
En el DB1 tengo declarado un array doble 10x10 del tipo INT con el nombre
"variable1"
y quiero acceder a él desde el OB1. Además, si fuera posible acceder a esta
tabla mediante otros 2 índices "j" y "k" desde el OB1 es decir algo como
DB1.variable1[j,k] la cuestión es
¿Se puede hacer esto?
en caso afirmativo, ¿Cómo?
¿Hay alguna manera mejor?
Seguramente algún SFC para manejo de tablas haga eso.

Si no, deberás currartelo. Ese trozo de código lo tendrás que hacer en
AWL para poder utilizar direccionamiento indirecto. Si deseas hacer eso en
un programa KOP, deberás crear un FC en AWL con ese trozo de código para
poder luego llamarlo desde KOP.

El procedimiento sería más o menos el siguiente:

VAR_INPUT
j : INT; //Fila, basada en 0
k : INT; //Columna, basada en 0
puntero_a_vector : DWORD; //Puntero INTRAAREA a comienzo del
// vector
END_VAR

VAR_OUTPUT
resultado : INT;
END_VAR

VAR_TEMP
ptr : DWORD; //Puntero resultado
END_VAR

BEGIN
NETWORK
L #j; //Fila, basada en 0.
L 10; //Número de elementos/fila.
MUL; //¿Es esta la multiplicación 16x16?

L #k; //Columna, basada en 0.
+D; //Sumo, ya tengo 10*j+k.

L p#2.0; //Tamaño de INT.
MUL; //¿Es esta la multiplicación 16x16?

L #puntero_a_vector; //¡OJO!, puntero INTRAAREA.
+D; //Ya tengo puntero_a_vector+
// +(10*j+k)*Tamaño(INT)

T #ptr; //El resultado lo guardo en ptr

AUF DB1; //Invocamos el bloque de datos JUSTO
// ANTES DEL DIRECCIONADO INDIRECTO
L DBW [#ptr]; //Leemos entero del DB invocado...

T #resultado; //...y lo cargamos en resultado

La compilación te dará un warning en la penúltima línea de código. Es
normal.

De este código no recuerdo cual es el comando de multiplicación de dos
numeros enteros de 16 bits. Si no es MUL, busca en la referencia de AWL.
Todo esto lo escribo de memoria.

Asegúrate que el puntero sea intraarea. Si no estás seguro, hazle al
puntero un AND con 0x00FFFFFF. En código AWL sería:

L #puntero_a_vector;
L DW#16#00FFFFFFF;
UD;
T #puntero_intraarea_a_vector;

Si en cambio estuvieses seguro que el puntero es interarea, seguramente
(si la memoria no me falla) podrías sustituir la penultima linea por

L W [#ptr];

Si te vas a hacer un FC para llamarlo desde KOP, tendrás que hacerlo
elegante haciendo que el parámetro de entrada puntero_a_vector sea de tipo
POINTER y no DWORD. Esto te complicará algo el código, pues tendrás que
sacar el puntero de la estructura POINTER.

En fin, un show. Para mi gusto los lenguajes de programación KOP y AWL
del Step7 son los más horribles que he conocido, y el entorno de
desarrollo de lo más anti-intuitivo, lento e inestable que he visto. Y
encima cuesta un riñón.
ByTePTr
2003-08-31 07:45:11 UTC
Permalink
Gracias.
La otra es que hay cosas en AWL que no puedo realizar en KOP y viceversa,
por ejemplo,

U DBX 0.0
SPBNB _001
L W#16#1
L MW 0
SLW
T MW 0
SET
SAVE
CLR
_001: U BIE
= M 3.3

que en KOP sería:
_______________
DBX 0.0 | SHL_W | M3.3
----| |-----| EN ENO |----------------( )--
| |
MW0-- | IN OUT |--MMW0
| |
W#16#1 - | N |
|______________|


Quiero cambiar la "entrada" DBX0.0 por DBX[MD 0] por ejemplo, esto, me lo
permite hacer en AWL pero no en KOP. Asimismo, para pasar de KOP a AWL es
necsario que estén todas las E/S del bloque (en este caso SHL_W) asignadas.
¿Es que no se puede hacer este tipo de direccionamiento en KOP? ¿Por qué?.
No tiene mucho sentido.
Post by Apatiko
Post by ByTePTr
¿Se puede leer una variable de un bloque DB desde un OB?
Sí. En AWL sería algo como...
L DB1.variable;
...o algo parecido.
L DB1.vector[3];
L DB1.matriz[3][4];
ó
L DB1.matriz[3,4];
Si usaras direccionamiento simbólico para el bloque de datos, harías
L "Nombre_del_bloque_de_datos".variable;
Post by ByTePTr
En el DB1 tengo declarado un array doble 10x10 del tipo INT con el nombre
"variable1"
y quiero acceder a él desde el OB1. Además, si fuera posible acceder a esta
tabla mediante otros 2 índices "j" y "k" desde el OB1 es decir algo como
DB1.variable1[j,k] la cuestión es
¿Se puede hacer esto?
en caso afirmativo, ¿Cómo?
¿Hay alguna manera mejor?
Seguramente algún SFC para manejo de tablas haga eso.
Si no, deberás currartelo. Ese trozo de código lo tendrás que hacer en
AWL para poder utilizar direccionamiento indirecto. Si deseas hacer eso en
un programa KOP, deberás crear un FC en AWL con ese trozo de código para
poder luego llamarlo desde KOP.
VAR_INPUT
j : INT; file://Fila, basada en 0
k : INT; file://Columna, basada en 0
puntero_a_vector : DWORD; file://Puntero INTRAAREA a comienzo del
// vector
END_VAR
VAR_OUTPUT
resultado : INT;
END_VAR
VAR_TEMP
ptr : DWORD; file://Puntero resultado
END_VAR
BEGIN
NETWORK
L #j; file://Fila, basada en 0.
L 10; file://Número de elementos/fila.
MUL; file://¿Es esta la multiplicación 16x16?
L #k; file://Columna, basada en 0.
+D; file://Sumo, ya tengo 10*j+k.
L p#2.0; file://Tamaño de INT.
MUL; file://¿Es esta la multiplicación 16x16?
L #puntero_a_vector; file://¡OJO!, puntero INTRAAREA.
+D; file://Ya tengo puntero_a_vector+
// +(10*j+k)*Tamaño(INT)
T #ptr; file://El resultado lo guardo en ptr
AUF DB1; file://Invocamos el bloque de datos JUSTO
// ANTES DEL DIRECCIONADO INDIRECTO
L DBW [#ptr]; file://Leemos entero del DB invocado...
T #resultado; file://...y lo cargamos en resultado
La compilación te dará un warning en la penúltima línea de código. Es
normal.
De este código no recuerdo cual es el comando de multiplicación de dos
numeros enteros de 16 bits. Si no es MUL, busca en la referencia de AWL.
Todo esto lo escribo de memoria.
Asegúrate que el puntero sea intraarea. Si no estás seguro, hazle al
L #puntero_a_vector;
L DW#16#00FFFFFFF;
UD;
T #puntero_intraarea_a_vector;
Si en cambio estuvieses seguro que el puntero es interarea, seguramente
(si la memoria no me falla) podrías sustituir la penultima linea por
L W [#ptr];
Si te vas a hacer un FC para llamarlo desde KOP, tendrás que hacerlo
elegante haciendo que el parámetro de entrada puntero_a_vector sea de tipo
POINTER y no DWORD. Esto te complicará algo el código, pues tendrás que
sacar el puntero de la estructura POINTER.
En fin, un show. Para mi gusto los lenguajes de programación KOP y AWL
del Step7 son los más horribles que he conocido, y el entorno de
desarrollo de lo más anti-intuitivo, lento e inestable que he visto. Y
encima cuesta un riñón.
Apatiko
2003-08-31 14:32:52 UTC
Permalink
Post by ByTePTr
Quiero cambiar la "entrada" DBX0.0 por DBX[MD 0] por ejemplo, esto, me lo
permite hacer en AWL pero no en KOP. Asimismo, para pasar de KOP a AWL es
necsario que estén todas las E/S del bloque (en este caso SHL_W) asignadas.
¿Es que no se puede hacer este tipo de direccionamiento en KOP? ¿Por qué?.
No tiene mucho sentido.
Al parecer no se puede hacer direccionamiento indirecto en KOP.

Yo también estuve peleandome con eso varios días hasta que lo di por
perdido y me olvidé del KOP para la aplicación que pretendía hacer. Creo
recordar haber leido posteriormente en uno de los manuales electrónicos de
Siemens que únicamente era posible el direccionamiento indirecto en AWL.

Sentido no tiene ninguno, y menos cuando el Microwin para los S7/200 sí
permite el direccionamiento indirecto en KOP. Pero parece que los de
Siemens son así de raros.
ByTePTr
2003-09-01 10:59:00 UTC
Permalink
Vale, muchas gracias, sobre todo era importante para mí saber que no se
puede hacer.

En caso de que sea necesario trataré de arreglármelas con una mezcla de
AWL+KOP. Que parece ser lo mejor, más que nada porque ciertas cosas como el
seteo de básculas y ver si se cumplen las condiciones lógicas de los
"contactos" se ven más claro en KOP.
Post by Apatiko
Post by ByTePTr
Quiero cambiar la "entrada" DBX0.0 por DBX[MD 0] por ejemplo, esto, me lo
permite hacer en AWL pero no en KOP. Asimismo, para pasar de KOP a AWL es
necsario que estén todas las E/S del bloque (en este caso SHL_W) asignadas.
¿Es que no se puede hacer este tipo de direccionamiento en KOP? ¿Por qué?.
No tiene mucho sentido.
Al parecer no se puede hacer direccionamiento indirecto en KOP.
Yo también estuve peleandome con eso varios días hasta que lo di por
perdido y me olvidé del KOP para la aplicación que pretendía hacer. Creo
recordar haber leido posteriormente en uno de los manuales electrónicos de
Siemens que únicamente era posible el direccionamiento indirecto en AWL.
Sentido no tiene ninguno, y menos cuando el Microwin para los S7/200 sí
permite el direccionamiento indirecto en KOP. Pero parece que los de
Siemens son así de raros.
ByTePTr
2003-08-31 07:57:43 UTC
Permalink
Me funcionan estos:

AUF DB 3 // abrimos DB3
L DBW 0 // word del DB abierto (DB3) la 0
L DBW 2 // word 2 cargada db3.dbw 2
L DB3.DBW 2 // en teoria esto es lo mismo

AUF DB 2 // abrimos db2
AUF DI 4 // abrimos db4 como bloque de
instancia

L DB1.DBB 0
T DBB [MD 7] // T db2.dbw[md7] no permitido
L DBB [MD 7] // leeemos del db2 (abierto con auf
db)
T DIB [MD 11] // dejamos en db4 (abierto con auf
di o sea de instancia)

U DB2.DBX 1.0
= DB1.DBX 3.1

L #cadena // cargamos la variable cadena
indicada en la estructura de datos del FB
T DBW 3 // La dejamos en db2.dbw3 podria ser
dbw[mw0] con mw = 3

U DBX [MD 0]
= DBX [MD 4]
L DB2.DBB 0

y esto por ejemplo, no se permite: L DB2.DBB[MW 0]

Tampoco entiendo porqué si en un bloque DBn hemos creado variables con sus
respectivos nombres, luego al llamar desde un bloque FB u OB no nos reconoce
los nombres de dichas variables, es decir, no me coge por ejemplo
DB2.nombre_ variable ni nada por el estilo, por tanto, tienes que acceder de
las formas que he indicado anteriormente, esto lo que he sacado en claro
haciendo pruebas. Estaba pensando quizás indicarlo en la tabla de símbolos,
por ejemplo: nombre_variable1 DB2.DBB0... etc. tal vez funcione, pero si es
asi, ¿qué sentido tiene entonces que tengas que declarar los nombres en el
bloque OB?.
Post by ByTePTr
¿Se puede leer una variable de un bloque DB desde un OB?
AUF DB 1
DB1
----------------------(OPN)---
En el DB1 tengo declarado un array doble 10x10 del tipo INT con el nombre
"variable1"
y quiero acceder a él desde el OB1. Además, si fuera posible acceder a esta
tabla mediante otros 2 índices "j" y "k" desde el OB1 es decir algo como
DB1.variable1[j,k] la cuestión es
¿Se puede hacer esto?
en caso afirmativo, ¿Cómo?
¿Hay alguna manera mejor?
El objetivo en sí es poder leer/escribir en una tabla o vector y que sea
direccionado por unos indices, vamos, algo como
int tabla[10][10],j=0,k=0;
tabla[j][k] = valor;
sencillo de hacer en C o pascal, me resulta imposible hacerlo para el
autómata.
Tengo manuales etc... pero en ninguno veo una explicación clara y precisa a
esta cuestión.
Apatiko
2003-08-31 15:15:38 UTC
Permalink
Post by ByTePTr
L DB1.DBB 0
T DBB [MD 7] // T db2.dbw[md7] no permitido
Al parecer sólo puedes utilizar el formato bloque_de_datos.variable con
direccionamiento directo. Para hacerlo con direccionamiento indirecto
debes hacer:

AUF DB 2;
T DBB [MD 7];

¡OJO! el T DBB [MD 7] que tu pones a continuación seguramente no equivale
a T db2.dbb[md7], sino a T db1.dbb[md7]. La causa es el L DB1.DBB0 que hay
justo antes.

Ten en cuenta que el AWL no es un lenguaje ensamblador, sino un lenguaje
de un nivel algo superior. Cuando tu escribes L DB1.DBB0 el compilador
traduce eso en:

AUF DB 1;
L DBB 0;

Por lo que el bloque de datos que usarás en T DBB [MD 7] es el DB1, y no
el DB2 que seleccionaste con el AUF inicial. Esa es la razón por la cual
el compilador genera un warning "Asegúrese que el DB global esté
correctamente ajustado" por cada operacion con una variable de
un bloque de datos en la que el bloque de datos no esté explicitamente
indicado.

En general no puedes confiar es que el DB global ni el registro de
direccion AR1 mantengan los valores aunque tú no los modifiques en
tu programa. El compilador los usa a su discreción ante la aparición de
ciertas instrucciones por lo que te aconsejo encarecidamente que los
inicialices justo antes de hacer uso de ellos, por ejemplo pon un AUF
antes de cada operacion de direccionamiento indirecto con un bloque de
datos global. Y si usas direccionamiento directo usa el formato
bloque_de_datos.variable para asegurarte que se utiliza el bloque de datos
correcto.

Todo esto se explica en una sección MUY ESCONDIDA de uno de los manuales
eléctrónicos de Step7 (creo que era "Programar con Step7", y el capítulo
creo recordar que era en torno al 9). En esa sección para empezar se
desaconseja completamente cualquier técnica de programación que se salga
del direccionamiento directo (seguramente por ese motivo hayan restringido
el uso del direccionamiento indirecto a AWL). Por desgracia, cualquiera
que haya programado algo medio en serio sabe que es difícil vivir sin
direccionamiento indirecto, por muy proclive a fallos que sea.
Post by ByTePTr
Tampoco entiendo porqué si en un bloque DBn hemos creado variables con sus
respectivos nombres, luego al llamar desde un bloque FB u OB no nos reconoce
los nombres de dichas variables, es decir, no me coge por ejemplo
DB2.nombre_ variable ni nada por el estilo, por tanto, tienes que acceder de
las formas que he indicado anteriormente, esto lo que he sacado en claro
haciendo pruebas. Estaba pensando quizás indicarlo en la tabla de símbolos,
por ejemplo: nombre_variable1 DB2.DBB0... etc. tal vez funcione, pero si es
asi, ¿qué sentido tiene entonces que tengas que declarar los nombres en el
bloque OB?.
El problema está en que estás usando una mezcla de direccionamiento no
simbólico (DB2) con direccionamiento simbólico (nombre_variable). Debes
hacerlo todo no simbólico (DB2.DBB10) o todo simbólico
("Bloque_de_datos".nombre_variable).

Lo que tienes que hacer es bautizar el bloque de datos en la tabla de
símbolos. Por ejemplo:

VARIABLES_TURBINA DB2

No te olvides de guardar los cambios de la tabla de símbolos antes de
compilar el programa.

Entonces, si en el DB1 tienes una variable que sea "presion", entonces
puedes acceder a ella así:

L "VARIABLES_TURBINA".presion;

Las comillas creo que sí son necesarias.
Apatiko
2003-09-04 00:21:09 UTC
Permalink
Entonces cada vez que accedes a una DB.loquesea, se traduce a 2
instrucciones, una la apertura del DB (AUF) y otra el acceso al dato para
hacer con él lo que sea.
No viene especificado en ninguna parte, pero eso es lo que parece a la
vista de dos razones:

- Existe un PDF en la página web de Siemens en el que se documenta lo que
sería el "lenguaje ensamblador" de los autómatas desde el 312 al 315-2/DP.
Es básicamente idéntico al AWL, pero ciertas cosas faltan. Por ejemplo,
a diferencia de AWL no hay instrucciones en las que se pueda especificar a
la vez un bloque de datos y una variable (p.e. L DB1.DBB56 o T DB5.DBW4).
En cambio sí existen el AUF y las operaciones de carga (L) y transferencia
(T).

- En la sección 9.9.3 del PDF "Programar en STEP7" (de obligada lectura)
indica que se deben tomar precauciones con ciertas estructuras de
programación pues pueden alterar el DB global o el registro AR1, entre
ellas cualquier acceso del tipo DBx.variable.

A la vista de ambos hechos, parece factible que se generen dos
instrucciones en esos casos (el AWL y la carga o transferencia).

Por cierto, tiene c*j*n*s que haya que enterarse de ciertas cosas
absolutamente cruciales (según el propio documento con "Riesgo de daños a
las personas y a las cosas") en la subsección más perdida del manual de
programación.

Loading...