【C#】三菱PLCとのMCプロトコルによる通信アプリを作る(メモリ読み書き)

2020年6月10日

C#の実装メモ。

TCPにて、三菱製PLC(内蔵Ethernetポート)とMCプロトコルにて通信を行い、GUI上でPLCのメモリをスムーズに読み書きできるアプリケーションを作製しました。ほぼ製品レベルのクオリティですが、ソースコード全文をほとんどそのまま公開します。参考にしてもらえれば、様々な通信系アプリに応用できると思います。(私は慣れているので1日程度で作成できましたが、慣れていないと、マネして作るだけでも1週間はかかると思います)

「キーワード」の章をご参照頂き、そこに読みたい情報があれば参考にしていただけると幸いです。主に画面処理(delegate、invokeなどのコールバック系/各種ボタンのイベントハンドラ)、通信処理(TCPクライアント)あたりで、色々参考になるかと思います。

開発環境/動作環境

開発環境(WindowsPC)

  • Windows(7以降)
  • VisualStudio2017
  • C#
  • .Net4.7

動作環境

(1) PCは、.Net4.7インストール済みPC(Windows7/Windows10)で動作します。
(2) 三菱PLC側は、「Q**CPU」系統で、CPUユニット内蔵のEthernet内蔵のCPUのみ通信可能です(通信コマンド「QnA互換3Cフレーム」を使用するため)。ただし、ちょこっと改造して、「QnA互換3Eフレーム」に対応すれば、Ethernetユニットとも通信可能に出来ます。(暇があればやるかも。)

完成画面(動作イメージ)

下記画面にて、三菱PLC(CPUユニット内蔵Ethernetポート)のIPアドレス、ポート番号を設定して、三菱PLCとリアルタイムに通信を行います。通信は以下2種類の処理を行います。

(1) 指定したメモリアドレスの値を読み出し、画面に表示します。
(2) 画面で編集した値をPLCに書き込みます。

Cで作る三菱PLCテスター(MCプロトコル通信)

キーワード

ハードウェア関連

  • 三菱PLC
  • Ethernet

画面処理関連

  • iniファイル読込/書込
  • イベントハンドラ(invoke / delegate)
  • dataGridView(データグリッドビュー)

通信処理関連

  • C# / TCPクライアント
  • MCプロトコル
  • QnA互換3Cフレーム
  • メモリ読み書き

実装内容(ソースコード)

1. 画面クラス(Form1.cs)

1-1. 画面レイアウト

クラスの名前、デフォルトだった…(笑)。画面のレイアウトと各コントロール名は以下の様につけています。「GuiMelsecData」は「dataGirdView(データグリッドビュー)」というコントロールを使用しています。

Cで作る三菱PLCテスター(MCプロトコル通信)_GUI説明

1-2. ソースコード

メイン画面の処理部分のソースコードです。デザイナ―部分は割愛しますが、画面レイアウトと同じコントロール名にすれば、以下のソースがそのまま使えるかと思います。画面処理部分のソースを丸々載せておきます。

深く解説はしませんが、ポイントは以下の通りです。

(1) 起動時、コンストラクタ(Form1())にて、三菱PLC通信クラス「m_melsecMgr」に、「通信切断検知」用のコールバック(m_melsecMgr.m_onConnect)、「受信検知」用のコールバック(m_melsecMgr.m_onRecv)を登録します。

(2) 「通信開始」ボタン(GuiStartButton)押下で、イベントハンドラ「GuiStartButton_Click()」を駆動します(画面デザイナにて、「通信開始」ボタンをダブルクリックすれば、イベントハンドラの登録が自動的に出来ます)。関数内で、「m_melsecMgr.StartMelsec()」を呼び、通信を開始します。

(3) 受信検知時は、(1)でm_onRecvに登録したコールバック関数「OnRecv()」が駆動します。OnRecv()内で、受信データをデータグリッドビュー(GuiMelsecData)に反映します。

(4) ユーザーが画面からデータグリッドビュー(GuiMelsecData)を編集時、編集開始時にイベントハンドラ「MelsecData_EditingControlShowing()」、編集終了時にイベントハンドラ「MelsecData_CellValueChanged()」が駆動します。編集終了と共に、三菱PLC通信クラスの送信キューに、編集したセルの値を書き換える「メモリ書込」電文を追加します。通信クラスは、キューに追加された電文を送信する仕組みにしています。

2. 設定値クラス(Config.cs)

2-1. ソースコード

iniファイルとのアクセスを行うクラスです。画面の「設定値読込」時にファイルから読み出し、「設定値書込」時にファイルに書き込みます。また、「通信監視」(画面下部)側の各パラメータは、変更時に即座にiniファイルに書き込むようにしています。
iniファイルの読み書きを参考にしたい方は読んでみて下さい。通信部分を読みたい方は特に気にせず飛ばしてOKです。大したことはやっていませんので。

3. TCPクライアントクラス(TcpClient.cs)

3-1. ソースコード

TCPクライアント部分は、先の記事『C#で「TCPクライアントを実装する」』で紹介したソースコードをゴッソリそのまま使っています(namespaceだけ変えました)ので、ここでの紹介は割愛します。以下の記事をご参照し、そのままご使用下さい。

4. 三菱PLC通信クラス(MelsecMgr.cs)

4-1. ソースコード

三菱PLCとの通信を行う、本アプリケーションの一番重要部分ですね。メイン画面の「通信開始」ボタンから本クラスの「StartMelsec()」が呼ばれ、通信開始します。通信の実体自体は「TcpClient」クラスにて実装しています。

といっても、結構ソースはシンプルです。ポイントは以下です。

(1) メンバに「ConnectEventHandler」と「RecvEventHandler」をdelegateで宣言します。いわば型なので、名前は自由に付けられます。delegateで宣言したこの型を、event型でメンバに宣言しておきます。メイン側で「切断検知」と「受信検知」時にコールバックしたい関数を、このevent型で登録したメンバに追加(+=)することで、三菱PLC通信クラス側からコールバックを呼ぶことができます。

(2) 通信開始関数「StartMelsec()」で、通信スレッド「MelsecThread」を駆動します。


(3) 通信スレッド「MelsecThread」にて、通信処理を行います。メモリ書込電文は、送信キューの「m_sendQue」にデータが入っていれば、それを送ります。その後、メモリ読出電文を「MakeCommData()」にて作成し、メモリ読出を行います。「m_melsecComm.Receive()」にて受信が行えるので、受信結果を解析し、メイン画面側にコールバック「m_windowHandle.Invoke()」にて通知します。

(4) 通信電文作成関数「MakeCommData()」は、三菱PLCとの通信プロトコル「QnA互換 3Cフレーム」にて実装しています。「3Eフレーム」等に対応したい場合でも、この関数を数行いじるのと、受信処理を数行いじるだけで対応できるかと思います。

免責事項

おそらく産業系ネットワークプログラマに需要があるかなと思い、公開してみました。何か間違いなどあれば、コメント欄にお願いします。
また、本ソースを商用利用することはかまいませんが、本ソースの不具合による損害・損失等の補償は致しかねるので、ご了承下さい(かたっ)。

ご購読、ありがとうございました。