How to: Configure Raspberry Pi to Receive Communication from PLC - Mitsubishi FX3U using Modbus RTU

 

Integrating Mitsubishi FX3U PLC with Raspberry Pi via Modbus RTU

I. Introduction

This report details the process of establishing communication between a Mitsubishi FX3U series Programmable Logic Controller (PLC) and a Raspberry Pi single-board computer using the Modbus RTU protocol. The primary objective is to enable the Raspberry Pi to act as a Modbus master, capable of reading data from and writing data to the FX3U PLC, which will be configured as a Modbus slave. This project is particularly relevant when the FX3U PLC lacks native TCP/IP capabilities, making serial communication protocols like Modbus RTU an essential alternative for integration with supervisory systems or data logging applications hosted on platforms like the Raspberry Pi.

Modbus RTU is selected for this application due to its widespread adoption in industrial environments, simplicity, and efficiency over serial communication links. It provides a standardized method for transmitting information between electronic devices. The Mitsubishi FX3U PLC, a robust controller often found in industrial automation, can be configured to support Modbus RTU communication through an appropriate serial communication module. The Raspberry Pi, a versatile and cost-effective computing platform, can be programmed (typically in Python) to implement Modbus master functionality, allowing it to poll the PLC for data or send control commands.

This document will provide a comprehensive guide covering the necessary hardware components, wiring procedures, PLC configuration steps using GX Works2 software, Raspberry Pi setup, Python programming for Modbus communication, and troubleshooting common issues. The aim is to equip engineers and technicians with the knowledge to successfully implement this integration.

II. Understanding Modbus RTU

Modbus RTU is a master-slave communication protocol widely utilized in industrial automation for its simplicity and reliability in exchanging data over serial connections. Developed by Modicon (now Schneider Electric) in 1979, it has become a de facto standard.2

A. Protocol Basics

In a Modbus RTU network, there is one master device and one or more slave devices (up to 247 unique addresses).1 Communication is always initiated by the master, which sends a request to a specific slave. The addressed slave then processes the request and sends a response back to the master.1 Other slaves on the network ignore requests not addressed to them. Modbus RTU is characterized by its binary data encoding and robust error checking, making it efficient for serial lines.1

B. Frame Structure

Each Modbus RTU message, or frame, adheres to a specific structure 1:

  1. Slave Address (1 byte): Identifies the target slave device. Addresses range from 1 to 247. Address 0 is reserved for broadcast messages, which are not typically responded to by slaves.1

  2. Function Code (1 byte): Specifies the action requested by the master, such as reading discrete inputs, reading holding registers, writing a single coil, or writing multiple registers.1 Valid codes are typically in the range of 1-127.

  3. Data Field (N bytes): Contains information pertinent to the function code, such as the starting register address, the number of registers to read/write, and the actual data values to be written. The length of this field varies depending on the function code and the amount of data.1 The maximum length of the Modbus RTU message is 256 bytes, with the data field itself being up to 253 bytes.4

  4. CRC (Cyclic Redundancy Check) (2 bytes): An error-checking field calculated over the address, function code, and data fields. This 16-bit value allows the receiving device to verify the integrity of the message.1

A silent interval of at least 3.5 character times must separate messages to allow devices to detect the end of one frame and the beginning of another.5

C. Modbus Data Types (Register Types)

Modbus defines four primary data types or register areas within a slave device 1:

  1. Coils (0xxxx addresses): Single-bit read/write data items. These are often used to control discrete outputs or represent internal binary states. (Function codes e.g., 01 Read Coils, 05 Write Single Coil).

  2. Discrete Inputs (1xxxx addresses): Single-bit read-only data items. These typically represent the status of digital inputs. (Function code e.g., 02 Read Discrete Inputs).

  3. Input Registers (3xxxx addresses): 16-bit read-only data items. These are often used to hold data from analog inputs or other measurements. (Function code e.g., 04 Read Input Registers).

  4. Holding Registers (4xxxx addresses): 16-bit read/write data items. These are the most versatile and commonly used registers for storing various types of data, such as setpoints, operational parameters, or analog output values.2 (Function codes e.g., 03 Read Holding Registers, 06 Write Single Register, 16 Write Multiple Registers).

D. Physical Layer: RS-485

Modbus RTU commonly operates over an RS-485 serial interface. RS-485 is favored in industrial settings for several reasons:

  • Multi-drop Capability: Allows multiple devices (one master, multiple slaves) to be connected on the same two-wire bus in a daisy-chain topology. Star or ring topologies should be avoided due to signal reflection issues.

  • Differential Signaling: Uses two wires (typically labeled A and B) for data transmission, providing high noise immunity, which is crucial in electrically noisy industrial environments.

  • Distance: Supports communication over relatively long distances, up to 1200 meters at lower baud rates (e.g., 9600 bps).

  • Baud Rates: Common baud rates range from 1200 bps to 115200 bps, though many Modbus RTU devices support up to 38400 bps.2

E. Cable and Termination Requirements for RS-485

For reliable RS-485 communication :

  • Cable Type: Shielded Twisted Pair (STP) cable is recommended, especially in noisy environments, to reduce electromagnetic interference (EMI). Unshielded Twisted Pair (UTP) can also be used. Wire gauge should typically be 24 AWG or thicker.

  • Termination: Termination resistors (typically 120 ohms) must be placed at both ends of the RS-485 bus segment, across the A and B lines. This prevents signal reflections that can corrupt data.

  • Biasing: Pull-up and pull-down resistors (biasing resistors, often around 10 kΩ) may be required to maintain a defined idle state on the bus, ensuring a minimum differential voltage (e.g., 200 mV) when no device is transmitting. Some modern transceivers or adapters incorporate auto-biasing.

III. Hardware Setup and Wiring

Proper hardware selection and meticulous wiring are foundational for successful Modbus RTU communication. This section details the components and connections for interfacing the Mitsubishi FX3U PLC with a Raspberry Pi.

A. Mitsubishi FX3U PLC Side: FX3U-485-BD Communication Board

To enable Modbus RTU communication on the Mitsubishi FX3U PLC, an RS-485 communication interface is required. The FX3U-485-BD expansion board is a suitable option for this purpose.7

  1. FX3U-485-BD Specifications:

  • Interface: Provides an RS-485/RS-422 communication port via a European-style terminal block.7

  • Communication Method: Supports half-duplex communication, which is standard for 2-wire Modbus RTU.7

  • Applicable PLCs: Compatible with FX3U Series PLCs (Ver. 2.20 or later) and specific FX3UC models. Only one such expansion board can typically be used per main unit and cannot be used with other BD-type serial boards simultaneously.7

  • Baud Rates: Supports various baud rates suitable for Modbus, including 300, 600, 1200, 2400, 4800, 9600, and 19200 bps for non-protocol communication (which is used for Modbus RTU).7

  • Termination Resistor: Features an onboard terminal resistor changing-over switch with settings for 330Ω, OPEN (no resistor), and 110Ω.7 The selection depends on the PLC's position in the Modbus network (end device or intermediate device) and the overall network impedance characteristics. For standard 120Ω twisted-pair cable, the 110Ω setting is generally the closest match if the PLC is an end device.

  • LED Indicators: Equipped with RD (Receive Data) and SD (Send Data) LEDs that indicate communication activity.7

  1. Installation and Precautions for FX3U-485-BD:

  • Power Off: Always disconnect all power to the PLC before installing or wiring the FX3U-485-BD to prevent electric shock or damage.7

  • Environment: Install in an environment compliant with the PLC's general specifications, avoiding excessive dust, corrosive gases, high temperatures, and vibration.7

  • Secure Connection: Ensure the board is securely connected to the PLC's main unit connector.7 Loose connections can cause malfunctions. Refer to the FX3U Series User's Manual - Hardware Edition for detailed installation steps.7

  1. FX3U-485-BD Terminal Connections for 2-Wire Modbus RTU:
    The FX3U-485-BD features a terminal block with markings: RD, RDA, RDB, SDA, SDB, SG, SD.7 For 2-wire (half-duplex) Modbus RTU communication, the connections are typically as follows, based on general RS-485 principles and information from related Mitsubishi Modbus manuals 8:

  • SDA (Send Data A): Connects to the Modbus A (Data+) line.

  • SDB (Send Data B): Connects to the Modbus B (Data-) line.

  • SG (Signal Ground): Connects to the Modbus Signal Ground (GND) line of the RS-485 network. This provides a common voltage reference. The RDA (Receive Data A) and RDB (Receive Data B) terminals are generally used for 4-wire (full-duplex) RS-422/RS-485 communication. In a 2-wire half-duplex Modbus RTU setup, they are typically not used or are internally jumpered/managed by the communication board. The "FX Series User's Manual - Data Communication Edition" (JY997D16901) and "FX3S/FX3G/FX3GC/FX3U/FX3UC Series User's Manual - MODBUS Serial Communication Edition" (JY997D26201) should be consulted for definitive wiring diagrams for the FX3U-485-BD in Modbus RTU mode.7 Some forum discussions suggest that for Modbus RTU with FX3U-485-BD, you might need to implement the Modbus protocol (including CRC calculation) in the PLC program using non-protocol communication (RS/RS2 instructions), as the board itself may not inherently handle the full Modbus protocol layer like the FX3U-485ADP-MB does.11 However, it can serve as the physical RS-485 interface.

  1. Termination Resistor Setting on FX3U-485-BD:
    If the FX3U PLC with the FX3U-485-BD is at one physical end of the Modbus RTU bus segment, the termination resistor switch should be set to an appropriate value (e.g., 110Ω).7 If it's an intermediate device in a daisy chain, the switch should be set to OPEN.

B. Raspberry Pi Side: RS-485 Interface

The Raspberry Pi's GPIO pins do not directly support RS-485. An external interface is required.

  1. Interface Options:

  • USB to RS-485 Adapter: This is a common and convenient solution. Adapters based on FTDI chips (e.g., FT232RL combined with an RS-485 transceiver) are generally reliable and well-supported on Linux.5

  • RS-485 HAT (Hardware Attached on Top): These boards connect directly to the Raspberry Pi's GPIO header and provide RS-485 transceivers.14

  1. Recommended Features for USB to RS-485 Adapter:

  • FTDI Chipset: For good compatibility and driver support on Raspberry Pi (Linux).13

  • Automatic Direction Control: Simplifies software development as the adapter automatically handles switching between transmit and receive modes on the half-duplex RS-485 bus.5

  • ESD Protection: Important for industrial environments to protect against electrostatic discharge.13

  • Isolation (Optional but Recommended): Galvanic isolation between USB and RS-485 sides can protect the Raspberry Pi from ground loops and voltage surges.

  • Termination Resistor: Some adapters include a built-in selectable termination resistor (e.g., 120Ω jumper).13

C. Wiring Connection: FX3U-485-BD to USB RS-485 Adapter

The connection involves linking the RS-485 A, B, and Ground lines.

  • Table III-1: FX3U-485-BD to USB RS-485 Adapter Wiring

FX3U-485-BD Terminal

Signal

USB RS-485 Adapter Terminal

Notes

SDA

Data A +

A / Data+ / D+ / +

Ensure polarity matches the adapter's markings.

SDB

Data B -

B / Data- / D- / -

Ensure polarity matches the adapter's markings.

SG

Ground

GND / SG / Ground

Connect if available on the adapter; improves noise immunity.

RDA, RDB

N/A

N/A

Typically not used for 2-wire RS-485. Refer to specific manuals.

  • Wiring Best Practices:

  • Polarity: Crucially, ensure the A (+) and B (-) lines are connected consistently between the PLC and the adapter. Incorrect polarity will result in communication failure.

  • Twisted Pair Cable: Use shielded twisted pair cable for the A and B lines.

  • Grounding: Connect the SG (Signal Ground) terminals. The cable shield should typically be connected to ground at one end only (often the PLC or master end) to prevent ground loops. Consult the "MODBUS Serial Communication Edition" manual (JY997D26201) for specific grounding recommendations for the FX3U.8

  • Termination: As mentioned, ensure termination resistors are active at both extreme ends of the RS-485 segment. If the USB adapter is an end device, enable its termination resistor (if available) or add one externally.

The physical setup requires careful attention to detail. Using an adapter with an FTDI chip is advisable due to robust Linux driver support, simplifying the Raspberry Pi configuration. The FX3U-485-BD's terminal designations (SDA, SDB) are standard for Mitsubishi's send data lines, which in a 2-wire half-duplex system, also function as the receive lines.

IV. Configuring the Mitsubishi FX3U as a Modbus RTU Slave

To enable the Mitsubishi FX3U PLC to communicate as a Modbus RTU slave, specific parameters must be configured using the GX Works2 programming software. This involves setting serial port parameters and utilizing special data registers (D registers) to define the Modbus behavior.

A. Software Requirement: GX Works2

GX Works2 is the Mitsubishi Electric software environment for programming and configuring FX series PLCs, including the FX3U.17

B. Communication Parameter Setup in GX Works2

The primary communication settings are configured within the PLC parameters:

  1. Open your project in GX Works2.

  2. Navigate to "Parameter" → "PLC Parameter".

  3. Select the "Serial Port" tab (or "Communication Setting" → "Serial Port 1 (or 2)" as described in some guides 17). This guide will assume Channel 1 (CH1) is being used with the FX3U-485-BD.

  4. Configure the following parameters for the selected serial channel:

  • Communication Protocol/Mode: Set to "MODBUS" or enable Modbus RTU Slave mode. Some configurations might involve setting it to "Non-Protocol Communication" and then using special registers to define Modbus behavior if the FX3U-485-BD requires manual Modbus frame handling.7 However, for dedicated Modbus functionality, specific settings are available.

  • Slave Address (Station Number): Assign a unique Modbus slave address to the PLC, typically in the range of 1 to 247.1 This value is often stored in a special D register.

  • Transmission Speed (Baud Rate): Select the desired baud rate (e.g., 9600, 19200 bps). This must match the Raspberry Pi master's setting.6

  • Data Length (Data Bits): Typically 8 bits for Modbus RTU.2

  • Parity: Choose Even, Odd, or None. "Even" is common.8 This must match the master.

  • Stop Bit(s): Usually 1 stop bit.8 This must also match the master.

  • Protocol Selection: Ensure "RTU" mode is selected over ASCII if the option is presented directly in the GUI.8

C. Using Special D Registers for Configuration

The FX3U PLC uses special internal data registers (D registers) to control and monitor Modbus communication settings, especially when configuring via ladder logic or for finer control.8 For Channel 1 (typically associated with the first communication board like FX3U-485-BD):

  • Table IV-1: Key FX3U Special Registers for Modbus RTU Slave Configuration (CH1)


D Register

Hex Value Example

Description

Reference(s)

D8400

H1097

Communication Format/Parameters: Defines baud rate, data bits, parity, stop bits, and potentially RS-485 mode. The value H1097 in an example sets 19200 bps, 8-bit, Even, 1 stop bit, RS485.

8

D8401

H11

Protocol Mode Setting: Defines the communication protocol. H11 in an example sets Modbus RTU Slave mode. Bit 0=1 (MODBUS), Bit 4=1 (Slave), Bit 8=0 (RTU).

8

D8411

K10 (decimal)

Timing Parameters: Configures Modbus communication timing, such as message-to-message delay.

8

D8414

H1

Slave Address (Station Number): Sets the PLC's Modbus slave address. H1 sets the address to 1.

8

D8063

-

Serial Communication Error Code (CH1): Stores error codes related to serial communication.

8

D8402

-

MODBUS Communication Error Code (CH1): Stores specific Modbus error codes.

8




*Note: The exact bit definitions within D8400 can be complex and should be referenced from the "FX3S/FX3G/FX3GC/FX3U/FX3UC Series User's Manual - MODBUS Serial Communication Edition" (JY997D26201).[8] The example H1097 combines these settings into a single word.*

D. Ladder Logic Example for Configuration

To ensure these settings are applied, ladder logic can be used to write the desired values into these special D registers upon PLC startup or under specific conditions.17

  • M8411 (Modbus Communication Enable for CH1): This special relay must be ON to enable the Modbus communication settings defined in D8400-D8414 to take effect for channel 1.17 It effectively activates the Modbus protocol on the port.

  • Example Ladder Rungs (Conceptual):
    Code snippet
    // Assuming M8000 is an always ON contact after PLC RUN
    -| |--------------   // Set Comm Params: 19200, 8E1, RS485
    M8000

    -| |--------------     // Set Protocol: Modbus RTU Slave
    M8000

    -| |--------------     // Set Comm Timing
    M8000

    -| |--------------      // Set Slave Address to 1
    M8000

    -| |-------------(M8411)-             // Enable Modbus CH1 Settings
    M8000
    After writing the parameters to the PLC (Parameter+Program), a power cycle of the PLC is often required for these communication settings to become active.8

E. Modbus Register Mapping

The FX3U PLC maps its internal data areas (like D registers, M coils, X inputs, Y outputs) to the standard Modbus address spaces. Understanding this mapping is crucial for the Raspberry Pi master to access the correct data.

The "FX3U USER'S MANUAL MODBUS Serial Communication Edition" (JY997D26201) Section 9.2 details the default mapping.8

  • Table IV-2: Default FX3U to Modbus RTU Address Mapping (Examples for CH1)

FX3U Device Area

Example FX3U Address

Modbus Data Type

Modbus Address (Decimal, 0-based)

Modbus Address (Traditional Notation)

Read/Write

D (Data Register)

D0

Holding Register

0

40001

R/W

D (Data Register)

D1

Holding Register

1

40002

R/W

D (Data Register)

D7999

Holding Register

7999

48000

R/W

M (Internal Coil)

M0

Coil

0

00001

R/W

M (Internal Coil)

M1

Coil

1

00002

R/W

M (Internal Coil)

M7679

Coil

7679

07680

R/W

X (Input Relay)

X0

Discrete Input

(Mapped via M or S) see note

(Mapped via M or S) see note

Read-Only

Y (Output Relay)

Y0

Coil

(Mapped via M or S) see note

(Mapped via M or S) see note

R/W




*References: [8, 17, 18, 19, 20]*
*Note on X and Y: Direct Modbus mapping for X (inputs) and Y (outputs) might be to Discrete Inputs (1xxxx) and Coils (0xxxx) respectively, or they might be mirrored/mapped through internal M or S coils/registers depending on PLC configuration or user-defined mapping. The manual [8] indicates X0-X377 map to Modbus addresses 0x3400-0x34FF (Discrete Inputs) and Y0-Y377 map to 0x3300-0x33FF (Coils). For simplicity in programming, it's common practice to map physical I/O to M coils or D registers in the PLC ladder logic, and then access these M/D areas via Modbus.*

  • User-Defined Mapping: FX3U PLCs also support user-defined Modbus mapping using special registers like D8470-D8485, allowing more flexible allocation of PLC devices to Modbus addresses.8 This is an advanced feature not typically required for basic communication.

The configuration of the FX3U as a Modbus RTU slave involves careful setup of communication parameters, typically through special D registers activated by ladder logic (M8411). The default Modbus register map provides access to a wide range of internal PLC data, with D registers mapping to Holding Registers (4xxxx) and M coils to Coils (0xxxx) being the most commonly used for data exchange with a master device like the Raspberry Pi.

V. Setting up Raspberry Pi as Modbus RTU Master

The Raspberry Pi will act as the Modbus RTU master, initiating requests to the FX3U PLC slave. This requires configuring the Raspberry Pi's serial port and using a Python library for Modbus communication.

A. Operating System and Python Environment

  • Operating System: Raspbian (now Raspberry Pi OS) is the standard OS and is well-suited for this project. Ensure it is up to date.

  • Python: Python 3 is recommended. It usually comes pre-installed on Raspberry Pi OS. Verify the installation by typing python3 --version in the terminal.

B. Serial Port Configuration on Raspberry Pi

  1. Enabling Hardware Serial Port (if using GPIO UART):
    If an RS-485 HAT connected to GPIO pins (typically GPIO14/TXD0 and GPIO15/RXD0) is used, the hardware UART needs to be enabled and configured for application use.

  • Use the raspi-config tool: sudo raspi-config.14

  • Navigate to 'Interfacing Options' (or similar, menu structure may vary slightly).

  • Select 'Serial Port'.

  • When asked "Would you like a login shell to be accessible over serial?", answer NO. This frees the serial port from being used by the Linux console.14

  • When asked "Would you like the serial port hardware to be enabled?", answer YES.14

  • Finish and reboot the Raspberry Pi.

  • The serial port will typically be available as /dev/serial0 (a symbolic link to /dev/ttyAMA0 or /dev/ttyS0 depending on Pi model and configuration).14

  1. Identifying USB RS-485 Adapter Port:
    If a USB to RS-485 adapter is used, it will appear as a USB serial device.

  • Connect the adapter to a USB port on the Raspberry Pi.

  • Check the system log for the device name: dmesg | grep tty.

  • Commonly, it will be named /dev/ttyUSB0, /dev/ttyUSB1, etc..13

  • The specific port name (e.g., /dev/ttySC0 as seen in some industrial Pi examples 21) depends on the hardware and drivers. For standard USB adapters, /dev/ttyUSBx is typical.

  1. Serial Port Permissions:
    By default, user-level scripts may not have permission to access serial ports.

  • Add your user (e.g., pi) to the dialout group: sudo usermod -a -G dialout pi.14

  • Log out and log back in, or reboot for the group change to take effect.

  • Alternatively, scripts can be run with sudo, but this is generally not recommended for security reasons.

C. Python Modbus Libraries

Several Python libraries facilitate Modbus communication.

  1. MinimalModbus:

  • An easy-to-use library primarily for Modbus RTU and ASCII.14

  • It has minimal dependencies (pySerial).22

  • Example usage involves creating an Instrument object and calling methods like read_register() or write_register().22

  1. Pymodbus:

  • A more comprehensive and actively developed library supporting Modbus RTU, ASCII, TCP, and UDP, with both synchronous and asynchronous clients/servers.25

  • This report will focus on Pymodbus due to its features and robust nature.

  • Installation: Install Pymodbus with serial support using pip:
    Bash
    sudo apt update
    sudo apt install python3-pip
    pip3 install pymodbus pyserial
    Or, as suggested for specific Pymodbus extras: pip3 install pymodbus[serial].21

D. Pymodbus Python Scripting for Modbus RTU Master

The following outlines the typical structure of a Pymodbus script for RTU master operations.e

  1. Import Necessary Class:
    Python
    from pymodbus.clied`

  2. nt import ModbusSerialClient

    21

  3. Instantiate the Modbus Client:
    The ModbusSerialClient is used for RTU communication. Key parameters include:

  • Table V-1: Pymodbus Client Setup Parameters


Parameter

Description

Example Value (Matching FX3U Config)

Reference(s)

method

Communication method. Must be 'rtu' for Modbus RTU.

'rtu'

21

port

Serial port device name (e.g., /dev/ttyUSB0, /dev/serial0, /dev/ttySC0).

'/dev/ttyUSB0'

14

baudrate

Communication speed in bits per second. Must match the slave's setting.

19200

21

stopbits

Number of stop bits (1 or 2). Must match the slave.

1

21

bytesize

Number of data bits (7 or 8). Typically 8 for Modbus RTU. Must match the slave.

8

21

parity

Parity checking ('N' for None, 'E' for Even, 'O' for Odd). Must match the slave.

'E'

21

timeout

Timeout for communication in seconds.

1 (or as needed)

21




```python
client = ModbusSerialClient(
    method='rtu',
    port='/dev/ttyUSB0',  # Or /dev/serial0, /dev/ttySC0
    baudrate=19200,       # Must match PLC configuration
    stopbits=1,
    bytesize=8,
    parity='E',           # 'E' for Even, 'N' for None, 'O' for Odd
    timeout=1             # Timeout in seconds for a response
)
```
[21, 25]

  1. Connecting to the Slave:
    Establish the connection to the serial port.

    Python
    if not client.connect():
        print("Unable to connect to Modbus slave")
        exit(1)

    21
    It's crucial to manage the serial port resource effectively. Explicitly opening and closing the connection prevents the port from being locked, which could hinder subsequent operations or other applications.

  2. Reading Data from PLC (Slave):

  • Slave ID: The PLC's Modbus slave address (e.g., 1, as configured in D8414). Pymodbus client methods typically use the parameter slave (or sometimes unit or device_id in older versions or different contexts) for this.21 For clarity and consistency with current Pymodbus, slave will be used here.

  • Reading Holding Registers (e.g., D-registers):

  • Function: client.read_holding_registers(address, count, slave=slave_id)

  • address: The 0-based Modbus register address. For D0 (Modbus 40001), the address is 0.

  • count: The number of registers to read.

  • Example:
    Python
    try:
        response = client.read_holding_registers(address=0, count=2, slave=1) # Read D0 and D1
        if not response.isError():
            print(f"D0: {response.registers}, D1: {response.registers}")
        else:
            print(f"Modbus error reading holding registers: {response}")
    except Exception as e:
        print(f"Error reading holding registers: {e}")
    23

  • Reading Coils (e.g., M-relays):

  • Function: client.read_coils(address, count, slave=slave_id)

  • Example:
    Python
    try:
        response = client.read_coils(address=0, count=1, slave=1) # Read M0
        if not response.isError():
            print(f"M0 status: {response.bits}")
        else:
            print(f"Modbus error reading coils: {response}")
    except Exception as e:
        print(f"Error reading coils: {e}")
    21

  1. Writing Data to PLC (Slave):

  • Writing Single Holding Register (e.g., to a D-register):

  • Function: client.write_register(address, value, slave=slave_id)

  • Example:
    Python
    try:
        client.write_register(address=10, value=1234, slave=1) # Write 1234 to D10 (Modbus address 10)
        print("Successfully wrote to D10")
    except Exception as e:
        print(f"Error writing holding register: {e}")

  • Writing Single Coil (e.g., to an M-relay):

  • Function: client.write_coil(address, value, slave=slave_id) where value is True or False.

  • Example:
    Python
    try:
        client.write_coil(address=100, value=True, slave=1) # Turn ON M100 (Modbus address 100)
        print("Successfully wrote to M100"
    except Exception as e:
        print(f"Error writing coil: {e}")
    21

  1. Error Handling:

  • Pymodbus methods return a response object. Check response.isError() for Modbus-specific errors (e.g., exception codes from the slave).21

  • Use Python try...except blocks to catch communication errors (e.g., ModbusException from Pymodbus, or general IOError for port issues).23

  1. Closing the Connection:
    It's essential to close the client connection to release the serial port.
    Python
    client.close()

    21
    This should ideally be in a finally block to ensure it executes even if errors occur.

  2. Full Python Script Example (Pymodbus):
    Python
    from pymodbus.client import ModbusSerialClient
    from pymodbus.exceptions import ModbusException

    # --- Configuration ---
    SERIAL_PORT = '/dev/ttyUSB0'  # Adjust as needed
    BAUD_RATE = 19200
    PARITY = 'E'
    STOP_BITS = 1
    BYTE_SIZE = 8
    PLC_SLAVE_ID = 1
    TIMEOUT_SEC = 1

    # D-register addresses (0-based for Pymodbus)
    D_REGISTER_READ_START_ADDR = 0  # Corresponds to D0 (Modbus 40001)
    D_REGISTER_READ_COUNT = 2       # Read D0, D1
    D_REGISTER_WRITE_ADDR = 10      # Corresponds to D10 (Modbus 40011)
    D_REGISTER_WRITE_VALUE = 5678

    # M-coil addresses (0-based for Pymodbus)
    M_COIL_READ_START_ADDR = 0      # Corresponds to M0 (Modbus 00001)
    M_COIL_READ_COUNT = 1
    M_COIL_WRITE_ADDR = 100         # Corresponds to M100 (Modbus 00101)
    M_COIL_WRITE_VALUE = True

    # --- Initialize Modbus Client ---
    client = ModbusSerialClient(
        method='rtu',
        port=SERIAL_PORT,
        baudrate=BAUD_RATE,
        parity=PARITY,
        stopbits=STOP_BITS,
        bytesize=BYTE_SIZE,
        timeout=TIMEOUT_SEC
    )

    try:
        print(f"Attempting to connect to Modbus slave ID {PLC_SLAVE_ID} on {SERIAL_PORT}...")
        if not client.connect():
            print(f"Failed to connect to Modbus slave on {SERIAL_PORT}")
            exit(1)
        print("Successfully connected to Modbus slave.")

        # 1. Read Holding Registers (D-registers)
        print(f"\nReading {D_REGISTER_READ_COUNT} holding registers starting from address {D_REGISTER_READ_START_ADDR}...")
        rr_response = client.read_holding_registers(address=D_REGISTER_READ_START_ADDR,
                                                    count=D_REGISTER_READ_COUNT,
                                                    slave=PLC_SLAVE_ID)
        if rr_response.isError():
            print(f"Modbus Error (Read Holding Registers): {rr_response}")
        elif rr_response.registers:
            print(f"Successfully read holding registers: {rr_response.registers}")
            for i, val in enumerate(rr_response.registers):
                print(f"D{D_REGISTER_READ_START_ADDR + i}: {val}")
        else:
            print("No data received or unexpected response (Read Holding Registers).")

        # 2. Write Single Holding Register (D-register)
        print(f"\nWriting value {D_REGISTER_WRITE_VALUE} to holding register address {D_REGISTER_WRITE_ADDR}...")
        wr_response = client.write_register(address=D_REGISTER_WRITE_ADDR,
                                            value=D_REGISTER_WRITE_VALUE,
                                            slave=PLC_SLAVE_ID)
        if wr_response.isError():
            print(f"Modbus Error (Write Single Register): {wr_response}")
        else:
            print(f"Successfully wrote to holding register {D_REGISTER_WRITE_ADDR}.")
            # Optionally, read back to verify
            # verify_response = client.read_holding_registers(D_REGISTER_WRITE_ADDR, 1, slave=PLC_SLAVE_ID)
            # if not verify_response.isError() and verify_response.registers == D_REGISTER_WRITE_VALUE:
            #     print("Write verified successfully.")
            # else:
            #     print("Write verification failed or error reading back.")


        # 3. Read Coils (M-coils)
        print(f"\nReading {M_COIL_READ_COUNT} coils starting from address {M_COIL_READ_START_ADDR}...")
        rc_response = client.read_coils(address=M_COIL_READ_START_ADDR,
                                        count=M_COIL_READ_COUNT,
                                        slave=PLC_SLAVE_ID)
        if rc_response.isError():
            print(f"Modbus Error (Read Coils): {rc_response}")
        elif rc_response.bits:
            print(f"Successfully read coils: {rc_response.bits}") # Pymodbus may return more bits
            for i in range(M_COIL_READ_COUNT):
                print(f"M{M_COIL_READ_START_ADDR + i}: {rc_response.bits[i]}")
        else:
            print("No data received or unexpected response (Read Coils).")

        # 4. Write Single Coil (M-coil)
        print(f"\nWriting value {M_COIL_WRITE_VALUE} to coil address {M_COIL_WRITE_ADDR}...")
        wc_response = client.write_coil(address=M_COIL_WRITE_ADDR,
                                        value=M_COIL_WRITE_VALUE,
                                        slave=PLC_SLAVE_ID)
        if wc_response.isError():
            print(f"Modbus Error (Write Single Coil): {wc_response}")
        else:
            print(f"Successfully wrote to coil {M_COIL_WRITE_ADDR}.")
            # Optionally, read back to verify
            # verify_coil = client.read_coils(M_COIL_WRITE_ADDR, 1, slave=PLC_SLAVE_ID)
            # if not verify_coil.isError() and verify_coil.bits == M_COIL_WRITE_VALUE:
            #     print("Coil write verified successfully.")
            # else:
            #     print("Coil write verification failed or error reading back.")

    except ModbusException as exc:
        print(f"Pymodbus library exception: {exc}")
    except Exception as e:
        print(f"General Python exception: {e}")
    finally:
        if client.is_socket_open():
            print("\nClosing Modbus client connection.")
            client.close()

The choice of Pymodbus over MinimalModbus is driven by its more extensive feature set and active development, making it suitable for projects that might evolve. Careful configuration of the Raspberry Pi's serial port, including permissions and ensuring it's not used by the system console, is a common prerequisite that can often be overlooked, leading to communication issues.

VI. Implementing and Testing Data Exchange

Once the FX3U PLC is configured as a Modbus slave and the Raspberry Pi is set up as a Modbus master with the Pymodbus library, the next step is to implement and test data exchange scenarios.

A. Example Scenarios for Data Exchange

These scenarios demonstrate common use cases for PLC-master communication.

  1. Scenario 1: Reading PLC Input Status (X registers) via Modbus

  • PLC Ladder Logic (GX Works2): Map a physical input (e.g., X0) to an internal M coil (e.g., M100) that is accessible via Modbus.
    Code snippet
    -|X0|-----(M100)-

  • Raspberry Pi Python (Pymodbus): Read the status of M100 (Modbus coil address corresponding to M100). If M100 is Modbus coil address 100 (0-based):
    Python
    # Assuming client is connected and PLC_SLAVE_ID is defined
    response = client.read_coils(address=100, count=1, slave=PLC_SLAVE_ID)
    if not response.isError() and response.bits:
        x0_status = response.bits
        print(f"Status of X0 (via M100): {x0_status}")

  1. Scenario 2: Reading Sensor Value from PLC (D register)

  • PLC Ladder Logic (GX Works2): Assume an analog input module provides a scaled sensor value into D10.

  • Raspberry Pi Python (Pymodbus): Read the value from D10 (Modbus holding register address 10).
    Python
    response = client.read_holding_registers(address=10, count=1, slave=PLC_SLAVE_ID)
    if not response.isError() and response.registers:
        sensor_value = response.registers
        print(f"Sensor value from D10: {sensor_value}")

  1. Scenario 3: Controlling PLC Output (Y registers) from Raspberry Pi

  • PLC Ladder Logic (GX Works2): An M coil (e.g., M200), controlled via Modbus, drives a physical output (e.g., Y0).
    Code snippet
    -|M200|-----(Y0)-

  • Raspberry Pi Python (Pymodbus): Write to M200 (Modbus coil address 200) to toggle Y0.
    Python
    # To turn ON Y0 (via M200)
    client.write_coil(address=200, value=True, slave=PLC_SLAVE_ID)
    print("Sent command to turn ON Y0 (via M200)")

  1. Scenario 4: Writing a Setpoint to PLC (D register)

  • PLC Ladder Logic (GX Works2): A D register (e.g., D20) is used as a temperature setpoint in a control loop.

  • Raspberry Pi Python (Pymodbus): Write a new setpoint value to D20 (Modbus holding register address 20).
    Python
    new_setpoint = 75
    client.write_register(address=20, value=new_setpoint, slave=PLC_SLAVE_ID)
    print(f"Sent new setpoint {new_setpoint} to D20")

B. Verifying Data Integrity

  • Cross-Verification: The most straightforward method is to simultaneously monitor the relevant PLC registers (D, M, X, Y) in GX Works2 using the "Online" → "Monitor" → "Device Buffer Memory Batch" tool while the Raspberry Pi script is reading or writing data.17 This allows for direct comparison of values.

  • Application-Level Checks: For critical data, implementing checksums or sequence counters at the application layer (within the data payload of Modbus registers) can provide an additional layer of integrity checking, though this is an advanced technique beyond standard Modbus CRC.

The ability to independently verify data on both the master and slave sides is critical. If the Raspberry Pi attempts to write a value, observing that value appear correctly in GX Works2's monitor confirms the write operation. Conversely, if the Pi reads a value, ensuring it matches what GX Works2 shows for that register confirms the read operation. This dual-ended observation helps isolate whether a problem lies with the master's request, the slave's response, or the PLC's internal logic.

C. Monitoring Communication

Effective monitoring is key to diagnosing issues.

  1. PLC Side:

  • RD/SD LEDs: The "RD" (Receive Data) and "SD" (Send Data) LEDs on the FX3U-485-BD provide a quick visual indication of communication activity. Both LEDs should flash during active data exchange.7

  • GX Works2 Diagnostics: Monitor special registers for communication status and errors. Key registers include D8063 (CH1 Serial Comm Error Code), M8063 (CH1 Serial Comm Error Flag), D8402 (CH1 MODBUS Comm Error Code), and M8402 (CH1 MODBUS Comm Error Flag).8 These registers provide detailed error information if communication fails.

  1. Raspberry Pi Side:

  • Script Logging: Incorporate print() statements or use Python's logging module in the Pymodbus script to display requests sent, responses received, and any errors encountered.

  • Pymodbus Logging: Pymodbus itself has built-in logging capabilities that can be enabled for more verbose output, showing low-level communication details.29
    Python
    import logging
    logging.basicConfig()
    log = logging.getLogger()
    log.setLevel(logging.DEBUG) # Or INFO, WARNING, ERROR

  • External Modbus Tools: If a graphical environment is available on the Raspberry Pi, or if another computer can be temporarily connected to the RS-485 bus, Modbus master tools like Modbus Poll or ModbusScan can be used to independently test communication with the PLC.

D. Test Plan Outline

A structured test plan ensures all aspects of the communication link are verified:

  1. Physical Layer Verification: Double-check all wiring connections (A/A, B/B, SG/GND), termination resistor settings on both the FX3U-485-BD and the RS-485 adapter. Ensure both devices are powered on.

  2. PLC Configuration Confirmation: Verify in GX Works2 that the Modbus slave parameters (Slave ID, Baud, Parity, Data Bits, Stop Bits in D8400, D8401, D8414) are correctly set and that the PLC is in RUN mode with M8411 (Modbus enable) active.

  3. Raspberry Pi Serial Port Confirmation: Ensure the correct serial port (/dev/ttyUSB0, etc.) is identified and accessible by the Python script (permissions).

  4. Basic Read Test: Execute a Python script to read a single, known holding register from the PLC (e.g., a D-register manually set to a fixed value in GX Works2). Verify the correct value is received.

  5. Multiple Register Read Test: Read a block of consecutive holding registers and verify their values.

  6. Coil Write Test: Write to an M-coil from the Raspberry Pi and observe the corresponding change in GX Works2 (and any linked Y output).

  7. Register Write Test: Write a value to a D-register from the Raspberry Pi and verify the new value in GX Works2.

  8. Data Type Test (if applicable): If using multi-register data types (e.g., 32-bit integers or floats, though not the primary focus here), test their encoding and decoding. Pymodbus includes utilities like BinaryPayloadDecoder for handling such data, which also requires attention to endianness.30 For simple 16-bit D-registers and single M-coils, this is less of a concern.

  • Table VI-1: Common Modbus Function Codes Used in Examples

Modbus Function Code (Decimal)

Description

Pymodbus Client Function

FX3U Register Type Accessed (Typical)

01

Read Coils

read_coils()

M-coils, Y-outputs (via M)

02

Read Discrete Inputs

read_discrete_inputs()

X-inputs (via M or direct map)

03

Read Holding Registers

read_holding_registers()

D-registers

04

Read Input Registers

read_input_registers()

Analog Inputs (via D or direct map)

05

Write Single Coil

write_coil()

M-coils, Y-outputs (via M)

06

Write Single Register

write_register()

D-registers

15 (0x0F)

Write Multiple Coils

write_coils() (plural)

M-coils

16 (0x10)

Write Multiple Registers

write_registers() (plural)

D-registers




*References: [1, 3, 4, 21, 25, 28]*

This structured approach to implementation and testing, combined with careful monitoring of both the PLC and Raspberry Pi, will facilitate a smooth data exchange process.

VII. Troubleshooting Common Modbus RTU Issues

Modbus RTU communication, while conceptually simple, can present challenges during initial setup. A systematic approach to troubleshooting is essential. Problems often stem from the physical layer, mismatched communication parameters, or incorrect Modbus addressing.

A. Systematic Troubleshooting Approach

  1. Check Physical Layer First: Verify wiring integrity (A to A, B to B, SG to SG), proper termination resistor placement (at both ends of the bus), and power to all devices. Loose connections or incorrect polarity are common culprits.

  2. Verify Communication Parameters: Ensure baud rate, data bits, parity, and stop bits are identically configured on both the FX3U PLC (via D8400 settings) and the Raspberry Pi (in the Pymodbus client instantiation).

  3. Check Slave ID: Confirm the Slave ID set in the FX3U (D8414) matches the ID used in the Raspberry Pi's Modbus requests.

  4. Simplify the Test: Attempt the simplest possible Modbus operation, such as reading a single, known holding register.

  5. Use Diagnostic Tools: Observe PLC LEDs (RD/SD), check PLC error registers (D8063, D8402), and enable logging in the Python script on the Raspberry Pi.

B. Common Problem Areas and Solutions

  • Incorrect Wiring or Termination:

  • Symptoms: No communication at all, intermittent errors, SD/RD LEDs on FX3U-485-BD not blinking or blinking erratically, CRC errors.

  • Solution: Meticulously check A/B polarity. Ensure all connections are secure. Confirm the Signal Ground (SG) is connected if used. Verify that termination resistors (e.g., 110Ω or 120Ω) are enabled/installed only at the two physical ends of the RS-485 bus segment. For the FX3U-485-BD, use its built-in switch; for the USB adapter, use its jumper or add an external resistor if it's an end device.1

  • Mismatched Communication Parameters:

  • Symptoms: Framing errors, parity errors, overrun errors reported by the PLC (e.g., error code 0204 in D8063/D8402 8), garbage data received, or no valid responses on the Raspberry Pi.

  • Solution: Double-check and ensure that Baud Rate, Data Bits (typically 8), Parity (e.g., Even), and Stop Bits (typically 1) are absolutely identical on the FX3U (D8400 settings) and in the Raspberry Pi's Pymodbus client configuration.8

  • Incorrect Slave ID:

  • Symptoms: The Raspberry Pi master sends requests, but receives no response (timeout). The FX3U PLC does not show RD/SD activity if the ID doesn't match. If another device on the bus has that ID, it might respond, leading to unexpected data or errors like "Slave Node Address Mismatch" (error 0213 8) if the master can detect it.

  • Solution: Verify that the slave address configured in the FX3U's D8414 register matches the slave (or unit) parameter used in the Pymodbus function calls on the Raspberry Pi.8 Ensure unique slave IDs if multiple devices are on the bus (though this project focuses on a single slave).

  • Modbus Exception Responses from PLC:

  • Symptoms: The Raspberry Pi master receives a valid Modbus frame, but it's an error response (exception) from the FX3U. Pymodbus will indicate this, often via response.isError() being true and the response object containing the exception code.

  • Common FX3U Supported Exception Codes 8:

  • 01H: Illegal Function: The requested Modbus function code (e.g., read coils, write register) is not supported by the PLC for the addressed item, or the function code itself is invalid.

  • 02H: Illegal Data Address: The register address specified in the master's request is invalid, does not exist in the PLC's Modbus map, or the combination of starting address and quantity of items exceeds the accessible range.

  • 03H: Illegal Data Value: A data value in a write request is invalid for the target register (e.g., out of range).

  • 04H: Slave Device Failure: An unrecoverable error occurred within the PLC while processing the request. This is less common and may indicate a more serious PLC issue.

  • Solution: Carefully check the Modbus register addresses being accessed (ensure they are within the PLC's mapped ranges for D-registers, M-coils, etc.). Verify that the Modbus function codes used are appropriate for the target register type (e.g., don't try to write to a read-only Input Register). Consult the FX3U Modbus mapping documentation.8

  • Timeout Errors on Raspberry Pi:

  • Symptoms: The Python script hangs for the duration of the timeout period and then reports a timeout error (e.g., Pymodbus ModbusIOException or similar).

  • Causes: This is a generic error indicating no response was received from the slave. Potential causes include:

  • Incorrect wiring or termination.

  • Mismatched communication parameters.

  • Incorrect Slave ID.

  • PLC not powered on or not in RUN mode.

  • PLC Modbus communication not enabled (e.g., M8411 for CH1 is OFF).

  • Error in PLC communication parameter settings (D8400, D8401, etc. – check D8402 for error codes like 0202 "Invalid Parameter Setup" 8).

  • Physical damage to the communication board or adapter.

  • Excessive noise on the communication line.

  • Solution: Systematically check all the points listed above. Increase the timeout value in the Pymodbus client temporarily for diagnostic purposes. Crucially, check the FX3U's diagnostic registers (M8063, D8063, M8402, D8402) and LED status.8 A timeout on the master often requires looking at the slave's diagnostics to understand why it didn't respond.

  • CRC/LRC Errors:

  • Symptoms: Either the master or slave reports a Cyclic Redundancy Check (CRC for RTU) error (PLC error code 0205 in D8063/D8402 8).

  • Causes: Often due to noise corrupting bits during transmission, incorrect serial parameters (especially data bits or stop bits affecting frame interpretation), or, very rarely, a software bug in CRC calculation (highly unlikely with established libraries like Pymodbus).

  • Solution: Improve wiring (shielding, proper grounding). Confirm all serial communication parameters. Ensure the correct Modbus mode (RTU vs. ASCII) is used.

  • FX3U Specific Communication Errors 8: The FX3U provides detailed diagnostic information through special M relays and D registers. For Channel 1:

  • M8063 / D8063: General Serial Communication Error Flag / Error Code for CH1.

  • M8402 / D8402: CH1 MODBUS Communication Error Flag / Error Code. These are critical for Modbus-specific issues.

  • M8403: CH1 MODBUS Communication Error Latch Flag (retains error status until reset).

  • Key Error Codes in D8402 (or D8063 for general serial issues):

  • 0201: Invalid Hardware Setup (e.g., FX3U-485-BD not detected correctly).

  • 0202: Invalid Parameter Setup (e.g., incorrect values in D8400, D8401 for Modbus configuration).

  • 0203: Channel Double Use (e.g., trying to use the same serial channel for Modbus and another protocol like RS/RS2 instructions simultaneously).

  • 0204: Bit-level Error (Parity, Overrun, or Framing error).

  • 0205: CRC/LRC Error.

  • 0206: Bus Character Overrun.

  • 0207: Data Length Mismatch.

  • 0209: Unsupported Command Code Error.

  • 0210: Invalid Device Address (Modbus register address out of range).

  • 0211: Communication Timeout (Master perspective, but can be logged by slave if it's acting as a master in some scenarios, or related to inter-message timing).

  • 0212: Exception Response Error (Slave sent an exception).

C. Interpreting PLC LEDs (RD/SD on FX3U-485-BD)

The RD (Receive Data) and SD (Send Data) LEDs on the FX3U-485-BD are invaluable first-line diagnostic tools 7:

  • Both RD and SD Flashing: Indicates normal communication; data is being sent and received.

  • RD Flashing, SD Off: The PLC is receiving data (requests from the Raspberry Pi) but not sending responses. This could point to an incorrect slave ID, the PLC not being in RUN mode, M8411 being off, or an internal PLC error preventing a response.

  • SD Flashing, RD Off: The PLC is attempting to send data but not receiving requests. This is less common in a master-slave setup where the PLC is the slave, unless it's erroneously trying to initiate communication.

  • Both RD and SD Off: No communication activity on the bus connected to the PLC. Check wiring, power, and master activity.

The rich diagnostic capabilities of the FX3U, through its special relays and data registers, are a significant aid in troubleshooting. When the Raspberry Pi master reports an error (like a timeout), the first step should often be to check these PLC-side diagnostics to understand the slave's perspective on the communication attempt.

  • Table VII-1: Common Modbus RTU Troubleshooting Scenarios


Symptom (Master/Pi)

Potential Cause(s)

Diagnostic Steps (Pi & PLC)

Key PLC Diagnostics (CH1)

Timeout on Raspberry Pi

Incorrect Slave ID; Wiring/Termination Fault; Mismatched Comm Parameters; PLC Off/Stop; M8411 Off; PLC Param Error

Verify Slave ID (Pi vs D8414); Check wiring & termination; Match Baud/Parity/Data/Stop; Check PLC RUN status & M8411; Check D8400/D8401 values in PLC.

M8063, D8063 (Error Code e.g., 0211); M8402, D8402 (Error Code e.g., 0201, 0202); RD/SD LEDs.

PLC Responds with Exception

Illegal Function Code Used; Illegal Data Address (Register out of range); Illegal Data Value Written

Review Modbus function used in Pi script; Verify register addresses against PLC map; Check data values being written.

M8402, D8402 (Error Code 0212, and the exception code itself will be in the response data); RD/SD LEDs will flash.

Framing/Parity/CRC Errors

Mismatched Comm Parameters (Data bits, Stop bits, Parity); Electrical Noise; Incorrect Termination; Faulty Cable

Strictly match ALL serial parameters; Improve shielding/grounding; Check termination resistors; Try a different cable.

M8063, D8063 (Error Codes 0204, 0205); RD/SD LEDs may be erratic.

No RD/SD LED activity on PLC

Wiring issue (no signal reaching PLC); Pi not sending requests; Incorrect serial port on Pi; PLC power issue.

Check wiring from Pi to PLC; Verify Pi script is running and sending; Confirm Pi serial port config; Check PLC power.

M8063, D8063; M8402, D8402. LEDs will be OFF.

PLC Error D8402 = 0202

Invalid Modbus parameter settings in D8400/D8401.

Review values written to D8400 and D8401 against FX3U Modbus manual requirements. Ensure M8411 is cycled or PLC power cycled after changes.

M8402 will be ON. D8400, D8401.

A layered troubleshooting approach, starting from the physical connections and moving systematically through parameter settings and protocol details, is generally the most effective way to resolve Modbus RTU communication problems.

VIII. Conclusion and Advanced Considerations

Successfully establishing Modbus RTU communication between a Mitsubishi FX3U PLC and a Raspberry Pi opens up numerous possibilities for enhanced industrial automation, data logging, and system integration. This project, while focused on a specific hardware combination, demonstrates fundamental principles applicable to a wide range of industrial communication tasks.

A. Summary of Key Steps

The integration process involves several critical stages:

  1. Hardware Selection and Wiring: Choosing the appropriate RS-485 interface for the FX3U (FX3U-485-BD) and the Raspberry Pi (USB to RS-485 adapter), followed by meticulous wiring of the A, B, and Signal Ground lines, including correct bus termination.

  2. PLC Configuration: Using GX Works2 to set the FX3U's serial communication parameters (baud rate, parity, data bits, stop bits) and Modbus-specific settings (slave address, protocol mode) via special data registers (D8400, D8401, D8414 for CH1) and enabling Modbus communication (e.g., M8411).

  3. Raspberry Pi Setup: Configuring the Raspberry Pi's operating system for serial communication, installing Python and the Pymodbus library, and ensuring correct serial port identification and permissions.

  4. Python Scripting: Developing a Pymodbus master script on the Raspberry Pi to connect to the PLC, read desired registers (coils, holding registers), write data if necessary, and handle potential communication errors.

  5. Testing and Verification: Implementing test scenarios, monitoring communication on both the PLC (LEDs, diagnostic registers) and Raspberry Pi (script logs), and cross-verifying data with GX Works2.

B. Best Practices for Robust Communication

To ensure reliable and long-term Modbus RTU communication:

  • Proper Grounding and Shielding: Use shielded twisted-pair cables and implement correct grounding practices to minimize electrical noise, a common source of communication errors in industrial environments.1

  • Correct Termination: Always use termination resistors (typically 110-120Ω) at both physical ends of the RS-485 bus to prevent signal reflections.1

  • Matched Communication Parameters: Ensure baud rate, parity, data bits, and stop bits are identically configured on all devices on the Modbus network.

  • Comprehensive Error Handling: Implement robust error detection and handling in the Raspberry Pi's Python script (checking Pymodbus responses, using try-except blocks) and regularly monitor PLC diagnostic flags and error codes.

  • Keep PLC Diagnostics Accessible: Familiarize oneself with the FX3U's Modbus-related diagnostic registers (M8063, D8063, M8402, D8402, etc.) as they provide invaluable insight during troubleshooting.8

C. Potential Next Steps or Expansions for the Project

This foundational connection can be extended in several ways:

  • Human-Machine Interface (HMI): Develop a graphical user interface on the Raspberry Pi (e.g., using Kivy, PyQt, or web-based frameworks) to display PLC data and allow operator input.

  • Data Logging and Analysis: Log PLC operational data read by the Raspberry Pi to a local database (e.g., SQLite, PostgreSQL) or a time-series database (e.g., InfluxDB) for historical analysis, trend monitoring, and predictive maintenance insights.

  • Cloud Integration (IIoT): Forward PLC data from the Raspberry Pi to cloud platforms (e.g., AWS IoT, Azure IoT Hub, Ubidots 17) for remote monitoring, dashboards, and advanced analytics, effectively bridging the operational technology (OT) with information technology (IT).

  • Advanced Control Logic: Implement more complex supervisory control algorithms on the Raspberry Pi that interact with the PLC based on real-time data.

  • Exploring Modbus TCP/IP: If the FX3U is later upgraded with an Ethernet module or if a Modbus RTU to Modbus TCP/IP gateway is introduced, the Raspberry Pi can be adapted to use Modbus TCP/IP, which offers advantages in terms of network infrastructure and speed.

  • Utilizing FX3U User-Defined Modbus Mapping: For more complex or optimized data layouts, explore the FX3U's capability to create custom Modbus register maps using special D registers (D8470-D8485).8

This project highlights the enduring relevance of serial communication protocols like Modbus RTU in the industrial sector. Even as newer technologies emerge, the ability to interface with existing, reliable PLCs like the Mitsubishi FX3U using cost-effective platforms such as the Raspberry Pi remains a valuable skill for automation engineers. This integration serves as a practical entry point into the broader field of the Industrial Internet of Things (IIoT), enabling legacy equipment to participate in modern data-driven manufacturing and control strategies.

D. Final Reference to Key Manuals

For authoritative and comprehensive details, the following Mitsubishi Electric manuals are indispensable:

  • "FX Series User's Manual - Data Communication Edition" (Manual No. JY997D16901, Model Code: 09R715): Covers general serial communication aspects for the FX series, including non-protocol communication which forms the basis for some Modbus implementations.7

  • "FX3S/FX3G/FX3GC/FX3U/FX3UC Series User's Manual - MODBUS Serial Communication Edition" (Manual No. JY997D26201): Specifically details Modbus communication setup, parameters, register mapping, and troubleshooting for the FX3U and related PLCs.8

  • FX3U Series User's Manual - Hardware Edition (e.g., JY997D16501): Provides details on installing expansion boards like the FX3U-485-BD.7

Consulting these official documents is highly recommended for any specific configurations or advanced troubleshooting beyond the scope of this report.

Works cited

  1. Modbus RTU: A Comprehensive Guide to Understanding and Implementing the Protocol, accessed May 10, 2025, https://www.wevolver.com/article/modbus-rtu-a-comprehensive-guide-to-understanding-and-implementing-the-protocol

  2. An Introduction to the Modbus Communication Protocol - SolisPLC, accessed May 10, 2025, https://www.solisplc.com/tutorials/modbus

  3. Modbus RTU Protocol - Kollmorgen Webhelp, accessed May 10, 2025, https://webhelp.kollmorgen.com/space/Content/Space%20Content/MODBUS%20Protocol.htm?TocPath=Modbus%20RTU%20Protocol%7C_____0

  4. Modbus Protocol Overview with Examples - Fernhill SCADA, accessed May 10, 2025, https://www.fernhillsoftware.com/help/drivers/modbus/modbus-protocol.html

  5. Serial communication — MinimalModbus 2.1.1 documentation, accessed May 10, 2025, https://minimalmodbus.readthedocs.io/en/stable/serialcommunication.html

  6. Introduction to Modbus Serial Communication | Precision Digital, accessed May 10, 2025, https://www.predig.com/whitepaper/introduction-to-modbus-serial-communication

  7. FX3U-485-BD INSTALLATION MANUAL - Mitsubishi Electric, accessed May 10, 2025, https://www.mitsubishielectric.com/dl/fa/document/manual/plc_fx/jy997d13001(e)/jy997d13001(e)h.pdf

  8. www.mitsubishielectric.com, accessed May 10, 2025, https://www.mitsubishielectric.com/dl/fa/document/manual/plc_fx/jy997d26201/jy997d26201g.pdf

  9. FX3U-MODBUS - Manual | PDF - Scribd, accessed May 10, 2025, https://www.scribd.com/document/608446822/FX3U-MODBUS-Manual

  10. FX3U Modbus communication - Mitsubishi - MrPLC.com, accessed May 10, 2025, https://mrplc.com/topic/26542-fx3u-modbus-communication/

  11. FX3U-Inverter Modbus Commuinication - Mitsubishi - MrPLC.com, accessed May 10, 2025, https://mrplc.com/forums/topic/29882-fx3u-inverter-modbus-commuinication/

  12. FX3U Modbus RTU with FX-485-BD - Mitsubishi - MrPLC.com, accessed May 10, 2025, https://mrplc.com/forums/topic/37921-fx3u-modbus-rtu-with-fx-485-bd/

  13. innomaker Industrial USB 2.0 to RS485 Converter Adapter Based on FTDI FT230 Chip Built-in ESD Protection Support Windows 11,10,8 XP Mac Os and Linux Support Raspberry Pi ARM Board and All Computers - Amazon.com, accessed May 10, 2025, https://www.amazon.com/Industrial-Converter-Adapter-Protection-Support/dp/B0B2QSW67D

  14. How to Use Modbus With Raspberry Pi : 6 Steps (with Pictures) - Instructables, accessed May 10, 2025, https://www.instructables.com/How-to-Use-Modbus-With-Raspberry-Pi/

  15. RS485 Interfaces - RobotShop, accessed May 10, 2025, https://www.robotshop.com/collections/rs485-serial

  16. USB to RS485 adapters (HIGH SPEED) — Connective Peripherals - Global Store, accessed May 10, 2025, https://connectiveperipherals.com/products/usb-to-rs485-adapters-high-speed

  17. Mitsubishi PLC as Modbus TCP Server: A Quick Tutorial - Ubidots, accessed May 10, 2025, https://ubidots.com/blog/mitsubishi-plc-as-modbus-tcp-server/

  18. Where do I find the device address in GX developer? : r/PLC - Reddit, accessed May 10, 2025, https://www.reddit.com/r/PLC/comments/1csye3a/where_do_i_find_the_device_address_in_gx_developer/

  19. Mitsubishi D Registers, with a twist? | PLCS.net - Interactive Q & A, accessed May 10, 2025, https://www.plctalk.net/threads/mitsubishi-d-registers-with-a-twist.105991/

  20. Any question about Modbus FX3U block size & PLC mapping - Mitsubishi - MrPLC.com, accessed May 10, 2025, https://mrplc.com/forums/topic/35462-any-question-about-modbus-fx3u-block-size-plc-mapping/

  21. Part 3. Modbus and Raspberry PI PLC - Industrial Shields, accessed May 10, 2025, https://www.industrialshields.com/blog/raspberry-pi-for-industry-26/introduction-to-modbus-and-raspberry-plc-part-3-588

  22. minimalmodbus 0.5 - PyPI, accessed May 10, 2025, https://pypi.org/project/minimalmodbus/0.5/

  23. Modbus RTU Master Implementation in Python - Read Data from Modbus RTU Slave, accessed May 10, 2025, https://www.youtube.com/watch?v=k0lMSC02SMY&pp=0gcJCdgAo7VqN5tD

  24. Easy Modbus Using A Raspberry Pi - YouTube, accessed May 10, 2025, https://www.youtube.com/watch?v=FUfxETGIyUo

  25. Client — PyModbus 4.0.0dev4 documentation, accessed May 10, 2025, https://pymodbus.readthedocs.io/en/latest/source/client.html

  26. pymodbus-dev/pymodbus: A full modbus protocol written in python - GitHub, accessed May 10, 2025, https://github.com/pymodbus-dev/pymodbus

  27. Raspberry Pi 3 B + Tutorial Series | Modbus RTU Protocol - YouTube, accessed May 10, 2025, https://www.youtube.com/watch?v=ZlHqEOmvW6M

  28. Examples — PyModbus 4.0.0dev4 documentation, accessed May 10, 2025, https://pymodbus.readthedocs.io/en/dev/source/examples.html

  29. How to use PyModbus with Raspberry Pi PLC - Industrial Shields, accessed May 10, 2025, https://www.industrialshields.com/blog/raspberry-pi-for-industry-26/how-to-use-pymodbus-with-raspberry-pi-plc-558

  30. Is there any way to connect using python a PLC FX3U using ENET ADP and read registers(D)? - Stack Overflow, accessed May 10, 2025, https://stackoverflow.com/questions/61788681/is-there-any-way-to-connect-using-python-a-plc-fx3u-using-enet-adp-and-read-regi

  31. FX3G-485-BD INSTALLATION MANUAL - Suport, accessed May 10, 2025, https://suport.siriustrading.ro/02.DocArh/01.PLC/02.Compacte/04.MELSEC%20FX3S,FX3U,FX3G/05.Module%20de%20interfata/FX3G-485-BD%20-%20Installation%20Manual%20JY997D32201-H%20(09.16).pdf

  32. FX3U-232-BD INSTALLATION MANUAL - Suport, accessed May 10, 2025, https://suport.siriustrading.ro/02.DocArh/01.PLC/02.Compacte/04.MELSEC%20FX3S,FX3U,FX3G/05.Module%20de%20interfata/FX3U-232-BD%20-%20Installation%20Manual%20JY997D12901-G%20(06.17).pdf

  33. suport.siriustrading.ro, accessed May 10, 2025, https://suport.siriustrading.ro/01.DocAct/1.%20Automate%20programabile%20PLC/1.2.%20Compacte%20MELSEC%20FX/1.2.5.%20Module%20de%20interfata/FX3%20-%20User's%20Manual%20(Data%20Communication)%20JY997D16901-R%20(08.20).pdf

  34. FX3U SERIES PROGRAMMABLE CONTROLLERS HARDWARE MANUAL - E-MotionSupply, accessed May 10, 2025, http://www.e-motionsupply.com/v/MITSUBISHI/PLC%20Controller/FX3U%20Series%20programmable%20controllers%20Hardware%20Manual.pdf

  35. www.mitsubishielectric.com, accessed May 10, 2025, https://www.mitsubishielectric.com/dl/fa/document/manual/plc_fx/jy997d72001/jy997d72001a(fx_modbus).pdf