Objeto Ascii

  • 7 Respuestas
  • 4104 Vistas

InduxSA

  • Aprendiz
  • **
  • Mensajes: 25
Objeto Ascii
« : junio 07, 2017, 18:02:07 pm »
Hola Boris

Estoy programando un HMI weintek con un PLC STX8092.

Quiero enviar 3 registros , el problema es que al colocar en la pantalla los tres objetos ascii, toman un valor del que se ingreso en cualquiera de los objetos te comparto las siguientes imágenes esperando me puedas ayudar.

También hice una prueba para ver si el valor que se escribía en los objetos secundarios se guardaba en la variable y resulto que si se guarda el valor que toma de lo ingresado en el otro objeto.

te adjunto mis programas espero me puedas ayudar.


Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2314
  • Soporte Técnico
Re:Objeto Ascii
« Respuesta #1 : junio 07, 2017, 18:59:21 pm »
Buenas tardes Jose,

Quiero enviar 3 registros , el problema es que al colocar en la pantalla los tres objetos ascii, toman un valor del que se ingreso en cualquiera de los objetos te comparto las siguientes imágenes esperando me puedas ayudar.

No comprendo bien, ¿queres mostrar una cadena ASCII (letras y numeros) en la pantalla o solo un registro numérico?.

También hice una prueba para ver si el valor que se escribía en los objetos secundarios se guardaba en la variable y resulto que si se guarda el valor que toma de lo ingresado en el otro objeto.

En tu programa solo veo que cargas los registros 40001, 40002 y 40018 con un valor X.

¿Cual te da problemas? ¿y que debería mostrar?.

Saludos



SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

InduxSA

  • Aprendiz
  • **
  • Mensajes: 25
Re:Objeto Ascii
« Respuesta #2 : junio 08, 2017, 09:22:17 am »
Hola Boris

Necesito enviar al PLC tres cadenas ascii( Letras y números)

El problema no lo tengo en los registros 40001 , 40002, 40018, el problema esta en los registros 40017 y 40018 de la ventana 011.

Lo que me sucede es que al ingresar un dato en cualquiera de los dos objetos una parte de los datos ingresados se muestran en el otro objeto, por ejemplo si ingreso W3311S94055 en el registro 40017 al presionar enter aparece 11S94055 en el registro 40018.

y algo similar me pasa al ingresar un dato en el registro 40017.

Saludos


Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2314
  • Soporte Técnico
Re:Objeto Ascii
« Respuesta #3 : junio 08, 2017, 17:22:57 pm »
El problema no lo tengo en los registros 40001 , 40002, 40018, el problema esta en los registros 40017 y 40018 de la ventana 011.

Lo que me sucede es que al ingresar un dato en cualquiera de los dos objetos una parte de los datos ingresados se muestran en el otro objeto, por ejemplo si ingreso W3311S94055 en el registro 40017 al presionar enter aparece 11S94055 en el registro 40018.

Mira, te adjunto una imagen probando tu programa (sin modificar nada):



Cada objeto ASCII según especificas en el diseño del HMI, tiene una longitud máxima de 8 registros, y como cada registro tiene 2 bytes, podes guardar hasta 16 caracteres ASCII.

En la imagen de arriba cargo 16 caracteres "1234567890123456" (8 registros) en el primer objeto y el HMI los escribe en el PLC a partir de la dirección 40017.

Luego el segundo objeto ASCII los lee a partir de la dirección 40018, es decir, empieza 1 registro después o 2 caracteres después.

Por lo tanto mostrará "34567890123456" como se aprecia en la imagen.

Para que sea mas claro:

En el PLC queda en cada registro cuando ingresas la cadena en 40017:

REGISTRO        VALOR
40017        12
40018        34
40019        56
40020        78
40021        90
40022        12
40023        34
40024        56

Por lo que es correcto ese comportamiento truncado que observas.

Decime si es esto responde a tu pregunta o es otra cosa.

Saludos



 
« Última Modificación: junio 08, 2017, 17:25:34 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

InduxSA

  • Aprendiz
  • **
  • Mensajes: 25
Re:Objeto Ascii
« Respuesta #4 : junio 08, 2017, 17:45:14 pm »
Si es lo que preguntaba,

Es posible guardar 12 caracteres en una variable de un solo registro

algo como
new OT[1]

MbServGetRegisters(40009, 1,Ort,0)

Saludos

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2314
  • Soporte Técnico
Re:Objeto Ascii
« Respuesta #5 : junio 08, 2017, 17:49:07 pm »
Es posible guardar 12 caracteres en una variable de un solo registro

algo como
new OT[1]

MbServGetRegisters(40009, 1, Ort, 0)

¿Obtener los caracteres escritos por el HMI en el PLC?

Bien, primero debes entender que 12 caracteres para poder almacenarse como cadena en el PLC, necesitan una variable o array de 12 elementos en el PLC, más un elemento de finalización con el valor cero que marca el "fin" de la cadena.

Entonces, necesitarías declarar una variable de 13 elementos asi:

Código: (Pawn) [Seleccionar]
new StringOT[12+1]   // Le agregué el texto "String" para que sepamos que contienen una cadena y puse una suma para ser explicito.
Por lo tanto, si queres almacenar la cadena "HOLA MUNDO!!" de 12 caracteres, podrías hacerlo de la siguiente forma:

Código: (Pawn) [Seleccionar]
StringOT[0]='H'
StringOT[1]='o'
StringOT[2]='l'
StringOT[3]='a'
StringOT[4]=' '
StringOT[5]='M'
StringOT[6]='u'
StringOT[7]='n'
StringOT[8]='d'
StringOT[9]='o'
StringOT[10]='!'
StringOT[11]='!'
StringOT[12]=0  // Valor cero de finalización.

Otro método alternativo (no utilizado acá), que solo sirve al inicializar el array es:

Código: (Pawn) [Seleccionar]
new StringOT[]="Hola Mundo!!"   // Aqui el tamaño y el cero al final se asignan automáticamente.
Con esto en mente, si en el HMI cargamos la cadena "Hola Mundo!!" a partir de la dirección 40009, nos quedaría:

40009 = "Ho"
40010 = "la"
40011 = " M"
40012 = "un"
40013 = "do"
40014 = "!!"


Desde el PLC podríamos obtenerla de la siguiente forma, leyendo 6 registros a partir de la dirección 40009:

Código: (Pawn) [Seleccionar]
   new Buffer[12]
   MbServGetRegisters(40009, 6, Buffer, 0)

Pero esto nos deja en "Buffer[]" los 6 elementos, y cada elemento con dos caracteres, ya que el HMI guarda dos por registro.

Buffer[0] = "Ho"
Buffer[1] = "la"
Buffer[2] = " M"
Buffer[3] = "un"
Buffer[4] = "do"
Buffer[5] = "!!"


Entonces tenemos que desempaquetarlo, para pasarlo a un modo "normal".

Como en Buffer[0] tenemos los caracteres "Ho", cada uno en un byte diferente, entonces, tenemos que separarlos.

Esto lo podemos hacer asi:

Código: (Pawn) [Seleccionar]
new Text[12+1]

// Toma Buffer[0] y hace cero todo, excepto el byte inferior (obtengo primer caracter "H").
Text[0] = Buffer[0] & 0xFF

// Toma Buffer[0], desplaza 8 bits a la derecha para mover el byte superior al byte inferior,
// y luego hace cero todo, excepto el byte desplazado (obtengo segundo caracter "o").
Text[1] = (Buffer[0] >> 8) & 0xFF

Y nos queda:

Text[0] = "H"
Text[1] = "o"




Todo esto se puede automatizar con una función "genérica" auxiliar:

GetHmiString(): Obtiene una cadena guardada por el HMI a partir de un registro ModBus.

ARGUMENTOS:

  • Address = Dirección ModBus donde esta la cadena (ej: 40009)
  • Qty = Cantidad Maxima de registros ModBus a leer (ej: valor 6, implica 12 caracteres)
  • Text[] = Array o cadena resultante en PLC, debe ser de una longitud minima Qty*2+1.

Código: (Pawn) [Seleccionar]

GetHmiString(Address, Qty, Text[])
{
   new Buf[40]
   MbServGetRegisters(Address, Qty, Buf, 0)
   
   for(new i=0; i<Qty; i++)
   {
      Text[i*2] = Buf[i] & 0xFF
      Text[i*2+1] = (Buf[i] >> 8) & 0xFF
   }
   
   // Fin de cadena, ultima posicion.
   Text[Qty*2]=0
}



Volviendo al ejemplo que propones y usando la función GetHmiString() que te escribo, te quedaría para leer 12 caracteres:

Código: (Pawn) [Seleccionar]
new OT[12+1]

GetHmiString(40009, 6, OT)

Listo, ya tenes la cadena en OT[ ].

Te adjunto tu programa modificado con esta función, donde imprimo como cadena en Virtual-HMI (192.168.1.81) lo que recibo del Objeto ASCII en registro 40017 (para verificar el método).

Lo importante es que entiendas como se guarda todo en memoria, puede costar entenderlo, pero es simple si encapsulas todo en funciones y así se evitan errores.

Saludos
« Última Modificación: junio 09, 2017, 10:08:06 am por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

InduxSA

  • Aprendiz
  • **
  • Mensajes: 25
Re:Objeto Ascii
« Respuesta #6 : julio 12, 2017, 15:08:31 pm »
Hola Boris

Como puedo tomar los valores de un vector y convertirlos en un entero, algo como la función atoid que se usa en C

Saludos

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2314
  • Soporte Técnico
Re:Objeto Ascii
« Respuesta #7 : julio 12, 2017, 21:16:30 pm »
Buenas tardes Jose,

Podes hacer una función de este tipo que se llame AtoI(), por ejemplo:

Código: (Pawn) [Seleccionar]
// ********************************************************************************
// Funcion     : AtoI()
// Descripcion : Convierte una cadena númerica en un valor entero.
//
// ENTRADAS:
//
//           - Str[] = Cadena con la representacion de un número,
//                     debe estar terminada en cero.
//
// SALIDA:
//
//           - El valor númerico del numero reperesento por la cadena,
//             si es inválido, retorna 0.
// ********************************************************************************

AtoI(Str[])
{
   if (StrLen(Str) <= 0)
   {
      // Cadena vacia.
      return 0;
   }

   new Res = 0; // Inicializar resultado.
   new Sign = 1; // Inicializar signo como positivo.
   new i = 0; // Inicializar indice de primer digito.
   
   // Ignorar espacios en blanco al inicio.
   for (; Str[i] != '\0'; ++i)
   {
      if(Str[i] == ' ')
      {
         continue;
      }
      else
      {
         break;
      }
   }
   
   // Comprobar signo.
   if (Str[i] == '-')
   {
       Sign = -1;
       
       // Actualizar indice.
       i++;
   }

   // Convertir caracteres a numeros.
   for (; Str[i] != '\0'; ++i)
   {
       // Si la cadena contiene algun caracter, retornar cero.
       if ( Str[i] < '0' || Str[i] > '9')
       {
           return 0;
       }
           
       Res = Res*10 + Str[i] - '0';
   }

   return Sign*Res;
}

La podes usar normalmente, por ejemplo:

Código: (Pawn) [Seleccionar]
new String1[] = "1248"
new String2[] = "-488792"
new String3[] = "  0509"

new Value1, Value2, Value3

// Convertir cadenas numericas a valores enteros.
Value1 = AtoI(String1)
Value2 = AtoI(String2)
Value3 = AtoI(String3)

Te adjunto abajo un proyecto StxLadder de ejemplo que usa la función AtoI() e imprime en VirtualHMI los valores númericos convertidos de las cadenas.

Saludos
« Última Modificación: julio 12, 2017, 21:24:04 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com