powershellスクリプトで三菱電機(株)製PLC(シーケンサ)iQ-R,Qシリーズとシリアル通信を行います。実行環境は、以下となります。
項目 | 内容 |
---|---|
対象としたシリアルポート | シリアルコミュニケーションユニット:RJ71C24,RJ71C24-R2,QJ71C24N,QJ71C24N-R2 QCPUのシリアルポート(RS-232C) |
通信手順 | MCプロトコル、QnA互換3Cフレーム形式4、サムチェックあり |
通信仕様 | 通信速度9600bps、データ長8ビット、1ストップビット、奇数パリティ |
GX Works3のナビゲーションウインドウのプロジェクトから[パラメータ]-[ユニット情報]-[****:RJ71C24]の「ユニットパラメータ」を マウスダブルクリックし設定シートを表示します。(RJ71C24は、ユニットパラメータに登録されているものとします。) CH1に設定します。交信プロトコル「MCプロトコル(形式4)」、通信速度「9600bps」、動作設定「独立」、データビット「8」、 パリティビット「あり」、奇数/偶数パリティ「奇数」、ストップビット「1」、サムチェックコード「あり」、RUN中書込み「許可」 と設定します。
GX Works2のナビゲーションウインドウのプロジェクトからインテリジェント機能ユニット「QJ71C24N-R2」の「スイッチ設定」を
マウスダブルクリックしスイッチ設定ダイアログを表示します。(QJ71C24N-R2は、インテリジェント機能ユニットに登録されている
ものとします。)
CH1に設定します。データビット「8」、パリティビット「あり」、奇数/偶数パリティ「奇数」、ストップビット「1」、
サムチェックコード「あり」、RUN中書込み「許可」、通信速度「9600bps」、交信プロトコル「MCプロトコル(形式4)」
と設定します。
GX Works2のナビゲーションウインドウのプロジェクトから
PCパラメータ マウスダブルクリックでQパラメータ設定ダイアログを表示します。
シリアルコミュニケーション設定ダブを選択します。
「シリアルコミュニケーション機能を使用する」にチェックを入れます。伝送速度を「9.6kBPS」、サムチェック「あり」にチェックを入れ、
伝送ウエイト時間を「ウエイト無し」、RUN中書込設定を「許可する」にチェックを入れます。
下記サンプルソフトは、レジスタのD0100より10ワード読み込みを行ってます。受信時のサムチェック及び
その他のエラー処理は行ってません。「Q」キーで終了します。
プログラム実行は、コンソールウインドウで実行して下さい。ISEでは、エラーとなります。
iQ-Rではコマンドが追加されています。(サブコマンド) 追加されたコマンドではデバイスコードが4バイド、デバイス番号が8バイトとなっています。下記プログラムでは、変数 $iQRExMode で iQ-R 追加コマンド使用ありなしを指定しています。
# C24MC_3C4.pas1
# 三菱PLC シリアル通信 MCプロトコル
# QnA互換3Cフレーム形式4
Set-StrictMode -Version latest
# キー入力
function Keyin{
$rtkey = $null
if ([Console]::KeyAvailable){
$rtkey = [Console]::ReadKey($true)
}
return $rtkey
}
# 受信処理
function receive{
$il = $compt.BytesToRead
if ($il -gt 0){
[byte[]] $brbuf = New-Object byte[] $il
$ir = $compt.Read($brbuf, 0, $il) # 受信
for($ip = 0; $ip -lt $ir; $ip++){
$ba = $brbuf[$ip]
if ($icstep -eq 1 -and ($ba -eq 0x02 -or $ba -eq 0x15)){ # STX,NAK
$Script:brcv[$ircvLen] = $ba
$Script:icstep = 2
$Script:ircvLen++
}
else{
if ($icstep -eq 2){
$Script:brcv[$ircvLen] = $ba
$Script:ircvLen++
if ($ba -eq 0x0a){ # LF
$Script:icstep = 3
break;
}
}
}
}
}
}
# サム値計算
function sumCal([byte[]] $bar){
$isum = 0
foreach($ia in $bar){
$isum += $ia
}
$shex = $isum.ToString("X4")
$Script:basum[0] = [byte]$shex[2]
$Script:basum[1] = [byte]$shex[3]
}
# メイン
function main{
switch($Script:irstep){
1 {$ssa = "F90000FF00" + $srcmd + $srsbcmd + $sdv + $itopad.ToString($dvketa) + $ireadsu.ToString("X4")
[byte[]] $baa = [System.Text.Encoding]::ASCII.GetBytes($ssa)
sumCal $baa
[byte[]] $baSend = $bENQ + $baa + $basum + $bCRLF
$compt.Write($baSend, 0, $baSend.Length) # 送信
$Script:icstep = 1
$Script:irstep = 2
$Script:ircvLen = 0
}
2 {
receive
if ($icstep -eq 3){
$ik = 0
if ($sdv.substring(0, 1) -eq "D"){$ik = 4}
if ($sdv.substring(0, 1) -eq "M"){$ik = 1}
$sv = ""
[byte[]] $bar = New-Object byte[] $ik
for($ip = 0; $ip -lt $Script:ireadsu; $ip++){
[System.Array]::Copy($Script:brcv, 11 + $ip * $ik, $bar, 0, $ik)
$sv += [System.Text.Encoding]::ASCII.GetString($bar) + ","
}
Write-Host $sv
$Script:irstep = 1
$Script:icstep = 0
}
}
}
}
$iQRExMode = 0 # 1:iQ-R追加モード
$irstep = 1
$icstep = 0
$srcmd = "0401" # 読み込みコマンド
# Dデバイス読み込み
if ($iQRExMode -eq 0){ # 通常
$srsbcmd = "0000" # サブコマンド
$sdv = "D*" # Dデバイス(デバイスコード)
$dvketa = "D6" # デバイス桁
}
else{ # iQ-R追加拡張
$srsbcmd = "0002" # サブコマンド
$sdv = "D***" # Dデバイス(デバイスコード)
$dvketa = "D8" # デバイス桁
}
$itopad = 100 # 読み込み先頭
$ireadsu = 10 # 読み込み個数
# Mデバイス読み込み
<#if ($iQRExMode -eq 0){ # 通常
$srsbcmd = "0001" # サブコマンド
$sdv = "M*" # Mデバイス(デバイスコード)
$dvketa = "D6" # デバイス桁
}
else{ # iQ-R追加拡張
$srsbcmd = "0003" # サブコマンド
$sdv = "M***" # Mデバイス(デバイスコード)
$dvketa = "D8" # デバイス桁
}
$itopad = 100 # 読み込み先頭
$ireadsu = 20 # 読み込み個数
#>
if ($iQRExMode -eq 0){
Write-Host "通常モードで実行"
}
else{
Write-Host "iQ-R追加拡張モードで実行"
}
[byte[]] $bENQ = @(0x05)
[byte[]] $bCRLF = @(0x0d, 0x0a)
[byte[]] $basum = New-Object byte[] 2
[byte[]] $brcv = New-Object byte[] 512
$ircvLen = 0
$compt = New-Object System.IO.Ports.SerialPort "COM3", 9600
$compt.DataBits = 8
$compt.Parity = [System.IO.Ports.Parity]::Odd
$compt.StopBits = [System.IO.Ports.StopBits]::One
$compt.DtrEnable = $true
$compt.RtsEnable = $true
try{
$compt.Open()
}
catch{
Write-Host("COMポートOpen失敗")
exit
}
Write-Host("COMポートopen")
while($true){
main
$inkey = Keyin
if ($inkey -ne $null -and $inkey.Key -eq "Q"){
break;
}
Start-Sleep -m 50
}
$compt.Close()
Write-Host("COMポートclose")