Escribir cadenas de log y método para enviar un valor float como entero por red

  • 2 Respuestas
  • 1836 Vistas

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2338
  • Soporte Técnico
Cristian nos consulta:

Cita de: Cristian C.
Hola Boris, quiero pedirte si me podes pasar los comandos para poder grabar un LOG con entradas de cadenas de texto en un archivo de la memoria Micro-SD, para que pueda ser utilizado en laboratorio y que nos permita identificar qué rutina es la que se bloquea. Por otro lado pedirte también como hacer para enviar por red la temperatura del PLC como número entero que no recuerdo bien lo que hablamos (te lo pido como entero ya que en vb no tengo la función >>).

Desde ya muchas gracias.
« Última Modificación: noviembre 03, 2022, 20:37:22 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2338
  • Soporte Técnico
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.
« Última Modificación: noviembre 04, 2022, 11:43:29 am por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 2338
  • Soporte Técnico
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
« Última Modificación: noviembre 03, 2022, 20:36:28 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com