今回はTc2_Utilitiesのライブラリを使用しCSV Filesを読み込みます。
Function Block
File処理するにはたくさんのFBありますので今回Exampleで使用してるFBだけを紹介します。
FB_FILEOPEN
このFB使用することによってFileを開きすることができます。
VAR_INPUT
sNetId | T_AmsNetId | AMSネットワークID |
sPathName | T_MaxString | アクセスするFileのPath |
nMode | DWORD | どんなModeでFileをアクセスするのか |
ePath | E_OpenPath | PATH_GENERICThe variable of this type selects generic or one of the TwinCAT system paths on the target device to perform the file open operation. |
bExecute | BOOL | 立ち上げ=実行 |
tTimeout | TIME | 実行取り消すまでの時間 |
VAR_OUTPUT
bBusy | BOOL | 1=実行中 |
bError | BOOL | 1=エラーあり |
nErrId | UDINT | エラーID |
hFile | UINT | File ID |
nMode
FOPEN_MODEREAD | “r”、Fileを開きます。もしFileが存在しないであればエラーになる。 |
FOPEN_MODEWRITE | “w”、Empty Fileを開きデータ書き込みます。もしFile存在なら内容が破棄する。 |
FOPEN_MODEAPPEND | “a”、FileをOpenし、データをいまのFileの一番最後に書き込む。Fileを事前に作成しておいでください。 |
FOPEN_MODEREAD OR FOPEN_MODEPLUS | “r+”: Fileを読み書きModeで開きます。Fileは事前存在するのが前提条件。 |
FOPEN_MODEWRITE OR FOPEN_MODEPLUS | “w+”: Empty Fileを読み書きModeで開きます。もしFile存在なら内容が破棄する。 |
FOPEN_MODEAPPEND OR FOPEN_MODEPLUS | “a+”: FileをOpenし、データをいまのFileの一番最後に書き込む。Fileが存在しないなら新規作成されます。 |
FOPEN_MODEBINARY | “b”: FileをBinary Modeで開く。 |
FOPEN_MODETEXT | “t”: FileをテキストModeで開く。 |
Error ID
0x703 | nMode・ePathが無効 |
0x70C | Fileが見つからない |
0x716 | 使用可能なFile Handlesがない |
FB_FILEGETS
そのFunction使うことによって開いたFileにOne Lineの文字列を読み込むことができます。そのOne Lineは Line Feed 文字までか、Fileの最後か(EOF)、読み込まれた文字数がsLineより多いのか。注意するのはFileは必ずText Modeで開く必要があります。
VAR_INPUT
sNetId | T_AmsNetId | AMSネットワークID |
hFile | UINT | File ID |
bExecute | BOOL | 立ち上げ=実行 |
tTimeout | TIME | 実行取り消すまでの時間 |
VAR_OUTPUT
bBusy | BOOL | 1=実行中 |
bError | BOOL | 1=エラーあり |
nErrId | UDINT | エラーID |
sLine : | T_MaxString | 読み込まれた文字列 |
bEOF | BOOL | 1=Fileを最後まで読み込まれた(cbRead=0)もしcbRead>0であればTrueになりません。 |
FB_CSVMemBufferReader
このFBを使用することによって読み込まれた文字列をCSVの間隔文字きりか分けて読むこむことができます。getValueのOutputやpValue/cbValueのOutputから転送先を指定する。
注意点:
CRLF (CR=Carriage Return, LF=Line Feed) を必ず使ってください。
Global変数DEFAULT_CSV_FIELD_SEP.からCSV Fileあkらの間隔文字を設定します。
VAR_INPUT
eCmd | E_EnumCmdType | eEnumCmd_First=Default,1つ目のData Field読み込む。eEnumCmd_Next=次のData Fieldを読み込む。 |
pBuffer | DWORD | 読み込みたいデータのPointer(ADRを使用すればOK) |
cbBuffer | UDINT | 読み込みたいデータサイズ(SizeOF使用すればOK) |
VAR_OUTPUT
bOk | BOOL | 1=実行成功、0=Fault |
getValue | T_MaxString | 読み込んでたDataを文字列としての保存先 |
pValue | DWORD | Dataの保存先のPointer値(ADR使用すればOK) |
cbValue | UDINT | Dataの保存先の変数サイズ(SizeOF使用すればOK) |
bCRLF | BOOL | 1=最後のデータが読み込まれまれた |
cbRead | UDINT | 読み込む成功したデータのサイズ |
Library Import
Tc2_Utilitiesを検索しOKで追加します。
Example
Flowは以下になります。
まずプログラム内で使用する変数を初期化しRead Commandを待ち続けます。
Command来たらFileを読み込め、中にの文字列を一列ずつ読み込み、Bufferに転送します。
次はBufferをCSV Fieldことに切り分け、実数に変換し格納します。
もしEOFではなければ、次の列を読みます。
最後はFileをCloseします。
DUT
今回は前RoboGuideからExportされたPointデータをImportします。
まずXYZなどの変数を作成します。
TYPE DUT_Coordinates : STRUCT x:REAL; y:REAL; z:REAL; xRot:REAL; yRot:REAL; zRot:REAL; END_STRUCT END_TYPE |
GVL
GVLで余裕を持って101個分のPointデータを作成。
{attribute ‘qualified_only’} VAR_GLOBAL Process1:ARRAY[0..100]OF DUT_Coordinates; END_VAR |
Program
VAR
VAR //Function Blocks CSVMemBufferReader:FB_CSVMemBufferReader; FileOpen:FB_FileOpen; FileGet:FB_FileGets; FileClose:FB_FileClose; // bReset:BOOL; nCol:INT; hFile:UINT; value:STRING[300]; sBufferString:ARRAY[0..15]OF STRING; iStep: INT; sCSVLine:STRING; sPathName:STRING; nRow:INT; bRead:BOOL; bEOF:BOOL; i:INT; iCRLFCounter:INT; END_VAR |
VAR CONSTANT
VAR CONSTANT cStepInit:INT:=0; cStepOpenFile:INT:=10; cStepGetLine:INT:=20; cStepEOFCheck:INT:=25; cStepReadLine:INT:=30; cStepParseData:INT:=35; cStepCloseFile:INT:=40; cStepError:INT:=8000; END_VAR |
Code
CASE iStep OF //Init the Configuration and Variables cStepInit: //* semicolon (;) := 16#3B => german field separator, comma (,) := 16#2C => US field separator DEFAULT_CSV_FIELD_SEP:=16#2C; //Varaibles using in the Program nRow:=0; nCol:=0; iCRLFCounter:=0; bEOF:=FALSE; sPathName:=’C:\p2.csv’; bReset:=FALSE; //FB Reset FileOpen(bExecute:=FALSE); FileClose(bExecute:=FALSE); FileGet(bExecute:=FALSE); //Read IF bRead AND NOT fileopen.bBusy AND NOT fileclose.bBusy AND NOT fileget.bBusy THEN FOR i :=0 TO 99 DO GVL_Points.Process1[i].x:=0.0; GVL_Points.Process1[i].y:=0.0; GVL_Points.Process1[i].z:=0.0; GVL_Points.Process1[i].xRot:=0.0; GVL_Points.Process1[i].yRot:=0.0; GVL_Points.Process1[i].zRot:=0.0; END_FOR iStep:=cStepOpenFile; bRead:=FALSE; END_IF; cStepOpenFile: Fileopen( sNetId:=’192.168.217.145.1.1′ ,sPathName:=’C:\p.csv’ ,nMode:=FOPEN_MODEREAD ,ttimeout:=T#3S ,ePath:=E_OpenPath.PATH_GENERIC ,bExecute:=TRUE ,hFile=>hfile ); IF NOT fileopen.bBusy THEN IF fileopen.bError THEN iStep:=cStepError; ELSE iStep:=cStepGetLine; END_IF END_IF cStepGetLine: FileGet( hFile:=hFile ,bExecute:=TRUE ,sLine=>scsvLine ); IF NOT FileGet.bBusy THEN IF FileGet.bError THEN iStep:=cStepError; ELSE IF FileGet.bEOF THEN bEOF:=TRUE; END_IF (* IF RIGHT( Fileget.sLine, 1 ) = ‘$N’ THEN sCSVLine := REPLACE( sCSVLine, ‘$R$L’, 2, LEN( sCSVLine ) ); END_IF *) iStep:=cStepEOFCheck; END_IF END_IF cStepEOFCheck: FileGet( bExecute:=FALSE ); IF bEOF THEN iStep:=cStepCloseFile; ELSE iStep:= cStepReadLine; END_IF cStepReadLine: nCol:=0; CSVMemBufferReader.eCmd:=E_EnumCmdType.eEnumCmd_First; REPEAT CSVMemBufferReader( pBuffer:=ADR(sCSVLine) ,cbBuffer:=SIZEOF(sCSVLine) ,getValue=>value ); IF CSVMemBufferReader.bOk THEN sBufferString[ncol]:=value; CSVMemBufferReader.eCmd:=E_EnumCmdType.eEnumCmd_Next; ncol:=ncol+1; IF CSVMemBufferReader.bCRLF THEN iCRLFCounter:=iCRLFCounter+1; END_IF END_IF UNTIL NOT CSVMemBufferReader.bOk END_REPEAT istep:=cStepParseData; cStepParseData: //Check EOF IF FileGet.bEOF THEN iStep:=cStepCloseFile; ELSE GVL_Points.Process1[nRow].x:=STRING_TO_REAL(sBufferString[0]); GVL_Points.Process1[nRow].y:=STRING_TO_REAL(sBufferString[1]); GVL_Points.Process1[nRow].z:=STRING_TO_REAL(sBufferString[2]); GVL_Points.Process1[nRow].xRot:=STRING_TO_REAL(sBufferString[3]); GVL_Points.Process1[nRow].yRot:=STRING_TO_REAL(sBufferString[4]); GVL_Points.Process1[nRow].zRot:=STRING_TO_REAL(sBufferString[5]); nRow:=nRow+1; iStep:=cStepGetLine; END_IF cStepCloseFile: FileClose( hFile:=hFile ,bExecute:=TRUE ); IF NOT FileClose.bBusy THEN IF FileClose.bError THEN iStep:=cStepError; END_IF ELSE FileClose( bExecute:=FALSE ); iStep:=cStepInit; END_IF cStepError: IF bReset THEN iStep:=cStepInit; END_IF END_CASE |
Sample Code Download
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT3%20Project%20CSV%20Read.7z