Can someone help me, for my 4in1 5pin probe RS485 THPH+EC Sensor, I have code but it doesn't read anything. I am using arduino uno for this

@shiloh14 ,

Your two or more topics on the same or similar subject have been merged.

Please do not duplicate your questions as doing so wastes the time and effort of the volunteers trying to help you as they are then answering the same thing in different places.

Please create one topic only for your question and choose the forum category carefully. If you have multiple questions about the same project then please ask your questions in the one topic as the answers to one question provide useful context for the others, and also you won’t have to keep explaining your project repeatedly.

Repeated duplicate posting could result in a temporary or permanent ban from the forum.

Could you take a few moments to Learn How To Use The Forum

It will help you get the best out of the forum in the future.

Thank you.

I sincerely apologize Sir and thank you for your message

1 Like

Yes that's similarly my sensor, but from the seller where i brought it does not give me any test codes or manuals.

Here's how i connect it Sir.

RS485 3IN1 SOIL SENSOR:
YELLOW WIRE --> A OF TTL TO RS485 MODULE
BLUE WIRE --> B OF TTL RS485 MODULE
BROWN WIRE --> (+) OF 9V BATT
BLACK WIRE --> (-) OF 9V BATT

TTL TO RS485 MODULE:
RE --> DIGITAL PIN 10
DE --> DIGITAL PIN 11
DI --> DIGITAL PIN 3
RO -->DIGITAL PIN 2

VCC --> 5V OF ARDUINO UNO (THROUGH BREAD BOARD)
GND --> GND OF ARDUINO UNO (THROUGH BREADBOARD)

LCD I2C:
SCL --> SCL OF ARDUINO UNO (DIRECT)
SDA --> SDA OF ARDUINO UNO (DIRECT)
VCC --> 5V OF ARDUINO UNO (DIRECT)
GND --> GND OF ARDUINO UNO (DIRECT)

RELAY:
VCC --> 5V OF ARDUINO UNO (THROUGH BREADBOARD)
GND --GND OF ARDUINO UNO (THROUGH BREADBOARD)
IN --> DIGITAL PIN 8
NO --> (+) OF 12V PSU
COM --> (+) OF WATER PUMP

WATER PUMP:
GND --> GND OF 12V PSU

post a real picture of your hardware. Some breadboards have a gap in the middle of the power-rails. This means if you connect power on one end of these power-rails and want to supply something on the opposite end no power is delivered caused by the gap.

an arduino-uno-board is NOT a power-supply. Trying to supply a relay from the 5V pin of the arduino is bad idea.

You should really post a picture of your hardware setup.

Additionally post your most actual code new. Even if you haven't changed anything.



this time i try to change pins:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

// Define LCD address and dimensions
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adjust 0x27 to your LCD's I2C address if necessary

#define RE 7
#define DE 6
#define RELAY_PIN 5 // Pin connected to the relay module controlling the water pump

const uint32_t TIMEOUT = 2000UL; // Increased timeout for sensor response
const byte moist[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
const byte temp[] = {0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xCA};
const byte PH[] = {0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A};

const float MOISTURE_THRESHOLD = 20.0; // Moisture level below which the pump will turn on

byte values[11];

SoftwareSerial mod(2, 3); // Rx pin, Tx pin

void setup() {
  Serial.begin(4800); // Match with the sensor's baud rate
  mod.begin(4800);

  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);

  lcd.init();        // Initialize the LCD
  lcd.backlight();   // Turn on the backlight

  digitalWrite(RELAY_PIN, LOW); // Ensure pump is off at startup

  lcd.setCursor(0, 0);
  lcd.print("Initializing...");
  delay(1000);
}

void loop() {
  // Moisture reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Moisture:");
  float moistureValue = readSensor(moist) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(moistureValue);
  lcd.print(" %");
  delay(2000); // Display for 2 seconds

  // Control water pump based on moisture level
  if (moistureValue < MOISTURE_THRESHOLD) {
    digitalWrite(RELAY_PIN,  LOW); // Turn pump ON
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pump ON");
  } else {
    digitalWrite(RELAY_PIN, HIGH); // Turn pump OFF
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pump OFF");
  }
  delay(2000); // Display for 2 seconds

  // Temperature reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperature:");
  float temperatureValue = readSensor(temp) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(temperatureValue);
  lcd.print(" C");
  delay(2000); // Display for 2 seconds

  // pH reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("pH Level:");
  float phValue = readSensor(PH) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(phValue);
  delay(2000); // Display for 2 seconds
}

int16_t readSensor(const byte* command) {
  uint32_t startTime = 0;
  uint8_t byteCount = 0;
  memset(values, 0, sizeof(values)); // Clear previous data

  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  mod.write(command, 8); // Send command (8 bytes)
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  startTime = millis();
  while (millis() - startTime <= TIMEOUT) {
    if (mod.available() && byteCount < sizeof(values)) {
      values[byteCount++] = mod.read();
    }
  }

  // Check if response is valid
  if (byteCount < 7) {
    Serial.println("Error: Incomplete response");
    return -1;
  }

  // Combine high and low bytes of data
  return (int16_t)(values[3] << 8 | values[4]);
}

void printHexByte(byte b) {
  Serial.print((b >> 4) & 0xF, HEX);
  Serial.print(b & 0xF, HEX);
  Serial.print(' ');
}


These two connections look not very reliable

im struggling to wire that because of the default wires from the sensor. I just think to connect it on a jumper wire, since was able to provide accurate readings before.

The other two wires seems to be soldered to a jumperwire and then isolated with shrink-tube.

Can you do that for the yellow and blue wire too?

Here is a code-version with additional debug-macros and additional serial printing of the bytes that you send towards the sensor and the bytes you receive from the sensor.

This will help analyse what is going on

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 13;

/*
  BlinkHeartBeatLED(OnBoard_LED,250);

  if ( TimePeriodIsOver(MyTestTimer,1000) ) {

  }
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

// Define LCD address and dimensions
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adjust 0x27 to your LCD's I2C address if necessary

#define RE 7
#define DE 6
#define RELAY_PIN 5 // Pin connected to the relay module controlling the water pump

const uint32_t TIMEOUT = 2000UL; // Increased timeout for sensor response
const byte moist[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
const byte temp[]  = {0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xCA};
const byte PH[]    = {0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A};

const float MOISTURE_THRESHOLD = 20.0; // Moisture level below which the pump will turn on

byte values[11];

SoftwareSerial mod(2, 3); // Rx pin, Tx pin

void setup() {
  Serial.begin(4800); // Match with the sensor's baud rate
  Serial.println("Setup-Start");
  PrintFileNameDateTime();
  mod.begin(4800);

  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);

  lcd.init();        // Initialize the LCD
  lcd.backlight();   // Turn on the backlight

  digitalWrite(RELAY_PIN, LOW); // Ensure pump is off at startup

  lcd.setCursor(0, 0);
  lcd.print("Initializing...");
  delay(1000);
}

void loop() {
  // Moisture reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Moisture:");
  float moistureValue = readSensor(moist) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(moistureValue);
  lcd.print(" %");
  delay(2000); // Display for 2 seconds

  // Control water pump based on moisture level
  if (moistureValue < MOISTURE_THRESHOLD) {
    digitalWrite(RELAY_PIN,  LOW); // Turn pump ON
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pump ON");
  }
  else {
    digitalWrite(RELAY_PIN, HIGH); // Turn pump OFF
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pump OFF");
  }
  delay(2000); // Display for 2 seconds

  // Temperature reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperature:");
  float temperatureValue = readSensor(temp) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(temperatureValue);
  lcd.print(" C");
  delay(2000); // Display for 2 seconds

  // pH reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("pH Level:");
  float phValue = readSensor(PH) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(phValue);
  delay(2000); // Display for 2 seconds
}

int16_t readSensor(const byte* command) {
  uint32_t startTime = 0;
  uint8_t  byteCount = 0;
  memset(values, 0, sizeof(values)); // Clear previous data

  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);

  Serial.println("sending command[");
  for (byte i = 0; i < 8; i++) {
    // print each and every byte that is sent
    Serial.print("command[");
    Serial.print(i);
    Serial.print("]=");
    Serial.println(command[i], HEX);
  }
  
  mod.write(command, 8); // Send command (8 bytes)
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  delay(100); // added this delay to give the sensor time to send his answer

  startTime = millis();
  while (millis() - startTime <= TIMEOUT) {
    // print number of bytes received
    dbg("01", mod.available());
    if (mod.available() && byteCount < sizeof(values)) {
      values[byteCount] = mod.read();

      // print each and every received byte
      Serial.print("values[");
      Serial.print(byteCount);
      Serial.print("]=");
      Serial.println(values[byteCount], HEX);
      byteCount++;
    }
  }

  // Check if response is valid
  if (byteCount < 7) {
    Serial.println("Error: Incomplete response");
    return -1;
  }

  // Combine high and low bytes of data
  return (int16_t)(values[3] << 8 | values[4]);
}

void printHexByte(byte b) {
  Serial.print((b >> 4) & 0xF, HEX);
  Serial.print(b & 0xF, HEX);
  Serial.print(' ');
}

// helper-functions
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}



void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}

you have written that you are powering the

  • LCD-display
  • relay
  • RS485-module

all from the 5V-pin of the Arduino.

Noted Sir, I will try

This is what i get from the serial monitor sir

I have to ask back if this is that part of the serial output direct after start or maybe 30 seconds after upload?

The more interesting part is where the sended bytes can be seen

yes sir, but i tried to change the source of it before even the sensor itself, it gives me the same outpu

yes sir

what source? What do you mean?
You have to be very precise in your descriptions

the source of the rs485 sensor since i thought 9v batt is not enough i try to change it into 12v, then the 9v to relay, and lcd. Still nothing happens

Is LCD still working?
because most of these LCD can stand only 5V
You should not power it by more than 5V

Test this code-version which does print a little less

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 13;

/*
  BlinkHeartBeatLED(OnBoard_LED,250);

  if ( TimePeriodIsOver(MyTestTimer,1000) ) {

  }
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

// Define LCD address and dimensions
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adjust 0x27 to your LCD's I2C address if necessary

#define RE 7
#define DE 6
#define RELAY_PIN 5 // Pin connected to the relay module controlling the water pump

const uint32_t TIMEOUT = 2000UL; // Increased timeout for sensor response
const byte moist[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
const byte temp[]  = {0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xCA};
const byte PH[]    = {0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A};

const float MOISTURE_THRESHOLD = 20.0; // Moisture level below which the pump will turn on

byte values[11];

SoftwareSerial mod(2, 3); // Rx pin, Tx pin

void setup() {
  Serial.begin(4800); // Match with the sensor's baud rate
  Serial.println("Setup-Start");
  PrintFileNameDateTime();
  mod.begin(4800);

  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);

  lcd.init();        // Initialize the LCD
  lcd.backlight();   // Turn on the backlight

  digitalWrite(RELAY_PIN, LOW); // Ensure pump is off at startup

  lcd.setCursor(0, 0);
  lcd.print("Initializing...");
  delay(1000);
}

void loop() {
  // Moisture reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Moisture:");
  float moistureValue = readSensor(moist) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(moistureValue);
  lcd.print(" %");
  delay(2000); // Display for 2 seconds

  // Control water pump based on moisture level
  if (moistureValue < MOISTURE_THRESHOLD) {
    digitalWrite(RELAY_PIN,  LOW); // Turn pump ON
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pump ON");
  }
  else {
    digitalWrite(RELAY_PIN, HIGH); // Turn pump OFF
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pump OFF");
  }
  delay(2000); // Display for 2 seconds

  // Temperature reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperature:");
  float temperatureValue = readSensor(temp) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(temperatureValue);
  lcd.print(" C");
  delay(2000); // Display for 2 seconds

  // pH reading
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("pH Level:");
  float phValue = readSensor(PH) * 0.1;
  lcd.setCursor(0, 1);
  lcd.print(phValue);
  delay(2000); // Display for 2 seconds
}

int16_t readSensor(const byte* command) {
  uint32_t startTime = 0;
  uint8_t  byteCount = 0;
  memset(values, 0, sizeof(values)); // Clear previous data

  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);

  Serial.println("sending command[");
  for (byte i = 0; i < 8; i++) {
    // print each and every byte that is sent
    Serial.print("command[");
    Serial.print(i);
    Serial.print("]=");
    Serial.println(command[i], HEX);
  }
  
  mod.write(command, 8); // Send command (8 bytes)
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  delay(100); // added this delay to give the sensor time to send his answer

  startTime = millis();
  while (millis() - startTime <= TIMEOUT) {
    // print number of bytes received
    //dbg("01", mod.available());
    if (mod.available() && byteCount < sizeof(values)) {
      values[byteCount] = mod.read();

      // print each and every received byte
      Serial.print("values[");
      Serial.print(byteCount);
      Serial.print("]=");
      Serial.println(values[byteCount], HEX);
      byteCount++;
    }
  }
  dbg("01", mod.available());
  
  // Check if response is valid
  if (byteCount < 7) {
    Serial.println("Error: Incomplete response");
    return -1;
  }

  // Combine high and low bytes of data
  return (int16_t)(values[3] << 8 | values[4]);
}

void printHexByte(byte b) {
  Serial.print((b >> 4) & 0xF, HEX);
  Serial.print(b & 0xF, HEX);
  Serial.print(' ');
}

// helper-functions
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}



void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}


is this the bytes you are talking to sir ?