NPK Sensor Keeps Returning 255

Hi. Last night when I tested the NPK Sensor it was still working perfectly but today when I tested it again it keeps returning 255 for N, P, and K. I followed all the instructions and used the code here: https://lastminuteengineers.com/soil-npk-sensor-arduino-tutorial/.

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

// RE and DE Pins set the RS485 module
// to Receiver or Transmitter mode
#define RE 8
#define DE 7

// 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};

// A variable used to store NPK values
byte values[11];

// Sets up a new SoftwareSerial object
// Digital pins 10 and 11 should be used with a Mega or Mega 2560
SoftwareSerial mod(2, 3);
//SoftwareSerial mod(10, 11);
 
void setup() {
  // Set the baud rate for the Serial port
  Serial.begin(9600);

  // Set the baud rate for the SerialSoftware object
  mod.begin(9600);

  // Define pin modes for RE and DE
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  
  delay(500);
}
 
void loop() {
  // Read values
  byte val1,val2,val3;
  val1 = nitrogen();
  delay(250);
  val2 = phosphorous();
  delay(250);
  val3 = potassium();
  delay(250);

  // Print values to the serial monitor
  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(mod.write(nitro,sizeof(nitro))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    //Serial.print(mod.read(),HEX);
    values[i] = mod.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}
 
byte phosphorous(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if(mod.write(phos,sizeof(phos))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    //Serial.print(mod.read(),HEX);
    values[i] = mod.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}
 
byte potassium(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if(mod.write(pota,sizeof(pota))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    //Serial.print(mod.read(),HEX);
    values[i] = mod.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

Please help :pray:

Please post your code and your schematic.

Hello. I just posted it :blush:

What is changed?

Nothing. I left as it is .

Can you post a clear picture of it!

Okey. The posting a link to the datasheet and schematics are requested. Those coloured pictures are not useful.

I think SoftwareSerial updated their library and broke it. I had the same issue and even bought a new NPK sensor because all my other troubleshooting failed. Try this, I found it in a similar post.

// Crude demo code to read NPK Soil sensor based on the How 2 Electronics code at
// https://how2electronics.com/measure-soil-nutrient-using-arduino-soil-npk-sensor/
// but without the display.
//
// Use with caution as I don't have the real sensor, just simulated it using WinModbus.
//
// Uses PJRC AltSoftSerial library which is better than the standard SoftwareSerial library
// Get it here: https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
//
// All pin numbers are for an Arduino UNO.

#include <AltSoftSerial.h>

// RO to pin 8 & DI to pin 9 when using AltSoftSerial
#define RE 6
#define DE 7

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};

byte values[11];
AltSoftSerial mod;

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

  // put RS-485 into receive mode
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  delay( 1000 );
}

void loop() {
  byte val1, val2, val3;
  Serial.print("   Nitrogen: ");
  val1 = nitrogen();
  Serial.print(" = ");
  Serial.print(val1);
  Serial.println(" mg/kg");
  delay(250);

  Serial.print("Phosphorous: ");
  val2 = phosphorous();
  Serial.print(" = ");
  Serial.print(val2);
  Serial.println(" mg/kg");
  delay(250);

  Serial.print("  Potassium: ");
  val3 = potassium();
  Serial.print(" = ");
  Serial.print(val3);
  Serial.println(" mg/kg");
  Serial.println();
  Serial.println();
  delay(5000);
}

byte nitrogen() {
  // clear the receive buffer
  mod.flushInput();

  // switch RS-485 to transmit mode
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(1);

  // write out the message
  for (uint8_t i = 0; i < sizeof(nitro); i++ ) mod.write( nitro[i] );

  // wait for the transmission to complete
  mod.flush();
  
  // switch RS-485 to receive mode
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  // crude delay to allow response bytes to be received!
  delay(100);

  // read in the received bytes
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
    Serial.print(values[i], HEX);
    Serial.print(' ');
  }
  return values[4];
}

byte phosphorous() {
  mod.flushInput();
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(1);
  for (uint8_t i = 0; i < sizeof(phos); i++ ) mod.write( phos[i] );
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  delay(100);
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
    Serial.print(values[i], HEX);
    Serial.print(' ');
  }
  return values[4];
}

byte potassium() {
  mod.flushInput();
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(1);
  for (uint8_t i = 0; i < sizeof(pota); i++ ) mod.write( pota[i] );
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  delay(100);
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
    Serial.print(values[i], HEX);
    Serial.print(' ');
  }
  return values[4];
}

Forgot to tell you, you will need to change your pinout. Pins 6,7,8,9. Look at the library URL for guidance.

1 Like

Thank you! I'll try this :smiling_face:

Measure Soil NPK values using Soil NPK Sensor with Arduino – Circuit Schools

@poetfury , I see you found one of my early pieces of code that attempts to read from an NPK sensor.

@nininyx , That code in post #8 is crude and essentially still has some of the flaws as almost all the NPK code found on various websites, including lastminuteengineers.

See post #116 here for how I used a modbus library to communicate with the sensor:

If you don't want to use a modbus library, then you could try this non-library code I created:

However, please note that the this code doesn't perform any checks on the validity of the data received. If you want that, then you need to either code the checks yourself or use the modbus library.

@markd833, I apologize for not linking back to your original post, I couldn't find it and only had the code.

No worries. The forum has plenty of hits on the NPK sensor and I should really bookmark my post(s) on this subject so it's easier to refer others to, rather than trying to repeat it. :grinning:

Hello, I used your code regarding your post #116. The response I got was Response Timed out.

May I know what this means and what should I do so that my sensor would return the values and not the frequent 255 and FFFF's like this one

"Response timed out" means that your sensor didn't respond to the modbus query. Those FF's in the second image are usually generated by the serial port trying to indicate that there is no character to be read.

There are numerous reasons why your sensor may not be responding:

  • Wiring error
  • Wrong sensor address
  • Wrong register address(es)

In your first post, you said your sensor was working. As @Railroader asked you back in post #4, what did you do that caused it to stop working?

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