ESP32: Conversión de 754 32-bit floats a 16-bit

Hola, estoy teniendo algunos problemas con un pequeño proyecto en el que estoy trabajando actualmente. Mi objetivo es el siguiente:

Tengo dos dispositivos:

  1. Un dispositivo de transferencia de datos que utiliza el protocolo de coma flotante de 32 bits IEEE 754.
  2. Un dispositivo receptor que solo puede aceptar datos de 16 bits.

Planeo usar un microcontrolador ESP32 y dos transceptores MAX485 para que actúen como una pasarela (gateway).

El objetivo es:

  • Recibir los datos del primer dispositivo (que están divididos porque cada valor de 32 bits llega a través de dos direcciones).
  • Concatenar las dos partes de 16 bits recibidas de nuevo en el valor original de coma flotante de 32 bits.
  • Convertir/reducir el valor de coma flotante de 32 bits a un formato de 16 bits (ya que el dispositivo receptor solo lo soporta).
  • Enviar los datos de 16 bits resultantes a través de una única dirección al dispositivo receptor.

Los datos del primer dispositivo siguen esta tabla:

Necesito recibir los datos de las direcciones 1 y 2, y 7 y 8. Quiero concatenar los datos de cada par (1 y 2, 7 y 8) y que los resultados (después de la conversión) se envíen a los Registros de Retención (Holding Registers) Modbus 40001 y 40002, respectivamente.

Algunos detalles importantes son:

Dispositivo 1 (Fuente):

  • ID Esclavo (Slave ID): 3
  • Velocidad (Baud Rate): 9600
  • Bits de Datos (Data Bits): 8
  • Bits de Parada (Stop Bits): 1
  • Paridad (Parity): Ninguna

Dispositivo Receptor (Destino):

  • ID Maestro (Master ID): 1
  • Velocidad (Baud Rate): 9600
  • Bits de Datos (Data Bits): 8
  • Bits de Parada (Stop Bits): 1
  • Paridad (Parity): Ninguna

He estado utilizando una IA para que me ayude, pero sigo topándome con un muro porque tengo problemas con las librerías ModbusRTUSlave.

Actualmente, este es mi progreso:

#include <ModbusIP_ESP.h>
#include <ModbusRTU.h>

#include <ModbusMaster.h>
// ¡ÚLTIMA CORRECCIÓN DE INCLUSIÓN! Forzando la ruta dentro del nombre de la librería:
#include <modbus-esp/Modbus.h> 

// ******************************************************
// --- DEFINICIONES DE HARDWARE Y PINES ---
// ******************************************************
#define SERIAL_MAESTRO Serial2 
#define RX2_PIN 16
#define TX2_PIN 17
#define CTRL_BUS1_MAESTRO 4       
#define BAUD_RATE_485_IN 9600     

#define SERIAL_ESCLAVO Serial1 
#define RX1_PIN 9
#define TX1_PIN 10
#define CTRL_BUS2_ESCLAVO 5       
#define BAUD_RATE_485_OUT 9600    

// ******************************************************
// --- OBJETOS MODBUS ---
// ******************************************************
ModbusMaster bus_maestro;
Modbus modbus_slave(SERIAL_ESCLAVO, CTRL_BUS2_ESCLAVO, CTRL_BUS2_ESCLAVO); 

// ******************************************************
// --- REGISTROS Y CONVERSIÓN ---
// ******************************************************
#define SLAVE_ID_ENTRADA 1
#define REG_COUNT_FLOAT 2 

#define START_REG_FLOAT_P 1       
#define START_REG_FLOAT_T 7       

#define SLAVE_ID_SALIDA 1

#define REG_SALIDA_P 0      // Mapeada a 40001
#define REG_SALIDA_T 1      // Mapeada a 40002

#define TOTAL_REGISTERS_SALIDA 2 
const float FACTOR_ESCALA = 100.0; 

typedef union {
    float f;       
    uint16_t w[2]; 
} ModbusFloat;

uint16_t holding_registers[TOTAL_REGISTERS_SALIDA] = {0, 0}; 

// ******************************************************
// --- FUNCIONES DE CONTROL DE DIRECCIÓN RS-485 ---
// ******************************************************
void preTransmissionBus1() { digitalWrite(CTRL_BUS1_MAESTRO, HIGH); }
void postTransmissionBus1() { digitalWrite(CTRL_BUS1_MAESTRO, LOW); }

// ******************************************************
// --- Función de Transferencia ---
// ******************************************************
void transferAndScale(uint16_t startRegIn, uint16_t regOut) {
    uint8_t result;
    ModbusFloat data_in;
    int16_t valor_final_16bit;

    result = bus_maestro.readHoldingRegisters(SLAVE_ID_ENTRADA, startRegIn, REG_COUNT_FLOAT);

    if (result == bus_maestro.ku8MBSuccess) {
        
        data_in.w[0] = bus_maestro.getResponseBuffer(0); 
        data_in.w[1] = bus_maestro.getResponseBuffer(1); 

        float valor_escalado = data_in.f * FACTOR_ESCALA;
        valor_final_16bit = (int16_t)valor_escalado; 
        
        if (abs(valor_escalado) > 32767) { 
             valor_final_16bit = (valor_escalado > 0) ? 32767 : -32768;
        }

        holding_registers[regOut] = (uint16_t)valor_final_16bit;
        
        Serial.printf("Reg %d (Float: %.2f) -> Reg 4000%d (Int: %d)\n", 
                       startRegIn, data_in.f, regOut + 1, valor_final_16bit);
        
    } else {
        Serial.printf("Error de lectura en Reg %d: %d\n", startRegIn, result);
    }
}

// ******************************************************
// --- SETUP: Inicialización de la Pasarela ---
// ******************************************************
void setup() {
    Serial.begin(115200); 
    Serial.println("Iniciando Pasarela Modbus...");

    // Inicialización de Pines
    pinMode(CTRL_BUS1_MAESTRO, OUTPUT);
    digitalWrite(CTRL_BUS1_MAESTRO, LOW); 
    pinMode(CTRL_BUS2_ESCLAVO, OUTPUT);
    digitalWrite(CTRL_BUS2_ESCLAVO, LOW); 

    // --- CONFIGURACIÓN MAESTRO (BUS DE ENTRADA) ---
    SERIAL_MAESTRO.begin(BAUD_RATE_485_IN, SERIAL_8N1, RX2_PIN, TX2_PIN); 
    bus_maestro.begin(SLAVE_ID_ENTRADA, SERIAL_MAESTRO); 
    bus_maestro.preTransmission(preTransmissionBus1);
    bus_maestro.postTransmission(postTransmissionBus1);

    // --- CONFIGURACIÓN ESCLAVO (BUS DE SALIDA) ---
    SERIAL_ESCLAVO.begin(BAUD_RATE_485_OUT, SERIAL_8N1, RX1_PIN, TX1_PIN); 
    
    modbus_slave.begin(SLAVE_ID_SALIDA, BAUD_RATE_485_OUT, SERIAL_8N1); 
    
    // ASIGNACIÓN CRÍTICA DE MEMORIA:
    modbus_slave.setupHoldingRegisters(holding_registers, TOTAL_REGISTERS_SALIDA);
    
    Serial.println("Configuración completa. Ejecutando LOOP.");
}

// ******************************************************
// --- LOOP: Lógica de Transferencia Continua ---
// ******************************************************
void loop() {
    
    transferAndScale(START_REG_FLOAT_P, REG_SALIDA_P);
    transferAndScale(START_REG_FLOAT_T, REG_SALIDA_T);
    
    modbus_slave.poll(); 
    
    delay(100); 
}

Agradezco cualquier apoyo y consejo que puedan darme

Por favor, no publicar en otros sitios. Tema cerrado.