7 in one multiparameter soil sensor with esp32

Seems like I'm getting values for all registers, also need to cross-verify once to check whether the values are right or wrong!

Yes, these are the values when I inserted probes into the soil and added some water to moisture the soil.

sweet, getting data in all 7 registers..
remember there in HEX, if you're using windows OS, launch the calculator and switch it to programmer mode, click on hex and enter hex value and it will display the decimal values up top, handy..
probably going to have to do some math on the figures multiply by 0.1 or something..
you can use your PC to figure out the math or proceed back to the uno and maybe even give the esp32 another go..

good luck.. ~q

Sure, but hey I have 1 doubt, why do temp and ph remain the same even after I remove the probes from the soil? ph value goes down but doesn't turn to 0 and the temp is always the same with probes being inserted or not inserted! The remaining parameters work great, immediately go to 0 when I remove the probe.

strange, i would try a glass of ice water..
might be slow to react, so let it sit in there a few minutes, then do another read and see if temp changes..
could be a bad sensor..

~q

The sensor is working, don`t know what do you plan with it, but it would be nice to have some kind of graphic representation of data where you could easily see charts with changing parameters, like ArduinoIOT cloud for example.

Okay now, I'm thinking to use this code and run it on a serial monitor, let me know if there is anything wrong.

#include <AltSoftSerial.h>

// RO to pin 10 & DI to pin 11 when using AltSoftSerial
#define RE 8
#define DE 9

const byte temp[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};//
const byte mois[]  = {0x02, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};
const byte econ[] =  {0x02, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};
const byte ph[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};//

const byte nitro[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};
const byte phos[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};
const byte pota[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08};

byte values[11];
AltSoftSerial mod;

float envhumidity = 0.0, envtemperature = 0.0, soil_ph = 0.0, soil_mois = 0.0, soil_temp = 0.0;
byte val1 = 0, val2 = 0, val3 = 0, val4 = 0,val5 = 0, val6 = 0, val7 = 0;

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(3000);
}

void loop() {
  val1 = moisture();
  soil_mois = val1/10.0;
  delay(1000);
  soil_temp = temperature()/10.0;
  delay(1000);
  val3 = econduc();
  delay(1000);
  val4 = phydrogen()/10;
  soil_ph = val4;
  delay(1000);
  val5 = nitrogen();
  delay(1000);
  val6 = phosphorous();
  delay(1000);
  val7 = potassium();
  delay(1000);

  Serial.print("Moisture: ");Serial.print(soil_mois);Serial.println(" %");
  delay(1000);
  Serial.print("Temperature: ");Serial.print(soil_temp);Serial.println(" C");
  delay(1000);
  Serial.print("EC: ");Serial.print(val3);Serial.println(" us/cm");
  delay(1000);
  Serial.print("ph: ");Serial.print(soil_ph);Serial.println(" ph");
  delay(1000);
  Serial.print("Nitrogen: "); Serial.print(val5);Serial.println(" mg/kg");
  delay(1000);
  Serial.print("Phosphorous: ");Serial.print(val6);Serial.println(" mg/kg");
  delay(1000);
  Serial.print("Potassium: ");Serial.print(val7);Serial.println(" mg/kg");
  Serial.println();
  delay(3000);
}

byte moisture() {
  // 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(mois); i++) mod.write(mois[i]);

  // wait for the transmission to complete
  mod.flush();

  // switching RS485 to receive mode
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

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

  // 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 temperature() {
  // 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(temp); i++) mod.write(temp[i]);

  // wait for the transmission to complete
  mod.flush();

  // switching RS485 to receive mode
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

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

  // 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[3]<<8|values[4];
}

byte econduc() {
  // 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(econ); i++) mod.write(econ[i]);

  // wait for the transmission to complete
  mod.flush();

  // switching RS485 to receive mode
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

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

  // 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 phydrogen() {
  // 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(ph); i++) mod.write(ph[i]);

  // wait for the transmission to complete
  mod.flush();

  // switching RS485 to receive mode
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

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

  // 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 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();

  // switching RS485 to receive mode
  digitalWrite(DE, LOW);
  digitalWrite(RE, LOW);

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

  // 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 to allow response bytes to be received!
  delay(200);
  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 to allow response bytes to be received!
  delay(200);
  for (byte i = 0; i < 7; i++) {
    values[i] = mod.read();
    // Serial.print(values[i], HEX);
    // Serial.print(' ');
  }
  return values[4];
}

And im using this pin diagram

Hi, im getting output like this for the above code! where did it go wrong?
image

meanwhile, in the Qmodbus, I'm getting the correct values!
image

The code given by @markd833 is working.
image

code:

// Get ModbusMaster  at https://github.com/4-20ma/ModbusMaster

#include <ModbusMaster.h>
#include <SoftwareSerial.h>

const int RO_PIN = 10;
const int DI_PIN = 11;
const int RE_PIN = 8;
const int DE_PIN = 9;

SoftwareSerial swSerial(RO_PIN, DI_PIN); // Receive (data in) pin, Transmit (data out) pin
ModbusMaster node;

// Put the MAX485 into transmit mode
void preTransmission()
{
  digitalWrite(RE_PIN, 1);
  digitalWrite(DE_PIN, 1);
}

// Put the MAX485 into receive mode
void postTransmission()
{
  digitalWrite(RE_PIN, 0);
  digitalWrite(DE_PIN, 0);
}

void setup() {
  Serial.begin(9600);

  // configure the MAX485 RE & DE control signals and enable receive mode
  pinMode(RE_PIN, OUTPUT);
  pinMode(DE_PIN, OUTPUT);
  digitalWrite(DE_PIN, 0);
  digitalWrite(RE_PIN, 0);
  
  // Modbus communication runs at 9600 baud
  swSerial.begin(9600);

  // Modbus slave ID of NPK sensor is 1
  node.begin(2, swSerial);

  // Callbacks to allow us to set the RS485 Tx/Rx direction
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
  
  delay(1000);
}

void loop() {
  uint8_t result;
  // remove any characters from the receive buffer
  while ( swSerial.available() > 0 ) {
    swSerial.read();
  }
  // ask for 7x 16-bit words starting at register address 0x0000
  result = node.readHoldingRegisters( 0x0000, 7 );  
  
  if (result == node.ku8MBSuccess)
  {
    Serial.print("Reply:: ");
    Serial.print(node.getResponseBuffer( 0 ));
    Serial.print(" ");
    Serial.print(node.getResponseBuffer( 1 ));
    Serial.print(" ");
    Serial.print(node.getResponseBuffer( 2 ));
    Serial.print(" ");
    Serial.print(node.getResponseBuffer( 3 ));
    Serial.print(" ");
    Serial.print(node.getResponseBuffer( 4 ));
    Serial.print(" ");
    Serial.print(node.getResponseBuffer( 5 ));
    Serial.print(" ");
    Serial.print(node.getResponseBuffer( 6 ));
    Serial.println("");
  } else {
    printModbusError( result );
  }
  delay(2000);
}

// print out the error received from the Modbus library
void printModbusError( uint8_t errNum )
{
  switch ( errNum ) {
    case node.ku8MBSuccess:
      Serial.println(F("Success"));
      break;
    case node.ku8MBIllegalFunction:
      Serial.println(F("Illegal Function Exception"));
      break;
    case node.ku8MBIllegalDataAddress:
      Serial.println(F("Illegal Data Address Exception"));
      break;
    case node.ku8MBIllegalDataValue:
      Serial.println(F("Illegal Data Value Exception"));
      break;
    case node.ku8MBSlaveDeviceFailure:
      Serial.println(F("Slave Device Failure"));
      break;
    case node.ku8MBInvalidSlaveID:
      Serial.println(F("Invalid Slave ID"));
      break;
    case node.ku8MBInvalidFunction:
      Serial.println(F("Invalid Function"));
      break;
    case node.ku8MBResponseTimedOut:
      Serial.println(F("Response Timed Out"));
      break;
    case node.ku8MBInvalidCRC:
      Serial.println(F("Invalid CRC"));
      break;
    default:
      Serial.println(F("Unknown Error"));
      break;
  }
}

remove this part.

Actually, I have slightly modified the code given by @markd833 based on the requirements for the project, I'm using the uno, rs485 module along with the rs485 dongle also. (if I don't use the dongle, the output displays like "Invalid Slave ID" so I'm using the dongle also connected to my pc) but as I mentioned earlier temperature and ph remain the same even after I unplug the probes from the soil!!

code :

// Get ModbusMaster  at https://github.com/4-20ma/ModbusMaster

#include <ModbusMaster.h>
#include <SoftwareSerial.h>

const int RO_PIN = 10;
const int DI_PIN = 11;
const int RE_PIN = 8;
const int DE_PIN = 9;

SoftwareSerial swSerial(RO_PIN, DI_PIN); // Receive (data in) pin, Transmit (data out) pin
ModbusMaster node;

// Put the MAX485 into transmit mode
void preTransmission()
{
  digitalWrite(RE_PIN, 1);
  digitalWrite(DE_PIN, 1);
}

// Put the MAX485 into receive mode
void postTransmission()
{
  digitalWrite(RE_PIN, 0);
  digitalWrite(DE_PIN, 0);
}

void setup() {
  Serial.begin(9600);

  // configure the MAX485 RE & DE control signals and enable receive mode
  pinMode(RE_PIN, OUTPUT);
  pinMode(DE_PIN, OUTPUT);
  digitalWrite(DE_PIN, 0);
  digitalWrite(RE_PIN, 0);
  
  // Modbus communication runs at 9600 baud
  swSerial.begin(9600);

  // Modbus slave ID of NPK sensor is 1
  node.begin(2, swSerial);

  // Callbacks to allow us to set the RS485 Tx/Rx direction
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
  
  delay(1000);
}

void loop() {
  uint8_t result;
  // remove any characters from the receive buffer
  // ask for 7x 16-bit words starting at register address 0x0000
  result = node.readHoldingRegisters( 0x0000, 7 );  
  
  if (result == node.ku8MBSuccess) {
    Serial.println("Reply:");
    Serial.print("Temp: ");
    Serial.print(node.getResponseBuffer(0) / 10.0);
    Serial.println(" F");

    Serial.print("Moisture: ");
    Serial.print(node.getResponseBuffer(1) / 10.0);
    Serial.println("%");

    Serial.print("EC: ");
    Serial.print(node.getResponseBuffer(2));
    Serial.println(" uS/cm");

    Serial.print("pH: ");
    Serial.print(node.getResponseBuffer(3) / 100.0);
    Serial.println("");

    Serial.print("N: ");
    Serial.print(node.getResponseBuffer(4) * 10);
    Serial.println(" mg/kg");

    Serial.print("P: ");
    Serial.print(node.getResponseBuffer(5) * 10);
    Serial.println(" mg/kg");

    Serial.print("K: ");
    Serial.print(node.getResponseBuffer(6) * 10);
    Serial.println(" mg/kg");
  } else {
    printModbusError(result);
  }
  delay(10000);
}




// print out the error received from the Modbus library
void printModbusError( uint8_t errNum )
{
  switch ( errNum ) {
    case node.ku8MBSuccess:
      Serial.println(F("Success"));
      break;
    case node.ku8MBIllegalFunction:
      Serial.println(F("Illegal Function Exception"));
      break;
    case node.ku8MBIllegalDataAddress:
      Serial.println(F("Illegal Data Address Exception"));
      break;
    case node.ku8MBIllegalDataValue:
      Serial.println(F("Illegal Data Value Exception"));
      break;
    case node.ku8MBSlaveDeviceFailure:
      Serial.println(F("Slave Device Failure"));
      break;
    case node.ku8MBInvalidSlaveID:
      Serial.println(F("Invalid Slave ID"));
      break;
    case node.ku8MBInvalidFunction:
      Serial.println(F("Invalid Function"));
      break;
    case node.ku8MBResponseTimedOut:
      Serial.println(F("Response Timed Out"));
      break;
    case node.ku8MBInvalidCRC:
      Serial.println(F("Invalid CRC"));
      break;
    default:
      Serial.println(F("Unknown Error"));
      break;
  }
}

Output when the probes are in the soil

Output when the probes are out of the soil

Output when the probes are in the water

Please let me know if I made any mistake.

Well at least now the code is working.
I dont understand the part with the dongle connected? There are slight temperature differences... you are using cold water? Dont know what ph value you should get when removed from soil but have you cleaned the probes and waited to see if there are differences?

OK, this is post 132 already, do some experiments on your own. Think about what you want to do and how to do it, I guess you don`t think this is going to continue in baby steps to the post #1320...

Okay sir, and thank you so much to all of you for helping me out, you all people will be remembered for a long. @markd833 @qubits-us @noobmastha :star_struck:

My first guess there would be that there was an issue with the resistors on the RS485 bus. The RS485 module you have should have all 3 resistors fitted.