variable desde arduino a PLC s-1200 por modbus

buenas llevo unos meses con un proyecto que trata de una bascula con el modulo HX711
la bascula funciona bien el problema es que meto el dato de la bascula en una variable de tipo float
y no consigo enviarla por comunicación Modbus a un PLC s-1200 he probado a enviar datos de una entrada analógica y el estado de un pin y funciona bien pero no consigo enviar datos tipo variables (BIT, INT, LINT, WORD, REAL ,ETC) el código que tengo es este

#include "HX711.h"                    
#include <EtherCard.h>   
#include <Modbus.h>
#include <ModbusIP_ENC28J60.h>
#define DOUT  A0                     
#define CLK  A1
const int SENSOR_IREG=50;

float balanzas;
float calibration_factor = 2035;
long Rohwert;               
long offset = 115920;  
float Scale = 6647.4;    
float Masa;                  
float units;
int tara = 2;     
int buttonState = 0; 


ModbusIP mb;                        
 
HX711 balanca;  
 

void setup()
{
  Serial.begin(9600);
  balanca.begin(DOUT, CLK);                          
  pinMode(tara, INPUT);
 
  Serial.println("Balanza com HX711 - celula de carga 200 g");            
  Serial.println("Presiona t para Tara");          
  balanca.set_scale(calibration_factor);             
  balanca.tare(); 
  byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF,0xFE, 0xED}; 
  byte ip [] = {192,168,0,3};
  mb.config (mac,ip);
  mb.addIreg(SENSOR_IREG);
  

}
 
void loop()
{
  Serial.println("     ");
  Serial.print("Peso: ");                           
  Serial.print(balanca.get_units(), 2);              
  Serial.println(" gramos");
  
 balanzas  = balanca.get_units();

  Serial.println( balanzas );
  delay(1000) ;  

  if (Serial.available())                           
  {
    char temp = Serial.read();                      
    if (temp == 't' || temp == 'T' )                 
    {
      balanca.tare();                                
      Serial.print(" Balanza calibrada");            
    }
   
  }
   units = balanca.get_units(); 
  if (units < 0)
   {
    units = 0.00;
   }
  
  
    {
    buttonState = digitalRead(tara);   

      if (buttonState == HIGH )                  
    {
      balanca.tare();                                
      Serial.println(" Balanza calibrada");  
      delay(3000);
      
    }
     
  }
     
    balanca.read_average(20);
Rohwert = balanca.read_average(20);   
  
    Masa = (Rohwert - offset) / Scale;  

    mb.task();

    mb.Ireg(SENSOR_IREG, balanzas);
 
    
    Serial.print(balanzas);

    
 }

si alguien sabe como lo puedo hacer se lo agradecería mucho
he estado buscando información pero no encuentro nada sobre enviar datos de variables
lo único que encuentro es de entradas analógicas y estados de pines

Creo que estas usando la libreria de @andresarmento, la cual desconozco internamente su funcionamiento.

Pero si te puedo indicar viendo tu código un posible error.

Estas utilando un tipo float para guardar el valor del peso en la variable ‘balanzas’, seguidamente guardas el valor en el registro modbus.

mb.Ireg(SENSOR_IREG, balanzas);

El problema es que el tipo ‘float’ es de 32 bits en arduino y el registro modbus tiene un tamaño de 16 bits. No hay una
transformación directa entre tipos, con lo cual, recibes una cosa que no se corresponde con lo que tu quieres.

Hay dos opciones:

  1. Si el peso de la balanza es un valor que quepa en un entero y no queremos decimales, podemos convertirlo a un entero sin signo realizando un ‘cast’.
int balanzas;
...
void loop() {
  ...
  balanzas  = (int)balanca.get_units();
  ...
}

Aunque esta solución te limita el peso al rango de enteros: 0…32767 y hay que tener cuidado con los valores mas grandes ya que te saldrán cosas negativas.

  1. Queremos conservar la estructura de float.

Aquí hay que hacer dos cosas. Modbus trabaja con 16 bits, por lo tanto hay que crear dos registros para la variable float de forma consecutiva.

mb.addIreg(SENSOR_IREG);
mb.addIreg(SENSOR_IREG+1);

El segundo paso se trata de convertir el ‘float’ a ‘unsigned long’ y luego partir en dos este último.
La conversión de uno a otro no es trivial, por eso he creado una función para ello.

// La función convierte un float en un unsigned long.
unsigned long convertir(float f) {
  union {
    float cf;
    unsigned long cu;
  } unidos;
  unidos.cf = f;
  return unidos.cu;
}

void loop() {
  ...
  // Convertimos a unsigned long.
  unsigned long t = convertir(balanzas);
  // Mandamos la parte ALTA (16 bits).
  mb.Ireg((SENSOR_IREG, (unsigned int)((t>>16)&0xffff)balanzas);
  // Mandamos la parte BAJA (16 bits).
  mb.Ireg((SENSOR_IREG+1, (unsigned int)((t)&0xffff)balanzas);
}

Ahora es cuando el PLC debe saber lo que va a leer. Desconozco si el siemens tiene una instrucción para transformar
dos registros en una variable float, uniendo los dos registros. Puede que incluso tenga la función, pero primero tome
la parte baja y luego la alta (Ya estoy oxidado de la programación de PLC’s).

He hecho el código a pelo, no he comprobado errores ni nada por el estilo. Es tan solo una orientación de lo que puedes hacer.

he probado a quitarle los decimales

Serial.print(balanca.get_units(), 0);

y la variable la he definido con int para que tenga el rango de 16 bits

int balanzas;

y continua sin comunicar

buenas muchas gracias victorjam por tu solución
tenia dos problemas en el código el primero es el que me comentaste que ya lo he solucionado y
te estoy muy agradecido por la solución que me distes y el otro problema es que al intentas enviar tantos datos tan seguidos La comunicación no lo puede gestionas que con un simple retardo lo he solucionado

if (millis()>ts+2000)
{
   ts = millis();
   mb.Ireg(Sensor_IREG, analogRead(SensorPin));
   mb.Ireg(Sensor_IREG1, polo);
   Serial.println(analogRead(SensorPin));
   Serial.println(polo);
   polo = polo + 500;
}