オムロン KM20-B40-FLK RS-485 通信 2020/10/04
オムロンの電力量センサ KM20-B40-FLK RS-485 通信です。
Modbus ではなく、CompoWay/F というオムロン独自の通信手順 + FINS-mini コマンドです。
現在 KM20-B40-FLK は廃番になっており、代替機種の KM-N1-FLK は Modbus RTU にも対応しているようです。
電力量ではなくて、簡単に交流電流値を計測(PLC に接続)するだけであれば、下記 URD 社製が良さそうです。
■平均値整流型 0-5V 出力(歪波形は誤差大)
https://jp.misumi-ec.com/vona2/detail/221000835720/
■実効値整流型 4-20mA 出力(2線式)
https://jp.misumi-ec.com/vona2/detail/221000835731/
{ OMRON KM20-B40-FLK (RS485タイプ) CompoWay/F は、オムロンの汎用シリアル通信における統一通信手順。 FINS (Factory Interface Network service) とは、 オムロンの FA ネットワーク上のコントローラ間で、メッセージ通信を行うためのプロトコル。 } unit uni232test; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Uni232C; type TForm5 = class(TForm) Uni232C1: TUni232C; Button1: TButton; Button2: TButton; Button3: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } end; var Form5: TForm5; implementation {$R *.dfm} // 接続 procedure TForm5.Button1Click(Sender: TObject); var ret : integer; begin Uni232C1.Port := 3; Uni232C1.BaudRate := 19200; Uni232C1.ByteSize := Bit8; Uni232C1.ParityBits := ParityNone; Uni232C1.StopBits := Stopbit1; Uni232C1.FlowControls := CtrlNone; ret := Uni232c1.Open; if ret < 0 then ShowMessage('Cannot OPEN' + Uni232C1.Error2Str(ret)); end; // 切断 procedure TForm5.Button2Click(Sender: TObject); begin if Uni232C1.Connect then Uni232C1.Close; end; // データ読み込み procedure TForm5.Button3Click(Sender: TObject); var txData, rxData : TBytes; cmd, res : string; bcc : Byte; len : integer; ret : integer; i : integer; begin if Uni232C1.Connect then begin cmd := #02; // STX cmd := cmd + '01'; // ノードNo. cmd := cmd + '00'; // サブアドレス = "00" cmd := cmd + '0'; // SID = "0" // 以下、FINS-mini コマンド・テキスト cmd := cmd + '0101'; // MRC, SRC 変数エリア読出の場合 cmd := cmd + 'C0'; // 変数種別 "C0","C2"~"C3" のいずれか // "0000" = P1-P2間電圧(瞬時値) 小数点以下 1 桁 // "0001" = P2-P3間電圧(瞬時値)小数点以下 1 桁 // "0002" = I1電流(瞬時値)(A) 小数点以下 2 桁 // "0003" = I2電流(瞬時値)(A) 小数点以下 2 桁 // "0004" = 有効電力(瞬時値)(kW) 小数点以下 2 桁 // "0005" (欠番) // "0006" = 力率 (瞬時値) 小数点以下 2 桁 // "0007" = 周波数(Hz) 小数点以下 1 桁 // "0008" = 積算電力量(kWh) 小数点以下 1 桁 // "0009" (欠番) // "000A" = ステータス // "000B" = バージョン cmd := cmd + '0000'; // 読み出し開始アドレス cmd := cmd + '00'; // ビット位置 "00" 固定 cmd := cmd + '000B'; // 読み出し数(16進表記)最大 11 ($0B) 個まで Len = 105( 8 * 11 +17 ) cmd := cmd + #03; // ETX txData := TEncoding.ANSI.GetBytes(cmd); len := Length(txData); // BCC (ブロックチェックキャラクタ)計算 // STX の次 ノードNo. から ETX までの XOR bcc := 0; for i := 1 to len - 1 do // ETX を含む bcc := bcc xor txData[i]; SetLength(txData, len + 1); txData[len] := bcc; // 最後に BCC を追加 // 送信 Uni232C1.Write(len + 1, @txData[0]); Sleep(10); SetLength(rxData, 128); // 受信データバイト数ピッタリ+1で良い // 受信 ret := Uni232C1.Read(128, @rxData[0]); Memo1.Lines.Add('Len = ' + ret.ToString); // 受信バイト数 // 正常時 // バイト数 = データ数 * 8 + 14 + 2(STX,ETX) + 1(#0) // データ数が2の時は 2 * 8 + 17 = 33 // BCC エラー時 // バイト数 = 9 ; STX + "0100" (ノードNo.+ サブアドレス) + "13"(BCCエラー) + ETX + #0 res := TEncoding.ANSI.GetString(rxData); res := Trim(res); // 制御文字を含まない Memo1.Lines.Add(res); if ret >= 8 * 11 + 17 then begin // データ数 = 11 の時 // "01" ノードNo. // "00" サブアドレス // "00" 終了コード "00" であれば正常終了 // "01" MRC, // "01" SRC // "00" MRES // "00" SRES // "000003FA" P1-P2 間の電圧 $3FA = 1018 これの 1/10 が電圧値 = 101.8 V // "00000000" P2-P3 間の電圧 // ....以降データ数に応じて、8 桁 16 進表記の文字が続く Memo1.Lines.Add('P1-P2 間電圧 = ' + Format('%.1f V', [StrToIntDef('$' + Copy(res, 15, 8), 0) * 0.1])); Memo1.Lines.Add('P2-P3 間電圧 = ' + Format('%.1f V', [StrToIntDef('$' + Copy(res, 23, 8), 0) * 0.1])); Memo1.Lines.Add('I1 電流 = ' + Format('%.2f A', [StrToIntDef('$' + Copy(res, 31, 8), 0) * 0.01])); Memo1.Lines.Add('I2 電流 = ' + Format('%.2f A', [StrToIntDef('$' + Copy(res, 39, 8), 0) * 0.01])); Memo1.Lines.Add('有効電力 = ' + Format('%.2f kW', [StrToIntDef('$' + Copy(res, 47, 8), 0) * 0.01])); // "0005" 欠番のデータは無視 Memo1.Lines.Add('力率 = ' + Format('%.2f ', [StrToIntDef('$' + Copy(res, 63, 8), 0) * 0.01])); Memo1.Lines.Add('周波数 = ' + Format('%.1f Hz', [StrToIntDef('$' + Copy(res, 71, 8), 0) * 0.1])); Memo1.Lines.Add('積算電力量 = ' + Format('%.1f kWh', [StrToIntDef('$' + Copy(res, 79, 8), 0) * 0.1])); end; end; end; end.