> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreflux.org/llms.txt
> Use this file to discover all available pages before exploring further.

# FINS Route (Omron)

> Connect to Omron PLCs using FINS protocol with support for multiple memory areas and TCP/UDP transport

## FINS Overview

The `FINS` route enables communication with Omron PLCs (CJ, CS, CP, and NJ/NX series) using the FINS (Factory Interface Network Service) protocol. It supports both TCP and UDP transport, multiple memory areas, and bit-level access.

> [!TIP]
>
> FINS is Omron's native protocol providing fast, efficient access to PLC memory. For newer NJ/NX series, consider OPC UA as an alternative.

## Basic Syntax

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronPLC WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
        WITH LOCAL_NODE 0
        WITH REMOTE_NODE 0
    ADD MAPPING ProcessData
        WITH EVERY 500 MILLISECONDS
        ADD TAG Temperature
            WITH ADDRESS "100"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/temperature"
```

***

## Connection Configuration

### FINS\_CONFIG Parameters

**IP** `string` *required*

Target Omron device IP address.

**PORT** `integer`

FINS protocol port. Default: 9600.

**PROTOCOL** `string`

Protocol type: `TCP` or `UDP`. Default: TCP.

**LOCAL\_NODE** `integer`

Local node address (0-255). Default: 0.

**REMOTE\_NODE** `integer`

Remote node address - target PLC (0-255). Default: 0.

**TIMEOUT** `integer`

Connection timeout in seconds. Default: 2.

**RETRIES** `integer`

Number of retries for FINS communication. Default: 5.

**POLLING** `integer`

Polling interval in milliseconds. Default: 200.

### Connection Examples

**TCP Connection**

Standard TCP connection (recommended):

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD FINS_CONFIG
    WITH IP "192.168.1.100"
    WITH PORT 9600
    WITH PROTOCOL "TCP"
    WITH LOCAL_NODE 0
    WITH REMOTE_NODE 0
    WITH TIMEOUT 2
    WITH RETRIES 5
```

> [!NOTE]
>
> TCP transport for FINS is currently in development. Use UDP for production deployments.

**UDP Connection**

UDP for lower latency:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD FINS_CONFIG
    WITH IP "192.168.1.100"
    WITH PORT 9600
    WITH PROTOCOL "UDP"
    WITH LOCAL_NODE 1
    WITH REMOTE_NODE 0
    WITH TIMEOUT 2
```

> [!NOTE]
>
> UDP requires proper node addressing and may have firewall considerations.

***

## Memory Areas

Omron PLCs organize data in different memory areas:

| Memory Type | Code | Description | Access |
| - | - | - | - |
| `CIO` | 0 | Core I/O and work area | Read/Write |
| `WR` | 1 | Work area | Read/Write |
| `HR` | 2 | Holding area (retentive) | Read/Write |
| `AR` | 3 | Auxiliary area | Read-only |
| `DM` | 4 | Data Memory | Read/Write |
| `CNT` | 5 | Counter values | Read/Write |
| `TIM` | 6 | Timer values | Read/Write |
| `EM` | 7 | Extended Memory | Read/Write |

> [!NOTE]
>
> DM (Data Memory) is the most commonly used area for user data. CIO is typically used for I/O and internal relays.

***

## Data Types

| Data Type | Description | Size |
| - | - | - |
| `BOOL` | Boolean (single bit) | 1 bit |
| `BYTE` | Unsigned 8-bit | 8 bits |
| `SINT` | Signed 8-bit integer | 8 bits |
| `USINT` | Unsigned 8-bit integer | 8 bits |
| `INT` | Signed 16-bit integer | 16 bits |
| `UINT` / `WORD` | Unsigned 16-bit integer | 16 bits |
| `DINT` | Signed 32-bit integer | 32 bits |
| `UDINT` / `DWORD` | Unsigned 32-bit integer | 32 bits |
| `LINT` | Signed 64-bit integer | 64 bits |
| `ULINT` / `LWORD` | Unsigned 64-bit integer | 64 bits |
| `REAL` / `FLOAT` | 32-bit floating point | 32 bits |
| `LREAL` / `DOUBLE` | 64-bit floating point | 64 bits |
| `CHAR` | Single character | 8 bits |
| `WCHAR` | Wide character | 16 bits |
| `TIME` | Time duration | 32 bits |
| `DATE` | Date value | 16 bits |
| `TOD` | Time of day | 32 bits |
| `ASCII` | ASCII string | 8 bits |
| `STRING` | String value; sized with `LENGTH` | Variable |

### String sizing

For `STRING` tags, `WITH LENGTH` is the string **payload** size in bytes and defaults to **256**. `STRING_SIZE` is accepted as an alias for the same field. The FINS route reserves **two additional header bytes**, so the protocol buffer is `LENGTH + 2` bytes.

Read a product label stored as a STRING in DM memory:

```lot wrap focus={14} theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronStrings WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
        WITH LOCAL_NODE 176
        WITH REMOTE_NODE 201
    ADD MAPPING Labels
        WITH EVERY 1 SECOND
        ADD TAG ProductLabel
            WITH ADDRESS "500"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "STRING"
            WITH LENGTH 256
            WITH SOURCE_TOPIC "production/label"
```

***

## TAG Configuration

### Complete TAG Example

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD TAG ProcessTemperature
    WITH ADDRESS "100"
    WITH BIT_ADDRESS 0
    WITH DATA_TYPE "REAL"
    WITH MEMORY_TYPE "DM"
    WITH SOURCE_TOPIC "plc/process/temperature"
    WITH DESTINATION_TOPIC "plc/process/temperature/write"
    WITH WRITABLE "true"
    WITH SCALING 0.1
    WITH OFFSET 0
    WITH UNIT "°C"
    WITH DECIMAL_PLACES 2
    WITH MIN_VALUE -50
    WITH MAX_VALUE 500
    WITH DEADBAND 0.5
    WITH PUBLISH_MODE "JSON"
    WITH DESCRIPTION "Main process temperature sensor"
```

### TAG Parameters

> **Address Configuration**
>
> **ADDRESS** `string` *required*
>
> Word address in PLC memory (e.g., 100, 200, 500).
>
> **BIT\_ADDRESS** `integer`
>
> Bit address for bit-specific data types (0-15). Used for BOOL values within a word.
>
> **MEMORY\_TYPE** `string`
>
> Memory area: `CIO`, `WR`, `HR`, `AR`, `DM`, `CNT`, `TIM`, `EM`. Default: DM.
>
> **DATA\_TYPE** `string` *required*
>
> FINS data type: BOOL, BYTE, INT, UINT, DINT, UDINT, LINT, ULINT, REAL, LREAL, ASCII, STRING.
>
> **LENGTH** `integer`
>
> String payload size in bytes; FINS adds two header bytes (`LENGTH + 2` on the wire). Default: **256**. Alias: `STRING_SIZE`.

> **Value Transformation**
>
> **SCALING** `double`
>
> Multiplier for value transformation. Default: 1.0.
>
> **OFFSET** `double`
>
> Offset added after scaling. Default: 0.0.
>
> **DECIMAL\_PLACES** `integer`
>
> Decimal places in output. Default: 2.

> **Filtering**
>
> **MIN\_VALUE** `double`
>
> Minimum allowed value.
>
> **MAX\_VALUE** `double`
>
> Maximum allowed value.
>
> **DEADBAND** `double`
>
> Minimum change to trigger publish. Default: 0.0.

> **Publishing**
>
> **SOURCE\_TOPIC** `string` *required*
>
> Topic where PLC values are published. Subscribe here to receive sensor data.
>
> **DESTINATION\_TOPIC** `string`
>
> Topic to send write commands. Publish a value here to write it to the PLC.
>
> **PUBLISH\_MODE** `string`
>
> Output format: `VALUE_ONLY` or `JSON`. Default: VALUE\_ONLY.
>
> **UNIT** `string`
>
> Engineering unit for documentation.
>
> **DESCRIPTION** `string`
>
> Human-readable description.

> **Write Configuration**
>
> **WRITABLE** `boolean`
>
> Allow writing to this address. Default: false.

***

## Addressing Examples

### Word Addressing

Access data at word level:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD TAG DataWord100
    WITH ADDRESS "100"
    WITH MEMORY_TYPE "DM"
    WITH DATA_TYPE "INT"
    WITH SOURCE_TOPIC "plc/dm/100"
```

### Bit Addressing

Access individual bits within a word:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD TAG Bit0
    WITH ADDRESS "100"
    WITH BIT_ADDRESS 0
    WITH MEMORY_TYPE "DM"
    WITH DATA_TYPE "BOOL"
    WITH SOURCE_TOPIC "plc/dm/100.0"

ADD TAG Bit15
    WITH ADDRESS "100"
    WITH BIT_ADDRESS 15
    WITH MEMORY_TYPE "DM"
    WITH DATA_TYPE "BOOL"
    WITH SOURCE_TOPIC "plc/dm/100.15"
```

### 32-bit Values

32-bit values span two consecutive words:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD TAG FloatValue
    WITH ADDRESS "200"
    WITH MEMORY_TYPE "DM"
    WITH DATA_TYPE "REAL"
    WITH SOURCE_TOPIC "plc/float"
```

> [!NOTE]
>
> REAL and DINT types use two consecutive words (e.g., DM200 and DM201).

***

## Event-Based Operations

For on-demand FINS operations (not polling), use the EVENT syntax. Publish a message to SOURCE\_TOPIC to trigger the operation; the route executes it and publishes the result to DESTINATION\_TOPIC.

### Supported Operations

| Operation | Description | Query Parameters |
| - | - | - |
| `READ` | Read from a memory area on demand | `memory_type`, `address`, `data_type`, `count` |
| `WRITE` | Write a value to a memory area | `memory_type`, `address`, `data_type`, `value` |

### Query Parameters

| Parameter | Description | Example |
| - | - | - |
| `operation` | Operation type: `READ` or `WRITE` | `READ` |
| `memory_type` | Memory area: `DM`, `CIO`, `WR`, `HR`, `AR`, `TIM`, `CNT`, `EM` | `DM` |
| `address` | Word address in the memory area | `100`, `200` |
| `data_type` | FINS data type | `REAL`, `INT`, `UINT`, `DINT`, `BOOL` |
| `count` | Number of consecutive values to read (READ only) | `10` |
| `value` | Value to write (WRITE only) | `25.5`, `100`, `true` |

### Read Example

Read a REAL value from DM area on demand:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD EVENT ReadDM
    WITH SOURCE_TOPIC "fins/commands/read"
    WITH DESTINATION_TOPIC "fins/responses/read"
    WITH QUERY "{operation: READ, memory_type: DM, address: 100, data_type: REAL}"
```

### Write Example

Write a REAL value to DM area on demand:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
ADD EVENT WriteDM
    WITH SOURCE_TOPIC "fins/commands/write"
    WITH DESTINATION_TOPIC "fins/responses/write"
    WITH QUERY "{operation: WRITE, memory_type: DM, address: 200, data_type: REAL, value: 25.5}"
```

***

## Complete Examples

**Basic Data Memory Reading**

Read values from DM area:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronBasic WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
        WITH LOCAL_NODE 0
        WITH REMOTE_NODE 0
    ADD MAPPING DataMemory
        WITH EVERY 500 MILLISECONDS
        ADD TAG Temperature
            WITH ADDRESS "100"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/temperature"
            WITH SCALING 0.1
            WITH UNIT "°C"
        ADD TAG Pressure
            WITH ADDRESS "102"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/pressure"
            WITH UNIT "bar"
        ADD TAG Counter
            WITH ADDRESS "104"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "DINT"
            WITH SOURCE_TOPIC "plc/counter"
```

**I/O and Work Areas**

Read CIO and Work areas:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronIO WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
    ADD MAPPING IOStatus
        WITH EVERY 100 MILLISECONDS
        ADD TAG DigitalInputs
            WITH ADDRESS "0"
            WITH MEMORY_TYPE "CIO"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/io/di"
        ADD TAG DigitalOutputs
            WITH ADDRESS "100"
            WITH MEMORY_TYPE "CIO"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/io/do"
        ADD TAG WorkBits
            WITH ADDRESS "0"
            WITH MEMORY_TYPE "WR"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/work"
```

**Bit-Level Access**

Access individual bits:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronBits WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
    ADD MAPPING BitStatus
        WITH EVERY 100 MILLISECONDS
        ADD TAG StartButton
            WITH ADDRESS "0"
            WITH BIT_ADDRESS 0
            WITH MEMORY_TYPE "CIO"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/buttons/start"
        ADD TAG StopButton
            WITH ADDRESS "0"
            WITH BIT_ADDRESS 1
            WITH MEMORY_TYPE "CIO"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/buttons/stop"
        ADD TAG MotorRunning
            WITH ADDRESS "100"
            WITH BIT_ADDRESS 0
            WITH MEMORY_TYPE "CIO"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "plc/motor/running"
            WITH WRITABLE "true"
            WITH DESTINATION_TOPIC "plc/motor/running/set"
```

**Timers and Counters**

Read timer and counter values:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronTimerCounter WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
    ADD MAPPING TimersCounters
        WITH EVERY 500 MILLISECONDS
        ADD TAG Timer0
            WITH ADDRESS "0"
            WITH MEMORY_TYPE "TIM"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/timer/0"
            WITH SCALING 0.1
            WITH UNIT "s"
        ADD TAG Timer1
            WITH ADDRESS "1"
            WITH MEMORY_TYPE "TIM"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/timer/1"
        ADD TAG Counter0
            WITH ADDRESS "0"
            WITH MEMORY_TYPE "CNT"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/counter/0"
        ADD TAG Counter1
            WITH ADDRESS "1"
            WITH MEMORY_TYPE "CNT"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/counter/1"
```

**Bidirectional Control**

Read and write process values:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronControl WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
    ADD MAPPING ControlLoop
        WITH EVERY 200 MILLISECONDS
        ADD TAG ProcessValue
            WITH ADDRESS "200"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/pv"
            WITH UNIT "°C"
            WITH PUBLISH_MODE "JSON"
        ADD TAG Setpoint
            WITH ADDRESS "202"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/sp"
            WITH UNIT "°C"
            WITH WRITABLE "true"
            WITH DESTINATION_TOPIC "control/sp/write"
            WITH MIN_VALUE 0
            WITH MAX_VALUE 100
        ADD TAG Output
            WITH ADDRESS "204"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "control/output"
            WITH UNIT "%"
        ADD TAG AutoMode
            WITH ADDRESS "206"
            WITH BIT_ADDRESS 0
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "BOOL"
            WITH SOURCE_TOPIC "control/auto"
            WITH WRITABLE "true"
            WITH DESTINATION_TOPIC "control/auto/write"
```

**Holding Area**

Read retentive data from HR area:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE OmronHolding WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
    ADD MAPPING RetentiveData
        WITH EVERY 5 SECONDS
        ADD TAG TotalRuntime
            WITH ADDRESS "0"
            WITH MEMORY_TYPE "HR"
            WITH DATA_TYPE "DINT"
            WITH SOURCE_TOPIC "plc/stats/runtime"
            WITH UNIT "seconds"
        ADD TAG ProductionTotal
            WITH ADDRESS "2"
            WITH MEMORY_TYPE "HR"
            WITH DATA_TYPE "DINT"
            WITH SOURCE_TOPIC "plc/stats/production"
        ADD TAG LastErrorCode
            WITH ADDRESS "4"
            WITH MEMORY_TYPE "HR"
            WITH DATA_TYPE "UINT"
            WITH SOURCE_TOPIC "plc/stats/error"
```

**Combined (Cyclic + On-Demand)**

Continuous monitoring with on-demand read and write events in the same route:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ROUTE FullFINSSetup WITH TYPE FINS
    ADD FINS_CONFIG
        WITH IP "192.168.1.100"
        WITH PORT 9600
        WITH PROTOCOL "TCP"
        WITH LOCAL_NODE 0
        WITH REMOTE_NODE 0
    
    ADD MAPPING ProcessData
        WITH EVERY 500 MILLISECONDS
        ADD TAG Temperature
            WITH ADDRESS "100"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/temperature"
            WITH UNIT "°C"
        ADD TAG Pressure
            WITH ADDRESS "102"
            WITH MEMORY_TYPE "DM"
            WITH DATA_TYPE "REAL"
            WITH SOURCE_TOPIC "plc/pressure"
            WITH UNIT "bar"
    
    ADD EVENT ReadDM
        WITH SOURCE_TOPIC "fins/commands/read"
        WITH DESTINATION_TOPIC "fins/responses/read"
        WITH QUERY "{operation: READ, memory_type: DM, address: 200, data_type: REAL}"
    
    ADD EVENT WriteDM
        WITH SOURCE_TOPIC "fins/commands/write"
        WITH DESTINATION_TOPIC "fins/responses/write"
        WITH QUERY "{operation: WRITE, memory_type: DM, address: 300, data_type: REAL, value: 0}"
```

The MAPPING continuously reads temperature and pressure from DM. To trigger an on-demand read, publish any message to `fins/commands/read`. To write a value, publish to `fins/commands/write`.

***

## Memory Area Details

> **CIO - Core I/O**
>
> * Used for I/O mapping and internal relays
> * Words 0-99: Typically input/output modules
> * Words 100-999: Work bits and internal relays
> * Addresses are PLC model dependent

> **DM - Data Memory**
>
> * Main user data storage
> * Typically DM0-DM32767
> * Best for process data, setpoints, configuration
> * Retentive (battery-backed)

> **HR - Holding Area**
>
> * Always retentive data
> * Survives power cycles
> * Use for counters, totals, settings
> * Typically HR0-HR511

> **WR - Work Area**
>
> * General purpose work bits
> * Non-retentive (cleared on power cycle)
> * Fast access for temporary data

> **TIM/CNT - Timers and Counters**
>
> * TIM: Timer present values
> * CNT: Counter present values
> * Values are 16-bit unsigned
> * Timer values often in 0.1s units

***

## Troubleshooting

> **Connection Failed**
>
> * Verify IP address is correct
> * Check firewall allows port 9600
> * Ensure PLC Ethernet module is configured
> * Try both TCP and UDP protocols
> * Verify node addresses match PLC configuration

> **Node Address Errors**
>
> * LOCAL\_NODE should be unique on the network
> * REMOTE\_NODE is the target PLC's node number
> * Check PLC's FINS settings for correct node configuration
> * For direct connections, try 0 for both nodes

> **Memory Address Errors**
>
> * Verify address is within valid range for memory type
> * Check MEMORY\_TYPE matches where data is stored
> * For 32-bit types, ensure two consecutive words are available
> * BIT\_ADDRESS must be 0-15

> **Timeout Errors**
>
> * Increase TIMEOUT value
> * Check network connectivity
> * Verify PLC is in RUN mode
> * Reduce POLLING rate if reading many tags
> * Try TCP instead of UDP

> **Write Operations Fail**
>
> * Ensure WRITABLE is "true"
> * Verify memory area is writable (not AR)
> * Check PLC is not in monitor mode
> * Verify value is within data type range

***

## Next Steps

> **[Modbus TCP Client](./modbus-tcp-client)**
>
> Universal industrial protocol support.

> **[Industrial Overview](./overview)**
>
> Common patterns for all industrial routes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.