Howto

Armadillo-IoT G3LのRS422/RS485シリアルポートでModbusの通信をする

Armadillo-IoT G3LのRS422/RS485 シリアルポートを用いてModbus通信を行う方法をご紹介します。
今回は例として、Armadillo-IoT G3Lをマスタとし、渡辺電機工業製のデジタル入出力モジュール WMB-DIO8Rの制御を行います。

※Armadillo-X1, Armadillo-IoT G3でModbus通信を行う場合は、Howto : Armadillo-X1, Armadillo-IoT G3の絶縁RS485アドオンモジュール RS02でModbusの通信をするを参照してください。

WMB-DIO8Rの通信仕様

WMB-DIO8Rの通信仕様は以下となります。

通信規格ModbusRTU
プロトコルRS-485に準拠
通信方法2線式半二重
エラー検出方式CRC-16
通信速度(設定可能)4800bps、9600bps、19200bps、38400bps
データ長8(固定)
スタートビット1(固定)
パリティービット(設定可能)偶数、奇数、なし
ストップビット(設定可能)1、2(パリティーなしの時のみストップビット2設定可)
スレーブID1~99
終端抵抗約120Ω

WMB-DIO8Rの設定

取扱説明書を参考に、WMB-DIO8Rの各種設定を行います。

通信速度19200bps
パリティビットなし
ストップビット1
スレーブID01

Armadillo-IoT G3LとWMB-DIO8Rの配線

Armadillo-IoT G3LとWMB-DIO8Rの配線を行います。

WMB-DIO8R側の配線

・WMB-DIO8Rの制御電源(電源+端子,電源-端子)に+24V、0Vを接続します。
・WMB-DIO8RのModbus通信端子(SG)にSG用の配線を接続します。
・WMB-DIO8RのModbus通信端子(通信+端子,通信-端子)に信号線DATA+、DATA-を接続します。
・WMB-DIO8RのModbus通信端子(通信+端子,通信-端子)の信号線DATA+、DATA-の間に120Ωの終端抵抗を接続します。

Armadillo-IoT G3L側の配線

・Armadillo-IoT G3LのCON4(ピン番号1)にSG用の配線を接続します。
・Armadillo-IoT G3LのCON4(ピン番号2,3)に信号線DATA-、DATA+を接続します。
・Armadillo-IoT G3LのCON4(ピン番号2,3)の信号線DATA-、DATA+の間に120Ωの終端抵抗を接続します。

※今回のHowtoでは簡易的にピン番号2,3に直接終端抵抗を設置しています。この設置方法では、ケーブルまたは終端抵抗が取れてしまう恐れがあるため、本格的な運用での使用は避けて下さい。

全体図

配線図

Armadillo-IoT G3LのRS485設定

Armadillo-IoT G3L側のRS485設定を行います。

=> setenv optargs imx.rs485_uart2=0x03,0,0
=> saveenv

RS485設定値

設定説明設定値
flagsflags ENABLED(bit0)0: RS485無効

1: RS485有効
1
RTS_ON_SEND(bit1)0: データ送信時のRTS(Driver Enable)がLow

1: データ送信時のRTS(Driver Enable)がHigh
1
RTS_AFTER_SEND(bit2)0: データ非送信時のRTS(Driver Enable)がLow

1: データ非送信時のRTS(Driver Enable)がHigh
0
RX_DURING_TX(bit4)0: 半二重通信

1: 全二重通信
0
delay_rts_before_send送信前遅延時間(ミリ秒)0
delay_rts_after_send送信後遅延時間(ミリ秒)0

※RS485に設定する値の詳細については、製品マニュアルを確認して下さい。
※RS485に設定する値は、初期値と同じ値です。Armadillo-IoT G3Lが初期状態であれば、この設定を行わない場合でもRS485を使うことができます。

Armadillo-IoT G3Lの起動

Armadillo-IoT G3Lを起動します。

=> boot

サンプルプログラムの作成

今回はC言語を用いて、WMB-DIO8RのDIGITAL OUTPUTのピン番号4をon/offさせるプログラムを作成します。

必要なパッケージのインストール

サンプルプログラムの実行に必要なライブラリをインストールします。

root@armadillo:~# apt-get update
root@armadillo:~# apt-get install libmodbus-dev

WMB-DIO8Rへの送信パケット

WMB-DIO8R 取扱説明書(Modbus通信仕様書)の「表 5.34 デジタル出力(DO)への出力制御 」を参考に、DIGITAL OUTPUTのピン番号4の制御するための送信パケットを書き出すと次のようになります。

送信パケットの内容
内容説明
スレーブID0x01WMB-DIO8RのスレーブID
機能コード0x05コイル 書き込み
開始アドレス(上位)0x00
開始アドレス(下位)0x03DIGITAL OUTPUTのピン番号4
データ(上位)0xFF または 0x00DIGITAL OUTPUTのon/off
データ(下位)0x00

送信パケットの内容を元に、サンプルプログラムを作成します。

サンプルプログラムのダウンロード

wmb-dio8r-ctrl.tar.gzをダウンロードします。

root@armadillo:~# wget http://download.atmark-techno.com/sample/armadillo-iot-g3l-modbus/wmb-dio8r-ctrl.tar.gz

wmb-dio8r-ctrl.tar.gzを展開します。

root@armadillo:~# tar zxvf wmb-dio8r-ctrl.tar.gz

wmb-dio8r-ctrlディレクトリに、wmb-dio8r-ctrl.cとMakefileがあることを確認して下さい。

root@armadillo:~# cd wmb-dio8r-ctrl
root@armadillo:~/wmb-dio8r-ctrl# ls
Makefile  wmb-dio8r-ctrl.c

サンプルプログラムの実装

サンプルプログラムwmb-dio8r-ctrl.cは、次のように実装されています。

/* Copyright (c) 2018 Atmark Techno, Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <modbus.h>

#define SERIAL_SPEED 19200
#define SERIAL_PARITY 'N'
#define SERIAL_DATABIT 8
#define SERIAL_STOPBIT 1

int main(int argc, char *argv[])
{
    static uint8_t raw_req[] = { 0x01, 0x05, 0x00, 0x03, 0x00, 0x00 }; /* 送信パケット */
    uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];
    int ret = EXIT_SUCCESS;
    int raw_req_size = sizeof (raw_req) / sizeof (raw_req[0]);
    int req_length;
    int rsp_length;
    modbus_t *ctx;

    if (argc <= 2) {
        printf("Usage: %s <device> <on/off>\n\n", argv[0]);
        return EXIT_SUCCESS;
    }

    if (!strcmp(argv[2], "on")) {
        raw_req[4] = 0xFF;
    } else if (!strcmp(argv[2], "off")) {
        raw_req[4] = 0x00;
    } else {
        printf("Usage: %s <device> <on/off>\n\n", argv[0]);
        return EXIT_SUCCESS;
    }

    ctx = modbus_new_rtu(argv[1], SERIAL_SPEED, SERIAL_PARITY, SERIAL_DATABIT, SERIAL_STOPBIT);
    if (ctx == NULL) {
        fprintf(stderr, "Unable to allocate libmodbus context\n"
            "modbus error\n");
        return EXIT_FAILURE;
    }

    modbus_set_debug(ctx, TRUE);
    modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK | MODBUS_ERROR_RECOVERY_PROTOCOL );
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n"
            "modbus error\n",
            modbus_strerror(errno));
        modbus_free(ctx);
        return EXIT_FAILURE;
    }

    req_length = modbus_send_raw_request(ctx, raw_req, raw_req_size);
    if (req_length < 0 ) { 
        fprintf(stderr, "faild: %s\n"
            "modbus error\n",
            modbus_strerror(errno));
        ret = EXIT_FAILURE;
    }

    rsp_length = modbus_receive_confirmation(ctx, rsp);
    if (rsp_length < 0 ) { 
        fprintf(stderr, "faild: %s\n"
            "modbus error\n",
            modbus_strerror(errno));
        ret = EXIT_FAILURE;
    }

    modbus_close(ctx);
    modbus_free(ctx);

    return ret;
}

WMB-DIO8Rへの送信パケットの一部には、ベンダーが独自に定義したパケットが使われています。
libmodbusの標準関数ではベンダーが独自に定義したパケットを送信するための専用関数は用意されていません。そこで、本サンプルプログラムではmodbus_send_raw_request関数を使用し、ソースコード内に記載したパケットをそのまま送信するようにしています。

※libmodbusの標準関数を用いてパケットを送信する場合は、Howto : Armadillo-400シリーズでModbusの通信をするを参考にして下さい。

ビルド方法

ソースコードのビルドを行います。

root@armadillo:~/wmb-dio8r-ctrl# make

動作確認方法

WMB-DIO8Rの電源投入

WMB-DIO8Rの電源を入れて下さい。

サンプルプログラムの実行

サンプルプログラムを実行します。

root@armadillo:~/wmb-dio8r-ctrl# ./wmb-dio8r-ctrl /dev/ttymxc1 on 
Opening /dev/ttymxc0 at 19200 bauds (N, 8, 1)
[01][05][00][03][FF][00][7C][3A]
Waiting for a confirmation...
<01><05><00><03><FF><00><7C><3A>
root@armadillo:~# 

実行結果

DIGITAL OUTPUTのピン番号4がon(LEDが点灯)になれば、通信成功です。

注意点

・本Howtoは、渡辺電機工業株式会社製のデジタル入出力モジュール WMB-DIO8Rとの接続例を記載したものです。
 Modbus通信を行う全ての機器の動作を保証するものではありませんので、ご注意下さい。
・本Howtoは、簡易的な手順を示したものです。エラー処理等は考慮されていません。
 本格的に運用する際は、電気的特性、ノイズ等を考慮した回路設計、エラー処理、フェイルセーフ等のソフト設計を行う必要があります。