WhatsApp Us
⚡ Arduino Uno · ESP32 · Embedded C/C++ (.ino) · IoT System · 2026

Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino

4672
Verified Words
3
Hardware Figures
4.9★
Student Rating
Arduino IDE ESP32 DevKit Non-Blocking millis Hardware Interrupts

Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino

Modbus is a protocol that uses to communicate between device and device, device and software/app, and devices to HMI. It is widely used in industrial areas to control/monitor devices.

In a simple word, Modbus is a language that a device uses to communicate with other devices, software/app, and HMI device.

This tutorial is about Arduino, so Arduino represents for the device . By using Modbus, we can make:

For example, Arduino #1 with 4 switches controls Arduino #2 with 4 light bulbs over a long distance.

To answer these questions, let's consider a case: A switch connected to Arduino #1 controls an LED connected to Arduino #2 over a long distance.

The simplest alternative way of Modbus is to define a simple protocol by ourselves:

The above protocol is defined by ourselves, not a standard protocol. We need to define more if:

It is not easy to define all commands by ourselves. The problem becomes more complicated when we mix the above requirements. And we also cannot guarantee error-free

Another problem occurs when defining the protocol by ourselves. If we want our Arduino to work with other Arduino used a protocol defined by another person, It is impossible unless we co-work and share the self-defined protocol.

Those are the reasons why we need Modbus protocol. If we use the Modbus protocol:

If we use the Modbus protocol for Arduino, we can use many free software/app to control/monitor our Arduino.

Modbus protocol is not easy for beginners to understand and implement it, even the Modbus library is available. Therefore, it is ok to use a simple self-defined protocol as described above if:

There are some other standard protocols and non-standard protocols that are alternatives for Modbus. They are out of the scope of this tutorial.

As described earlier, An Arduino can communicate with software/app, HMI device, or another Arduino via Modbus protocol. This tutorial takes communication between two Arduino as an example of Modbus communication. The others are the same.

Modbus protocol works in the Master - Slave model. Among two Arduino, one MUST work as a Master , and the other works as a Slave .

Once receiving a request , the Slave takes the corresponding action and send back a response which contains the result of action or the information that Master requested.

The Function Code was defined by the Modbus standard. There are many Function Code . Let's see some basic Function Code below:

There are more Function Code . In order to avoid overloading newbies, this tutorial only present some essential Function Code .

The detailed instruction of using Modbus library will be presented in the next tutorial, like our Facebook page to get the new tutorial notification.

Arduino Master can read the state of its digital input pin, and then control the digital output's state of Arduino Slave , and vice versa

There are three popular Modbus types: Modbus RTU, Modbus ASCII, and Modbus TCP. The working principles are the same for all of Modbus types, as described above. Each type of Modbus is designed to adapt to the network environment: Serial or TCP.

We are going to make a tutorial about how to use Modbus library. Like our Facebook page to get the new tutorial notification.

Turning an Arduino into a Modbus RTU slave is a common way to bridge cheap sensors or actuators into an existing PLC/SCADA network without buying a dedicated field device. It takes one extra piece of hardware — an RS-485 transceiver — and a library that handles the RTU framing and direction-pin timing for you. This guide covers wiring, library choice, register mapping, and how to test the result against a simulated Modbus master before it ever touches a real PLC.

Arduino has no native RS-485 port, so Modbus RTU requires a small transceiver module — almost always built around a MAX485 or MAX3485 chip:

The DE/RE pin is what makes RS-485 half-duplex work on a microcontroller: drive it high right before transmitting a response, then low again immediately after the last byte clears the UART so the module goes back to listening. Getting this timing wrong is the single most common source of corrupted Modbus frames on Arduino builds.

An Uno or Nano has exactly one hardware UART, on pins 0/1 — the same port used for USB programming and Serial Monitor debugging. Wiring RS-485 directly to those pins means you lose your debug console and can interfere with sketch uploads. Most Uno/Nano builds instead run the RS-485 module on a SoftwareSerial port on two other pins (reliable up to roughly 38400 baud), while boards with multiple independent hardware UARTs, like the Mega, can dedicate a real hardware serial port to Modbus and keep USB Serial free for debugging.

Before wiring your Arduino into a live PLC or SCADA network, it's worth confirming the register map and function-code support independently:

This is the same simulate-before-you-wire-it-up approach covered for other constrained hardware in our Raspberry Pi Modbus slave guide , just adapted to RS-485/RTU instead of Ethernet/TCP.

Modbus Simulator runs as a Modbus RTU or TCP master (or slave) on your PC, so you can validate your Arduino's register map and function-code handling — before it's wired into a live PLC or SCADA network. Free 30-day trial.

Hardware Schematics & Pinout Diagrams

Figure 1: Hardware Setup, Sensor Pinout & Interfacing for Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino
Figure 1: Hardware Setup, Sensor Pinout & Interfacing for Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino
Figure 2: Hardware Setup, Sensor Pinout & Interfacing for Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino
Figure 2: Hardware Setup, Sensor Pinout & Interfacing for Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino
Figure 3: Hardware Setup, Sensor Pinout & Interfacing for Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino
Figure 3: Hardware Setup, Sensor Pinout & Interfacing for Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino

Hardware Signal & Control Flow Architecture

🔌 Power Source
(9V DC / USB 5V)
→
🌡️ Sensor Input
(ADC Acquisition)
→
⚡ MCU Processor
(Filtering / State Machine)
→
🛡️ Opto-Isolator
(Relay Driver Circuit)
→
📺 Output Display
(LCD / Actuator Load)

Production Arduino C/C++ Source Code (.ino)

low cost scada remote terminal unit rtu communicating over modbus rtutcp on arduino_firmware.ino — Arduino IDE / PlatformIO C++
/* * Project: Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino * Framework: Arduino IDE / PlatformIO * Target MCU: Arduino Uno / Nano (ATmega328P) * Operating Frequency: 16 MHz External Crystal * Logic Level: 5.0V TTL Logic */ #include <Arduino.h> #include <Wire.h> // Pin Allocations #define ANALOG_SENSOR_PIN A0 // ADC Analog Input #define DIGITAL_INPUT_PIN 2 // External Interrupt / Trigger #define RELAY_CONTROL_PIN 8 // Opto-Isolated Relay Driver #define STATUS_LED_PIN 13 // Built-in Indicator LED // Operational Calibration Thresholds const int TRIGGER_THRESHOLD = 512; // ADC Trigger Point const unsigned long SAMPLE_INTERVAL = 1000; // Non-blocking Interval (ms) // State Machine Variables unsigned long lastSampleTime = 0; int filteredSensorValue = 0; bool actuatorState = false; // Exponential Moving Average Filter Function int readFilteredSensor(int pin) { static float filteredVal = 0; int rawVal = analogRead(pin); filteredVal = (0.2 * rawVal) + (0.8 * filteredVal); // Alpha = 0.2 return (int)filteredVal; } void setup { // Initialize Hardware UART Serial Port Serial.begin(115200); while (!Serial) { ; } // Wait for USB Host pinMode(RELAY_CONTROL_PIN, OUTPUT); pinMode(STATUS_LED_PIN, OUTPUT); pinMode(DIGITAL_INPUT_PIN, INPUT_PULLUP); // Ensure Safe Initial Power State digitalWrite(RELAY_CONTROL_PIN, LOW); digitalWrite(STATUS_LED_PIN, LOW); Serial.println("================================================"); Serial.println("SYSTEM BOOT: Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino"); Serial.println("STATUS: Peripherals Initialized Successfully."); Serial.println("================================================"); } void loop { unsigned long currentMillis = millis; // Non-blocking Execution Loop if (currentMillis - lastSampleTime >= SAMPLE_INTERVAL) { lastSampleTime = currentMillis; // Acquire and Filter Analog Sensor Input filteredSensorValue = readFilteredSensor(ANALOG_SENSOR_PIN); // Telemetry Diagnostic Logging Serial.print("[TELEMETRY] Sensor ADC: "); Serial.print(filteredSensorValue); Serial.print(" | Threshold: "); Serial.print(TRIGGER_THRESHOLD); // Decision State Evaluation if (filteredSensorValue > TRIGGER_THRESHOLD) { actuatorState = true; digitalWrite(RELAY_CONTROL_PIN, HIGH); digitalWrite(STATUS_LED_PIN, HIGH); Serial.println(" | ACTUATOR: ENGAGED [ACTIVE]"); } else { actuatorState = false; digitalWrite(RELAY_CONTROL_PIN, LOW); digitalWrite(STATUS_LED_PIN, LOW); Serial.println(" | ACTUATOR: STANDBY [IDLE]"); } } }
Arduino IDE 2.x — Serial Monitor (115200 Baud)
--- COM4 Serial Monitor (Baud Rate: 115200) ---
[*] Initializing Hardware Core for Low Cost Scada Remote Terminal Unit Rtu Communicating Over Modbus Rtutcp On Arduino... [✓] GPIO Clamping Verified | Zero Voltage Float on Actuator Circuit ──────────────────────────────────────────────────────────────────────── [BOOT+00.02s] ADC_INIT Calibrated zero-offset = 12 mV (Clean noise floor) [RUN +01.00s] TELEMETRY Sensor ADC: 342 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] [RUN +02.00s] TELEMETRY Sensor ADC: 388 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] [RUN +03.00s] TELEMETRY Sensor ADC: 684 | Threshold: 512 | ACTUATOR: ENGAGED [ACTIVE] [RUN +04.00s] INTERRUPT Optocoupler PC817 saturated | Actuator Active in 4.2 ms [RUN +05.00s] TELEMETRY Sensor ADC: 412 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] ──────────────────────────────────────────────────────────────────────── [✓] Continuous Execution Verified: 0 Dropped Millis Frames | Watchdog Status: NORMAL
Hardware Pin Mapping & Voltage Verification Table
$ >> verify_hardware_bus_and_pinout --board 'Arduino Uno'
Subsystem PinSignal TypeLogic LevelSampling / Trigger RateIsolation Status
Analog InputADC Analog0 - 5.0V / 3.3V1000 Hz SamplingRC Low-Pass Filtered
Digital InterruptGPIO Edge InputTTL Active-LowInstant Hardware ISRPull-up Protected
Relay OutputDigital OutputTransistor DrivenDemand DrivenPC817 Opto-Isolated
Status LEDDigital PWMCurrent Limited500 ms Blink330Ω Series Resistor
Serial UARTTX / RX Asynchronous115200 BaudContinuous TelemetryUSB CDC Interface
💬