みなさんこんにちは。またsimit よ話になりますね。その前に、simulationのゴールは何でしょうか?私はよりによって現実世界の装置をできる限り再現できるようにすることが最終目的だと思います。なので、バーチャルのシミュレーションはどれほど実現できるかが重要になります。
SiemensのPLCSIM advancedを使用するか、
他社のplc のシミュレーターを使用する(ここでベッコフオートメーションのtwincat 3は実機なくても大分の機能も自分のパソコン上に実装でき、それも今回の記事がtwincat3を、使用する大きな理由です。)
Simit では様々なモデルを提供し、ほかの3Dモデルソフトと連携は可能です。
今回使用するドライブライブラリは標準のシーメンスdrive を拡張し、より多くのprofinet telegramをsupportできます。今回の記事ではその一つ、telegram 111を取り上げ説明します。
もちろんsimit のリリースによりさらに対応できるシミュレーションもふえますのでそこでsios (Siemens Industry Online Support)を見てください。
Simit のそれらのライブラリはprofinet telegramのベースで作成され、現地立ち上げやデバッグの時間短縮を期待できます。さらにオペレーターのトレーニングや新人研修なども活用できると思います。
Download
下記のリンク先にアクセスし、ライブラリをダウンロードしましょう。
Configration
今回の構成はこうなります。PLCはTwinCATに置き換え、表示はTF1800表示します。SIMIT側がOPCUAServer立ち上げ、TwinCATがTF6100使用しアクセスします。
TwinCAT側のPLCプログラムはできるだけOOPのコンセプトを導入しProgram Exampleとしてみせます。みんな一緒に頑張りましょう。
Telegram111?
シーメンスの標準telegram 111は主にdrive のepos blocks とデータやり取りし、plc からdrive を制御することが可能になります。
そのtelegram 111はtelegram 110とすごく似ていて、さらにmessage frame が大きくなるイメージで、つまり交換できるデータ量が増えます。telegram 111 は12word のメモリを使用します。
そのtelegram111は以下の機能を提供します。
- Basic positioner 位置決め機能
- 32 bit 位置データ
- 32 bit 速度データ
- 16bit 加減速度データ
- signs of lifeの監視
- Error code warning code の周期受信
EPOS Operation Flow
TEL_111 Target
ここからtelegram111を説明します。
STW1
Bit | Device | Description |
0 | Off1 | ONコマンド0=OFF1有効中 1=ON |
1 | Off2 | 0=Off2 有効中 |
2 | Off3 | 0=Off3 有効中 |
3 | Enc | Inverter 有効中 |
4 | RejTrvTask | 0=Travering Records使用1=MDI Discard travsering task使用 |
5 | IntMStop | 1=即停止しない |
6 | TrvStart | Traversing Task実行 |
7 | AckFault | Faultリセット |
8 | Jog1 | Jog信号1 |
9 | Jog2 | Jog信号2 |
10 | LB | Life Bit(1=PLC制御) |
11 | RefStart | Homing開始 |
12 | Bit12 | |
13 | Bit13 | External block 変更(0>1) |
14 | Bit14 | |
15 | Bit15 |
STW2
Bit | Device | Description |
0 | DDSBit0 | Drive data set bit0 |
1 | DDSBit1 | Drive data set bit1 |
2 | DDSBit2 | Drive data set bit2 |
3 | DDSBit3 | Drive data set bit3 |
4 | DDSBit4 | Drive data set bit4 |
5 | GlbStart | Global start |
6 | ReslComp | Speed ControllerのI-Component リセット |
7 | ActPrkAxis | Parking axis有効する |
8 | TrvFixedStp | Fixed endstopへ移動中 |
9 | GlbTrgCom | Global トリガーコマンド |
10 | Bit10 | |
11 | MotSwOver | Motor Switchover完成 |
12 | MsZykBit0 | Master sign of life bit0 |
13 | MsZykBit1 | Master sign of life bit1 |
14 | MsZykBit2 | Master sign of life bit2 |
15 | MsZykBit3 | Master sign of life bit3 |
POS_STW1
Bit | Device | Description |
0 | TrvBit0 | Selection Bit 0 |
1 | TrvBit1 | Selection Bit 1 |
2 | TrvBit2 | Selection Bit 2 |
3 | TrvBit3 | Selection Bit 3 |
4 | TrvBit4 | Selection Bit 4 |
5 | TrvBit5 | Selection Bit 5 |
6 | Bit6 | |
7 | Bit7 | |
8 | MdiTyp | 位置決めの種類0=相対位置決め1=絶対位置決め |
9 | MdiPos | 回転軸がMDI Operationの位置決め・Setup Taskの回転方向1=正回転 |
10 | MdiNeg | 回転軸がMDI Operationの位置決め・Setup Taskの回転方向1=逆回転 |
11 | Bit11 | |
12 | MdiTrTyp | MDI Task実行の信号種類設定0=立ち上げ1=Setpointが変わるだけで実行 |
13 | Bit13 | |
14 | MdiSetup | MDI Mode設定0=位置決め1=Setup |
15 | MdiStart | 1=MDI Operation Mode |
POS_STW2
Bit | Device | Description |
0 | TrkMode | Tracking Mode開始 |
1 | SetRefPt | Reference Pointを設定する |
2 | ActRefCam | Reference Camを有効する |
3 | Bit3 | Fixed stopを有効する |
4 | Bit4 | |
5 | JogInc | 0=連続Jog1=パラメタからJog動作設定 |
6 | Bit6 | |
7 | Bit7 | |
8 | RefTyp | Homingの方法設定0=Reference Point approach1=Passive (on-the-fly) homing |
9 | RefStDi | Reference pointと開始位置の方向0=プラス方向1=マイナス方向 |
10 | RefInpS | Passive (on-the-fly) homingの信号ソース0=Probe 1有効1=Probe 2有効 |
11 | RefEdge | Passive homingの検知方式設定0=立ち上げ1=たち下げ |
12 | Bit12 | |
13 | Bit13 | |
14 | SftLimAct | Software Limit スイッチを有効する |
15 | StpCmaAct | Stop Cam有効する |
OVERRIDE
Overrideです。
MDI_TARPOS
位置指令値になります。
MDI_VELOCITY
速度指令値になります。
MDI_ACC
加速度指令値です。
MDI_DEC
減速度指令値です。
User
1word のあまりがあり、アプリケーションに合わせて自由に割り当てることができます。
TEL_111 Actual
ZSW1
Bit | Device | Description |
0 | RTS | 1=Power UP準備OK |
1 | RDY | 1=Operation準備OK |
2 | IOp | 1=Servo ONした、EPOS使用するの条件 |
3 | Fault | 1=重故障発生中 |
4 | NoOff2Act | 1=Off2が無効中 |
5 | NoOff3Act | 1=Off3が無効中 |
6 | PowInhbt | 1=Drive ONが無効中 |
7 | Alarm | 1=アラーム・Warning発生中 |
8 | NoFlwErr | |
9 | LbCr | 1=制御を要求 |
10 | TargPos | Driveは目標位置に到着(Jog/相対位置決め/絶対位置決めでも使える) |
11 | RefPSet | DriveはReference Point設定された |
12 | TrvTskAck | Travering Block有効状態がDriveに承認された |
13 | StndStill | 1=Driveは停止状態現在速度< Speed threshold3 |
14 | Accel | Drive加速中 |
15 | Decel | Drive減速中 |
ZSW2
Bit | Device | Description |
0 | ActDDSBit0 | Drive data Set Bit0 |
1 | ActDDSBit1 | Drive data Set Bit1 |
2 | ActDDSBit2 | Drive data Set Bit2 |
3 | ActDDSBit3 | Drive data Set Bit3 |
4 | ActDDSBit4 | Drive data Set Bit4 |
5 | CmdActRelBrk | Release holding brake 有効 |
6 | TrqContMode | トルク制御 Operation中 |
7 | ParkAxisAct | Parking axis |
8 | Bit8 | |
9 | GibTrgReq | Global Trigger Request中 |
10 | PulsEn | Servo ONのパルス信号受け、Drive Enable中 |
11 | MotSwOverAct | Motor Data set switchover Active |
12 | SlvZykBit0 | Slave – Sign of life bit0 |
13 | SlvZykBit1 | Slave – Sign of life bit1 |
14 | SlvZykBit2 | Slave – Sign of life bit2 |
15 | SlvZykBit3 | Slave – Sign of life bit3 |
POS_ZSW1
Bit | Device | Description |
0 | ActTrvBit0 | Activating Traveling Block Bit0 |
1 | ActTrvBit1 | Activating Traveling Block Bit1 |
2 | ActTrvBit2 | Activating Traveling Block Bit2 |
3 | ActTrvBit3 | Activating Traveling Block Bit3 |
4 | ActTrvBit4 | Activating Traveling Block Bit4 |
5 | ActTrvBit5 | Activating Traveling Block Bit5 |
6 | Bit6 | |
7 | Bit7 | |
8 | StpCamMinAct | Stop CAM Minus active |
9 | StpCamPlsAct | Stop CAM Plus active |
10 | JogAct | Jog mode有効中 |
11 | RefAct | Reference mode有効中 |
12 | FlyRefAct | On-the-fly homing有効中 |
13 | TrvBlAct | Traversing Blocks mode有効中 |
14 | MdiStupAct | MDI setup Mode有効中 |
15 | MdiPosAct | MDI 位置決めMode有効中 |
POS_ZSW2
Bit | Device | Description |
0 | TrkModeAct | Tracking Mode有効中 |
1 | VeloLimact | Speedリミット有効中 |
2 | SetPSたt | Setpoint set |
3 | PrntMrkOut | Print mark outside outer window |
4 | FWD | 軸が正回転中 |
5 | BWD | 軸が逆回転中 |
6 | SftSwMinAct | Software リミット-が有効中 |
7 | SftSwPlsAct | Software リミット+が有効中 |
8 | PosSmCam1 | 現在位置は<=Cam switch 位置1 |
9 | PosSmCam2 | 現在位置は<=Cam switch 位置2 |
10 | TrvOut1 | Traversing block経由のDirect out 1 |
11 | TrvOut2 | Traversing block経由のDirect out 2 |
12 | FxStpRd | Fixed Stop reached |
13 | FxStpTrRd | Fixed stop clamping torque reached |
14 | TrvFxStpAct | Travel to fixed stop active |
15 | CmdAct | Traversing Task有効された |
MELDW
DriveのStatus -codeです。
XIST_A
現在の位置です。
NIST_B
現在の速度です。
FAULTCode
DriveのFault Codeです。
WARNCode
DriveのWarning Codeです。
user
1word のあまりがあり、アプリケーションに合わせて自由で割り当てることができます。
Block EPOS_Tel111
State
Simulation Block EPOS_Tel111は現在の状態を示す表示があります。
Test with Jog
01>02>08>1EこのようにServo OnからJogまでは01>02>08>1EのようにStatusをシフトしています、詳しくはManualみてください。
Test
Servo ON From Panel
ブログラムで動かす前に、まずcontrol panel から手で動かし動作確認するのが私のやり方です。simit simulationを起動し、block のところをクリックします。
そのような画面が表示されます。
Stw の強制on off やzsw の信号一覧やドライブのステータス確認できます。
最初はSTW1のLB信号をオンにします。
LBのとなりにある四角をクリックしてください。
そうすると、LBとなりにもう一つの四角が青色になります。もしエラーがあればまずAckFault 信号をいれてリセットしてください。
エラーがリセットされたら、次はservo を準備状態に移行します。
Enc、 ReqTrvTsk、IntMSop 信号をオンにします。
次はOff2、 Off3をオンにします。
ドライブでZSW1のNoOff2Act NoOff3Actがオンになるはずです。あとRTS信号も返してくれます。
Servo on します。
Off1 をオンにしてください。
Servo onになったら、RTS、RDY、IOpはTrue になります。それでservo の準備OKです。
Absolute Positioning From Panel
絶対位置決めをpanel 上で行います。
Operation Mode settingsのエリアでValid のランプが赤くなってます。これは指令値が問題が有ることを示してます。
最後にこのエラーを解除するまで、続けてください。
POS_STW1 にあるMidTyp を1つ入れます。Mdiの絶対位置決めモードになり、そしMdiStartをオンし、Mdi mode にセットします。
さきvaild 赤ランプのエラー原因はMDI_VELOCITY MDI_ACC MDI_DECの3つのprofidrive data が0になってるからです。
Simulation block をクリックし、下のプロパティにあるinput をクリックします。
MDI_TARPOS MDI_VELOCITY MDI_ACC MDI_DECにそれぞれの指令値を入力します。
変数の隣にあるマイナスボタンをクリックします。
いまそれぞれのテスト値を入れてみました。
そしてblock 上に現在値が表示されるように123ボタンをクリックします。
よし、強制設定した値が入りましたね。
さっきのpanel をもう一度みますと、valid ランプが緑になりました。それで問題なし。
どこのメーカーでも同じだと思いますが、位置決めする前にまずreference point を決める必要があります。色々なhoming 方法がありますが、今回は一番簡単な直接reference point 指定する方法をしました。
POS_STW2のSetRelPt信号をオンにします。
もちろん、homing 方向きめ、STW1のRefStart 信号をオンする方法もありますが、ここで説明しませんので、きになる方manual を参考にしてください。
話に戻りますが、reference point がOKになった状態であれらZSW1のRefPSet がTrue になります。
最後は、Mdi task を実行するのみです。
TrvStart をオンにしてみてください。
下記のgif のように、servo が目標値に向かって加速したり減速したりします。
そして、目標値に到着するとZSW1のTargPos
信号がtrue になります。そのflag を位置決め完了信号として使用しましょう。
Relative Positioning From Panel
次は相対位置決めをします。
やり方はさっきの絶対位置決めと同じく、POS_STW1のMidTyp を0にします。
そうすると、いまservo が相対位置決めモードになります。
MDI_TARPOSをテスト値50にいれます。
つまり今いる位置が+50 になります。
逆に-50ならいまいる位置を50バックします。
以下のgif のように、相対位置決めを開始すると元が500はいま550になります。
Project
SIMIT SIde
ではSIMIT側から始めます。
Mapping
まずOPCUA Couplingを作成します。
Input/Outptを定義します。
Chart
最後は変数群をEPOS_Tel111割り付ければOKです。
TwinCAT Side
SIMT側が終わったら次はTwinCAT側です。このFunction BlockはSiemensのEPOS Library、あの有名なSINA_POSを分解した簡単バージョンです。よろしくおねがいします。
DUT
DUT_Telg111_ePos_HMI_P
このDUTではhim からのservo 操作に必要なデバイスを定義します。
TYPE DUT_Telg111_ePos_HMI_PB : STRUCT //PB bOFF1 :BOOL; bReset :BOOL; bJogFw :BOOL; bJogbw :BOOL; bHome :BOOL; bMoveAbs :BOOL; bMoveRel :BOOL; //Pars d32CmdVel :DINT:=100; d32CmdAcc :DINT:=10; d32CmdDec :DINT:=10; d32RelPos :DINT:=10; //Station arrStations :ARRAY[0..9]OF DINT; d16CmdStations :INT; // bTableInput :BOOL:=True; END_STRUCT END_TYPE |
DUT_Telg111_ePos_HMI_PL
Servo の状態をhim 表示させるためのデバイスです。
TYPE DUT_Telg111_ePos_HMI_PL : STRUCT bReady :BOOL; bBusy :BOOL; bError :BOOL; bWarning :BOOL; bFwing :BOOL; bBwing :BOOL; bHomed :BOOL; bReached :BOOL; bStopped :BOOL; d32ActualSpeed :DINT; d32ActualPos :DINT; d16WarningCode :DINT; d16ErrorCode :DINT; d16StatusWord :DINT; d16ActualStation :int; END_STRUCT END_TYPE |
DUT_Telg111_ePos_HMI
PBとPLを定義したあと、こちらのDUTでまとめて定義する。
TYPE DUT_Telg111_ePos_HMI : STRUCT PB:DUT_Telg111_ePos_HMI_PB; PL:DUT_Telg111_ePos_HMI_PL; END_STRUCT END_TYPE |
DUT_Telegram111_ePos_Pos_STW1
STW1のDUTです。
TYPE DUT_Telegram111_ePos_Pos_STW1 : STRUCT bTrvBit0 :BIT; bTrvBit1 :BIT; bTrvBit2 :BIT; bTrvBit3 :BIT; bTrvBit4 :BIT; bTrvBit5 :BIT; b6,b7 :BIT; bMdiTyp :BIT; //0=Relative,1=absolute bMdiPos :BIT; bMdiNeg :BIT; b11 :BIT; bMdiTrTyp :BIT; b13 :BIT; bMdiSetup :BIT; //0=Position,1=Setup bMdiStart :BIT; //Operating mode MDI / direct setpoint specification END_STRUCT END_TYPE |
DUT_Telegram111_ePos_Pos_STW2
STW2のDUTです。
TYPE DUT_Telegram111_ePos_Pos_STW2 : STRUCT bTrkMode :BIT; bSetRefPt :BIT; bActRefCam :BIT; b3,b4 :BIT; bJogInc :BIT; b6,b7 :BIT; bRefTyp :BIT; bRefStDi :BIT; bRefInpS :BIT; bRefEdge :BIT; b12,b13 :BIT; bSftLimAct :BIT; bStpCamAct :BIT; END_STRUCT END_TYPE |
DUT_Telegram111_ePos_STW1
POS_STW1のDUTです。
TYPE DUT_Telegram111_ePos_STW1 : STRUCT bOff1 :BIT; bOff2 :BIT; bOff3 :BIT; bEnc :BIT; //Ivnerter Enable bRejTrvTsk :BIT; bIntMStop :BIT; bTrvStart :BIT; //Activate traversing task bAckFault :BIT; bJog1 :BIT; bJog2 :BIT; bLB :BIT; bRefStart :BIT; b12,b13,b14,b15 :BIT; END_STRUCT END_TYPE |
DUT_Telegram111_ePos_STW2
POS_STW2のDUTです。
TYPE DUT_Telegram111_ePos_STW2 : STRUCT bDDSBit0 :BIT; bDDSBit1 :BIT; bDDSBit2 :BIT; bDDSBit3 :BIT; bDDSBit4 :BIT; bGlbStart :BIT; bResIComp :BIT; bActPrkAxis :BIT; bTrvFixedStp :BIT; bGlbTrgCom :BIT; b10 :BIT; bMotSwOver :BIT; bMsZykBit0 :BIT; bMsZykBit1 :BIT; bMsZykBit2 :BIT; bMsZykBit3 :BIT; END_STRUCT END_TYPE |
u_Telegram111_ePos_STW1
Simit のopcua server がsupport てきるdata type と合わせる必要がありますのでunion type わ再定義します。
そうするとtwincat 側が割付け必要なのはそのrawだけになります。
TYPE u_Telegram111_ePos_STW1 : UNION STW :DUT_Telegram111_ePos_STW1; raw :LINT; END_UNION END_TYPE |
u_Telegram111_ePos_STW2
u_Telegram111_ePos_STW1の定義理由と同じです。
TYPE u_Telegram111_ePos_STW2 : UNION STW :DUT_Telegram111_ePos_STW2; raw :LINT; END_UNION END_TYPE |
DUT_Telegram111_ePos_STW
最後に、telegram 111のSTW message frame まとめで再定義するOKです!
TYPE DUT_Telegram111_ePos_STW : STRUCT STW1 :u_Telegram111_ePos_STW1; Pos_STW1 :u_Telegram111_ePos_Pos_STW1; Pos_STW2 :u_Telegram111_ePos_Pos_STW2; STW2 :u_Telegram111_ePos_STW2; OVERRIDE :LINT; MDI_TAGPOS :LINT; MDI_VELOCITY :LINT; MDI_ACC :LINT; MDI_DEC :LINT; User :LINT; END_STRUCT END_TYPE |
DUT_Telegram111_ePos_Pos_ZSW1
ZSW1のDUTです。
TYPE DUT_Telegram111_ePos_Pos_ZSW1 : STRUCT bActTrvBit0 :BIT; bActTrvBit1 :BIT; bActTrvBit2 :BIT; bActTrvBit3 :BIT; bActTrvBit4 :BIT; bActTrvBit5 :BIT; b6,b7 :BIT; bStpCamMinAct :BIT; bStpCamPlsAct :BIT; bJogAct :BIT; bRefAct :BIT; bFlyRefAct :BIT; bTrvBlAct :BIT; bMdiStupAct :BIT; bMdiPosAct :BIT; END_STRUCT END_TYPE |
DUT_Telegram111_ePos_Pos_ZSW2
ZSW2のDUTです。
TYPE DUT_Telegram111_ePos_Pos_ZSW2 : STRUCT bTrkModeAct :BIT; bVeloLimAct :BIT; bSetPStat :BIT; bPrntMrkOut :BIT; bFWD :BIT; bBWD :BIT; bSftSwMinAct :BIT; bSftSwPlsAct :BIT; bPosSmCam1 :BIT; bPosSmCam2 :BIT; bTrvOut1 :BIT; bTrvOut2 :BIT; bFxStpRd :BIT; bFxStpTrRd :BIT; bTrvFxStpAct :BIT; bCmdAct :BIT; END_STRUCT END_TYPE |
DUT_Telegram111_ePos_ZSW1
POS_ZSW1のDUTです。
TYPE DUT_Telegram111_ePos_ZSW1 : STRUCT bRTS :BIT; bRDY :BIT; bIOp :BIT; bFault :BIT; bNoOff2Act :BIT; bNoOff3Act :BIT; bPowInhbt :BIT; bAlarm :BIT; bNoFlwErr :BIT; bLbCr :BIT; bTargPos :BIT; bRefPSet :BIT; bTrvTskAck :BIT; bStndStill :BIT; bAccel :BIT; bDecel :BIT; END_STRUCT END_TYPE |
DUT_Telegram111_ePos_ZSW2
ZSW2のDUTです。
TYPE DUT_Telegram111_ePos_ZSW2 : STRUCT bActDDSBit0 :BIT; bActDDSBit1 :BIT; bActDDSBit2 :BIT; bActDDSBit3 :BIT; bActDDSBit4 :BIT; bCmdActRelBrk :BIT; bTrqContMode :BIT; bParkAxisAct :BIT; b8 :BIT; bGlbTrgReq :BIT; bPulsEn :BIT; bMotSwOverAct :BIT; bSlvZykBit0 :BIT; bSlvZykBit1 :BIT; bSlvZykBit2 :BIT; bSlvZykBit3 :BIT; END_STRUCT END_TYPE |
u_Telegram111_ePos_Pos_ZSW1
u_Telegram111_ePos_STW1の定義理由と同じです。
TYPE u_Telegram111_ePos_Pos_ZSW1 : UNION ZSW :DUT_Telegram111_ePos_Pos_ZSW1; raw :LINT; END_UNION END_TYPE |
u_Telegram111_ePos_Pos_ZSW2
u_Telegram111_ePos_STW1の定義理由と同じです。
TYPE u_Telegram111_ePos_Pos_ZSW2 : UNION ZSW :DUT_Telegram111_ePos_Pos_ZSW2; raw :LINT; END_UNION END_TYPE |
u_Telegram111_ePos_ZSW1
u_Telegram111_ePos_STW1の定義理由と同じです。
TYPE u_Telegram111_ePos_ZSW1 : UNION ZSW :DUT_Telegram111_ePos_ZSW1; raw :LINT; END_UNION END_TYPE |
u_Telegram111_ePos_ZSW2
u_Telegram111_ePos_STW1の定義理由と同じです。
TYPE u_Telegram111_ePos_ZSW2 : UNION ZSW :DUT_Telegram111_ePos_ZSW2; raw :LINT; END_UNION END_TYPE |
DUT_Telegram111_ePos_ZSW
最後に、telegram 111のZSW
message frame まとめで再定義するOKです!
TYPE DUT_Telegram111_ePos_ZSW : STRUCT ZSW1 :u_Telegram111_ePos_ZSW1; POS_ZSW1 :u_Telegram111_ePos_Pos_ZSW1; POS_ZSW2 :u_Telegram111_ePos_Pos_ZSW2; ZSW2 :u_Telegram111_ePos_ZSW2; MELDW :LINT; XIST_A :LINT; NIST_B :LINT; FAULTCode :LINT; WARNCode :LINT; User :LINT; END_STRUCT END_TYPE |
DUT_Telegram111_ePos
STW とZSWをそれぞれ分けてfunction block 定義するのは面倒だし名前ややこしくなりますので、STWはprocess output , ZSWはprocess input として更に定義します。
このデータタイブのfunction block内で使用します。
TYPE DUT_Telegram111_ePos : STRUCT STW AT %Q* :DUT_Telegram111_ePos_STW; ZSW AT %I* :DUT_Telegram111_ePos_ZSW; END_STRUCT END_TYPE |
FB_Telgram111_Basic
このfunction block はtelegram 111使用しMdi mode でservo on , home , jog ,相対位置決め,絶対位置決めと状態診断を最低限で実装したものです。なのでinterlock は絶対たりませんので、流用するのであればそのock extend しinterlock と機能を追加するか、参考にして書き直すかがおすすめです。
VAR
FUNCTION_BLOCK FB_Telgram111_Basic IMPLEMENTS ITF_Teleg111 VAR_INPUT END_VAR VAR_OUTPUT END_VAR VAR IOs :DUT_Telegram111_ePos; _bError :BOOL; _bWarning :BOOL; END_VAR |
PROPERTY Busy : BOOL
GET
Servo がコマンド実行中か動いてる最中であればtrue 返しします。
Busy:=NOT Fwing AND NOT Bwing AND NOT IOs.ZSW.POS_ZSW2.ZSW.bCmdAct ; |
PROPERTY Bwing : BOOL
GET
Servo が逆回転であればtrue 返しします。
Bwing:=IOs.ZSW.POS_ZSW2.ZSW.bBWD; |
PROPERTY DriveErroCode : DINT
GET
Servo のerror code を返しします。
DriveErroCode:=LINT_TO_DINT(IOs.ZSW.WARNCode); |
PROPERTY DriveStatusCode : DINT
GET
Servo のstatus code を返しします。
DriveStatusCode:=LINT_to_DINT(IOs.ZSW.MELDW); |
PROPERTY DriveWarningCode : DINT
GET
Servo のwarning code を返しします。
DriveWarningCode:=LINT_TO_DINT(IOs.ZSW.WARNCode); |
PROPERTY Error : BOOL
Servo がエラー中であればtrue 返しします。
GET
Error:=IOs.ZSW.ZSW1.ZSW.bFault; |
PROPERTY Fwing : BOOL
Servo が正回転であればtrue 返しします。
GET
Fwing:=IOs.ZSW.POS_ZSW2.ZSW.bFWD; |
PROPERTY Homed : BOOL
Servo がreferenceすみの状態であればtrue 返しします。
GET
Homed:=IOs.ZSW.ZSW1.ZSW.bRefPSet; |
PROPERTY ReachPosition : BOOL
Servo が位置決め完了であればtrue 返しします。
GET
ReachPosition:=IOs.ZSW.ZSW1.ZSW.bTargPos; |
PROPERTY Ready : BOOL
Servo がready の状態であればtrue 返しします。
GET
Ready:=IOs.ZSW.ZSW1.ZSW.bIOp; |
PROPERTY Stopped : BOOL
Servo が停止中であればtrue 返しします。
GET
Stopped:=NOT Fwing AND NOT Bwing; |
PROPERTY Warning : BOOL
Servo がwarning発生中であればtrue 返しします。
GET
Warning:=IOs.ZSW.ZSW1.ZSW.bAlarm; |
PROPERTY ActualPos : DINT
Servo の現在位置を返します。
GET
ActualPos:=LINT_TO_DINT(IOs.ZSW.XIST_A); |
PROPERTY ActualSpeed : DINT
Servo の現在速度を返します。
GET
ActualSpeed:=LINT_TO_DINT(IOs.ZSW.NIST_B); |
METHOD Home : BOOL
呼び出すとservo がreference point をセットします。
VAR_INPUT in : BOOL; END_VAR VAR_INST R_TRIG:R_TRIG; TON:TON; END_VAR R_TRIG( CLK:=in ); IF R_TRIG.Q AND Stopped AND NOT Error THEN IOs.STW.Pos_STW2.STW.bSetRefPt:=TRUE; END_IF TON(IN:=IOs.STW.Pos_STW2.STW.bSetRefPt ,PT:=T#1S ); IF TON.Q THEN IOs.STW.Pos_STW2.STW.bSetRefPt:=False; END_IF |
METHOD JogBW : BOOL
呼び出すとinがtrue であればservo がjog 逆回転し始めます。
VAR_INPUT in:BOOL; END_VAR IOs.STW.STW1.STW.bJog2:=in AND NOT Error; JogBW:=IOs.STW.STW1.STW.bJog2; |
METHOD JogFW : BOOL
呼び出すとinごtrueてあればservo がjog 正回転し始めます。
VAR_INPUT in:BOOL; END_VAR IOs.STW.STW1.STW.bJog1:=in AND NOT Error; JogFW:=IOs.STW.STW1.STW.bJog1; |
METHOD moveAbs : BOOL
呼び出すとservoがメソッドの位置、速度、加速度と減速度に沿って絶対位置決めします。
VAR_INPUT in : BOOL; pos:DINT; vel:DINT; Acc:DINT; dec:DINT; END_VAR VAR_INST StartCmd :R_TRIG; CmdDelay :TON; CmdOff :TON; END_VAR . CmdDelay( IN:=CmdDelay.Q AND NOT Busy AND Homed ,PT:=T#0.2S ); StartCmd( CLK:=in ); IF StartCmd.Q THEN IOs.STW.Pos_STW1.STW.bMdiTyp:=TRUE; IOs.STW.MDI_TAGPOS:=pos; IOs.STW.MDI_ACC:=Acc; IOs.STW.MDI_DEC:=dec; IOs.STW.MDI_VELOCITY:=vel; IOs.STW.STW1.STW.bTrvStart:=TRUE; END_IF CmdOff( IN:=IOs.STW.STW1.STW.bTrvStart ,PT:=T#1S ); IF CmdOff.Q THEN IOs.STW.STW1.STW.bTrvStart:=FALSE; END_IF moveAbs:=IOs.STW.Pos_STW1.STW.bMdiTyp ; |
METHOD moveRel : BOOL
呼び出すとservoがメソッドの位置、速度、加速度と減速度に沿って相対位置決めします。
VAR_INPUT in : BOOL; pos : DINT; vel : DINT; Acc : DINT; dec : DINT; END_VAR VAR_INST StartCmd :R_TRIG; CmdDelay :TON; CmdOff :TON; END_VAR CmdDelay( IN:=CmdDelay.Q AND NOT Busy AND Homed ,PT:=T#0.2S ); StartCmd( CLK:=in ); IF StartCmd.Q THEN IOs.STW.Pos_STW1.STW.bMdiTyp:=FALSE; IOs.STW.MDI_TAGPOS:=pos; IOs.STW.MDI_ACC:=Acc; IOs.STW.MDI_DEC:=dec; IOs.STW.MDI_VELOCITY:=vel; IOs.STW.STW1.STW.bTrvStart:=TRUE; END_IF CmdOff( IN:=IOs.STW.STW1.STW.bTrvStart ,PT:=T#1S ); IF CmdOff.Q THEN IOs.STW.STW1.STW.bTrvStart:=FALSE; END_IF moveRel:=NOT IOs.STW.Pos_STW1.STW.bMdiTyp ; |
METHOD Reset : BOOL
呼び出すとリセットflag をservo に渡しします。
VAR_INPUT in:BOOL; END_VAR IOs.STW.STW1.STW.bAckFault:=in; |
METHOD ServoON : BOOL
呼び出すとin がオンしてる間servo off1 信号をservo へ渡しします。
VAR_INPUT in : BOOL; END_VAR VAR_INST TON:TON; END_VAR TON(IN:=in ,PT:=T#0.2S ); IOs.STW.STW1.STW.bOff1:=TON.Q; |
METHOD SetDefaultConfiguration : BOOL
最低限必要なビットをセットします。アプリケーションに合わせてそのメソッドをoverwriteしてください。
IOs.STW.STW1.STW.bOff2 :=TRUE; IOs.STW.STW1.STW.bOff3 :=TRUE; IOs.STW.STW1.STW.bEnc :=TRUE; IOs.STW.STW1.STW.bIntMStop :=TRUE; IOs.STW.STW1.STW.bRejTrvTsk :=TRUE; IOs.STW.STW1.STW.bLB :=TRUE; IOs.STW.Pos_STW1.STW.bMdiStart :=TRUE; |
POU-MAIN
今回はあえてhmi のデバイスをfunction blockに組み込めないようにします。なぜかというと最近は色々組めすぎるになるとあとからの柔軟性が減ってしまうと感じた。でも、そのまま書くとプログラムが長くなり可読性が減少します。
Beckhoff Siemens codesys などライブラリを提供するときはあくまでもここまでで、そのあとのほかの操作の連携は自力で実装する必要があります。もちろんもっとかっつりの操作画面と自動手動インタフェースが提供されますが、カスタマイズするときにその分、難易度が上がります。
そのサンブルコードはまずopc ua 接続をチェック>function block呼び出し>servo on> reset >home > jog >error 検知>相対位置決めと絶対位置決め>hmi data とやり取りの順です。
PROGRAM MAIN VAR bEnable:BOOL; OpcUaDeviceStatus AT %I*:OpcUaDeviceStatus; OpcUaDeviceControl AT %Q*:OpcUaDeviceControl; Servo1 :FB_Telgram111_Basic; HMIs:DUT_Telg111_ePos_HMI; bCmdsVaild:BOOL; BackupCmd:INT; d32Cmdpos:DINT; bIL:BOOL; R_TRIG,PosReached,AbsMoving:R_TRIG; END_VAR IF OpcUaDeviceStatus.Connected THEN OpcUaDeviceControl.Write_Enable:=TRUE; bEnable:=True; ELSE OpcUaDeviceControl.Write_Enable:=FALSE; bEnable:=FALSE; END_IF Servo1(); Servo1.SetDefaultConfiguration(); Servo1.ServoON(in:=HMIs.PB.bOFF1 AND bEnable); Servo1.Reset(in:=HMIs.PB.bReset); Servo1.Home(in:=HMIs.PB.bHome); R_TRIG( CLK:=Servo1.Homed ); IF R_TRIG.Q THEN HMIs.PB.bHome:=FALSE; END_IF; bIL:= NOT HMIs.PB.bMoveRel AND NOT HMIs.PB.bJogbw AND NOT HMIs.PB.bMoveAbs; IF Servo1.JogFW(in:=HMIs.PB.bJogFw AND bIL) THEN HMIs.PL.d16ActualStation:=0; END_IF bIL:= NOT HMIs.PB.bMoveRel AND NOT HMIs.PB.bJogfw AND NOT HMIs.PB.bMoveAbs; IF Servo1.JogBW(in:=HMIs.PB.bJogbw AND bIL) THEN HMIs.PL.d16ActualStation:=0; END_IF bIL:= NOT HMIs.PB.bMoveRel AND NOT HMIs.PB.bJogbw AND NOT HMIs.PB.bJogFw; bCmdsVaild:=HMIs.PB.d16CmdStations <>0 AND BackupCmd <> HMIs.PB.d16CmdStations; AbsMoving(CLK:=HMIs.PB.bMoveAbs AND bCmdsVaild AND bIL); IF AbsMoving.Q THEN d32Cmdpos:=HMIs.PB.arrStations[HMIs.PB.d16CmdStations]; BackupCmd:=HMIs.PB.d16CmdStations; HMIs.PB.d16CmdStations:=0; HMIs.PL.d16ActualStation:=0; END_IF Servo1.moveAbs( in:=HMIs.PB.bMoveAbs AND bCmdsVaild ,pos:=d32Cmdpos ,vel:=HMIs.PB.d32CmdVel ,Acc:=HMIs.PB.d32CmdAcc ,dec:=HMIs.PB.d32CmdDec ) ; bIL:= NOT HMIs.PB.bMoveAbs AND NOT HMIs.PB.bJogbw AND NOT HMIs.PB.bJogFw; IF Servo1.moveRel( in:=HMIs.PB.bMoveRel AND bIL ,pos:=HMIs.PB.d32RelPos ,vel:=HMIs.PB.d32CmdVel ,Acc:=HMIs.PB.d32CmdAcc ,dec:=HMIs.PB.d32CmdDec) THEN HMIs.PL.d16ActualStation:=0; END_IF; PosReached(CLK:=Servo1.ReachPosition); IF PosReached.Q THEN HMIs.PL.d16ActualStation:=BackupCmd; HMIs.PB.d16CmdStations:=0; BackupCmd:=0; END_IF //Status HMIs.PL.bBusy:=Servo1.Busy; HMIs.PL.bBwing:=Servo1.Bwing; HMIs.PL.bFwing:=Servo1.Fwing; HMIs.PL.bError:=Servo1.Error; HMIs.PL.bHomed:=Servo1.Homed; HMIs.PL.bReached:=Servo1.ReachPosition; HMIs.PL.bReady:=Servo1.Ready; HMIs.PL.bStopped:=Servo1.Stopped; HMIs.PL.bWarning:=Servo1.Warning; HMIs.PL.d32ActualPos:=Servo1.ActualPos/10; HMIs.PL.d32ActualSpeed:=Servo1.ActualSpeed/100; HMIs.PL.d16ErrorCode:=Servo1.DriveErroCode; HMIs.PL.d16StatusWord:=Servo1.DriveStatusCode; HMIs.PL.d16WarningCode:=Servo1.DriveWarningCode; HMIs.PB.arrStations[1]:=-100; HMIs.PB.arrStations[2]:=100; HMIs.PB.arrStations[3]:=150; HMIs.PB.arrStations[4]:=300; HMIs.PB.arrStations[5]:=10; HMIs.PB.arrStations[6]:=0; HMIs.PB.arrStations[7]:=-40; HMIs.PB.arrStations[8]:=60; HMIs.PB.arrStations[9]:=90; |
Visualization
こちらは操作画面です。
Result
必要なposition とコマンドに応じてservo が動きます。
Jog
Rel
Abs
Source Code
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT%20Project1_Telegram111_WithSIMIT.zip