NPK-Sensor is Not Responding

Currently, I am doing a project for my school and I have decided to do a IoT based smart agriculture device which I am using the Arduino MKR WAN 1310 since it has LoRa capabilities. I am having a lot of issues with an NPK sensor that I am using that I have been tackling for weeks with no progress. The connections I have for my MAX485 are as goes: DE -> 1, RE ->2, DI -> TX(14), RO -> RX(13). The MAX485 is being powered via 5v which I believe is correct too. But the issue I am having is the arduino is giving this output:

FFFFFFFFFFFFFF
FFFFFFFFFFFFFF
FFFFFFFFFFFFFF
Nitrogen: 255 mg/kg
Phosphorous: 255 mg/kg
Potassium: 255 mg/kg

The NPK is being powered by 12v DC which is what is recommended from the manual that came with it. Here is the code that I am using for this project maybe someone can help me pinpoint if there is anything wrong with it (I am also very very new to this forum and arduinos themselves):

// Define RE and DE Pins to set the RS485 module to Receiver or Transmitter mode
#define RE 1
#define DE 2

// Modbus RTU requests for reading NPK values
const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xB5, 0xCC};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xE4, 0x0C};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xC0};

// Array to store NPK values
byte values[11];

void setup() {
  // Set the baud rate for the Serial port
  Serial.begin(9600);

  // Set the baud rate for Serial1 (hardware serial on MKR WAN 1310)
  Serial1.begin(9600);

  // Define pin modes for RE and DE
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);

  delay(500);
}

void loop() {
  // Read and print values
  byte val1 = nitrogen();
  delay(250);
  byte val2 = phosphorous();
  delay(250);
  byte val3 = potassium();
  delay(250);

  Serial.print("Nitrogen: ");
  Serial.print(val1);
  Serial.println(" mg/kg");
  Serial.print("Phosphorous: ");
  Serial.print(val2);
  Serial.println(" mg/kg");
  Serial.print("Potassium: ");
  Serial.print(val3);
  Serial.println(" mg/kg");

  delay(2000);
}

byte nitrogen() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  if (Serial1.write(nitro, sizeof(nitro)) == 8) {
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = Serial1.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte phosphorous() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  if (Serial1.write(phos, sizeof(phos)) == 8) {
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = Serial1.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte potassium() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  if (Serial1.write(pota, sizeof(pota)) == 8) {
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = Serial1.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

Update, I have updated my code a bit:

#define RE 1  
#define DE 2  

const byte nitro[] = { 0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xB5, 0xCC };
const byte phos[] = { 0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xE4, 0x0C };
const byte pota[] = { 0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xC0 };

byte values[11];

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
}

void loop() {
  byte val1, val2, val3;
  val1 = nitrogen();
  delay(250);
  val2 = phosphorous();
  delay(250);
  val3 = potassium();
  delay(250);

  Serial.print("Nitrogen: ");
  Serial.print(val1);
  Serial.println(" mg/kg");
  Serial.print("Phosphorous: ");
  Serial.print(val2);
  Serial.println(" mg/kg");
  Serial.print("Potassium: ");
  Serial.print(val3);
  Serial.println(" mg/kg");
}

byte nitrogen() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  if (Serial1.write(nitro, sizeof(nitro)) == 8) {
    Serial1.flush();
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = Serial1.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte phosphorous() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  if (Serial1.write(phos, sizeof(phos)) == 8) {
    Serial1.flush();
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = Serial1.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte potassium() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  if (Serial1.write(pota, sizeof(pota)) == 8) {
    Serial1.flush();
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = Serial1.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

And here is the output now, looks like the nitrogen readings are coming through:

Nitrogen: 24 mg/kg
Phosphorous: 255 mg/kg
Potassium: 255 mg/kg
132018B84E
FFFFFFFFFFFFFF
FFFFFFFFFFFFFF

Off the top of my head, there are a few things that occur to me.

Your MKR board is a 3.3v setup whereas the MAX485 is a 5v device. There have been a few projects here that use a 3.3v micro (ESP32 etc) with a 5v MAX485 and they appear to work ok. The main signal you need to handle is DO (Data Out) which swings between 0v and 5v.

A simple potential divider can be used to drop the 5v down to 3.3v.

Any reason you are not using the MKR485 board which is designed to plug into your MKR board.

Regarding your code - code very similar can be found on multiple websites that claim to show you how to use an NPK type sensor with an Arduino UNO. Unfortunately that code has problems.

For example, when the canned modbus message is transmitted, the code assumes that the sensor response is instantly available and blindly reads from the serial port without checking that there is any data available.

There is a modbus library specifically for the MKR boards that handles all this for you. You should look to using it.

The value 255 you see is likely associated with the values of FF being "read in". I suspect that the "FF" is the serial library reporting -1 i.e. no data available.

That's another issue with the code you are using. That's not the Nitrogen value, it is actually the Potassium value from the previous query message!

132018B84E

This looks promising and would be more readable if you had put spaces between the values. I suspect that the actual response was:

01 03 02 00 18 B8 4E

That is a valid modbus response which suggests that you may have your wiring correct.

Do you have the user manual for you actual NPK sensor? It has to be for your specific sensor as there are several variations out there.

There are some forum members with agricultural experience who say that this type of sensor doesn't work and can't measure the parameters it claims to.

Can you please send the Topic where they used ESP32 for their NPK sensor?

Thanks!