Connecting 2 npk sensors

Hi!

Im trying to combine capacitive moisture sensors and soil NPK sensors in 1 using an Arduino MEGA2560. Right now, im trying to get both NPK sensors to be working.
image

as you can see, only one of the NPK sensors is working while the other isn't. However, if I test them individually, they both work. Can someone help me with this?

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

// Define the pins for the first NPK sensor
#define RE 8
#define DE 7

// Define the pins for the second NPK sensor
#define RE2 6
#define DE2 5

#define sensorPin A1
#define sensorPin2 A2

// Modbus RTU requests for reading NPK values
const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};

// Arrays to store NPK values
byte values1[7];
byte values2[7];

// Create two instances of SoftwareSerial
SoftwareSerial mod1(10, 11); // RX, TX for first sensor
SoftwareSerial mod2(12, 13); // RX, TX for second sensor

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

  // Set the baud rate for the first SoftwareSerial object
  mod1.begin(9600);

  // Set the baud rate for the second SoftwareSerial object
  mod2.begin(9600);

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

  delay(500);
}

void loop() {
  // Read values from the first NPK sensor
  byte val1 = nitrogen(DE, RE, mod1, values1);
  delay(250);
  byte val2 = phosphorous(DE, RE, mod1, values1);
  delay(250);
  byte val3 = potassium(DE2, RE2, mod2, values2);
  delay(250);

  // Read values from the second NPK sensor
  byte val4 = nitrogen(DE2, RE2, mod2, values2);
  delay(250);
  byte val5 = phosphorous(DE2, RE2, mod2, values2);
  delay(250);
  byte val6 = potassium(DE2, RE2, mod2, values2);
  delay(250);

  int value = analogRead(sensorPin);
  int value2 = analogRead(sensorPin2);

  // Print values to the serial monitor
  Serial.print("NPK 1 - Nitrogen: ");
  Serial.print(val1);
  Serial.println(" mg/kg");
  Serial.print("NPK 1 - Phosphorous: ");
  Serial.print(val2);
  Serial.println(" mg/kg");
  Serial.print("NPK 1 - Potassium: ");
  Serial.print(val3);
  Serial.println(" mg/kg");
  Serial.print("NPK 2 - Nitrogen: ");
  Serial.print(val4);
  Serial.println(" mg/kg");
  Serial.print("NPK 2 - Phosphorous: ");
  Serial.print(val5);
  Serial.println(" mg/kg");
  Serial.print("NPK 2 - Potassium: ");
  Serial.print(val6);
  Serial.println(" mg/kg");
  Serial.print("Analog output 1: ");
  Serial.println(value);
  Serial.print("Analog output 2: ");
  Serial.println(value2);

  delay(2000);
}

byte nitrogen(int DE_pin, int RE_pin, SoftwareSerial& mod, byte* values) {
  digitalWrite(DE_pin, HIGH);
  digitalWrite(RE_pin, HIGH);
  delay(10);
  if (mod.write(nitro, sizeof(nitro)) == 8) {
    digitalWrite(DE_pin, LOW);
    digitalWrite(RE_pin, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = mod.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte phosphorous(int DE_pin, int RE_pin, SoftwareSerial& mod, byte* values) {
  digitalWrite(DE_pin, HIGH);
  digitalWrite(RE_pin, HIGH);
  delay(10);
  if (mod.write(phos, sizeof(phos)) == 8) {
    digitalWrite(DE_pin, LOW);
    digitalWrite(RE_pin, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = mod.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte potassium(int DE_pin, int RE_pin, SoftwareSerial& mod, byte* values) {
  digitalWrite(DE_pin, HIGH);
  digitalWrite(RE_pin, HIGH);
  delay(10);
  if (mod.write(pota, sizeof(pota)) == 8) {
    digitalWrite(DE_pin, LOW);
    digitalWrite(RE_pin, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = mod.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

im not the best at arduino... its been 2 weeks since I've started so please bear with me :smiley:
(both npk sensors have their own 12v power supply)

I'll split my - hopefully useful - answer into 3 parts.

Firstly, when using more than 1 SoftwareSerial, you need to know that only 1 software serial port can be "active" (i.e. listening for data) at once. In order to switch between them, you need to use the listen() function. See here for details.

Secondly, you are using a MEGA2560 which has 4 hardware serial ports. You should use Serial1 and Serial2 instead of any software serial ports.

Thirdly, your NPK sensors are RS485 devices that use a comms protocol called Modbus. What all that means is that you can have more than 1 sensor connected to 1 serial port.

In order to use this feature, you need to be able to change the device address of one of your NPK sensors. They usually get shipped with a default address of 01. Have a look at your user manual as it will tell you how to change the device address so that one of your NPK sensors can become device 02.

You then need to create a second set of those canned modbus message arrays for device 02. You need to change the first byte to 0x02 and then recompute the CRC16 checksum in the final 2 bytes.

However, it's a lot easier if you use the ModbusMaster library as that will take care of a lot of the comms for you.

Are you sure that your sensor is responding? Values like 255 are often seen when a serial port read() function is trying to tell you that there isn't any data to read.

It's unfortunate that the code floating around the various websites (and YouTube) has bugs in it which the authors don't seem to know about. Your code (likely based on their code) also has the same problem.

When you write out the message to the sensor, you need to wait for a response before you attempt to read in any values. The ModbusMaster library will take care of all this for you.

Also you need to be aware that the values returned by the sensor are 16-bit values and as such occupy 2 bytes in the response message. You need to combine the 2 bytes into a 16-bit word in order to get the actual value sent by your sensor. Again, the ModbusMaster library takes care of all this for you.

However, after it sounds like the ModbusMaster is the answer to everything, is very poor at helping you out if your sensor simply isn't responding. Search these forums for NPK sensor and you will come across some of my other posts where code that looks similar to yours is used to check out the comms with the NPK sensor.

2 Likes

Hi Mark thanks for helping me. I want to try out the second option. Will the wiring look like this?

Lastly, is it ok if I can ask for assistance with the code? The coding part is where I struggle the most.

That wiring will give you an RS485 link to an NPK sensor using Serial1 and a second RS485 link to the other NPK sensor using Serial2.

Of course. Just ask here and myself or another forum member will help out.

EDIT: If you go down that route, concentrate on getting just 1 NPK sensor working correctly. Once you have solid comms, then you can introduce the second NPK sensor. The code will be almost identical.

1 Like

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