🚀

CODESYS Example Projectを調べてみた #1

2024/10/26に公開

はじめに

少し前からCODESYSを使い始めたので、Example Projectを活用したconnpassでの勉強会を始めてみました。
せっかくやるからには学びの記録を残そうと思い、コードリーディング中の気づきや、Example Projectを動かす手順などをまとめることにしました。

https://connpass.com/event/334631/

CODESYSのExample Projectは以下のサイトにあります。第1回目は「Object Oriented Programming.project」を見ていきます。

https://forge.codesys.com/prj/codesys-example/object-oriented/home/Home/

Example Projectのセットアップ

上記のサイト右上にダウンロードボタンがあるので、それをクリックすることで.projectファイルをダウンロードできます。ダウンロードしたファイルをダブルクリックするとCODESYSの開発環境が立ち上がります。複数バージョンの開発環境が入っている場合は、どのバージョンの環境で立ち上げるか確認画面がでてきます。

私のCODESYS開発環境は、V3.5 SP20 Patch 3ですが、Example Projectは、V3.5.14.0なので、バージョンを上げるかどうかの確認画面が出てきます。勉強目的なので、とりあえず自分の環境にバージョンを上げることにしました。

V3.5.20を選択
環境選択

development phaseを選択
Project Inspection

Set All to Newestを選択して、OKをクリック
Project Environment

Yesを選択
storage format upgrade

この状態ではerrorが発生するので、画面のアイコンをクリックしてUpdate placeholder "library name"を実行します。
Err

DeviceをUpdateします。Deviceを右クリックして、Update Deviceを選択します。適当にデバイスを選んで、Update Deviceボタンを押します。
Update Device

Example Projectの中身

Devices

Building_Objectsフォルダ内にInterface、RoomFBs、Visualizationサブフォルダがあり、メインはBuildingManager(PRG)となっていました。

BuildingManager(PRG)の中で、RoomType1, 2, 3をつかって部屋タイプに応じたインスタンスを8つ生成していました。部屋インスタンスをまとめて管理する配列も定義してあり、その際にはインターフェースのIRoom型をつかっていました。

PROGRAM BuildingManager
VAR
	(* define all rooms *)
	r1:RoomType1;		
	r2:RoomType3;
	r3:RoomType2;
	r4:RoomType3;
	r5:RoomType1;
	r6:RoomType3;
	r7:RoomType2;
	r8:RoomType1;
	(* Array of rooms simpilifies working with the building.*)
	Rooms: ARRAY [1..iNumberOfRooms] OF IRoom:=[r1,r2,r3,r4,r5,r6,r7,r8];
	CheckTimeOfDay: CheckFB; 	(* It's getting day? It's getting night? *)		
	xDusk: BOOL; (* nighttime *)
	xDawn:BOOL; (* daytime*)
	itfTemp: ITemp;
	xTemp: BOOL; (* Result of the Interface mapping.*) 
	i: INT;
END_VAR

プログラムの処理については、部屋配列をFORループで回して、xDawn, xDusk, xTempなどの条件(朝、夕、気温のチェック)に応じてインターフェースのメソッドを呼び出すようになっていました。

(* Check if there is daytime or nighttime.*)
CheckTimeOfDay(xGetsDay=>xDawn,xGetsNight=>xDusk);
FOR i:=1 TO iNumberOfRooms DO
	IF xDawn THEN	(* Daytime*)
		Rooms[i].Operation_Daytime(); (* Disable the light and depending on the roomtype set the temperature. *)
	END_IF
	IF xDusk THEN	(* Nighttime *)
		Rooms[i].Operation_Nighttime(); (* Enable the light and depending on the roomtype set the temperature. *)
	END_IF
	
	(* If temperature is available for the Room, then set the temperature  --> RoomType3*)
	xTemp:=__QUERYINTERFACE(Rooms[i], itfTemp);
	IF xTemp AND i=6 THEN
		(* Now itfTemp has the address of Rooms[6] *)
		itfTemp.SetTemperature(35); (* The temperature of the Rooms[6] is set. *)
	END_IF
	
END_FOR 

気づき・疑問

  • Update Deviceを実行するとUpdate placeholderを実行しなくてもよかった?
  • Interfaceでメソッドを定義して、FBでIMPLEMENTS "Interface Name" で実装する。
  • FBは、EXTENDS "FB name" で継承できる。
  • 継承ど実装を同時にするときは、EXTENDS ”FB name” IMPLEMENTS ”Interface Name”のようにFBの定義に続けて書けばよい。
  • __QUERYINTERFACE(対象のオブジェクト, 取得したいインターフェース) を使用して、指定されたオブジェクトが特定のインターフェースを実装しているかどうかを確認し、インターフェースの参照を取得できる。結果はインターフェースの参照として返され、インターフェースが実装されていない場合には NULL が返される。第1引数にインスタンス(対象オブジェクト)を指定し、第2引数にInterface型の変数を指定する。処理が成功すると、第2引数にインターフェースへの参照が設定される。
  • https://content.helpme-codesys.com/en/CODESYS Development System/_cds_operator_queryinterface.html

Discussion