Beckhoff#TwinCAT3 TF7000 VisionでQRCode読み込んでみよう

みなさんこんにちは。このシリーズはBeckhoff TwinCAT3のTF7xxx Visionライブラリのメモになります。きっかけはいまRoboDKを使用しロボットの勉強を始めたところで、Visionもやってみたいと思って、最初はOpenCVを試してみようと考えていました。調べたらBeckhoffにもVisionライブラリがあり、まずある程度Visionはどんな流れになるかを把握し、そのあとOpencvに切り替えるかしないかになりました。

TF7xxxのライブラリを使用するには、OOPプログラミングやPointer/Refプログラミングについての理解がMustなので、基礎が問われるところになりますね!

About TF7000 Vision

では、まずTF7000はどんなものなのかを簡単にまとめます。TF7000はBeckhoff社が提供する画像処理ライブラリで、UserがIEC61131-1準じるPLCプログラム言語からVisionのリアルタイムアプリケーションを組むことが可能になります。

カメラのCalibration・セットアップ・DebugなどもTwinCAT環境で完結できます。

注意するのはTF7000 Supportできるのは GigE Vision interfaceのカメラのみです。

あとTE2000と統合できるようですが、これはまた少し深く理解してから説明します。

TF7000 Vision使用すると実装できるアプリケーションは、いま頭に浮かぶのは:

  • 間隔を計測
  • 物体の色・位置・状態を検出
  • QRCode/Bar Codeの読むこむ
  • Cloudに接続し

つまりそのようなことを一括TwinCATだけで統合できます。

License for Camera TF700x

TF7000はBasicライセンスで2つのカメラだけになります。

もし追加したいなら数により、TF7001/TF7002/TF7003を使用できます。

License for Library TF7xxx

次は画像処理で使うアルゴリズムに関するライセンスも別です。

  • TF7100はTc3_VisionライブラリのBasicバージョンになります。Filters・色処理・カメラのパラメタ書き込みなどができます。
  • TF7200には2D Matching機能が追加されます。多分Pattern認識などかな?
  • TF7250は1D/2Dのコードを読み取る機能です。(BarCodeやQRCodeなど)
  • TF7300は距離測定などの最適化・エッジ検出のようです。

Installation.

下記のLinkにアクセスします。

TF7100 | TwinCAT 3 Vision Base | Beckhoff Worldwide

Software DownloadのところでExeをダウンロードしましょう。

ダブルクリックでSetupをスタートします。

英語を選んで、OK。

Nextします。

ライセンス同意し、Nextします。

情報を入れて、Nextします。

Completeを選び、Nextします。

Nextします。

Installをクリックし、インストールを始めます。

しばらく待ちください。

完成です!

System Requirment

IPC

Camera

Software


SetUP A Vision Devices

申し訳ございませんが、自分はカメラを持っていませんのでこの部分をSkipさせていただきます。カメラもし手持ちくる日があれば、また別の記事で説明しますね★


API

TwinCAT VisionライブラリはAPI提供しており、IEC61131-3準じるプログラム言語使用し画像処理することができます。いまからAPIの中にいくつの重要なコンセプトを紹介します。

Interface Pointer

APIから2種類はよく使うInterface Pointerがあります。それは:

  • ITcVnImage:画像処理用
  • ITcVnContainer: 複数の部品を保存するvector 

たとえば下記の例でF_VN_CreateImage() 関数を使用し800×600、1チャンネルの画像を作成します。

IF bCreateImage THEN
hr:=F_VN_CreateImage(
ipImage
,nWidth:=800
,nHeight:=600
,ePixelType:=ETcVnElementType.TCVN_ET_SINT
,nChannelNum:=1
,hrPrev:=hr
);
IF hr <> 0 THEN
bError:=TRUE;
END_IF
bCreateImage:=FALSE;
END_IF;

そのような画像が作成されますね。

Some Rules

ここでプログラミングするときいくつかのヒントを書きます。ヒントとはいえ、BeckhoffやCodesysでプログラムするときの基本ですので、気楽にみてください。

1-Method呼び出す前のPointerCheck

ITcVnImage などのPointer interfaceのMethodをCallする前に、必ずPointerが有効かどうかをCheckしてください。もしMethodがCallされたPointerが無効であればRuntimeが止まってしまうので。一番簡単な方法は0かどうかをCheckしますね。

//GetInfo
IF ipImage <> 0 THEN
ipImage.GetImageInfo(
stImageInfo:=ImageInfo
);
END_IF;

2- PointerのMethodよりF_VN Functionを使用

TwinCATのTC3_VisionライブラリはF_VN_xxx Functionが提供しており、ITcVnImage のMethodはすべて代用ではないが、該当するMethodがあればF_VN_XXX関数を使ってください。理由はF_VN_XXX関数はPointerが有効かどうかをCheck機能がついているからです。

F_VN_GetImageInfo(
ipImage
,stImageInfo:=stImageInfo_1
,hrPrev:=hr
);

3- Pointer IntefaceをVAR_INPUTしましょう。

Function BlockやPOUでPointer Interfaceを使用するときはVAR_INPUTを使いましょう。みなさんも知ってると思いますが、FBやPOUでは変数値をCycle完了したあとにも保持します。そのため、私たちは次のCycleでアクセスするメモリエリアが使用できるかどうかを確信持つことができます。

VAR_INPUT    
      ipSrcImage: ITcVnImage;
END_VAR
//… functional code
ipSrcImage := 0; 

4-使わないPointerはリリースしましょう

VARでPointer interfaceを定義しプログラムを使用しますね。Pointerも使わないとき(例えば画像処理プログラム完了したあと)にMemoryを解放しましょう。

例えば以下の例ように:

VAR    
ipImageWork: ITcVnImage;
END_VAR

//… functional code
hr := FW_SafeRelease(ADR(ipImageWork));

実際関数 FW_SafeRelease()はこのようなコードを実行しています:

IF binit THEN
IF ipImage <> 0 THEN
ipImage.TcRelease();
ipImage:=0;
END_IF
binit:=FALSE;

END_IF

5- VAR_OUTPUTでInterface Pointer定義やめましょう

ここで簡単に言いますと、FBやPOUはCycle実行終わっても変数値が保持するとみなさんもすでに知ってると思います。それはVAR_INPUTだけではなく、VAR_OUTでも同じです。それはなんの問題になるかというと1つCycleの前持ってたVAR_OUT変数のメモリアドレスがまだ有効かどうかの確信がありません。

無効なメモリ領域にアクセスすることによりRuntimeが止まることになりますので、できればVAR_INPUTでInterface Pointerを定義しましょう。


HRESULT

すべてのTwinCAT Vision 関数にはHRESULT も戻り値があり、関数の実行結果を示します。このコンセプトはFile 作成などするときと似ています。

以下は関数が実行成功したときのHRESULTの見方です。

こちらはSuccess-Codes値の意味一覧です。

以下は関数が実行失敗したときのHRESULTの見方です。

こちらはFault-Codes値の意味一覧です。

SUCCEEDED()関数を使用し関数の実行結果をCheckすることができます。

PROGRAM MAIN
VAR     hr     : HRESULT := S_OK;
END_VAR

IF SUCCEEDED(hr) THEN    
//code
END_IF

Image processing

ITcVnImage InterfaceはTc3_Visionライブラリの画像処理Interfaceの基本です。最後のExampleでは自分がそのITcVnImage を使用し画像をTwinCATに読み込み、QRCodeを探します。

ITcVnImage InterfaceはいくつかのMehtodが提供しており、画像の横縦やSize、Raw Dataにアクセスすることができます.


Container

次はContainerです。ContainerはTc3_Visionというより、TwinCATの中でもちょっと特別な部品だと思います。なぜかというとContainerに保存してるのは複数の部品でVectorとしてまとめられているからです。Containerに入ってる部品(いわゆる変数)は可変でプログラムより自由に変わります。注意するのは中に入ってるもののデータ・タイプは同じにする必要があります。

いまの時点でContainerのことを難しく考える必要がなく、大きさが自由変更できる箱だと思えばよいです。

PROGRAM MAIN VAR    
hr           : HRESULT;    
ipContainer  : ITcVnContainer;
END_VAR

以下の例でContainer がどう動くかを簡単に説明します。

もちろんContainer のCopyやContainer の中に更にContainer を格納するなどの上級の使い方があるらしくて、自分もまだそこまでわかりませんのでとりあえず一番基本なところから行きます。

  1. File Systemから写真をTwinCATに読み込まれせます。
  2. 関数を使用しQRCodeを検索します。
  3. DecodeされたデータがContainersのメモリに格納されます。
  4. 関数を使用しContainerのDataを取り出します。
  5. DataをUser Programに使用します。
  6. Container メモリ、画像メモリを解放します。

Function/Function Block 

TwinCAT Tc3_Visionは数多くのFB/FCありますので、全て説明するには不可能ですので今回Exampleで使われるもののみ説明します。

FB_VN_ReadImage

このFBを使用することでFile Systemから画像をTwinCATに読み込むことができます。

VAR_INPUT

sFilePathSTRING 画像のFull Path
ipDestImage Reference To ITcVnImagereturn image
bRead BOOL 立ち上げ=画像読み込む
nTimeout TIME VISION_ADS_TIME OUTTimeout


VAR_OUTPUT

bBusyBOOL True=実行中
bErrorBOOL True=エラーあり
nErrorIdUDINTそのErroID

F_VN_ReadQRCode

ITcVnImage内でQR Codeを検知する関数です。

VAR_INPUT

ipSrcImageITcVnImageSoruce Image、RGB可能で内部でGaryに変換します。
ipDecodeDataReference To ITcVnContainerDecodeされたDataのContainer
hrPrevHRESULT一回前の関数実行結果

Return Value

F_VN_ReadQRCodeHRESULT実行関数結果

F_VN_ExportSubContainer_String

SubContainerから文字列をExportする関数です。

VAR_INPUT

ipContainerITcVnContainer Container type with ContainerType_Vector_String_SINT 
nIndexULINT
hrPrevHRESULT一回前の関数実行結果
sTextSTRING Exportされた文字列
nMaxLength ULINT最大出力文字列数

Return Value

F_VN_ReadQRCodeHRESULT実行関数結果


Implemention

Configuration

この例では自分がRoboDKをOPCUA Clientとして使用し、RoboDKはCamera シミュレーション機能ついておりそのおかけでCamera実機なくても連動Pick>撮影>Placeの動作ができます。

TwinCAT SideではTF6100を使用しOPCUA Serverを立ち上げ、TF7250を使ってRoboDKが撮った写真をTwinCAT内に読み込み、QRCodeを検知します。

この記事ではRoboDKの部分はあまり詳しく説明しませんので、最後にProjectをダウンロードしてください。Python Scriptで実装していますだけなので。

Connect>Simulate 2D Cameraするとカメラを模擬できます。そのあとはOpenCVでもよいし、アクセス方法は自由自在です。


Flow

以下の図はRoboDKと連動したFlowです。

Add library

まずLibraryを追加します。

References>Add Libraryします。

Tc3_Visionを検索しOKします。

OPCUA Connections

下記のLinkからTF6100のOPCUA Server立ち上げ方法を参考にしてください。

Beckhoff#TwinCAT3 TF6100 OPCUA _Part1_Server立ち上げよう | (soup01.com)

Script to Create QRCode

from robolink import *  # RoboDK API
from robodk import *  # Robot toolbox
import qrcode
import tempfile


#———————————————-
# Create the QR code
data = mbox(“QRCode inside the text;”, entry=”Beckhoff.com”)
if data is None or data is False or type(data) is not str:
    # User cancelled
    quit()
img = qrcode.make(data)

#———————————————-
# Save to file

filename=None
if filename is None or filename == ”:
    filename=r”C:\Users\root\Desktop\qrcode1.png”

img.save(filename)

import os.path
if not os.path.exists(filename):
    quit(-1)

# Import in RoboDK
RDK = Robolink()
img_item = RDK.AddFile(filename)
if not img_item.Valid():
    quit(-1)


プログラム

以下のコードSmapleはFile SystemからImageを読み込み、QRCodeを検知、最後は情報をTE1800で表示させます。

VAR

VAR
//FB
FB_Images:FB_VN_ReadImage;
R_TRIG1,R_TRIG2 :R_TRIG;
TON:TON;
hr,hr2:HRESULT:=S_OK;
index:ULINT;
//Pointers
ipImage:ITcVnImage;
ipDecodedData:ITcVnContainer;
stImageInfo_1:TcVnImageInfo;
ImageInfo:TcVnImageInfo;
//Trigger Devices
read:BOOL;
readQR:BOOL;
binit:BOOL;
safetyInit:BOOL;
//Image Information
width:UDINT;
height:UDINT;
sText:STRING;
END_VAR

Code

//init
IF binit THEN
IF ipImage <> 0 THEN
ipImage.TcRelease();
ipImage:=0;
END_IF
binit:=FALSE;

END_IF
//Safety Init
IF safetyInit THEN

FW_SafeRelease(ADR(ipImage));
FW_SafeRelease(ADR(ipDecodedData));
safetyInit:=FALSE;
read:=FALSE;
readQR:=FALSE;
hr:=0;
hr2:=0;
END_IF

//GetInfo
IF ipImage <> 0 THEN
ipImage.GetImageInfo(
stImageInfo:=ImageInfo
);
END_IF;

F_VN_GetImageInfo(
ipImage
,stImageInfo:=stImageInfo_1
,hrPrev:=hr
);

//Robot Status Handshake
R_TRIG1(
CLK:=GVL_OPCUAServer.Node.Command2 = 1
OR GVL_OPCUAServer.Node.Command2 = 3

);

R_TRIG2(
CLK:=GVL_OPCUAServer.Node.Command1 = 1
);

IF R_TRIG2.q THEN
GVL_OPCUAServer.Node.Command2:=0;
height:=0;
width:=0;
sText:=”;
END_IF

IF R_TRIG1.Q THEN
GVL_OPCUAServer.Node.Command1:=0;
END_IF


//Read the Image
//Trigger the Image read Function
FB_Images.bRead:=read;
FB_Images(
sFilePath:=’C:\images\Images.png’
,ipDestImage:=ipImage
);
TON(
IN:=readQR
,PT:=T#0.1S
);

//Trigger the QR Read Function
IF NOT FB_Images.bError AND read THEN
readQR:=TRUE;

END_IF
//get the image information
IF readQR THEN
IF ipImage <> 0 THEN
ipImage.GetHeight(nHeight:=height);
ipImage.GetWidth(nWidth:=width);
END_IF;
END_IF;
//read the QRCode
IF TON.q THEN
hr:=F_VN_ReadQRCode(
ipSrcImage:=ipImage
,ipDecodedData:=ipDecodedData
,hrPrev:=hr
);
//Get the Text from Container
IF SUCCEEDED(hr) AND ipImage <> 0 THEN
hr:=
F_VN_ExportSubContainer_String(
ipContainer:=ipDecodedData
,sText:=sText
,hrPrev:=hr
,nIndex:=index
,nMaxLength:=255
);

IF SUCCEEDED(hr) THEN
read:=FALSE;
readQR:=FALSE;
FW_SafeRelease(ADR(ipDecodedData));
END_IF
END_IF;
END_IF;

Visualization

Run Button:RoboDKに送るのStart Command

Snap!:Snap RoboDKに送る撮影コマンド

Read QR Data:画像を読み込みます。

Clear QR Data:Pointer・画像・Flagをクリアします。

Sample Code

TwinCAT3/TwinCAT Project_Vision_Part1.zip at main · soup01Threes/TwinCAT3 (github.com)

Result

お疲れ様ですー

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする