Mensajes recientes

Páginas: [1] 2 3 ... 10
1
Voy a fraccionar la generación del CSV. Igualmente me parece que los límites son más altos de los que me ponés en tu post.
Para que tengas una referencia, actualmente la línea que genera el string CSV tiene:
- 328 caracteres en el código fuente pawn
- Imprime 20 variables %
- El string CSV generado tiene 85 caracteres

Mientras cadena resultante total, la que se imprime finalmente (una vez que los códigos de formato son remplazados), no supere los 199 caracteres estaría bien. Superado este valor, puede ocupar otras áreas de memoria y traer errores (esta cadena dinámica no se limita internamente).

Saludos!
2
OK Boris, muchas gracias.
Voy a fraccionar la generación del CSV. Igualmente me parece que los límites son más altos de los que me ponés en tu post.
Para que tengas una referencia, actualmente la línea que genera el string CSV tiene:
- 328 caracteres en el código fuente pawn
- Imprime 20 variables %
- El string CSV generado tiene 85 caracteres

Al intentar agregar un par de variables más, es que se trunca.

Saludos y gracias!
Pablo
3
Buenos días Pablo, qué tal,

... pareciera que cuando se genera la página mediante WebServerPrintStr(), hubiera alguna limitación en cuanto al número de caracteres que puede tener el renglón; aparentemente serían 90 caracteres. Cuando llega al caracter 90 el string se trunca. Puede ser ?
Esta es la sintaxis utilizada (todo es 1 renglón Pawn):
WebServerPrintStr("%02d/%02d/%02d,%02d:%02d:%d,%s,%d,%d,%d,%s,%d,%s,%02d/%02d,%02d:%02d,%02d/%02d,%02d:%02d,%d.%d,%d.%d,%d.%d,FIN", Dia, Mes, Anio, Hora, Min, Seg, DATO1, DATO2, DATO3, DATO4, DATO5, DATO6, DATO7, DATO8, DATO9, DATO100, DATO11, DATO12, DATO13, DATO14, DATO15, DATO16, DATO17, DATO18, DATO19, DATO20, DATO21)

Para la función WebServerPrintStr(), el límite de la cadena que contiene el formato, es decir "%d, %d, etc", es de 99 caracteres. Y la cadena resultante final, una vez que los formatos son remplazados por sus valores al llamar a la función e impresa en la página, es de 199 caracteres. Así mismo, la cantidad de variables en la lista variable de argumentos no debería sobrepasar los 10.

Si debés imprimir gran cantidad de variables en la misma página, podrías subdividirlo en varias llamadas a WebServerPrintStr(), por ejemplo:

Código: (Pawn) [Seleccionar]
case 1:
WebServerPrintStr("%d, %d, %d, %d,", value1, value2, value3, value4)
case 2:
WebServerPrintStr("%d, %d, %d, %d,", value1, value2, value3, value4)
case 3:
WebServerPrintStr("%d, %d, %d, %d,", value1, value2, value3, value4)
case 4:
WebServerPrintStr("%d, %d, %d, %d", value1, value2, value3, value4)

Es un poco más lento, pero para gran cantidad de valores, es la única forma.

También, te recomiendo usar separador punto y coma ";" para CSV, ya que es más estándar para luego importar desde Excel, si esa es la finalidad.

De paso: la instrucción en lenguaje Pawn que genera ese string es larga (tiene como 480 caracteres)... hay alguna limitación en el compilador para el largo de un renglón de código fuente?  Me surgió esta duda buscando de resolver el problema del punto anterior...

No menciona una limitación de ese tipo, que no quiere decir que no la tenga, pero en cuanto a la cadena, debería estar dentro de los límites mencionados arriba para esa función.

Saludos!
4
Hola Boris, como estás,
Una consulta: en la aplicación de mi PLC estoy creando una "pagina web" que en realidad es una simple cadena de texto (valores separados por comas); en definitiva la "página" es simplemente un renglón, una línea de texto. Así lo tuve funcionando hace meses.
Al agregarle ahora más datos al string CSV (se hizo más largo), pareciera que cuando se genera la página mediante WebServerPrintStr(), hubiera alguna limitación en cuanto al número de caracteres que puede tener el renglón; aparentemente serían 90 caracteres. Cuando llega al caracter 90 el string se trunca. Puede ser ?
Esta es la sintaxis utilizada (todo es 1 renglón Pawn):
WebServerPrintStr("%02d/%02d/%02d,%02d:%02d:%d,%s,%d,%d,%d,%s,%d,%s,%02d/%02d,%02d:%02d,%02d/%02d,%02d:%02d,%d.%d,%d.%d,%d.%d,FIN", Dia, Mes, Anio, Hora, Min, Seg, DATO1, DATO2, DATO3, DATO4, DATO5, DATO6, DATO7, DATO8, DATO9, DATO100, DATO11, DATO12, DATO13, DATO14, DATO15, DATO16, DATO17, DATO18, DATO19, DATO20, DATO21)

De paso: la instrucción en lenguaje Pawn que genera ese string es larga (tiene como 480 caracteres)... hay alguna limitación en el compilador para el largo de un renglón de código fuente?  Me surgió esta duda buscando de resolver el problema del punto anterior...

Desde ya muchas gracias.
Saludos!
Pablo
5
Kinco / Re:Consulta HMI KINCO + PUERTO SERIE ASCII
« Último mensaje por Soporte noviembre 09, 2022, 11:56:21 am »
Lo poco que encontré utilizan el Universal ASCII Slave. pero justamente no se a donde ir a leer ni como tratar lo que llega.

Sí, pero no especifica como debe ser el formato de los datos para que lo interprete el HMI. A lo mejor el fabricante puede darte más información, pero creo que es un protocolo que requiere un formato en la misma cadena.

Por otra parte conoces o me recomendarías algún HMI que si pudiese hacer esto que necesito.

Generalmente los HMI vienen listo para utilizar con el PLC, por ello implementan protocolos y no dan mucha libertad, menos para tomar la cadena y procesarla a medida.

Lo otro que puede ser, es que desde el PLC leas la cadena, interpretes el número o extraigas la parte de la cadena útil y se lo pases a la pantalla.

Por ejemplo con este PLC utilizando las funciones del puerto serie en lenguaje Pawn:

https://www.slicetex.com/hw/stx8091/dx.php

Saludos!

6
Kinco / Re:Consulta HMI KINCO + PUERTO SERIE ASCII
« Último mensaje por Alexnch noviembre 09, 2022, 11:12:07 am »
Gracias por la pronta respuesta!

Lo poco que encontré utilizan el Universal ASCII Slave. pero justamente no se a donde ir a leer ni como tratar lo que llega.

Por otra parte conoces o me recomendarías algún HMI que si pudiese hacer esto que necesito.

Muchas Gracias!
7
Kinco / Re:Consulta HMI KINCO + PUERTO SERIE ASCII
« Último mensaje por Soporte noviembre 09, 2022, 11:02:08 am »
Tengo una HMI Kinco MT4434TE la cual necesito leer en el puerto serie del HMI un String o cadena de datos de un equipo que envía permanentemente valores.
Ejemplo: "<STX>000025<CR>"
luego mostrarlo por pantalla.

Buenos días.

Hasta donde sé no podrías hacerlo. El HMI permite seleccionar una lista de protocolos predefinidos para la comunicación e interpretación de datos, para así posteriormente poder mapear los datos en registros/variables cuya dirección corresponde a un botón, indicador, entrada numérica, etc.

Por ejemplo, un protocolo universal soportado es ModBus RTU (que generalmente encontrás en equipos a medida), sino, los específicos para cada PLC (Siemens, ABB, etc).

En tu caso es una cadena de datos que no correspondería a un protocolo soportado, sino que es arbitraria, por lo tanto, el HMI no la va a poder procesar.

Saludos!
8
Kinco / LECTURA DE CADENA A MEDIDA EN PUERTO SERIE ASCII
« Último mensaje por Alexnch noviembre 09, 2022, 10:38:34 am »
Hola buenos días a todos, soy nuevo con el tema de HMI y me encuentro intentando resolver algo y no se como por eso quería hacerles una consulta:
Tengo una HMI Kinco MT4434TE la cual necesito leer en el puerto serie del HMI un String o cadena de datos de un equipo que envía permanentemente valores.
Ejemplo: "<STX>000025<CR>"
luego mostrarlo por pantalla.

Vi en algunos ejemplo que se puede escribir en el puerto serie, pero en ninguno explica bien como leer.

Desde ya muchas gracias y ojala puedan ayudarme

Saludos

9
STX8180 / Re:Escribir cadenas de log y método para enviar un valor float como entero por red
« Último mensaje por Soporte noviembre 03, 2022, 20:25:02 pm »
Extra, si necesitás agregar Logs, pero solo para pruebas, y no en el código de producción, podés utilizar directivas de preprocesamiento para incluir código opcionalmente de acuerdo al valor de una constante, y evitar crear dos proyectos diferentes.

Ejemplo:

Definimos en un archivo de cabeceras, por ejemplo Globals.inc, la constante DEBUG_LOG:

Código: (Pawn) [Seleccionar]
#define DEBUG_LOG    (1)
Luego, en un archivo Pawn, por ejemplo, DebugLog.p, las funciones para hacer entradas de log, por ejemplo:

Código: (Pawn) [Seleccionar]
stock DebugLogInit()
{
   DiskMount()
   DiskLogInit(1, "log", "txt", "/", 100000, 9, DISKLOG_OPT_PPPPPPPX|DISKLOG_OPT_CIRCULAR|DISKLOG_OPT_FAST_WRITE)
}

stock DebugLogFuncName(const FunctionName[])
{
   DiskLogAddString(1, FunctionName)
}

Finalmente, desde el código del proyecto escribimos en cada llamada a función que queramos añadir su nombre al log lo siguiente:

Código: (Pawn) [Seleccionar]
#if DEBUG_LOG  == 1
DebugLogFuncName("NombreFuncion1)
#endif

// ... CÓDIGO DEL PROYECTO ...

#if DEBUG_LOG  == 1
DebugLogFuncName("NombreFuncion2)
#endif

Si DEBUG_LOG  == 1 se agregan entradas al log, si es 0, directamente no se incluye en el código.

En en log aparecerán las entradas con los textos NombreFuncion1, NombreFuncion2, etc
10
STX8180 / Re:Escribir cadenas de log y método para enviar un valor float como entero por red
« Último mensaje por Soporte noviembre 03, 2022, 20:06:48 pm »
Buenas tardes Cristian,

La forma más simple de hacer un log es mediante la función:

DiskWriteLogString(Options, PathStr[], FormatStr[], ...)

Donde:

  • Options: Opciones para el log, usar DISK_WRITELOG_OPT_DEFAULT para opciones por defecto.
  • PathStr: Ruta al archivo, por ejemplo "log.txt"
  • FormatStr: Cadena con formato, por ejemplo "Hola Mundo!" o "Temperatura %f" (%f será remplazado por un valor float de la lista de argumentos variables.
  • ...: Argumentos con variables separadas por coma (opcional).

Ejemplo:

Código: (Pawn) [Seleccionar]
// Agregar mensaje de log con la temperatura del sistema.
DiskWriteLogString(DISK_WRITELOG_OPT_DEFAULT, "/log.txt", "Sistema listo, temperatura %f [C]", SysTempRead())

El código anterior creará una entrada similar a la siguiente si la temperatura es de 25.4 °C:

03/11/2022 19:45:03 Sistema listo, temperatura 25.4 [C]

Para que el ejemplo funcione, se debe montar una sola vez la tarjeta Micro-SD antes de utilizarla, por ejemplo al iniciar el PLC con el siguiente código:

Código: (Pawn) [Seleccionar]
   // Montar disco Micro-SD.
   DiskMount()

Ejemplo completo:

www.slicetex.com/docs/an/an036/files/examples/DiskExample1.zip



El método anterior no define la longitud del archivo, ni su tamaño máximo, lo cual, para log extensos, puede llenar la memoria o hacer archivos gigantes. Una forma más eficiente es utilizar las funciones DiskLog.

Primero montamos el disco como vimos antes:

Código: (Pawn) [Seleccionar]
DiskMount()
Luego inicializamos el canal número 1 de DiskLog (este número lo usaremos luego para loguear cada entrada) para que permita hasta 9 archivos de log, con un máximo de 100000 entradas cada uno, con un prefijo "log" de nombre y extensión "txt". El archivo se almacena en la raiz del disco "/".

Código: (Pawn) [Seleccionar]
DiskLogInit(1, "log", "txt", "/", 100000, 9, DISKLOG_OPT_PPPPPPPX|DISKLOG_OPT_CIRCULAR|DISKLOG_OPT_FAST_WRITE)
Los archivos resultantes serán: log1.txt, log2.txt y así hasta log9.txt. Cuando se llega a log9.txt, se vuelve a log1.txt porque está colocada la opción DISKLOG_OPT_CIRCULAR. Cada archivo tendrá un máximo de 100000 entradas.

Finalmente, para agregar una entrada de texto al log, utilizamos la función DiskLogAddString() pero especificando el canal 1 del DiskLog:

Código: (Pawn) [Seleccionar]
// Agregar mensaje de log con la temperatura del sistema.
DiskLogAddString(1, "Sistema listo, temperatura %f [C]", SysTempRead())

El código anterior creará una entrada similar a la siguiente si la temperatura es de 25.4 °C:


1 03/11/2022 19:45:03 Sistema listo, temperatura 25.4 [C]
2 03/11/2022 19:46:03 Sistema listo, temperatura 25.4 [C]
3 03/11/2022 19:47:03 Sistema listo, temperatura 25.4 [C]


Notar como al comienzo de cada entrada está el número de entrada.

Usar DiskLog con la opción DISKLOG_OPT_FAST_WRITE es más rápido para escribir en memoria que la función DiskWriteLogString() vista anteriormente.

Ejemplo completo:

www.slicetex.com/docs/an/an036/files/examples/DiskSamplerLog1.zip



Finalmente, contestando a tu consulta para enviar un valor float como entero por la red, sin usar desplazamientos, es sencillo. Utilizamos un entero como si tuviera un punto fijo y no flotante. Si multiplicamos por 100 antes de enviar, es como mover la coma dos posiciones hacia la derecha.

Por ejemplo:

Código: (Pawn) [Seleccionar]
new Float: Temperatura = 25.59
new Entero
new DataBytes[4]

// Multiplicamos temperatura por 100 para preservar dos decimales y luego convertimos a entero.
Entero = FloatToInt(Temperatura * 100.0)

// Enviamos el valor "Entero" por la red, byte a byte desde el array DataByte[].
DataByte[0] = Entero & 0xFF
DataByte[1] = (Entero >> 8) & 0xFF
DataByte[2] = (Entero >> 16) & 0xFF
DataByte[3] = (Entero >> 24) & 0xFF

Al recibir en Visual Basic armamos el entero (sugerido):

Código: (VB .Net) [Seleccionar]
Dim Entero As Integer
Dim DataByte(3) As Byte  ' Array de 4 bytes

' Opción #1
Entero = (DataByte(0)) Or (DataByte(1) << 8) Or (DataByte(2) << 16) Or (DataByte(3) << 24)

' Opción #2
Entero = BitConverter.ToInt32(DataByte, 0)



Posteriormente, en Visual Basic el valor "Entero" lo convertimos a "float" y dividimos por 100 para obtener los dos decimales, es decir, movemos la coma decimal hacia la izquierda.
Páginas: [1] 2 3 ... 10