Raspberry Pi & Python 開発ブログ ☆彡

Raspberry PiとPythonの基本的な使い方をわかりやすく解説。初心者、入門者必見!!

MinimalModbusモジュールでRS485通信をする

minimalmodbus

この記事の内容はRaspberry Pi 4と3の両方で動作確認済みです

ブログ管理者のP.Hです!

今回はMinimalModbusモジュールの使い方を紹介します。通信で制御を行う時、RS485を使う場面は多いと思いますが、その時に活躍してくれるモジュールです。

それでは、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接続のケーブルだけで多くの機能を制御できます。

ラズパイ ハードウェアに戻る
トップページに戻る