Connecting Schneider M340 / M221 / M241 to the cloud via Modbus TCP

This guide covers the complete setup process for connecting Schneider Modicon-series PLCs to the Eziwan platform: M340 (BMX P34), M221, M241, M251, and M262. Each series has its own specific configuration requirements.


Schneider Compatibility Chart

M340 Series (BMX P34)

CPUFirmware%MW accessibleETH ModuleCPU Unit ID
BMX P34 1000≥ 2.300..1023 (1,024 words)BMX NOE or ETH module255
BMX P34 2010≥ 2.300..9999 (10,000 words)Integrated ETH255
BMX P34 2020≥ 2.300..9999Integrated ETH255
BMX P34 2030≥ 2.300..9999Integrated ETH255

M221 Series (TM221)

CPUFirmware% of MWs accessibleUnit ID
TM221CE16R≥ 1.00..99991
TM221C16T≥ 1.00..99991
TM221ME16R (Ethernet)≥ 1.00..99991
TM221M16R (+ ETH module)≥ 1.00..99991

M241 Series (TM241)

CPUFirmware%MW accessibleUnit ID
TM241CE40R≥ 1.00..99991
TM241CE40T≥ 1.00..99991
TM241C40R (+ TMBM module)≥ 1.00..99991

M251 and M262 Series

CPUFirmwareProtocolsUnit ID
TM251MESE≥ 1.0Modbus TCP, EtherNet/IP1
TM262M15MESS8T≥ 1.0Modbus TCP, EtherNet/IP, native MQTT1
tip

The M262 has a native MQTT client—Eziwan can directly receive data published by the M262 without going through Modbus polling. Contact Eziwan support for MQTT configuration.


EcoStruxure Configuration — M340 Series

Enabling the Modbus TCP Server on the BMX P34

In EcoStruxure Control Expert (Unity Pro):

  1. Structure View → double-click on the BMX P34 xxxx CPU
  2. "Configuration" tab → click on the Ethernet interface (ETH 1 or NOE module)
  3. "Services" tab → check "Modbus Server"
  4. Port: 502 (do not change unless necessary)
  5. "Ethernet Addresses" tab → enter the static IP address

Advanced Settings (recent firmware versions):

  • Inactive connection timeout: increase to 120s (default 30s) for long-running connections
  • IP filtering (firmware ≥ 2.60): restrict access to the Eziwan gateway’s IP address

BMX NOE 0100 / BMX NOE 0110 Module

For M340 models with an external Ethernet module:

ParameterBMX NOE 0100BMX NOE 0110
Data Rate10/100 Mbit10/100 Mbit
I/O ScannerNoYes
Modbus ServerYesYes
ConfigurationVia CPU PropertiesVia Module Properties
Unit IDConfigurableConfigurable
warning

On the BMX NOE 0110, the Modbus TCP server may have a Unit ID other than 255. Check the module's configuration in EcoStruxure and use the Unit ID configured in Eziwan.


EcoStruxure Configuration — M221 / M241 Series

SoMachine / EcoStruxure Machine Expert

Modbus TCP configuration on the M221 and M241 is performed in EcoStruxure Machine Expert (formerly SoMachine):

  1. Configuration"Ethernet" tab
  2. Enter the static IP address and subnet mask
  3. Configuration"Modbus TCP Slave" tab (or "Modbus TCP Servant")
  4. Check "Enabled"
  5. Port: 502
  6. Unit ID: 1 (default on M221/M241 — different from the M340!)

Key Difference Between the M340 and the M221/M241

ParameterM340 (BMX P34)M221 / M241 (TM2xx)
Default Unit ID2551
Configuration softwareEcoStruxure Control ExpertEcoStruxure Machine Expert
Max %MW10,000 (CPU >= 2010)9,999
Modbus serverEnabled in CPU propertiesEnabled in Ethernet configuration
warning

This is the most common pitfall: if you configure Eziwan with Unit ID 255 on an M221 or M241, the connection will fail with a Modbus exception or a timeout. Use Unit ID 1 on the M221/M241.


Modbus Register Addressing by Range

M340 — %MW Mapping ↔ Modbus Register

Variable EcoStruxure │ Adresse Modbus │ Type Modbus
─────────────────────────────────────────────────────
%MW0 │ 0 │ Holding Register (FC=03)
%MW100 │ 100 │ Holding Register
%MWn │ n │ (direct, 0-based)
%QW0.0 │ 0 │ Input Register (FC=04) *
%IW0.0 │ 0 │ Discrete Input (FC=02) *
%Q0.0 to %Q0.7 │ bits 0 through 7 │ Coil (FC=01)

*The exact mapping of analog inputs and outputs depends on the hardware configuration.

M221 / M241 — %MW Mapping ↔ Modbus Register

The mapping is the same as for the M340: %MWn corresponds to the Modbus address n.


Advanced Data Type Management

REAL Variables (32-bit floating-point) in 2 Registers

A variable named REAL in Unity Pro / EcoStruxure occupies two consecutive %MW units in IEEE 754:

REAL variable "Temperature" stored at %MW100:
%MW100: most significant word (MSW, bytes A and B)
%MW101: low-weight word (LSW, bytes C and D)
Order: ABCD (big-endian by default on M340/M221/M241)

Eziwan type to configure: float32_abcd

If the values are incorrect (constant error factor): Try float32_cdab (little-endian per register). Some Unity Pro projects use the DWORD_TO_REAL function with a different order.

DINT / UDINT variables (32-bit integer) across 2 registers

DINT variable "Counter" at %MW200:
%MW200 : partie haute (MSW)
%MW201 : partie basse (LSW)
Type Eziwan : int32_abcd

Boolean Compression in a %MW

To minimize the number of Modbus requests, group the Boolean states into a single memory word:

(* EcoStruxure Control Expert — Programme *)
(* Group of 16 states in %MW300 *)

%MW300 := 0; (* Reset *)
IF %Q0.0 THEN %MW300 := %MW300 OR 16#0001; END_IF; (* Pump 1 *)
IF %Q0.1 THEN %MW300 := %MW300 OR 16#0002; END_IF; (* Pump 2 *)
IF %I0.5 THEN %MW300 := %MW300 OR 16#0004; END_IF; (* P1 error *)
IF %I0.6 THEN %MW300 := %MW300 OR 16#0008; END_IF; (* P2 error *)
IF %M10 THEN %MW300 := %MW300 OR 16#0010; END_IF; (* Alarme *)

With this technique, 16 Booleans can be read with a single Modbus query (FC=03, 1 register).


To maximize query efficiency (automatic grouping by Eziwan):

Range %MW0 to %MW9 : Operator setpoints (editable)
Range %MW10 to %MW49 : Simple analog measurements (int16 ×10)
Range %MW50 to %MW99: Dual analog measurements (REAL in 2 registers)
Range %MW100 to %MW149: 16-bit counters
Range %MW150 to %MW199: 32-bit counters (DINT, 2 registers each)
Range %MW200 to %MW249: Machine states (bitfields)
Range %MW250 to %MW299: Error codes
Range %MW300 to %MW349: Manufacturer settings (read-only for customers)

Connection Test

Testing from Python

from pymodbus.client import ModbusTcpClient
import struct

def tester_connexion_schneider(ip: str, unit_id: int = 255):
"""
Test de connexion Modbus TCP.
unit_id : 255 pour M340, 1 pour M221/M241
"""
client = ModbusTcpClient(ip, port=502, timeout=3)

if not client.connect():
print(f"✗ Connexion TCP impossible à {ip}:502")
return

print(f"✓ Connexion TCP établie → {ip}:502 (Unit ID {unit_id})")

# Reading Test: %MW100 to %MW109
result = client.read_holding_registers(
address=100, count=10, slave=unit_id
)

if not result.isError():
print(f"✓ Modbus FC=03 OK — %MW100 à %MW109 : {result.registers}")

# Decoding float32 if %MW100+101 contains a REAL (test)
if len(result.registers) >= 2:
raw = struct.pack(">HH", result.registers[0], result.registers[1])
float_val = struct.unpack(">f", raw)[0]
if abs(float_val) < 1e6: # Valeur plausible ?
print(f" → Si %MW100-%MW101 est un REAL : {float_val:.2f}")
else:
exc = getattr(result, 'exception_code', '?')
print(f"✗ Erreur Modbus FC=03 — exception code: {exc}")

# Diagnostics selon le code
messages = {
1: "Unsupported FC → Modbus server not enabled",
2: "Adresse invalide → plage %MW dépassée (M340 1000: max 1024)",
3: "Valeur invalide → count trop grand",
4: "Erreur serveur → serveur non initialisé, CPU en STOP",
6: "Serveur occupé → trop de connexions simultanées",
}
if exc in messages:
print(f" Diagnostic : {messages[exc]}")

client.close()

# Tests
tester_connexion_schneider("192.168.1.20", unit_id=255) # M340
tester_connexion_schneider("192.168.1.30", unit_id=1) # M221/M241

Advanced Troubleshooting

SymptomProbable CauseSolution
TCP connection refusedModbus server not enabledCheck "Modbus Server" in EcoStruxure
TCP connection refusedNetwork misconfiguredPing the PLC from a PC on the same network
Exception 02 (invalid address)BMX P34 1000 — address > 1023Shift the supervision zone between 0 and 1023
Exception 06 (server busy)Too many clients connectedClose unused local SCADA connections
Incorrect Unit IDM221/M241 with Unit ID 255Change to Unit ID 1 in the Eziwan configuration
All values set to 0Variables not assigned in the programVerify that %MW100+ are powered by the program
Incorrect REALCDAB byte order instead of ABCDTry float32_cdab in Eziwan
Disconnects every 30 secondsDefault M340 idle timeoutIncrease "idle timeout" to 120s in EcoStruxure
NOE module not respondingModule IP different from CPUUse the NOE module’s IP, not the CPU’s
%IW and %QW registers inaccessibleFC=04 or FC=01 required, not FC=03Use the appropriate FCs or copy to %MW

👉 Additional Resources

Frequently Asked Questions

Which Schneider PLCs are compatible?

The entire Modicon product line that communicates via Modbus TCP: M221, M241, M251, M340, M580, as well as the Premium and Quantum models equipped with Ethernet couplers. The serial-based series (Twido, TSX) connect via the gateway’s RS-485 port.

Should the PLC program be modified?

Not for reading data: the gateway queries the existing %MW words in Modbus TCP. Only when writing setpoints, if necessary, may it be necessary to reserve a dedicated range of words in the program.

Which network port should be accessible?

Modbus TCP port 502 is used only on the local network between the gateway and the PLC. Nothing is exposed to the Internet: the gateway establishes an outbound VPN tunnel to the cloud.

How do you diagnose a connection that isn't working?

Check the following in this order: ping the PLC from the gateway, ensure port 502 is open (no local firewall), verify the Unit ID is correct, and ensure the %MW addressing is aligned (offset 0 vs. 1 depending on the tools). The Eziwan console displays Modbus frames and error codes in real time.