Arduino opta + soil sensor

Hello, I have a temperature and humidity measurement sensor for soil. This sensor is more industrial, totally different from the DHT sensors that I use with Arduino UNO and I am trying to make an application using this sensor with OPTA through Modbus RTU.
At the moment I managed to establish communication with my programming, including being able to read some information, but this information doesn't make sense. I don't know exactly what programming to use to read this sensor or in this case what modification to make to it.

#include <ArduinoModbus.h>
#include <ArduinoRS485.h>

constexpr auto baudrate { 4800 }; 
constexpr auto btime { 1.0f / baudrate };
constexpr auto predl { btime * 9.6f * 3.5f * 1e6 };
constexpr auto postdl { btime * 9.6f * 3.5f * 1e6 };

void setup() {
  Serial.begin(115200);
  delay(2000);
  RS485.setDelays(predl, postdl);
  if (!ModbusRTUClient.begin(baudrate, SERIAL_8N1 ) ) {
    Serial.println("Erro Modbus");
    while(1);
  }

}

void loop() {

  float i = readdata(0x01, 0x258);

  float m = readdata(0x01, 0x190);

  Serial.println(String(i, 10) + "A " + String(m, 10) + "M ");
  delay(3000);
}


float readdata(int addr, int reg) {
  float res = 0.0;
  if (!ModbusRTUClient.requestFrom(addr, INPUT_REGISTERS, reg, 2)) {
    Serial.println("Erro de comunicação");
    Serial.println(ModbusRTUClient.lastError());
  } else {
    uint16_t word1 = ModbusRTUClient.read();
    uint16_t word2 = ModbusRTUClient.read();
    uint32_t parz = word1 << 16 | word2;
    res = *(float *)&parz;
  }
  return res;
}

Note that I define the ID of my sensor and enter the reading addresses that I want to read, but as I said, the data doesn't make sense. I'm sure I'm doing something wrong in the programming.
Below is the datasheet for the Modbus addresses of my sensor


Soil TH & TH-EC (3pin probe) manual_V1.1.pdf (352,2,KB)

This is my measurement result on the serial monitor, proving that it is measuring something and that I have established communication

Can you expand on this. What doesn't make sense about the values you are seeing? Can you provide examples?

I think you should look at this bit of code.

Word1 is defined as a 16-bit integer. If you <<16 it, then you will shift all the bits out of the top and end up with zero. I think you would need to cast word1 as a 32-bit integer before shifting it left 16 bits.

1 Like

The readings I'm saying are "random" numbers, but when you put the sensor in water, that number fluctuates. With this, I understand that I am reading something, but the way in which I am receiving this reading is not correct.

In the image above inside my Serial Monitor, I have 2 measurements, at the time I took a screenshot I had changed an address and that's why I have a value of 0.00000... and in the other I have 0.946280598...
However, if I return the first address to the original I will have a measurement close to 0.946280598 (second measurement).

I say that maybe it doesn't make sense, because I saw in some Arduino tutorials using this sensor that in the programming, bytes are used instead of Modbus addresses and I don't know if this could be a possible solution.

I used software to read the bytes from this sensor and got this result, but I'm not sure if I actually need to use bytes instead of modbus addresses.

Check this demo??
ModbusRTUTemperatureSensor
Thinking this is closer to what you need..

good luck.. ~q

1 Like

Thank you very much!
With this example you sent me, it was possible to make some changes to my code so that it can now be read correctly. Thanks a lot for the help. Here is the working code below:

#include <ArduinoModbus.h>
#include <ArduinoRS485.h>

constexpr auto baudrate { 4800 }; 
constexpr auto btime { 1.0f / baudrate };
constexpr auto predl { btime * 9.6f * 3.5f * 1e6 };
constexpr auto postdl { btime * 9.6f * 3.5f * 1e6 };

float temperature;
float humidity;

void setup() {
  Serial.begin(115200);
  delay(2000);
  RS485.setDelays(predl, postdl);
  if (!ModbusRTUClient.begin(baudrate, SERIAL_8N1)) {
    Serial.println("Erro Modbus");
    while(1);
  }
}

void loop() {
  // Solicitar a leitura de 2 registradores de entrada do escravo com ID 1, começando do registrador 0x01
  if (!ModbusRTUClient.requestFrom(1, INPUT_REGISTERS, 0x00, 2)) {
    Serial.print("Falha ao ler os registradores! Erro: ");
    Serial.println(ModbusRTUClient.lastError());
  } else {
    if (ModbusRTUClient.available() == 2) { // Verifique se há dois registros disponíveis
      // Ler os valores brutos
      short rawtemperature = ModbusRTUClient.read();
      short rawhumidity = ModbusRTUClient.read();

      // Converter para os valores reais
      temperature = rawtemperature / 10.0;
      humidity = rawhumidity / 10.0;

      // Imprimir os valores
      Serial.print("Temperatura: ");
      Serial.print(humidity);
      Serial.println(" °C");

      Serial.print("Umidade: ");
      Serial.print(temperature);
      Serial.println(" %");
    } else {
      Serial.println("Número de registros lidos incorreto!");
    }
  }

  delay(5000);
}
1 Like