The NPK sensor doesn't change its value to 255mg

Hi, can anyone help me?. The NPK sensor value doesn't change to 255 and also can someone help me to understand hex registry using rs485 module and Arduino nano? I'm using this NPK sensor, this is the manual [CWT soil sensor manual download link (copy link and open in PC browser): https://wiki20210805.oss-cn-hongkong.aliyuncs.com/download/sensors/Smart_Agriculture/CWT%20soil%20sensor_2%20manual.zip](CWT soil sensor manual download link (copy link and open in PC browser): https://wiki20210805.oss-cn-hongkong.aliyuncs.com/download/sensors/Smart_Agriculture/CWT%20soil%20sensor_2%20manual.zip) given to me by the manufacturer. Or anyone can share their code about this topic?

#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128    // OLED display width, in pixels
#define SCREEN_HEIGHT 64    // OLED display height, in pixels
#define OLED_RESET -1       // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
#define RE 8
#define DE 7
 
//const byte code[]= {0x01, 0x03, 0x00, 0x1e, 0x00, 0x03, 0x65, 0xCD};
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];
SoftwareSerial mod(2,3);
 
void setup() {
  Serial.begin(9600);
  mod.begin(9600);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
  delay(500);
  display.clearDisplay();
  display.setCursor(25, 15);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.println(" NPK Sensor");
  display.setCursor(25, 35);
  display.setTextSize(1);
  display.print("Initializing");
  display.display();
  delay(3000);
}
 
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");
  delay(2000);
 
  display.clearDisplay();
  
 
  display.setTextSize(2);
  display.setCursor(0, 5);
  display.print("N: ");
  display.print(val1);
  display.setTextSize(1);
  display.print(" mg/kg");
 
  display.setTextSize(2);
  display.setCursor(0, 25);
  display.print("P: ");
  display.print(val2);
  display.setTextSize(1);
  display.print(" mg/kg");
 
  display.setTextSize(2);
  display.setCursor(0, 45);
  display.print("K: ");
  display.print(val3);
  display.setTextSize(1);
  display.print(" mg/kg");
 
  display.display();
}
 
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];
}

THANK YOU!!!!

Search these forums for NPK and you will find several discussions about how to connect and power them correctly as well as the issues with the software approach you are using to communicate with the sensor.

EDIT: You can try this very basic code that bypasses all Modbus type communication and simply prints out the raw response from the sensor:

// This attempt uses the SoftwareSerial & raw Modbus packets.
//
// RS485 module wired up as:
// RS485 DI signal to pin 3
// RS485 RO signal to pin 2
// RS485 RE signal to pin 8
// RS485 DE signal to pin 7
// RS485 VCC to 5V
// RS485 GND to GND
//
#include <SoftwareSerial.h>

#define RE 8
#define DE 7

const uint32_t TIMEOUT = 500UL;

// canned message to your RS485 device
// change this for any other canned modbus message you like
// remember to make sure that the checksum is correct!
uint8_t msg[] = {0x01, 0x03, 0x00, 0x1E, 0x00, 0x01, 0xE4, 0x0C};
uint8_t rxByte;

SoftwareSerial swSerial(2, 3); // Receive (data in) pin, Transmit (data out) pin

void setup() {
  Serial.begin(9600);
  swSerial.begin(9600);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
  delay(1000);
}

void loop() {
  uint32_t startTime = 0;

  Serial.print("TX: ");
  printHexMessage( msg, sizeof(msg) );

  // send the command
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay( 10 );
  swSerial.write( msg, sizeof(msg) );
  swSerial.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  Serial.print("RX: ");
  
  // read any data received and print it out
  startTime = millis();
  while ( millis() - startTime <= TIMEOUT ) {
    if (swSerial.available()) {
      printHexByte(swSerial.read());
    }
  }
  Serial.println();
  delay(2000);
}

void printHexMessage( uint8_t values[], uint8_t sz ) {
  for (uint8_t i = 0; i < sz; i++) {
    printHexByte( values[i] );
  }
  Serial.println();
}

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

You should see several hexadecimal values printed next to the RX: text. If you don't then your sensor isn't responding. It could be a power issue, a missing ground issue or your sensor using different addresses and/or baud rate.

Thank you for the reply. I'll try it later

Hi! I've already tried the code that you provided and I received this value(photo below) RX value is not responding does it mean that the sensor is not working? or is there another code that I could try? Thank you.
Connection:
RS485: VCC to Arduino nano 5V, Sensor B and A connected to RS485 B and A, RS485 GND to arduino nano gnd then sensor V+ and GND connected to 12V power supply.

Hi,
When i was receiving this value i realize that the default baud of my device was 4800, not 9600. I also had to chang many other things....

Do you have a GND between the power supply and the Nano?

Looking at the NPK Type (5Pin probe) manual, there is this section on RS485:

Assuming that the supplier has sent you the correct manual, then you need to alter your software serial port baud rate to 4800 baud. Also, the various soil parameters are at different register addresses to some of the other NPK sensors. This means that you will have to create different canned modbus messages.

I've quickly modified, but not tested, my previous code for you here:

// This attempt uses the SoftwareSerial & raw Modbus packets.
//
// RS485 module wired up as:
// RS485 DI signal to pin 3
// RS485 RO signal to pin 2
// RS485 RE signal to pin 8
// RS485 DE signal to pin 7
// RS485 VCC to 5V
// RS485 GND to GND
//
#include <SoftwareSerial.h>

#define RE 8
#define DE 7

const uint32_t TIMEOUT = 500UL;

// canned message to your RS485 device
// change this for any other canned modbus message you like
// remember to make sure that the checksum is correct!
uint8_t msg[] = {0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xCA};
uint8_t rxByte;

SoftwareSerial swSerial(2, 3); // Receive (data in) pin, Transmit (data out) pin

void setup() {
  Serial.begin(9600);
  swSerial.begin(4800);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
  delay(1000);
}

void loop() {
  uint32_t startTime = 0;

  Serial.print("TX: ");
  printHexMessage( msg, sizeof(msg) );

  // send the command
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay( 10 );
  swSerial.write( msg, sizeof(msg) );
  swSerial.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

  Serial.print("RX: ");
  
  // read any data received and print it out
  startTime = millis();
  while ( millis() - startTime <= TIMEOUT ) {
    if (swSerial.available()) {
      printHexByte(swSerial.read());
    }
  }
  Serial.println();
  delay(2000);
}

void printHexMessage( uint8_t values[], uint8_t sz ) {
  for (uint8_t i = 0; i < sz; i++) {
    printHexByte( values[i] );
  }
  Serial.println();
}

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

If this works, then the sensor should respond with the temperature message.

Hi Pedro. I have the same sensor as you from ComWinTop! I tried your code but i get the following...
16:16:27.430 -> Condutividade = 65535 us/cm
16:16:28.153 -> Salinidade = 65535 mg/L
16:16:31.419 -> Nitrogenio = 65535 mg/kg
16:16:32.146 -> Phosphorous = 65535 mg/kg
16:16:32.871 -> Potassium = 65535 mg/kg
16:16:33.564 -> PH = 65535

I only changed the baudrate on the code.

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

 
#define RE 8
#define DE 7

 
const byte cond[] = {0x01,0x03, 0x00, 0x02, 0x00, 0x01, 0x25, 0xca};
const byte ph[]   = {0x01,0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0a};
const byte nitro[]= {0x01,0x03, 0x00, 0x04, 0x00, 0x01, 0xc5, 0xcb};
const byte phos[] = {0x01,0x03, 0x00, 0x05, 0x00, 0x01, 0x94, 0x0b};
const byte pota[] = {0x01,0x03, 0x00, 0x06, 0x00, 0x01, 0x64, 0x0b};
const byte sali[] = {0x01,0x03, 0x00, 0x07, 0x00, 0x01, 0x35, 0xcb};

uint16_t values[11];
char buffer[40];
 
SoftwareSerial mod(2,3);
 
void setup() {
  Serial.begin(9600);
  mod.begin(4800);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  pinMode(2, INPUT);
  pinMode(3, OUTPUT);
  delay(1000);
}


void loop() {
 uint16_t val1,val2,val3,val4,val5,val6;
 
  val1 = sensor_request(nitro[0],nitro[1],nitro[2],nitro[3],nitro[4],nitro[5],nitro[6],nitro[7]);
  sprintf(buffer, "Nitrogenio    = %04u mg/kg\r\n",    val1);
  Serial.print(buffer);  delay(450);
  
  val2 = sensor_request(phos[0],phos[1],phos[2],phos[3],phos[4],phos[5],phos[6],phos[7]);
  sprintf(buffer, "Phosphorous   = %04u mg/kg\r\n", val2);
  Serial.print(buffer);  delay(450);
 
  val3 = sensor_request(pota[0],pota[1],pota[2],pota[3],pota[4],pota[5],pota[6],pota[7]);
  sprintf(buffer, "Potassium     = %04u mg/kg\r\n",   val3);
  Serial.print(buffer); delay(450);

  val4 = sensor_request(ph[0],ph[1],ph[2],ph[3],ph[4],ph[5],ph[6],ph[7]);
  sprintf(buffer, "PH            = %04u  \r\n",               val4);
  Serial.print(buffer); delay(450);

  val5 = sensor_request(cond[0],cond[1],cond[2],cond[3],cond[4],cond[5],cond[6],cond[7]);
  sprintf(buffer, "Condutividade = %04u us/cm\r\n",val5);
  Serial.print(buffer); delay(450);
 
  val6 = sensor_request(sali[0],sali[1],sali[2],sali[3],sali[4],sali[5],sali[6],sali[7]);
  sprintf(buffer, "Salinidade    = %04u mg/L\r\n",    val6);
  Serial.print(buffer);
 
  delay(3000);

}
 
 uint16_t sensor_request(byte d1,byte d2,byte d3,byte d4,byte d5,byte d6,byte d7,byte d8){
  byte inicio;
  uint16_t hbyte;
  while (mod.available()) mod.read(); //Esvazia Buffer Leitura...
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(1);
  mod.write(d1);mod.write(d2);mod.write(d3);mod.write(d4);
  mod.write(d5);mod.write(d6);mod.write(d7);mod.write(d8);
  mod.flush(); 
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
  delay(250);
 
  inicio=0;
   for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
    if (inicio == 0 and values[i] ==0 and mod.available()) values[i] = mod.read();
    if (inicio == 0 and values[i] ==0 and mod.available()) values[i] = mod.read();
    if (inicio == 0 and values[i] ==0 and mod.available()) values[i] = mod.read();
    inicio=1;
  }
 /*
  sprintf(buffer,"%02x %02x %02x %02x %02x %02x %02x %02x ", d1,d2,d3,d4,d5,d6,d7,d8);
  Serial.print(buffer);
  Serial.print(" => ");
  for(byte i=0;i<7;i++){
        sprintf(buffer,"%02x ", values[i]);
        Serial.print(buffer);
  }
  Serial.println();  
*/ 
  return (values[3] << 8 | values[4]);
}

















uint8_t salinidade(){
  while (mod.available()) mod.read(); //Esvazia Buffer Leitura...
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(1);
  for (uint8_t i = 0; i < sizeof(sali); i++ ) mod.write( sali[i] );
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
  delay(200);
  if (mod.available()>7) mod.read();
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
  }
    for(byte i=0;i<8;i++) {
        sprintf(buffer,"%02x ", sali[i]);
        Serial.print(buffer);
  }
  Serial.print(" => ");
  for(byte i=0;i<7;i++){
        sprintf(buffer,"%02x ", values[i]);
        Serial.print(buffer);
  }
  Serial.println();
  return (values[3] << 16 | values[4]);
}


uint8_t PH(){
  uint8_t ph_val=0;
  while (mod.available()) mod.read(); //Esvazia Buffer Leitura...
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(1);
  for (uint8_t i = 0; i < sizeof(ph); i++ ) mod.write( ph[i] );
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
  delay(200);
  if (mod.available()>7) mod.read();
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
  }
    for(byte i=0;i<8;i++) {
        sprintf(buffer,"%02x ", ph[i]);
        Serial.print(buffer);
  }
  Serial.print(" => ");
  for(byte i=0;i<7;i++){
        sprintf(buffer,"%02x ", values[i]);
        Serial.print(buffer);
  }
  Serial.println();
  ph_val = values[3] << 16 | values[4];
  return (ph_val);
}


uint8_t condutividade(){
  while (mod.available()) mod.read(); //Esvazia Buffer Leitura...
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(1);
  for (uint8_t i = 0; i < sizeof(cond); i++ ) mod.write( cond[i] );
  mod.flush();
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);
  delay(200);
  if (mod.available()>7) mod.read();
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
  }
  for(byte i=0;i<8;i++) {
        sprintf(buffer,"%02x ", cond[i]);
        Serial.print(buffer);
  }
  Serial.print(" => ");
  for(byte i=0;i<7;i++){
        sprintf(buffer,"%02x ", values[i]);
        Serial.print(buffer);
  }
  Serial.println();  
  return (values[3] << 16 | values[4]);
}

 
uint8_t phosphorous(){
  while (mod.available()) mod.read(); //Esvazia Buffer Leitura...
  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(200);
  if (mod.available()>7) mod.read();  
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
  }
  for(byte i=0;i<8;i++) {
        sprintf(buffer,"%02x ", phos[i]);
        Serial.print(buffer);
        // Serial.print(nitro[i] ,HEX); Serial.print(" ");
  }
  Serial.print (" => ");
  for(byte i=0;i<7;i++){
        sprintf(buffer,"%02x ", values[i]);
        Serial.print(buffer);
  }
  Serial.println();
  return (values[3] << 16 | values[4]);
}
 
uint8_t potassium(){
  while (mod.available()) mod.read(); //Esvazia Buffer Leitura...
  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(200);
  if (mod.available()>7) mod.read();  
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
  }
  for(byte i=0;i<8;i++) {
        sprintf(buffer,"%02x ", pota[i]);
        Serial.print(buffer);
  }
  Serial.print(" => ");
  for(byte i=0;i<7;i++){
        sprintf(buffer,"%02x ", values[i]);
        Serial.print(buffer);
  }
  Serial.println();
  return (values[3] << 16 | values[4]);
 }