MAX485 TTL to RS-485 Modules for soil NPK sensor

Hi All,
I am trying to read the JXCT soil sensor [1] using MAX485 TTL to RS485 and Arduino Uno. I am referring materials available in how2electronics.com [2] to make this sensor work.
The seller has provided a serial monitor software to read the sensor output in the computer using USB to RS485 Converter [3], following is the screenshot
Example_image

When I try to replicate the same using Arduino I am facing some issues. When I request for single sensor data the sensor is responding and I can read the sensor data.
Ex. The code only contains inquiry frame for Ph
ph_read.ino (1.3 KB)

When I request for multiple sensor data the return values from the sensor are not correct
Ex. The code contains inquiry frame for Ph and Moisture
ph_and_moisture.ino (1.7 KB)

Following is the circuit diagram I am using


(taken from (2. Measure Soil Nutrient using Arduino & Soil NPK Sensor))

I have referred following forum question for possible solution but I unable to get relevant information
RS232-TTL Module with Arduino

NPK Soil Sensor Making - Nitrogen Phosphorus Potassium levels in Soil
NPK Soil nutrients measurement sensor for Mesh network

Thank you

1 Like

Usually with RS485, there is a check made to see if all the bytes have been transmitted before switching the 485 transceiver back into receive mode. I think the serial write() function returns as soon as the bytes have been placed in the transmit queue.

Hi mark, thank you for your reply, can you please provide more information regarding this.

Actually I may have been wrong there. With the hardware serial port, the printing functions transfer the characters to a buffer and then an interrupt driven piece of code takes them out of the buffer one at a time and sends them off to the UART. With the software serial port, from what I could see (and I may be looking at the wrong software serial library here!) there isn't a buffer and the character gets clocked out right there and then. Which means that when the write() function returns, the character has been clocked out of the chip.

Can you expand on what is not correct? Are both readings corrupt? Does only 1 reading work correctly?

Both the reading are not correct,


Actually it should read Ph around 7 and moist around 30%.

Ok, so you get the correct answer when asking for ph on its own. Do you get the correct answer if you ask for moisture on its own?

If you do, then that indicates an unwanted interaction between the 2 requests. Maybe it needs a longer time period between requests for readings.

Yes, whenever I request for single sensor vales I am getting correct answer, if I request more than one sensor value then I am getting wrong values.
To avoid unwanted interactions I tried with different time delay values but no success.

It looks like your code should print out the actual bytes received from the sensor in hex. Can you provide a screenshot/screendump or cut & paste of the actual hex values you receive.

Hi Mark,
Following images shows the readings received when I request single sensor data and the values are within the acceptable range

When I request Ph and Moisture sensor data the out put is swapping
Ph_and_moisture

and when I request all seven sensor data than the order of output has changed
All_seven

In the above image the first value should represent for K but it is displaying as Ph

Thank you

Following is one more example of change in output

The N value is getting associated with P
The P value is getting associated with K and
The K value is getting associated with N

If I request for single vale then it is working fine

Can you show the actual commands you send to the device and the associated responses. I couldn't find a manual for the sensor that clearly detailed the messages - specifically which addresses to use for which type of reading.

Or better still, post your current code.

Hi Mark,
I am using following commands to request sensor data

nitro[] = {0x01,0x03, 0x00, 0x1E, 0x00, 0x01, 0xE4, 0x0C};
phosp[] = {0x01,0x03, 0x00, 0x1F, 0x00, 0x01, 0xB5, 0xCC};
potas[] = {0x01,0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xC0};

Following is the code
NPK.ino (2.2 KB)

The checksums all look correct for Modbus.

I'm not sure that checking if 8 bytes have been written to the software serial port adds any value in this case. But I do wonder if you should check that a byte has been received by the software serial port before doing a read().

My only other suggestion at the moment is if you have a way of listening to the RS485 comms independently to see if this is a sensor issue or a software issue.

hi HPsunil
i'm facing same issue in soil sensor could you help me out, if you have any solution....

Hello! I'm facing a very similar issue as well. When I use the same code that how2electronics has provided for the NPK sensor, the RS845 converter / Modbus we're using simply returns FFFFFF, and thus just constantly outputs 255, 255, 255 for the values. @markd833 , any idea on why this might be happening?

Code:

#include <SoftwareSerial.h>
#include <Wire.h>
 
#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);
  
  delay(500);
  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);
}
 
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];
}
1 Like

How have you wired things up?

Does it work for 1 parameter?

I'm guessing that if you have an UNO, then you should have:

VCC -> 5V
GND -> GND
RE  -> 8
DE  -> 7
RO  -> 2
DI  -> 3

I don't see the point of checking if 8 bytes have been written so I would remove the if() check on mod.write(). There's the potential for RE & DE to remain HIGH if mod.write() doesn't return 8, which will keep the RS485 transceiver in TX mode.

How sure are you that the line "mod.write(nitro,sizeof(nitro))==8" is correct?
Because if you are using Serial, this only guarantees that 8 characters have been written into the internal buffer, it does not guarantee that they effectively left the serial port. So this could disturb your handshake with DE and RE. Then, how is your RS485 bus terminated?

@anshgupta1234 I'm observing the same behaviour, getting back FFFFFF. But it seems that the Sensor does not respond at all. I checked this with different blinking rhythms of the L-LED on the board.
I guess this is a different problem than the initial post so I will start a new post and leave you a link once it's done. I hope we can track this down and make it work.

@HPsunil Could you provide us a link to the serial monitor software? I have two sensors and none of the sellers are responding to my request for the monitoring software.
It would help a lot to see if the sensors do work. Just to rule out a broken sensor...

1 Like

As a suggestion, if you can get hold of one of the cheap USB->RS485 dongles, you can use one of the free MODBUS software programs available on PC (not sure about Mac) to talk to the sensor just to figure things out.