MAX485 TTL to RS-485 Modules for soil NPK sensor

A follow-up to my previous post. Here is my attempt to use the ModbusMaster library on an Arduino UNO with a software serial port using AltSoftSerial rather than the canned Modbus messages and error prone software that seems to be circulating various websites:

// Attempt to access a JXCT NPK sensor to read Nitrogen, Potassium & Phosphorus
// values using an Arduino UNO clone.
//
// This attempt uses the AltSoftSerial & ModbusMaster libraries. Get the libraries
// via the Arduino IDE or manually:
// Get AltSoftSerial at https://github.com/PaulStoffregen/AltSoftSerial
// Get ModbusMaster  at https://github.com/4-20ma/ModbusMaster
//
// RS485 module connected to Arduino UNO as follows:
// RS485 DI signal to pin 9
// RS485 RO signal to pin 8
// RS485 RE signal to pin 7
// RS485 DE signal to pin 6
// RS485 VCC to 5V
// RS485 GND to GND
//
// Assumes that the sensor address is 1, Nitrogen is address 0x1E, Phosphorus is address 0x1F
// and Potassium is address 0x20. Change the code if yours are different.
//
// NOTE: I do not have this sensor, so I simulated it using ModRSsim2 available from https://sourceforge.net/projects/modrssim2/
// 

#include <ModbusMaster.h>
#include <AltSoftSerial.h>

#define NITROGEN_ADDR   0x1E
#define PHOSPHORUS_ADDR 0x1F
#define POTASSIUM_ADDR  0x20

#define MAX485_DE      6
#define MAX485_RE_NEG  7

AltSoftSerial swSerial;
ModbusMaster node;

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

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

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

  // configure the MAX485 RE & DE control signals and enable receive mode
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);

  // Modbus communication runs at 9600 baud
  swSerial.begin(9600);

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

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

void loop() {
  uint8_t result;

  // NITROGEN
  result = node.readHoldingRegisters(NITROGEN_ADDR, 1);
  if (result == node.ku8MBSuccess)
  {
    Serial.print("   Nitrogen: ");
    Serial.print(node.getResponseBuffer(0x0));
    Serial.println(" mg/kg");
  } else {
    printModbusError( result );
  }

  // PHOSPHORUS
  result = node.readHoldingRegisters(PHOSPHORUS_ADDR, 1);
  if (result == node.ku8MBSuccess)
  {
    Serial.print("Phosphorous: ");
    Serial.print(node.getResponseBuffer(0x0));
    Serial.println(" mg/kg");
  } else {
    printModbusError( result );
  }

  // POTASSIUM
  result = node.readHoldingRegisters(POTASSIUM_ADDR, 1);
  if (result == node.ku8MBSuccess)
  {
    Serial.print("  Potassium: ");
    Serial.print(node.getResponseBuffer(0x0));
    Serial.println(" mg/kg");
  } else {
    printModbusError( result );
  }
  Serial.println();
  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;
  }
}

And this is the wiring diagram:

I've also added in printing of Modbus errors. Check that your NPK sensor is set for Modbus address 1 and that the Nitrogen, Phosphorus & Potassium addresses are the same as I used.