😺

CODESYS Example Projectを調べてみた#6(Task Manager)

2024/12/30に公開

Task Manager

今回は、Task Managerについて調べました。このExampleでは、CmplecTaskというライブラリを使用してタスク情報を読み取る方法を示しています。

セットアップ

コードをダウンロードし、デバイスのアップデートを行うだけで、問題なく動作させることができました。

プログラムの内容

サンプルプログラムでは、MainTaskとSecondTaskの2つのタスクが「Fixed Pinned」とプライオリティ(1, 10)の設定で実行されています。MainTaskの役割は、タスク名やプライオリティ値などの情報を取得することです。

MainTaskの実装は、以下のようになっています。Task_Info2型IecTaskGetCurrent()がライブラリで提供されている機能です。

PLC_PRG
PROGRAM PLC_PRG
VAR
	tTask 			: Task_Info2; (* Information about the task *)
	aIecTasks 		: ARRAY[1..20] OF Task_Info2; (* Information about all tasks *)
	hCurrentTask	: RTS_IEC_HANDLE := SysTypes.RTS_INVALID_HANDLE; (* Current task *)	
	Result			: RTS_IEC_RESULT; (* Result Code *)
END_VAR

// Retrieve information about the current task.
IF hCurrentTask = SysTypes.RTS_INVALID_HANDLE THEN
	hCurrentTask := IecTaskGetCurrent(pResult:=ADR(Result));
	tTask := CurrentTaskInfo(hCurrentTask := hCurrentTask);
END_IF

// Retrieve all task information.
aIecTasks := AllTaskInfo();

SecondTaskは、カウントアップ処理のみ実装されており、MainTask側から他のTask情報が取得できるか確認するために実行されています。

Second_PRG
PROGRAM Second_PRG
VAR
	udiCount	: UDINT;
END_VAR

udiCount := udiCount + 1;

自身のTask情報を取得するために、CurrentTaskInfo()関数が定義されています。この関数内で、IecTaskGetInfo3()関数を使ってTask情報を取得しています。タスクの指定には、IecTaskGetCurrent() 関数で取得した RTS_IEC_HANDLE 型のハンドルを、CurrentTaskInfo()関数の引数として渡しています。

CurrentTaskInfo
FUNCTION CurrentTaskInfo : Task_Info2
VAR_INPUT
	hCurrentTask : RTS_IEC_HANDLE;
END_VAR

VAR
	Result 	: RTS_IEC_RESULT;
	hIecTask: RTS_IEC_HANDLE;
END_VAR

hIecTask := hCurrentTask; 
IF hIecTask <> RTS_INVALID_HANDLE AND Result = 0 THEN
	CurrentTaskInfo := IecTaskGetInfo3(hIecTask:=hIecTask, pResult:=ADR(Result))^;
END_IF

取得したTask情報は以下のようなものがあります。iJitterなども取得できそうですが、今回の実行環境では値は0のままでした。(DeviceのMonitor機能では、有限の値になっている。)pJitterDistribution.wCountJitterPos変数は、逐次値が更新されていました。
Comment列に記載されている[c]と[s]の記号は、ライブラリのドキュメントによると

IecTaskCreateで使用されるタスク設定メンバには[c]、ステータスメンバには[s]が付きます。

tTask

Main Taskで呼ばれるAllTaskInfo()関数は、他のTask情報も取得しTask_Info2の配列に保存しています。最初にIecTaskGetFirst()でハンドルを取得し、IecTaskGetInfo3()でTask情報の取得します。そして、IecTaskGetNext()https://content.helpme-codesys.com/en/libs/CmpIecTask/Current/IecTaskGetNext.htmlで次のタスクハンドルを取得することで、すべてのタスクを順番にしらべられうようになっています。

AllTaskInfo(FUN)
FUNCTION AllTaskInfo : ARRAY[1..20] OF Task_Info2
VAR_INPUT
END_VAR
VAR
	hTask 	: RTS_IEC_HANDLE; (* task handle *)
	iTasks  : INT; (* task counter *)
	pTask 	: POINTER TO Task_Info2; (* pointer to task information *)
	sAppName: STRING := 'Application'; (* name of the application *)
	Result	: RTS_IEC_RESULT; (* error code *)
END_VAR

iTasks   := 0;
hTask := IecTaskGetFirst(pszAppName:=ADR(sAppName), pResult:=ADR(Result));
WHILE hTask <> RTS_INVALID_HANDLE AND Result = 0 DO
	iTasks   := iTasks + 1;
	pTask    := IecTaskGetInfo3(hIecTask:=hTask, pResult:=ADR(Result));
	IF pTask <> 0 AND Result = 0 THEN
		AllTaskInfo[iTasks] := pTask^;
	END_IF
	
	(* Get the next task *)
	hTask := IecTaskGetNext(pszAppName:=ADR(sAppName), hPrevIecTask:=hTask, pResult:=ADR(Result));
END_WHILE

学びと気づき

  • Jitterなどが表示・グラフ表示できればデバッグに使えそう。
  • Taskに関する異常値をMonitorしたい場合に使えそう。
  • 動的なタスクの負荷分散が必要な場合に使えそう。

まとめ

  • CmplecTaskでTaskの内容を取得できる。
  • Task情報取得の流れ
    • IecTaskGetCurrent(), IecTaskGetFirst()などでハンドラ取得
    • IecTaskGetInfo3()でTask情報取得
    • Task_Info2型の変数にデータ格納

Discussion