見出し画像

生成AIの製造業への適用1 - Claude3でPLCプログラムを作成してみる

Summary

  • 生成AIでPLCプログラムを生成することは可能

  • 出力できるプログラムは、ST言語などの文字ベースのプログラムであり、ラダーでの出力はできない

  • 簡単な課題を出し、その仕様を満たすプログラムを出力できた

  • 複雑な仕様で対応できるかは検討が必要

製造業は課題が多い

私は元々製造業出身だったということもあり、メーカー勤務の友人が多いのですが、その友人とビジネスの課題に関して話していた際に、生成AIで製造業の課題解決をできるのではないかと思い、製造業への生成AIの適用方法を検討しています。

中小メーカーの友人の課題の一つに、PLCプログラミングができる人の採用が難しいことが挙げられました。特に友人の会社は、オーダーメイドの装置を開発していることから、一からPLCプログラムを開発できる人が求められます。しかし、市場には、そのような方は少ないと言われます。
理由としては、多くのメーカーが特定の製品を持っており、毎回一から開発していくわけではないため、一から開発した経験のあるエンジニアは少ないためです。特定の製品を持つ企業で開発してきたエンジニアは、編集開発(以前に開発された製品の一部を改変する)で開発してきた方が多く、一からPLCプログラムを作る経験をした人は少ないです。
編集開発をメインで行なってきたエンジニアを採用した場合、経歴が長くても会社でのサポートが必要になります。中小企業だと、常にリソース不足のため、通常はミドル層(経歴10年前後の方)に求められることは、一人前に働いてもらうことですが、サポートが必要となると、ミドル層でも採用を躊躇してしまいます。

このような課題を解決するために生成AIを利用できないか考え、今回はClaude3でPLCプログラムの生成を試してみました。生成AIでPLCプログラムの生成ができれば、生成AIのサポートを得ながら開発することができるため、人間のサポートを減らすことができます。
今回使用したClaude3は、テキストベースならばGPT4を超える性能を持つと言われていることと、入力できるトークン数が多いということで、Claude3を採用しました。
本記事では、その試みの過程と結果をまとめてみました。

課題の作成

まずは、どんなPLCプログラムを作成してもらうかを決めるため、課題の作成を行いました。この課題もClaudeで考えてもらいました。

プロンプト

ラダープログラムの勉強をしています。実際の機械を制御することを想定した課題を出力してください。

出力結果

課題: 自動充填システムのラダープログラム設計
概要:
あなたは、自動でボトルに液体を充填するシステムのラダープログラムを設計する任務を受けています。
このシステムは、空のボトルがコンベアベルトに乗って検出センサーの前を通過すると、充填機が作動して一定量の液体をボトルに充填し、その後ボトルを次の工程へ送り出すという流れで動作します。

要件:
1. 開始/停止制御: システムは、開始ボタンが押されると動作を開始し、停止ボタンが押されると動作を停止します。動作中は、内部のインジケーターライトが点灯します。
2. ボトル検出: コンベアベルト上を移動するボトルは、検出センサーによって検出されます。ボトルが検出されると、充填機が起動します。
3. 充填制御: 充填機はボトルが検出された後、設定された時間だけ液体を充填します。充填が終わると、充填機は自動的に停止します。
4. 充填完了後の処理: 充填が完了すると、コンベアベルトはボトルを次の工程へと移動させます。次のボトルが検出センサーに到達するまで、充填機は待機状態になります。

ラダープログラムに含めるべき主要な要素:
- 入力: 開始ボタン、停止ボタン、ボトル検出センサー
- 出力: インジケーターライト、充填機制御、コンベアベルト制御
- タイマー: 充填時間の制御

PLCプログラムの生成

次に、課題を解決するPLCプログラムの生成をClaude3にお願いしました。
手元にPLCやPLC用のソフトウェアがないため、OSSのOpenPLC Editorで動作させるためのプログラムの生成をお願いしました。

また、生成AIはラダー図を出力できないので(ラダー図はあくまで図なので)、C言語に近いST言語での出力をお願いしました。

プロンプト

以下の課題を解決するラダープログラムを生成してください。
OpenPLC Editorを使用するので、ST言語でのプログラムの生成と、デバイス名設定を出力してください。

課題: 自動充填システムのラダープログラム設計
概要:
あなたは、自動でボトルに液体を充填するシステムのラダープログラムを設計する任務を受けています。このシステムは、空のボトルがコンベアベルトに乗って検出センサーの前を通過すると、充填機が作動して一定量の液体をボトルに充填し、その後ボトルを次の工程へ送り出すという流れで動作します。

要件:
1. 開始/停止制御: システムは、開始ボタンが押されると動作を開始し、停止ボタンが押されると動作を停止します。動作中は、内部のインジケーターライトが点灯します。
2. ボトル検出: コンベアベルト上を移動するボトルは、検出センサーによって検出されます。ボトルが検出されると、充填機が起動します。
3. 充填制御: 充填機はボトルが検出された後、設定された時間だけ液体を充填します。充填が終わると、充填機は自動的に停止します。
4. 充填完了後の処理: 充填が完了すると、コンベアベルトはボトルを次の工程へと移動させます。次のボトルが検出センサーに到達するまで、充填機は待機状態になります。

ラダープログラムに含めるべき主要な要素:
- 入力: 開始ボタン、停止ボタン、ボトル検出センサー
- 出力: インジケーターライト、充填機制御、コンベアベルト制御
- タイマー: 充填時間の制御

出力結果

デバイス名設定:

VAR_INPUT
    START_BUTTON : BOOL; (* 開始ボタン *)
    STOP_BUTTON : BOOL; (* 停止ボタン *)
    BOTTLE_SENSOR : BOOL; (* ボトル検出センサー *)
END_VAR

VAR_OUTPUT
    INDICATOR_LIGHT : BOOL; (* インジケーターライト *)
    FILLING_MACHINE : BOOL; (* 充填機制御 *)
    CONVEYOR_BELT : BOOL; (* コンベアベルト制御 *)
END_VAR

VAR
    SYSTEM_RUNNING : BOOL := FALSE; (* システム動作状態 *)
    FILLING_TIMER : TON; (* 充填タイマー *)
    FILLING_TIME : TIME := T#5S; (* 充填時間 *)
END_VAR


ST言語プログラム:

PROGRAM AutoFillingSystem
    (* 開始/停止制御 *)
    IF START_BUTTON AND NOT SYSTEM_RUNNING THEN
        SYSTEM_RUNNING := TRUE;
        INDICATOR_LIGHT := TRUE;
        CONVEYOR_BELT := TRUE;
    END_IF;

    IF STOP_BUTTON THEN
        SYSTEM_RUNNING := FALSE;
        INDICATOR_LIGHT := FALSE;
        FILLING_MACHINE := FALSE;
        CONVEYOR_BELT := FALSE;
    END_IF;

    (* ボトル検出と充填制御 *)
    IF SYSTEM_RUNNING AND BOTTLE_SENSOR THEN
        CONVEYOR_BELT := FALSE;
        FILLING_MACHINE := TRUE;
        FILLING_TIMER(IN := TRUE, PT := FILLING_TIME);
    ELSIF SYSTEM_RUNNING AND NOT BOTTLE_SENSOR THEN  
        FILLING_MACHINE := FALSE;
        FILLING_TIMER(IN := FALSE);
    END_IF;

    (* 充填完了後の処理 *)
    IF FILLING_TIMER.Q THEN
        FILLING_MACHINE := FALSE;
        CONVEYOR_BELT := TRUE;
    END_IF;
END_PROGRAM

出力されたデバイス名設定をOpenPLCに設定し、ST言語のプログラムをOpenPLCで動作させてみました。PLCが繋がっていないので、想定通りの動きになっているかどうかは確認できないのですが、コンソールのログを見ると、動作してはいるようです。

Start build in /Users/yasuhiro/Documents/Development/Code/PLC/ladder_test_st/build
Generating SoftPLC IEC-61131 ST/IL/SFC code...
    Collecting data types
    Collecting POUs
    Generate POU program0
    Generate Config(s)
Compiling IEC Program into C code...
Extracting Located Variables...
C code generated successfully.
PLC :
   [CC]  plc_main.c -> plc_main.o
   [CC]  plc_debugger.c -> plc_debugger.o
PLC :
   [CC]  Config0.c -> Config0.o
   [CC]  Res0.c -> Res0.o
Linking :
   [CC]  plc_main.o plc_debugger.o Config0.o Res0.o -> ladder_test_st.dynlib
Successfully built.
Starting local runtime...
2024-04-07 08:57:34.234 Python[50779:11602311] WARNING: Secure coding is not enabled for restorable state! Enable secure coding by implementing NSApplicationDelegate.applicationSupportsSecureRestorableState: and returning YES.
Pyro port : 61700
Current working directory : /var/folders/yx/tnx4x_md55sdmlkm1d85f1200000gn/T/tmpamu7t3r2
PYRO connecting to URI : PYRO://localhost:61700
PLC did not provide identity and security infomation.
Latest build does not match with connected target.
PLC data transfered successfully.
PLCobject : No files to purge
PLCobject : NewPLC (3f4299e78335fbcc8b953acc4540b3d2)
PLC installed successfully.
PLCobject : PLC started
PLCobject : Python extensions started
Starting PLC

アクティビティ図で確認

PLCでの動作確認ができないので、本当に目的通りのプログラムになっているか確認するために、ST言語のプログラムをPlainUMLのアクティビティ図のコードに変換してもらい、それをPlainUMLで図として成形し、処理内容を確認しました。
まず、ST言語のプログラムをPlainUMLのコードに変換してもらいました。

プロンプト

次のST言語で書かれたPLCプログラムをPlainUMLのアクティビティ図として出力するためのコードに変換してください。
アクティビティ図で用いる要素名は、デバイス名設定を参照してください。

デバイス名設定:

VAR_INPUT
    START_BUTTON : BOOL; (* 開始ボタン *)
    STOP_BUTTON : BOOL; (* 停止ボタン *)
    BOTTLE_SENSOR : BOOL; (* ボトル検出センサー *)
END_VAR

VAR_OUTPUT
    INDICATOR_LIGHT : BOOL; (* インジケーターライト *)
    FILLING_MACHINE : BOOL; (* 充填機制御 *)
    CONVEYOR_BELT : BOOL; (* コンベアベルト制御 *)
END_VAR

VAR
    SYSTEM_RUNNING : BOOL := FALSE; (* システム動作状態 *)
    FILLING_TIMER : TON; (* 充填タイマー *)
    FILLING_TIME : TIME := T#5S; (* 充填時間 *)
END_VAR


ST言語プログラム:

PROGRAM AutoFillingSystem
    (* 開始/停止制御 *)
    IF START_BUTTON AND NOT SYSTEM_RUNNING THEN
        SYSTEM_RUNNING := TRUE;
        INDICATOR_LIGHT := TRUE;
        CONVEYOR_BELT := TRUE;
    END_IF;

    IF STOP_BUTTON THEN
        SYSTEM_RUNNING := FALSE;
        INDICATOR_LIGHT := FALSE;
        FILLING_MACHINE := FALSE;
        CONVEYOR_BELT := FALSE;
    END_IF;

    (* ボトル検出と充填制御 *)
    IF SYSTEM_RUNNING AND BOTTLE_SENSOR THEN
        CONVEYOR_BELT := FALSE;
        FILLING_MACHINE := TRUE;
        FILLING_TIMER(IN := TRUE, PT := FILLING_TIME);
    ELSIF SYSTEM_RUNNING AND NOT BOTTLE_SENSOR THEN  
        FILLING_MACHINE := FALSE;
        FILLING_TIMER(IN := FALSE);
    END_IF;

    (* 充填完了後の処理 *)
    IF FILLING_TIMER.Q THEN
        FILLING_MACHINE := FALSE;
        CONVEYOR_BELT := TRUE;
    END_IF;
END_PROGRAM

出力結果

@startuml
skinparam backgroundColor transparent
skinparam defaultTextAlignment center

start

if (開始ボタンが押されて、システムが停止状態の場合) then (yes)
   :システムを稼働状態にする;
   :インジケーターライトを点灯する;
   :コンベアベルトを動作させる;
else (no)
endif

if (停止ボタンが押された場合) then (yes)
   :システムを停止状態にする;
   :インジケーターライトを消灯する;
   :充填機を停止する;
   :コンベアベルトを停止する;
else (no)
endif

if (システムが稼働状態で、ボトルがセンサーで検出された場合) then (yes)
   :コンベアベルトを停止する;
   :充填機を動作させる;
   :充填タイマーを設定された充填時間でスタートさせる;
else if (システムが稼働状態で、ボトルがセンサーで検出されない場合) then (yes)
   :充填機を停止する;
   :充填タイマーをリセットする;
else (no)
endif

if (充填タイマーが完了した場合) then (yes)
   :充填機を停止する;
   :コンベアベルトを再開する;
else (no)
endif

stop
@enduml

これをPlainUMLで図として出力しました。
PlainUMLは、自分で環境構築することも可能ですが、以下のWebサイトでも実行することができます。

https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000

生成した図が次の図になります。

PLCプログラムの内容をアクティビティ図で表現

「システムが稼働状態で、ボトルがセンサーで検出されない場合」の処理で、毎回充填機の停止とタイマーのリセットをしている点が気になりますが、処理としては概ね課題の要件を満たしているように感じます。

結論:工夫すれば使えそう

ここまでの試みから、プロンプトを調整したり、優れたPLCプログラムをRAGとして用いれば、より優れた結果を出力してくれると感じました。
特にPLCプログラムは、各メーカーがインターネット上にオープンにしていないことから、LLMの学習に使われているデータが少ないと考えています。
そのため、各メーカーが独自に保持しているデータを用いて、LLMを調整すれば、実務で使えるレベルに持っていけると感じました。

弊社は、生成AIから組み込みソフトウェアまで、幅広いテクノロジーを駆使して、お客様の課題解決をいたします。
お気軽にご相談ください。

この記事が気に入ったらサポートをしてみませんか?