Modbus Sensor Is Not Reading a Negative Number Correctly

Hello, I have my Modbus sensor reading on a Arduino Opta RS485. It is working fine when reading a positive number but as soon as it goes to read a negative number it reads 65XXX. I cannot figure out how to get it to read a negative number. Thanks n advanced for any help!
My code

/**
  Getting Started with Modbus RTU on Opta™
  Name: Opta_Client
  Purpose: Writes Coil and Holding Register values; Reads Coil, Discrete Input, Holding Registers, and Input Register values.

  @author Arduino
*/

#include <ArduinoModbus.h>
#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library

constexpr auto baudrate { 19200 };

// Calculate preDelay and postDelay in microseconds as per Modbus RTU Specification
// MODBUS over serial line specification and implementation guide V1.02
// Paragraph 2.5.1.1 MODBUS Message RTU Framing
// https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf
constexpr auto bitduration { 1.f / baudrate };
constexpr auto preDelayBR { bitduration * 9.6f * 3.5f * 1e6 };
constexpr auto postDelayBR { bitduration * 9.6f * 3.5f * 1e6 };
// constexpr auto preDelayBR { bitduration * 10.0f * 3.5f * 1e6 };

int counter = 0;

void setup() {
    Serial.begin(9600);
    while (!Serial);

    Serial.println("Modbus RTU Client");

    RS485.setDelays(preDelayBR, postDelayBR);

    // Start the Modbus RTU client
    if (!ModbusRTUClient.begin(baudrate, SERIAL_8N1)) {
        Serial.println("Failed to start Modbus RTU Client!");
        while (1);
    }
}

void loop() {
  readInputRegisterValues();

    counter++;

    delay(1500);
    Serial.println();
}
/**
  Reads Input Register values from the server under specified address.
*/
void readInputRegisterValues() {
    Serial.print("Reading input register values ... ");

    // Read 10 discrete input values from (server) id 42,
    if (!ModbusRTUClient.requestFrom(2, INPUT_REGISTERS, 0x00, 1)) {
        Serial.print("failed! ");
        Serial.println(ModbusRTUClient.lastError());
    } else {
        Serial.println("success");

        while (ModbusRTUClient.available()) {
            Serial.print(ModbusRTUClient.read()*0.001, 3);

            Serial.print(' ');
        }
        Serial.println();
    }

    // Alternatively, to read a single Input Register value use:
    // ModbusRTUClient.inputRegisterRead(...)
}

Simply because the Modbus protocol doesn't define negative numbers. Every register returns a 16 bit unsigned integer by the protocol. It's up to you to convert the returned value to the correct measurement according to the manual of the device.

In your case it seems to be relatively easy, just a cast away:

uint16_t mvalue = ModbusRTUClient.read();
int16_t rvalue = *((in16_t *)&mvalue);
float units = 0.001 * rvalue;

pylon, Works great now. Thanks for the help!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.