Uniones sobre estructuras de variables (Float a Registro ModBus)

  • 7 Respuestas
  • 178 Vistas

damianmuracciole

  • Novato
  • *
  • Mensajes: 6
Buenos dias, estoy realizando una comunicacion modbus rtu entre el plc, una pantalla kinco y unos modulos medidores.
El plc esta como master.
El problema que me surge es que cada modulo genera una variable a transmitir flotante (32bits), y el tipo de variable en modbus es de 16 bits. lo que hago habitualmente es en un micro generar una estructura tipo union donde puedo convertir ese flotante en dos variables de 16 bits que copia bit a bit el flotante en estas dos variables. Del otro lado hago lo inverso, es decir cargo estos registros de 16 bits y a traves de una union paso bis a bit a una variable de 32 bits y tengo el flotante transmitido. El concepto de union es un clasico en C.

se puede hacer algo asi? no he encontrado data en lo que he leido de los manuales.

saludos
« Última Modificación: marzo 15, 2018, 12:06:18 pm por Soporte »

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 1844
  • Soporte Técnico
Re:Uniones sobre estructuras de variables
« Respuesta #1 : diciembre 14, 2017, 11:54:00 am »
El problema que me surge es que cada modulo genera una variable a transmitir flotante (32bits), y el tipo de variable en modbus es de 16 bits. lo que hago habitualmente es en un micro generar una estructura tipo union donde puedo convertir ese flotante en dos variables de 16 bits que copia bit a bit el flotante en estas dos variables. Del otro lado hago lo inverso, es decir cargo estos registros de 16 bits y a traves de una union paso bis a bit a una variable de 32 bits y tengo el flotante transmitido. El concepto de union es un clasico en C.

se puede hacer algo asi? no he encontrado data en lo que he leido de los manuales.

Buenos días,

Si, es posible, aclárame si lo que querés hacer, ¿es leer dos registros de 16-bits por ModBus, para luego unirlo en un float en el PLC y tenerlo disponible?.

O al revés, ¿tenés un float en el PLC y deseas transmitirlo como 2 registros de 16-bits vía ModBus?.

¿Que lenguaje estas utilizando?

Saludos
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

damianmuracciole

  • Novato
  • *
  • Mensajes: 6
Re:Uniones sobre estructuras de variables
« Respuesta #2 : diciembre 14, 2017, 12:00:23 pm »
Necesito hacer es lo primero, es decir, tengo un flotante dividido en dos variables que leo desde el modbus y las quiero unir para rehacer el float. Estoy trabajando en pawn.

damianmuracciole

  • Novato
  • *
  • Mensajes: 6
Re:Uniones sobre estructuras de variables
« Respuesta #3 : diciembre 14, 2017, 12:16:05 pm »
En realidad ambas cosas dado que despues voy a tener que enviar un dato flotante por modbus a la pantalla.

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 1844
  • Soporte Técnico
Re:Uniones sobre estructuras de variables
« Respuesta #4 : diciembre 14, 2017, 12:40:15 pm »
En realidad ambas cosas dado que despues voy a tener que enviar un dato flotante por modbus a la pantalla.

Bien, lo que debes utilizar es el operador "desplazamiento de bits" en Pawn.

Leer variable Float desde registros ModBus

En este caso, lees dos registros de 16-bits del dispositivo remoto que representan un valor float de 32-bits.

El float, debería estar almacenado en las direcciones de registros como sigue:

RegistroH  = 16-bits mas significativos.
RegistroL  = 16-bits menos significativos.

Entonces, debes leer ambos registros (supongamos que ya recibiste ambos valores vía ModBus y los tenes en las variables RegistroH y RegistroL):

// En Pawn (en rojo los valores ya recibidos)
new RegistroH = Valor Y
new RegistroL = Valor X


// Crear dos variables intermedias.
new RawValue
new Float: FloatValue = 0


// Convertir a 32-bits (unir ambos registros para formar el float de 32-bits).
// Notar en segunda linea como realizo una operación SHIFT y luego un OR bit-a-bit.
RawValue = RegistroL
RawValue |= (RegistroH << 16)


// Almacenar en float haciendo un cast (para que se interprete correctamente).
FloatValue = Float: RawValue


Finalmente, en FloatValue tenes el float obtenido del registro ModBus.

Escribir variable Float en registros ModBus

Acá debes hacer al revés, del float, copiar 16-bits más significativo en un registro y 16-bits menos significativos en otro registro.

// Valor float a transmitir.
new Float: FloatValue = 123.456

// Variables enteras a copiar en registros.
new RegistroH
new RegistroL


// Almacenamos 16-bits más significativos, desplazando 16 bits a la derecha:
RegistroH = FloatValue >> 16

// Almacenamos 16-bits menos significativos, haciendo cero 16-bits más significatios con operación AND.
RegistroL = FloatValue & 0xFFFF


Luego en RegistroH y RegistroL tenes el float descompuesto, que podes copiar a los registros ModBus.



En ambos ejemplos podes usar VirtualHMI para imprimir en pantalla el valor y corroborar operación.

Te recomiendo hacer la prueba con un código básico para entender el proceso.

Las operaciones con bits (desplazamientos, AND, OR, etc) son iguales que en lenguaje C. Si tenes alguna duda conceptual, avísanos.

Saludos.

« Última Modificación: diciembre 14, 2017, 12:47:50 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

damianmuracciole

  • Novato
  • *
  • Mensajes: 6
Re:Uniones sobre estructuras de variables
« Respuesta #5 : diciembre 14, 2017, 14:55:52 pm »
Buenisimo. Asi si funciona. En C o C++ convertis las variables directamente anteponiendo Float o word o dword a la variale o ecuacion en cuestion. en otros plcs convertis las variables con funciones determinadas dado que el formato float es diferente al binario en CA1 o CA2. Pense que podia existir alguna funcion asi. no importa, armo las funciones de conversion y listo.
muchas gracias.
saludos.

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 1844
  • Soporte Técnico
Re:Uniones sobre estructuras de variables
« Respuesta #6 : diciembre 14, 2017, 16:01:33 pm »
Buenisimo. Asi si funciona. En C o C++ convertis las variables directamente anteponiendo Float o word o dword a la variale o ecuacion en cuestion. en otros plcs convertis las variables con funciones determinadas dado que el formato float es diferente al binario en CA1 o CA2. Pense que podia existir alguna funcion asi. no importa, armo las funciones de conversion y listo.
muchas gracias.
saludos.

Podríamos crear algunas funciones genéricas para que ya este soportado de forma estándar en una actualización de firmware.

¿Cómo son en los PLC que utilizas?.

Se me ocurre que podría implementarse algo similar a lo siguiente para fácil uso:

  • FloatToReg16(FloatValue, Reg16Low, Reg16High): Separa FloatValue en dos variables enteras, con valores de 16-bits en Reg16Low y Reg16High.
  • Reg16ToFloat(Reg16Low, Reg16High): Une dos registros o variables enteras que contienen un valor float, retorna el valor convertido.

Básicamente para ser utilizado en operaciones ModBus.
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com

Soporte

  • Global Moderator
  • Experto
  • *****
  • Mensajes: 1844
  • Soporte Técnico
Re:Uniones sobre estructuras de variables (Float a Registro ModBus)
« Respuesta #7 : marzo 15, 2018, 12:05:48 pm »
Buenisimo. Asi si funciona. En C o C++ convertis las variables directamente anteponiendo Float o word o dword a la variale o ecuacion en cuestion. en otros plcs convertis las variables con funciones determinadas dado que el formato float es diferente al binario en CA1 o CA2. Pense que podia existir alguna funcion asi. no importa, armo las funciones de conversion y listo.
muchas gracias.
saludos.

Podríamos crear algunas funciones genéricas para que ya este soportado de forma estándar en una actualización de firmware.

¿Cómo son en los PLC que utilizas?.

Se me ocurre que podría implementarse algo similar a lo siguiente para fácil uso:

  • FloatToReg16(FloatValue, Reg16Low, Reg16High): Separa FloatValue en dos variables enteras, con valores de 16-bits en Reg16Low y Reg16High.
  • Reg16ToFloat(Reg16Low, Reg16High): Une dos registros o variables enteras que contienen un valor float, retorna el valor convertido.

Básicamente para ser utilizado en operaciones ModBus.

ACTUALIZACIÓN

En la última versión de firmware para el PLC y StxLadder disponibles para descargar, se agregan dos funciones útiles para cargar un valor Float en ModBus:

  • UnpackFloatToInt16(FloatValue, Int16Low, Int16High): Separa FloatValue en dos variables enteras, con valores de 16-bits en Int16Low y Int16High.
  • PackInt16ToFloat(Int16Low, Int16High): Une dos registros o variables enteras que contienen un valor float, retorna el valor convertido.

Ejemplo:

Código: (Pawn) [Seleccionar]

new Float: fv1 = -123.678
new Float: fv2

new i16l, i16h

// Desempaquetar/Separar Float de 32-bits en 2 enteros de 16 bits.
UnpackFloatToInt16(fv1, i16l, i16h)
   
// Empaquetar/Unir 2 enteros de 16-bits en un Float de 32-bits.
fv2 = PackInt16ToFloat(i16l, i16h)


Adjuntamos un proyecto con este ejemplo (y otros de conversión), la salida o resultados se imprimen por Virtual-HMI.

Saludos!


« Última Modificación: marzo 15, 2018, 12:09:58 pm por Soporte »
SOPORTE TÉCNICO

Slicetex Electronics
www.slicetex.com