> ## 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.
</Tip>

## Basic Syntax

```lot theme={null}
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

<ParamField path="IP" type="string" required>
  Target Omron device IP address.
</ParamField>

<ParamField path="PORT" type="integer">
  FINS protocol port. Default: 9600.
</ParamField>

<ParamField path="PROTOCOL" type="string">
  Protocol type: `TCP` or `UDP`. Default: TCP.
</ParamField>

<ParamField path="LOCAL_NODE" type="integer">
  Local node address (0-255). Default: 0.
</ParamField>

<ParamField path="REMOTE_NODE" type="integer">
  Remote node address - target PLC (0-255). Default: 0.
</ParamField>

<ParamField path="TIMEOUT" type="integer">
  Connection timeout in seconds. Default: 2.
</ParamField>

<ParamField path="RETRIES" type="integer">
  Number of retries for FINS communication. Default: 5.
</ParamField>

<ParamField path="POLLING" type="integer">
  Polling interval in milliseconds. Default: 200.
</ParamField>

### Connection Examples

<Tabs>
  <Tab title="TCP Connection">
    Standard TCP connection (recommended):

    ```lot theme={null}
    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.
    </Note>
  </Tab>

  <Tab title="UDP Connection">
    UDP for lower latency:

    ```lot theme={null}
    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.
    </Note>
  </Tab>
</Tabs>

***

## 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.
</Note>

***

## 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 (configurable `STRING_SIZE`) | Variable |

***

## TAG Configuration

### Complete TAG Example

```lot theme={null}
ADD TAG ProcessTemperature
    WITH ADDRESS "100"
    WITH BIT_ADDRESS 0
    WITH DATA_TYPE "REAL"
    WITH MEMORY_TYPE "DM"
    WITH STRING_SIZE 256
    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

<AccordionGroup>
  <Accordion title="Address Configuration">
    <ParamField path="ADDRESS" type="string" required>
      Word address in PLC memory (e.g., 100, 200, 500).
    </ParamField>

    <ParamField path="BIT_ADDRESS" type="integer">
      Bit address for bit-specific data types (0-15). Used for BOOL values within a word.
    </ParamField>

    <ParamField path="MEMORY_TYPE" type="string">
      Memory area: `CIO`, `WR`, `HR`, `AR`, `DM`, `CNT`, `TIM`, `EM`. Default: DM.
    </ParamField>

    <ParamField path="DATA_TYPE" type="string" required>
      FINS data type: BOOL, BYTE, INT, UINT, DINT, UDINT, LINT, ULINT, REAL, LREAL, ASCII, STRING.
    </ParamField>

    <ParamField path="STRING_SIZE" type="integer">
      Size of string for STRING types. Default: 256.
    </ParamField>
  </Accordion>

  <Accordion title="Value Transformation">
    <ParamField path="SCALING" type="double">
      Multiplier for value transformation. Default: 1.0.
    </ParamField>

    <ParamField path="OFFSET" type="double">
      Offset added after scaling. Default: 0.0.
    </ParamField>

    <ParamField path="DECIMAL_PLACES" type="integer">
      Decimal places in output. Default: 2.
    </ParamField>
  </Accordion>

  <Accordion title="Filtering">
    <ParamField path="MIN_VALUE" type="double">
      Minimum allowed value.
    </ParamField>

    <ParamField path="MAX_VALUE" type="double">
      Maximum allowed value.
    </ParamField>

    <ParamField path="DEADBAND" type="double">
      Minimum change to trigger publish. Default: 0.0.
    </ParamField>
  </Accordion>

  <Accordion title="Publishing">
    <ParamField path="SOURCE_TOPIC" type="string" required>
      Topic where PLC values are published. Subscribe here to receive sensor data.
    </ParamField>

    <ParamField path="DESTINATION_TOPIC" type="string">
      Topic to send write commands. Publish a value here to write it to the PLC.
    </ParamField>

    <ParamField path="PUBLISH_MODE" type="string">
      Output format: `VALUE_ONLY` or `JSON`. Default: VALUE\_ONLY.
    </ParamField>

    <ParamField path="UNIT" type="string">
      Engineering unit for documentation.
    </ParamField>

    <ParamField path="DESCRIPTION" type="string">
      Human-readable description.
    </ParamField>
  </Accordion>

  <Accordion title="Write Configuration">
    <ParamField path="WRITABLE" type="boolean">
      Allow writing to this address. Default: false.
    </ParamField>
  </Accordion>
</AccordionGroup>

***

## Addressing Examples

### Word Addressing

Access data at word level:

```lot theme={null}
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 theme={null}
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 theme={null}
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).
</Note>

***

## 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 theme={null}
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 theme={null}
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

<Tabs>
  <Tab title="Basic Data Memory Reading">
    Read values from DM area:

    ```lot theme={null}
    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"
    ```
  </Tab>

  <Tab title="I/O and Work Areas">
    Read CIO and Work areas:

    ```lot theme={null}
    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"
    ```
  </Tab>

  <Tab title="Bit-Level Access">
    Access individual bits:

    ```lot theme={null}
    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"
    ```
  </Tab>

  <Tab title="Timers and Counters">
    Read timer and counter values:

    ```lot theme={null}
    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"
    ```
  </Tab>

  <Tab title="Bidirectional Control">
    Read and write process values:

    ```lot theme={null}
    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"
    ```
  </Tab>

  <Tab title="Holding Area">
    Read retentive data from HR area:

    ```lot theme={null}
    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"
    ```
  </Tab>

  <Tab title="Combined (Cyclic + On-Demand)">
    Continuous monitoring with on-demand read and write events in the same route:

    ```lot theme={null}
    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`.
  </Tab>
</Tabs>

***

## Memory Area Details

<AccordionGroup>
  <Accordion title="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
  </Accordion>

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

  <Accordion title="HR - Holding Area">
    * Always retentive data
    * Survives power cycles
    * Use for counters, totals, settings
    * Typically HR0-HR511
  </Accordion>

  <Accordion title="WR - Work Area">
    * General purpose work bits
    * Non-retentive (cleared on power cycle)
    * Fast access for temporary data
  </Accordion>

  <Accordion title="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
  </Accordion>
</AccordionGroup>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="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
  </Accordion>

  <Accordion title="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
  </Accordion>

  <Accordion title="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
  </Accordion>

  <Accordion title="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
  </Accordion>

  <Accordion title="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
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Modbus TCP" icon="network-wired" href="./modbus-tcp">
    Universal industrial protocol support.
  </Card>

  <Card title="Industrial Overview" icon="industry" href="./overview">
    Common patterns for all industrial routes.
  </Card>
</CardGroup>
