この記事の内容はRaspberry Pi 4と3の両方で動作確認済みです
ブログ管理者のP.Hです!
今回はMinimalModbusモジュールの使い方を紹介します。通信で制御を行う時、RS485を使う場面は多いと思いますが、その時に活躍してくれるモジュールです。
- USB-RS485変換デバイス
- MinimalModbusモジュールのインストール
- 通信設定
- APIについて
- 1Bit読み込み ファンクションコード2
- 1Bit書き込み ファンクションコード5,15
- 16bit レジスタ読み込み ファンクションコード3,4
- 16bit レジスタ書き込み ファンクションコード 6、16
それでは、MinimalModbusモジュールでRS485通信をする方法を説明してきます。
USB-RS485変換デバイス
Raspberry Piは、RS485の機能がないのでUSB-RS485変換器もしくは、RS485拡張ボードを装着する必要があります。お試しであれば、下記の激安デバイスで動作すると思います。
MinimalModbusモジュールのインストール
pipでモジュールのインストールを行います。
$ pip install minimalmodbus $ pip install pyserial
通信設定
まず、通信設定をします。シリアル通信と同じですが、RTUモードかASCIIモードを選択する必要があります。ハードウェアのスペックが上がっているので、どちらでもあまり差はないですが、RTUの方が少ないバイト数で通信でき、効率が良いのでRTUを使います。
import minimalmodbus import serial # 接続デバイスのパス, スレーブアドレス, モード設定 instrument = minimalmodbus.Instrument("/dev/ttyUSB0", 1、minimalmodbus.MODE_RTU) #下記の設定変更が可能 instrument.debug = False # 通信ログを出力する or しない instrument.handle_local_echo = False # echo backするデバイス時はTrueに設定 close_port_after_each_call = True # 通信ごとに毎回ポートのopen/closeを行う場合はTrueに設定 instrument.mode = minimalmodbus.MODE_RTU # モード設定 minimalmodbus.MODE_RTU or minimalmodbus.MODE_ACSII instrument.serial.baudrate = 38400 # ボーレート instrument.serial.bytesize = 8 # バイトサイズ instrument.serial.parity = serial.PARITY_NONE # パリティ設定 serial.PARITY_NONE or serial.PARITY_EVEN or serial.PARITY_ODD instrument.serial.stopbits = 1 # ストップビット instrument.serial.timeout = 0.5 # タイムアウト時間(s)
RS485を使用したModbus通信では複数台デバイスを接続でき、それぞれにアドレスを割り振る必要があります。下記は、スレーブアドレス2と5のデバイスを接続している場合のサンプルです。
# スレーブアドレス:2の場合 instrument2 = minimalmodbus.Instrument("/dev/ttyUSB0", 2、minimalmodbus.MODE_RTU) # スレーブアドレス:5の場合 instrument5 = minimalmodbus.Instrument("/dev/ttyUSB1", 5、minimalmodbus.MODE_RTU)
APIについて
modbusではファンクションコードという1~16の番号で、機能が割り振られています。MinimalModbusモジュールはファンクションコードごとにAPIになってます(下記表を参考にしてください)。主に使うAPIの使い方を紹介していきます。
※また、どのファンクションコードを使うかは、デバイスの取扱説明書に記載がありますので、確認してください。
Data type in slave | Read | F code | Write | F code |
---|---|---|---|---|
Bit | read_bit() |
2 [or 1] | write_bit() |
5 [or 15] |
BitsSimultaneous reading | read_bits() |
2 [or 1] | write_bits() |
15 |
RegisterInteger, possibly scaled | read_register() |
3 [or 4] | write_register() |
16 [or 6] |
Long integer (32 bits = 2 registers) |
read_long() |
3 [or 4] | write_long() |
16 |
Float (32 or 64 bits =2 or 4 registers) |
read_float() |
3 [or 4] | write_float() |
16 |
String 2 characters per register |
read_string() |
3 [or 4] | write_string() |
16 |
RegistersIntegers | read_registers() |
3 [or 4] | write_registers() |
16 |
1Bit読み込み ファンクションコード2
指定したアドレスの値を1bit読み取ります。
# 引数説明 # registeraddress(int) スレーブ(デバイス)のレジスタアドレス # functioncode(int) ファンクションコード 1 or 2 read_data = instrument.read_bit(registeraddress, functioncode=2) print(read_data) # 0 or 1
1Bit書き込み ファンクションコード5,15
指定したアドレスに値を1bit書き込みます。
# 引数説明 # registeraddress(int) スレーブ(デバイス)のレジスタアドレス # value(int or bool) 0 or 1 もしくは True or False # functioncode(int) ファンクションコード 5 or 15 instrument.write_bit(registeraddress, value, functioncode=5)
16bit レジスタ読み込み ファンクションコード3,4
指定したアドレスの値を1Word(16bit)読み取ります。
# 引数説明 # registeraddress(int) スレーブ(デバイス)のレジスタアドレス # number_of_decimals(int) 少数点の位置 例 0 ⇒ 100 1 ⇒ 10.0 2 ⇒ 1.00 # functioncode(int) ファンクションコード 3 or 4 # signed(bool) 符号付き or 符号なし read_data = instrument.read_register(add, number_of_decimals=0, functioncode=3, signed=False) print(read_data)
16bit レジスタ書き込み ファンクションコード 6、16
指定したアドレスに値を1Word(16bit)書き込みます。
# 引数説明 # registeraddress(int) スレーブ(デバイス)のレジスタアドレス # value(int or float) レジスタに書き込む値 # number_of_decimals(int) 少数点の位置 例 0 ⇒ 100 1 ⇒ 10.0 2 ⇒ 1.00 # functioncode(int) ファンクションコード 3 or 4 # signed(bool) 符号付き or 符号なし read_data = instrument.write_register(registeraddress, value, number_of_decimals=0, functioncode=16, signed=False)
デバイスの取説を見ながら、設定を合わせたり、レジスタの値を読んだり、書いたりすることになります。Modbus通信できるようになれば、RS485接続のケーブルだけで多くの機能を制御できます。