Reading Modbus 32 bit holding Registers

Hi All,

I am looking to create some code to periodically log Temperature, Humidity, Barometric Pressure and Light Intensity from a SenseCAP ORCH S4 Version V1.1 to an SD card using an Arduino UNO or NANO, an RS485 to TTL converter and a real time clock.
The Arduino with the SD card and the RTC, a battery and a solar panel will be mounted in an IP66 rated enclosure on a pole with the ORCH S4. The logging interval is 6 minutes (10 per hour).
The User manual can be obtained from the following if required: [https://files.seeedstudio.com/products/101990661/doc/SenseCAP%20ORCH%20S4%20-%20User%20Guide%20v1.1.pdf]

I am very thankful to this Forum for providing the code to extract the data from the unit.
I have modified it code to my requirements and have successfully read the data from the 16 bit Holding Registers 0x0000(Temperature) and 0x0001(Humidity). I am having difficulty reading the 32 bit registers for Air Pressure 0x0002 & 0x0003 and Light intensity 0x0004 & 0x0005
The default address of my unit is 14

I can code all of the maths to to convert the raw data to decimal numbers and incorporate the RTC and SD card code, but I cant get the raw data from the 32 bit registers.

Code as follows:

// Code taken from following Forum
// https://forum.arduino.cc/t/error-in-communication-modbus-rtu-and-arduino/584876


#include <ModbusMaster.h>

`Use code tags to format code for the forum`/*!
  We're using a MAX485-compatible RS485 Transceiver.
  Rx/Tx is hooked up to the hardware serial port at 'Serial'.
  The Data Enable and Receiver Enable pins are hooked up as follows:
*/

int MAX485_RE_NEG = 3;
int MAX485_DE = 2;

// #define MAX485_RE_NEG  3 
// #define MAX485_DE      2                          


// instantiate ModbusMaster object
ModbusMaster node; // ModbusMaster called as node

void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, 1); // Set to Transmission Mode
  digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0); // Set to Receive Mode
  digitalWrite(MAX485_DE, 0);
}

void setup()
{
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);

  Serial.begin(9600);

  // Modbus slave ID 14
  node.begin(14, Serial);
  // Callbacks allow us to configure the RS485 transceiver correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop()
{
  uint8_t ReadResult;


  ReadResult = node.readHoldingRegisters(0x0000,3);

  if (ReadResult == node.ku8MBSuccess)

  {
    Serial.print("\nTemperature: ");
    Serial.println(node.getResponseBuffer(0x00) / 100.0f);
    Serial.print("\nHumidity: ");
    Serial.println(node.getResponseBuffer(0x01) / 100.0f);
  /*! 
    Serial.println(node.getResponseBuffer(0x03) / 100.0f);
    Serial.println(node.getResponseBuffer(0x04) / 100.0f);
  */

  }

  delay(5000);
}

I would greatly appreciate any assistance offered.

Many thanks
Stuart

It shows you how to do this in the manual you linked to, page 8.

When you read a register, you are reading a 16 bit quantity. Temperature is a 16 bit value, humidty is a 16 bit value, but barometric pressure is a 32 bit value so you are reading 4 16-bit registers, not 3.

ReadResult = node.readHoldingRegisters(0x0000,4);

The manual shows you that you combine register 2 and register 3:

Value=(uint32)(Register 0x0002 << 16 + Register 0x0003)

so that would be

uint32_t pressure = (uint32_t)node.getResponseBuffer(2) << 16 + node.getResponseBuffer(3);
Serial.println(pressure);

The same can be done for light intensity (reading 2 more registers, combining them like above)

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