耐圧試験システムの構築 その1からの続き。
プログラム作成について記述する。
1. プログラムの作成
繰り返しになるが、最初にシステム構成について記述しておく。
1-1. システム構成
今回は、絶縁耐圧試験器(日置電機社製 型番3159)の耐圧試験を例にシステムを構築する。
システムは、Raspberry Pi 4B(ラズパイ)、ATOM Lite、絶縁耐圧試験器から構成した。
ATOM Liteは、ラズパイに設定したWiFiアクセスポイントに接続し、ATOM Liteと絶縁耐圧試験器はレベルシフトしたRS232Cで接続した。
ラズパイとATOM Liteは、MQTTを用いてデータ交換することにした。
ラズパイに試験用データベースをMariaDBに設定し、試験項目一覧テーブルと試験結果テーブルを設けた。
ラズパイはNode-RED、ATOM LiteはUIFowでプログラムを作成した。
ユーザインタフェースは、Node-REDのダッシュボードを用いた。
1-2. シーケンス図
(1) DBに試験項目一覧を問合せ、Node-REDのダッシュボード上に表示する
(2) ダッシュボードで試験項目をキー入力し、OKボタンを押す。試験器に送信する設定コマンドが表示される。
(3) 送信ボタンを押すことで設定コマンド一式をMQTTでATOM Liteに送信する。
(4) ATOM Liteは、MQTTで設定コマンドをサブスクライブしたら、設定コマンドを1つずつRS232Cで試験器に送信する。すべてのコマンドが終了したらMQTTでreadyを返す。
(5) ラズパイは、MQTTでReadyをサブスクライブしたら、ダッシュボードのLEDを緑色にし、readyの文字を表示する。
(6) ダッシュボードでロットナンバーを入力すると、ロットナンバーがダッシュボードに表示される。
(7) ダッシュボードのスタートボタンを押すと、MQTTでstartがパブリッシュされる。
(8) ATOM Liteは、MQTTでstartをサブスクライブしたら、スタートコマンドをRS232Cで試験器に送信する。環境センサの温度、湿度、気圧をJSON形式に変換し、MQTTでパブリッシュする。
(9) ラズパイは、MQTTで温湿度データをサブスクライブしたら、flow変数に代入する。
(10) ATOM Liteは、:STARTコマンド送信後、一定間隔で:STATコマンドを送信して試験終了を確認する。
(11) WREADYを受信したら試験終了と判断して、試験結果問合せコマンド:MEAS:RES:WITH?を送信し、試験結果を取得し、JSON形式に変換してMQTTにパブリッシュする。
(12) ラズパイは、MQTTで試験結果をサブスクライブしたら、DBに登録し、ダッシュボード上に表示する。
1-2.プログラムの作成
1-2-1.Node-REDのプログラムについて
Node-REDプログラムについて、シーケンス図に沿って説明する。
(1) DBに試験項目一覧を問合せ、Node-REDのダッシュボード上に表示する
Nod-REDに以下のフローを配置する。
functionノードにSQL文をmsg.topicとして記述する。
msg.topic = "SELECT id, exam_mode, ref_voltage, exam_time, upper_limit, lower_limit, exam_volt_range FROM command;";
return msg;
mysqlノードを設定する。ユーザ名、パスワード、データベース名の欄を入力する。
templateノードを利用して表示する文字の大きさを調整する。
これを実行するとダッシュボード上に試験項目一覧が表示される。
(2) ダッシュボードで試験項目をキー入力し、OKボタンを押す。試験器に送信する設定コマンドが表示される。
formノードを利用して、試験一覧表のidを入力することで、試験器を送信する設定コマンドを選択する。
formノードは、OKボタンを押すと入力したidが表示されなくなるが、
idと送信するコマンドをテーブル表示することで確認できるようにした。
このテーブルを表示するために、formノードから出力されるidの値を元に、functionノードでSQL文を作成してデータベースを参照している。
msg.topic = "select id, cmd_mode, cmd_ref_volt, cmd_exam_time, cmd_upper_limit, cmd_lower_limit, cmd_exam_volt_range from command where id = \u0027";
msg.topic += msg.payload.id;
msg.topic += "\u0027;";
return msg;
ATOM Liteに送信するコマンド一式をflow変数commandに配列として代入し、一時保存した。
flow.set("command", [msg.payload[0].cmd_mode,vmsg.payload[0].cmd_exam_time, msg.payload[0].cmd_upper_limit, msg.payload[0].cmd_lower_limit, msg.payload[0].cmd_exam_volt_range]);
return msg;
また、試験結果をデータベースへ登録際に、idも記録するために、グローバル変数に代入する。
グローバル変数は、このフローのみに限定するために、フロー変数exam_idを設定して代入した。
flow.set("command", [msg.payload[0].cmd_mode,vmsg.payload[0].cmd_exam_time, msg.payload[0].cmd_upper_limit, msg.payload[0].cmd_lower_limit, msg.payload[0].cmd_exam_volt_range]);
return msg;
(3) 送信ボタンを押すことで設定コマンド一式をMQTTでATOM Liteに送信する。
コマンド送信ボタンを押すことで、buttonノードに接続されたfunctionノードで、flow変数commandから配列を取り出し、トピック3159/settingでMQTTにパブリッシュした。
flow変数commandから配列を取り出す。
msg.payload = flow.get("command");
return msg;
(5) ラズパイは、MQTTでReadyをサブスクライブしたら、ダッシュボードのLEDを緑色にし、readyの文字を表示する。
startをMQTTにパブリッシュする。
試験開始日時をflow変数に代入
const dt = new Date();
var date = dt.getFullYear() + '-' + (dt.getMonth() + 1) + '-' + dt.getDate();
var time = dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds();
var date_time = date +" "+ time;
flow.set("exam_date", date_time);
msg.payload = date_time;
return msg;
(6) ダッシュボードでロットナンバーを入力すると、ロットナンバーがダッシュボードに表示される。
flow.set("lot_no", msg.payload.lot_no);
msg.payload = msg.payload.lot_no;
return msg;
(7) ダッシュボードのスタートボタンを押すと、MQTTでstartがパブリッシュされる。
(9) 環境センサの値を受け取ったら、flow変数に代入する。
ATOM Liteから3159/tempのタグでMQTT送信されてくる環境センサの値(温度、湿度、気圧)をflow変数tmo, hum, atmに代入する
flow.set("tmp", msg.payload.tmp);
flow.set("hum", msg.payload.hum);
flow.set("atm", msg.payload.atm);
msg.payload = [msg.payload.tmp, msg.payload.hum, msg.payload.atm]
return msg;
また、試験結果をデータベースに登録するための準備として、試験結果保存テーブルresultから一番最後に登録したid番号を取得する。
msg.topic = "SELECT id FROM `result` ORDER BY id DESC LIMIT 1;";
return msg;
取得したid番号に1を加算して、flow変数に代入する。
var a = msg.payload[0].id;
a++;
flow.set("id", a);
msg.payload = a;
return msg;
(12) ラズパイは、試験結果を受信後、DBに登録し、ダッシュボード上に表示する。
ATOM Liteから3159/resultのタグでMQTT送信されてくる試験結果をデータベースに登録し、登録されたか確認するために最新登録のデータを取得してtableノードに送りダッシュボードに表示している。
//"INSERT INTO `result` VALUES ('id', 'lot_no', 'exam_date', 'exam_id', 'ret_volt', 'ret_current', 'ret_time', exam_result', 'tempature', 'humidity', 'atmosphere');
msg.topic = "INSERT INTO `result` VALUES ( \u0027";
msg.topic += flow.get("id");
msg.topic += "\u0027, \u0027";
msg.topic += flow.get("lot_no");
msg.topic += "\u0027, \u0027";
msg.topic += flow.get("exam_date");
msg.topic += "\u0027, \u0027";
msg.topic += flow.get("exam_id");
msg.topic += "\u0027, \u0027";
msg.topic += msg.payload.VOLT;
msg.topic += "\u0027, \u0027";
msg.topic += msg.payload.CURR;
msg.topic += "\u0027, \u0027";
msg.topic += msg.payload.TIME;
msg.topic += "\u0027, \u0027";
msg.topic += msg.payload.RSLT;
msg.topic += "\u0027, \u0027";
msg.topic += flow.get("tmp");
msg.topic += "\u0027, \u0027";
msg.topic += flow.get("hum");
msg.topic += "\u0027, \u0027";
msg.topic += flow.get("atm");
msg.topic += "\u0027 );";
return msg;
msg.topic = "select * from result where id = \u0027";
msg.topic += flow.get("id");
msg.topic += "\u0027;";
return msg;
1-2-2.UIFlowプログラムについて
初期化処理では、Raspberry PiのWiFiアクセスポイントへの接続、UARTの初期化、MQTTサーバへの接続、変数の初期化などの処理を行っている。
(4) ATOM Liteは、MQTTで設定コマンドをサブスクライブしたら、設定コマンドを1つずつRS232Cで試験器に送信する。すべてのコマンドが終了したらMQTTでreadyを返す。
MQTTのトピック3159/settingで試験器の設定コマンド配列が送られてくると、送信データの両端の[]を削除し、カンマを分割文字にリストを作成する。その後、setting変数を1にする。
ループ内では、MQTTをサブスクライブしたときに1を設定する変数をif文でチェックする構造にした。
変数settingが1である場合、settingサブルーチンを実行する。
settingサブルーチンでは、最初に絶縁耐圧試験試験器を初期化する*RSTコマンドをRS232Cへ送信する。
RS232Cのバッファをスキャンして試験器からの応答OKが確認できたら、RaspberryPiから送信された試験器の設定コマンドを順番にRS232Cに送信し、最後のコマンドに対する応答OKが確認できたら、MQTTのトピック3159/examに"ready"をパブリッシュする。
(8) ATOM Liteは、MQTTでstartをサブスクライブしたら、スタートコマンドをRS232Cで試験器に送信する。環境センサの温度、湿度、気圧をJSON形式に変換し、MQTTでパブリッシュする。
トピック3159/startをサブスクライブして受信を確認したら、変数start, status, contimueを1にする。
変数startが1なので、ループでサブルーチンstartが呼び出され実行される。
試験器にRS232Cで試験開始コマンド:SRARTを送信し、応答OKが確認されたら、MQTTのトピック3159/returnに"working"をパブリッシュする。
環境センサの値をサブルーチンtemp2Map2JSONを実行してJSON形式に変換し、MQTTのトピック3159/tempにパブリッシュする。
サブルーチンtemp2Map2JSON
(10) ATOM Liteは、:STARTコマンド送信後、一定間隔で:STAT?コマンドを送信して試験終了を確認する。
変数statusが1なので、ループでサブルーチンstatusが呼び出され実行される。
サブルーチンstatusでは、試験器にRS232Cで状態確認コマンド:STAT?を送信し、応答がWTESTであれば、MQTTのトピック3159/returnに"working"をパブリッシュする。応答がWREADYになるまで繰り返す。
応答がWREADYであれば、試験終了と判断し、試験結果問合せコマンド:MEAS:RES:WITH?を試験器に送信し、試験結果を取得する。
取得した試験結果は、サブルーチンresult2Map2JSONでJSON形式に変換してMQTTのトピック3159/resultにパブリッシュする。
また、同時にMQTTのトピック3159/returnに"ready"をパブリッシュする。
サブルーチンresult2Map2JSON
以上で、自動耐圧試システムが完成する。