![見出し画像](https://assets.st-note.com/production/uploads/images/136463611/rectangle_large_type_2_4549f92329316a76bf6f104db44321fa.png?width=1200)
生成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
生成した図が次の図になります。
![](https://assets.st-note.com/img/1712460243446-033YYCbzhV.png?width=1200)
「システムが稼働状態で、ボトルがセンサーで検出されない場合」の処理で、毎回充填機の停止とタイマーのリセットをしている点が気になりますが、処理としては概ね課題の要件を満たしているように感じます。
結論:工夫すれば使えそう
ここまでの試みから、プロンプトを調整したり、優れたPLCプログラムをRAGとして用いれば、より優れた結果を出力してくれると感じました。
特にPLCプログラムは、各メーカーがインターネット上にオープンにしていないことから、LLMの学習に使われているデータが少ないと考えています。
そのため、各メーカーが独自に保持しているデータを用いて、LLMを調整すれば、実務で使えるレベルに持っていけると感じました。
弊社は、生成AIから組み込みソフトウェアまで、幅広いテクノロジーを駆使して、お客様の課題解決をいたします。
お気軽にご相談ください。
この記事が気に入ったらサポートをしてみませんか?