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