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

# PLC Workflow

export const vp = 'Visual Prompting';

export const smartLabel = 'Smart Labeling';

export const productLL = 'LandingLens';

export const mi = 'Mobile Inference';

export const llsf = 'LandingLens on Snowflake';

export const companyName = 'LandingAI';

*This article applies to these versions of LandingLens:*

<table>
  <thead>
    <tr>
      <th>LandingLens</th>
      <th>LandingLens on Snowflake</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><span class="check-icon">✓</span></td>
      <td><span class="check-icon">✓</span></td>
    </tr>
  </tbody>
</table>

You can use Programmable Logic Controllers (PLCs) to communicate with LandingEdge. For example, you can configure the system so that the PLC tells LandingEdge when to take a photo, and then LandingEdge tells the PLC what the results were.

<img src="https://mintcdn.com/landinglens/TJ8p3AwYZ8yXbABY/images/LE_Workflow_PLC_2024.png?fit=max&auto=format&n=TJ8p3AwYZ8yXbABY&q=85&s=bdc316cdcaec91f8f2f6d666743ff0c2" alt="LE_Workflow_PLC_2024" width="1619" height="984" data-path="images/LE_Workflow_PLC_2024.png" />

<Info>If using an industrial camera, you can configure a PLC to trigger image capture. To learn how to set up industrial cameras in LandingEdge, go to [GenICam and GigE Vision Cameras](./industrial-cameras).</Info>

## Supported Controllers

LandingEdge is compatible with the following PLCs:

* Rockwell CompactLogix controllers
* Rockwell ControlLogix controllers
* Controllers that use the Open Platform Communications Unified Architecture (OPC UA) protocol

## Set Up Inspection Points for PLCs

<Info>You can set up multiple *configurations* for each Inspection Point.</Info>

To set up Inspection Points when using a PLC with LandingEdge, follow the instructions below:

1. Create an Inspection Point.
2. Select your [Image Source](./manage-inspection-points#image-source).If you want the PLC to trigger the inspection start and you are capturing images with a connected industrial camera, select **GigE Vision Camera** or **GenICam** and then select your camera.
   <img src="https://mintcdn.com/landinglens/HBWOq4xeHM0Cl6hQ/images/plc_image_source.png?fit=max&auto=format&n=HBWOq4xeHM0Cl6hQ&q=85&s=681de1dd846fa10ca5322748f3e522ed" alt="plc_image_source" width="704" height="443" data-path="images/plc_image_source.png" />
3. Select your [Inspection Start](./manage-inspection-points#inspection-start) method.If using an industrial camera, select **PLC**. Make sure you configure your PLC to start inspections. This will vary based on your PLC device.
   <img src="https://mintcdn.com/landinglens/i_hGHOXkVC0R_OQG/images/plc_inspection_start.png?fit=max&auto=format&n=i_hGHOXkVC0R_OQG&q=85&s=85602ef3632a0ee22112b0cc39272003" alt="plc_inspection_start" width="714" height="208" data-path="images/plc_inspection_start.png" />
4. Set up the [Cloud Connection and Model](./manage-inspection-points#cloud-connection-and-model-connect-to-a-landinglens-model)settings.
   <img src="https://mintcdn.com/landinglens/i_hGHOXkVC0R_OQG/images/plc_model.png?fit=max&auto=format&n=i_hGHOXkVC0R_OQG&q=85&s=939c827e98d3ec1031840b3c596bd7cd" alt="plc_model" width="705" height="765" data-path="images/plc_model.png" />
5. Complete the following steps in the **Communication** section.
6. Select your **PLC Type**.
   <img src="https://mintcdn.com/landinglens/i_hGHOXkVC0R_OQG/images/plc_plc_type.png?fit=max&auto=format&n=i_hGHOXkVC0R_OQG&q=85&s=a2dc551898cff1ab12b286fa8f9f39c1" alt="plc_plc_type" width="693" height="390" data-path="images/plc_plc_type.png" />
7. Enter the IP address of the controller in the **Address** field.
   * For Rockwell controllers, use this format: \[*IP Address*]/\[*Slot Number*].Example: **192.168.1.5/0**. (If there's no slot number, omit it.)
   * For OPC UA controllers, use this format: opc.tcp\://\[*IP Address*]:4840.Example: **opc.tcp\://192.168.1.10:4840**.
     <img src="https://mintcdn.com/landinglens/HBWOq4xeHM0Cl6hQ/images/plc_address.png?fit=max&auto=format&n=HBWOq4xeHM0Cl6hQ&q=85&s=b32cb4852e16cce6192274cf51a1c240" alt="plc_address" width="706" height="474" data-path="images/plc_address.png" />
8. Click **Set** to set up the [Inputs](./plc-workflow#inputs) and [Outputs](./plc-workflow#outputs), which are the data points that LandingEdge and the PLC can share with each other.
   <img src="https://mintcdn.com/landinglens/e3dn6upV4NR85srT/images/le_plc_set.png?fit=max&auto=format&n=e3dn6upV4NR85srT&q=85&s=9bacc866c68d8c97b8a0fc83ec8d9177" alt="le_plc_set" width="706" height="474" data-path="images/le_plc_set.png" />
9. Click **Add New Signal**.
   <img src="https://mintcdn.com/landinglens/RyS1eDX1H1P0yU5b/images/le_plc_add_newSignal.png?fit=max&auto=format&n=RyS1eDX1H1P0yU5b&q=85&s=8bbfbeaabe9e25bc0eacaf2bebc6414a" alt="le_plc_add_newSignal" width="998" height="301" data-path="images/le_plc_add_newSignal.png" />
10. Select an option from the **Signal** drop-down menu. For detailed information about the options, go to [Inputs](./plc-workflow#inputs) and [Outputs](./plc-workflow#outputs).
11. If you selected **Custom**, enter the **Name** and **Data Type**.If you selected an existing signal type, these fields auto-populate and can't be changed.
12. Enter the PLC Tag or Tag Address in the **Tag/Address** field for that data point. This field isn't case-sensitive. For information about how to program your PLC, refer to the device manufacturer's documentation.For example, the images below show the signals in the PLC application and the matching signals in LandingEdge:
    <img src="https://mintcdn.com/landinglens/RyS1eDX1H1P0yU5b/images/le_plc_DemoProgram_tags.png?fit=max&auto=format&n=RyS1eDX1H1P0yU5b&q=85&s=bfa4d5367f642a83099c5c9fecca60fb" alt="le_plc_DemoProgram_tags" width="1331" height="578" data-path="images/le_plc_DemoProgram_tags.png" />
    <img src="https://mintcdn.com/landinglens/RyS1eDX1H1P0yU5b/images/le_plc_DemoProgram_inputs_outputs.png?fit=max&auto=format&n=RyS1eDX1H1P0yU5b&q=85&s=3900f0037b1ec6d27c49f8e82055720e" alt="le_plc_DemoProgram_inputs_outputs" width="1779" height="336" data-path="images/le_plc_DemoProgram_inputs_outputs.png" />
13. After you've set up all the signals, click **Set Inputs & Outputs**.
14. Confirm that the **Communication** panel shows the number of signals you've set up.
    <img src="https://mintcdn.com/landinglens/i_hGHOXkVC0R_OQG/images/plc_io.png?fit=max&auto=format&n=i_hGHOXkVC0R_OQG&q=85&s=84c1321155cff6d676ab477d09060eff" alt="plc_io" width="703" height="502" data-path="images/plc_io.png" />
15. (Optional) Set up [Image Saving](./manage-inspection-points#image-saving) settings.
16. (Optional) Set up [Other Settings](./manage-inspection-points#other-settings) settings.
17. (Optional) Set up [Custom Processing](./custom-processing).

## Inputs

Use the **Inputs** settings to configure the signals that the PLC sends to LandingEdge.

The following table describes the configurable inputs.

| Input                           | Description                                                                                                                                                                                                                                                                                                                     | Paired Output                   | Data Type                                                 |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------------------------------- |
| Trigger                         | Takes images immediately when the Trigger goes from Low to High (False to True).                                                                                                                                                                                                                                                | Trigger Ready                   | Bool                                                      |
| Results Ack                     | Configure the PLC to set this setting to High (True) to indicate results and errors from LandingEdge have been received. When LandingEdge receives this signal, it resets the result signals and is ready to start the cycle again.                                                                                             | Results Ready, Error            | Bool                                                      |
| Request Sub-Configuration Index | The PLC can tell LandingEdge to change to a different Inspection Point [configuration](./configurations). Use the configuration Index, and not the configuration name.<br /><br />If you're not using multiple configurations for an Inspection Point, leave this blank.<br /><br />Available in LandingEdge v2.6.45 and later. | Current Sub-Configuration Index | Dint                                                      |
| Custom                          | Set up a custom signal that the PLC sends to LandingEdge. For example, this can be the "lot name" for a batch of images.<br /><br />Available in LandingEdge v2.10.x and later.                                                                                                                                                 | N/A                             | Must match the data type set in the PLC application<br /> |

<Info>
  Refer here to understand the signals emitted by LandingEdge and the PLC:<br />
  • <strong>True/High</strong>: Indicates that the value is on.<br />
  • <strong>False/Low</strong>: Indicates that the value is off.
</Info>

## Outputs

Use the **Outputs** settings to configure the signals that LandingEdge sends to the PLC.

The following table describes the configurable outputs.

| Output                          | Description                                                                                                                                                                                                                                                                       | Paired Input                    | Data Type                                           |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | --------------------------------------------------- |
| Trigger Ready                   | Indicates LandingEdge is ready to receive the trigger to capture and process an image.                                                                                                                                                                                            | Trigger                         | Bool                                                |
| Results Ready                   | Indicates inference is complete and results are ready on the output signals to be read by the PLC.                                                                                                                                                                                | Results Ack                     | Bool                                                |
| Results OK                      | Indicates the image is good. This is the default result if you are running a Classification Model.                                                                                                                                                                                | N/A                             | Bool                                                |
| Results NG                      | Indicates that the image is not good. An **Error** output will also be present.                                                                                                                                                                                                   | N/A                             | Bool                                                |
| Classification                  | This option is only for Classification Models. Indicates the predicted Class ID.<br /><br />If there is no image, the value is **-1**.                                                                                                                                            | N/A                             | Dint                                                |
| Error                           | Indicates an error occurred during acquisition or processing. Check the **Error Code** for more details. A **Results NG** output will also be present.<br /><br />To clear the error, assert the **Results Ack** input.                                                           | Results Ack                     | Bool                                                |
| Error Code                      | Indicates what kind of error occurred in the DINT data type. <ul><li>**All 0 bits**: No error</li><li>**A 1 in bit 0**: Non-specific error</li><li>**A 1 in bit 1**: Timeout during acquisition</li><li>**Bits 2-31**: Reserved for future use</li></ul>                          | N/A                             | Dint                                                |
| Online/Ready                    | Indicates LandingEdge is running.                                                                                                                                                                                                                                                 | N/A                             | Bool                                                |
| Heartbeat                       | LandingEdge toggles the value from True to False every 1 second. This allows the PLC to check if LandingEdge is still functioning and that the connection between the PLC and LandingEdge still exists.                                                                           | N/A                             | Bool                                                |
| Busy                            | Indicates LandingEdge is processing.                                                                                                                                                                                                                                              | N/A                             | Bool                                                |
| Current Sub-Configuration Index | LandingEdge tells the PLC the Index of the Inspection Point [configuration](./configurations) that is currently running.<br /><br />If you're not using multiple configurations for an Inspection Point, leave this blank.<br /><br />Available in LandingEdge v2.6.45 and later. | Request Sub-Configuration Index | Dint                                                |
| Custom                          | Set up a custom signal that LandingEdge sends to the PLC. For example, this can be the x and y coordinates of a bounding box.<br /><br />Available in LandingEdge v2.10.x and later.                                                                                              | N/A                             | Must match the data type set in the PLC application |

<Info>
  Refer here to understand the signals emitted by LandingEdge and the PLC:<br />
  • <strong>True/High</strong>: Indicates that the value is on.<br />
  • <strong>False/Low</strong>: Indicates that the value is off.
</Info>

## Test Inputs and Outputs

To test if a signal can be sent between LandingEdge and the PLC, click **Test**. If the signal works, **Success** displays. If not, **Fail** displays.

If the test fails, check if the Name, Data Type, and Tag/Address in LandingEdge match the information in the PLC application.

For example, the Custom "lot" signal in the image below failed because its address was incomplete.

<img src="https://mintcdn.com/landinglens/RyS1eDX1H1P0yU5b/images/le_plc_inputs_failed.png?fit=max&auto=format&n=RyS1eDX1H1P0yU5b&q=85&s=0e81a54324928e3c080bb2eec7cfff69" alt="le_plc_inputs_failed" width="989" height="437" data-path="images/le_plc_inputs_failed.png" />

## Example Setup of LandingEdge and a PLC

The following [example workflow](./plc-workflow#example-workflow) shows how setting up the Inputs and Outputs enable LandingEdge and the PLC to work together.

The example assumes that these Inputs and Outputs are set up:

| Input                           | Set Up                                         |   |        |        |
| ------------------------------- | ---------------------------------------------- | - | ------ | ------ |
| Trigger                         | ✓                                              |   |        |        |
| Results Ack                     | ✓                                              |   |        |        |
| Request Sub-Configuration Index | ✖                                              |   | Output | Set Up |
| ---                             | ---                                            |   |        |        |
| Trigger Ready                   | ✓                                              |   |        |        |
| Results Ready                   | ✓                                              |   |        |        |
| Results OK                      | ✓                                              |   |        |        |
| Results NG                      | ✓                                              |   |        |        |
| Classification                  | ✓<br /><br />(if using a Classification model) |   |        |        |
| Error                           | ✓                                              |   |        |        |
| Error Code                      | ✖                                              |   |        |        |
| Online/Ready                    | ✓                                              |   |        |        |
| Heartbeat                       | ✖                                              |   |        |        |
| Busy                            | ✓                                              |   |        |        |
| Current Sub-Configuration Index | ✖                                              |   |        |        |

### Example Workflow

1. LandingEdge indicates that it is **Online**.
2. LandingEdge is ready and asserts **Trigger Ready** (True).
3. The PLC asserts **Trigger** (True) based on the set configurations. LandingEdge receives this signal and recognizes it is time to take an image.
4. LandingEdge changes **Trigger Ready** to False. The PLC receives this signal and recognizes that LandingEdge acknowledged the **Trigger**.
5. LandingEdge asserts **Busy** (True) to indicate that it cannot be triggered again. The PLC can monitor this signal.
6. After LandingEdge has received and processed an image, **Result OK** is set to True and **Result NG** is set to False.
   * If using a Classification model, **Classification** is set to the predicted Class ID.
   * If an error occurs, **Error** is set to True.
7. After the Results are set, LandingEdge asserts **Results Ready** (True) to indicate that results are available for the PLC to read.
8. The PLC recognizes that **Results Ready** or **Error** is set to True.  It reads the appropriate values—like **Results OK** , **Results NG**, and **Classification**—to determine the final prediction from the model.
9. After the PLC reads the results, it asserts **Results Ack**. LandingEdge receives this signal and recognizes that the PLC has read the results and the cycle is complete.
10. LandingEdge resets the result signals and is ready to initiate the cycle again (starting from step 2).

## Sample Script: Read Inputs and Write Outputs

You can add [Results Processing](./custom-processing) scripts to any LandingEdge inspection point, including inspections with PLCs. When running inference with a PLC, you can use the `ReadInput` and `WriteOutput` methods to customize processing based on custom signals defined in the [Inputs](./plc-workflow#inputs) and [Outputs](./plc-workflow#outputs).

The scripts in this section show examples of how you can use these methods:

* `ReadInput`: Save inferenced images to directories and filenames based on custom signals defined in the [Inputs](./plc-workflow#inputs) and [Outputs](./plc-workflow#outputs).
* `WriteOutput`: Send the X and Y coordinates of bounding boxes of predicted objects to the PLC (applicable when using an Object Detection model).

In this example, these custom signals were set up in LandingEdge and the PLC application:

* `lot`: This is the lot number for a set of products, and is defined in the PLC.
* `batch`: This is the batch number for a set of products, and is defined in the PLC.
* `x`: This is the x coordinate of the bounding box for a predicted object of interest.
* `y`: This is the y coordinate of the bounding box for a predicted object of interest.

Here is the sample C# script:

```c# theme={null}
public void Run()
{
    // Read inputs for the lot and batch signals from the PLC; the arguments must match the signal names defined in LandingEdge ("lot" & "batch")
    var lotName = ReadInput("lot");
    var batchName = ReadInput("batch");

    // Save images to custom directories & filenames; these override any other settings
    Data.SaveResultsPath = $@"d:\productionImages\{lotName}\{batchName}";
    Data.SaveResultsFilename=$"{lotName}.png";

    // Send the X & Y coordinates to the PLC
    WriteOutput("x", 123.456);
    WriteOutput("y", 789.123);
}
```

Here is the sample Python script:

```python theme={null}
def run(self):
    # Read inputs for lot and batch from the PLC; the arguments must match the signal names defined in LandingEdge ("lot" & "batch")
    lot_name = self.ReadInput("lot")
    batch_name = self.ReadInput("batch")

    # Save images to custom directories & filenames; these override any other settings
    self.Data.SaveResultsPath = rf"d:\productionImages\{lot_name}\{batch_name}"
    self.Data.SaveResultsFilename = f"{lot_name}.png"
    
    # Send the X & Y coordinates to the PLC
    self.WriteOutput("x", 123.456)
    self.WriteOutput("y", 789.123)
```

## Results Processing Considerations

If you add a [Results Processing](./custom-processing) script that pulls data from the PLC application (using `ReadInput`), LandingEdge will use the values the PLC application sent the last time that you acquired an image. If you change a value in the PLC application, you must capture another image to send the updated value to LandingEdge.

For example, let's say you create a `lot` tag in the PLC application and set its value to 40. You then capture an image. At this point, the `lot` value in LandingEdge is 40. Let's say that you now change the `lot` value in the PLC application to 50. If you run the Results Processing script in LandingEdge again without capturing an image, the value will still be 40. Once you capture another image, the value will change to 50.
