1. Introduction
In industrial environments, standard sensors fail over long distances due to electrical noise. Modbus RS485 is the industry standard that allows an Arduino to communicate with industrial PLCs, VFDs, and high-end sensors over distances up to 1.2km. In this project, we will interface an Arduino with a Modbus slave device using the MAX485 TTL-to-RS485 converter.
2. Components
Arduino Uno or Nano
MAX485 TTL to RS485 Module
Modbus Slave Device (NPK Sensor or e.g., any Industrial Temperature Sensor or another Arduino configured as Slave)
120Ω Termination Resistor
16x2 I2C LCD Display
Jumper Wires and 9V/12V Power Supply
3. Circuit and Connections
| Arduino Uno Pinout Diagram |
| Max485-RS485 Pinout Diagram |
| NPK Sensor Pinout Diagram |

PIN-OUT Diagram LCD WITH I2C
MAX485 to Arduino:
VCC → 5V, GND → GND
RO (Receiver Out) → Pin 10 (Software RX)
DI (Driver In) → Pin 11 (Software TX)
DE & RE → Connected together to Pin 3 (Control Pin)
RS485 Bus (Output Side):
A Pin → Connect to Slave A (+)
B Pin → Connect to Slave B (-)
LCD: SDA → A4, SCL → A5
4. Detailed Step-by-Step Circuit Working
Level Shifting: The MAX485 converts the Arduino’s 5V UART signals into differential signals (A and B). This difference in voltage makes the communication immune to electromagnetic interference (EMI).
Half-Duplex Switching: RS485 uses only two wires for both sending and receiving. Pin 3 on the Arduino acts as a "traffic cop." When HIGH, the Arduino talks (Transmit); when LOW, the Arduino listens (Receive).
Data Request: The Arduino (Master) sends a specifically formatted packet containing the Slave ID, Function Code, and Register Address.
Slave Response: The target device recognizes its ID, processes the request, and sends the data back through the same A and B wires.
⚠️ Critical Wiring Reminder for your Blog Post:
To ensure projects actually work, check these three points
External Power: The NPK sensor requires 9V to 24V. Do not power it from the Arduino 5V pin.
Common Ground: The negative wire of the 12V sensor power supply must be connected to the Arduino GND pin.
A & B Wires: If the Serial Monitor shows
0xE2, try swapping the A and B wires on the MAX485 module. Many cheap sensors have their A/B labels reversed.
5. Libraries to be included
ModbusMaster.h (The most stable library for Arduino Modbus)
SoftwareSerial.h (To keep the hardware Serial free for debugging)
6. Code
/* * Project: Industrial Soil NPK Sensor Interfacing (Modbus RS485)
* Blog: simplebasicelectronics.blogspot.com
* Author: Prakash Mohan
*/
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define MAX485 Control Pins
#define MAX485_DE_RE 3
// Setup Software Serial for MAX485 (RX on 10, TX on 11)
SoftwareSerial swSerial(10, 11);
ModbusMaster node;
// Callback functions to switch MAX485 between Transmit and Receive modes
void preTransmission() {
digitalWrite(MAX485_DE_RE, HIGH);
}
void postTransmission() {
digitalWrite(MAX485_DE_RE, LOW);
}
void setup() {
// Pin modes for RS485 Control
pinMode(MAX485_DE_RE, OUTPUT);
digitalWrite(MAX485_DE_RE, LOW); // Start in Receive mode
// Initialize Hardware Serial for Debugging
Serial.begin(9600);
// Initialize Software Serial for Modbus (Standard NPK Baud Rate is 9600)
swSerial.begin(9600);
// Modbus Slave ID is usually 1 for NPK sensors
node.begin(1, swSerial);
// Attach the callback functions
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
Serial.println("--- Industrial NPK Sensor Ready ---");
}
void loop() {
uint8_t result;
uint16_t data[3];
// 0x03 is the Read Holding Registers function code
// 0x001E is the starting address for N (Nitrogen)
// 3 is the number of registers to read (N, P, and K)
result = node.readHoldingRegisters(0x001E, 3);
if (result == node.ku8MBSuccess) {
// Read the values from the buffer
int nitrogen = node.getResponseBuffer(0);
int phosphorus = node.getResponseBuffer(1);
int potassium = node.getResponseBuffer(2);
// Display Results
Serial.print("Nitrogen (N): ");
Serial.print(nitrogen);
Serial.println(" mg/kg");
Serial.print("Phosphorus (P): ");
Serial.print(phosphorus);
Serial.println(" mg/kg");
Serial.print("Potassium (K): ");
Serial.print(potassium);
Serial.println(" mg/kg");
Serial.println("-----------------------");
} else {
// If communication fails, print the error code
Serial.print("Modbus Error: 0x");
Serial.println(result, HEX);
// Error 0xE2 usually means a wiring or timeout issue
if(result == 0xE2) Serial.println("Check Wiring & External Power!");
}
delay(2000); // Wait 2 seconds before the next reading
}
7. Detailed Step-by-Step Code Working
pre/postTransmission: These functions automate the switching of the MAX485 module. Without this, the Arduino would "talk over" its own reception.node.begin(1, swSerial): This initializes the Modbus Master to look for a device with ID #1.readHoldingRegisters(0x0001, 1): This command asks the slave: "Please send me the value stored in your first data memory slot."ku8MBSuccess: This check is vital. In Modbus, if a wire is loose or the ID is wrong, it returns an error code (like0xE2), and this logic prevents the LCD from showing garbage data.
8. Tips
Termination Resistor: If your wires are longer than 10 meters, add a 120Ω resistor between A and B at the very end of the line to prevent signal reflection.
Common Ground: Even though RS485 is differential, ensure the GND of the Master and Slave are connected to prevent common-mode voltage errors.
Baud Rate: Ensure the Slave device and the Arduino are both set to the same speed (e.g., 9600).
9. Uses
Solar Inverters: Reading power data from commercial inverters.
VFD Control: Controlling the speed of industrial motors.
HVAC Systems: Reading temperature and pressure from large industrial chillers.
10. Conclusion
Mastering Modbus RS485 transforms your Arduino from a hobbyist tool into an industrial controller. It allows you to build systems that are rugged, reliable, and capable of working in the toughest factory environments.
Similar Posts you May Be Interested:
https://simplebasicelectronics.blogspot.com/2 026/03/arduino-pir-motion-sensor-alarm.html
https://simplebasicelectronics.blogspot.com/2026/03/arduino-gas-leak-detector-using-mq-2.html
https://simplebasicelectronics.blogspot.com/2026/03/arduino-flame-sensor-fire-alarm.html
https://simplebasicelectronics.blogspot.com/2026/04/arduino-driver-drowsiness-detection.html
https://simplebasicelectronics.blogspot.com/2026/03/diy-arduino-rain-alarm-yl83.html
https://simplebasicelectronics.blogspot.com/2026/04/arduino-noncontact-infrared-thermometer-using-mlx90614.html