Pythonを使用してRS485コマンドを送信する方法

D

Daniel Zhang

最終更新日 Jul 12, 2026

Pythonは広く使用されているプログラミング言語です。Python経由でModbusコマンドを送信することで、モーター動作をより便利に制御できます。以下は、Pythonを使用してModbusコマンドを送信する簡単なコード例です。Modbusコマンドは、記事「A6サーボモーター RS485操作説明」のセクション2.3「5000パルスの絶対位置移動(初期設定:10000パルス/回転、C00.02=10000)」から引用しています。このコードはStepperOnlineのA6-RSシリーズサーボドライブに適用でき、モーターを絶対位置モードで5000パルス運転するように制御します。

以下がPythonコードです:

import serial
import time
import binascii
from crcmod import crcmod

# シリアルポート設定 - 実際のデバイスに合わせて変更してください
PORT = 'COM3'  # シリアルポート(Windows: 'COM3'、Linux: '/dev/ttyUSB0')
BAUDRATE = 9600  # ボーレート(一般的な値: 9600, 19200, 38400, 57600, 115200)
PARITY = serial.PARITY_NONE
STOPBITS = serial.STOPBITS_ONE
BYTESIZE = serial.EIGHTBITS
TIMEOUT = 0.5  # 読み取りタイムアウト(秒)

# Modbus CRC16関数の作成
modbus_crc = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)

# コマンド定義(CRCなし)
commands_without_crc = [
    "010600000000",  # ドライブ制御モードを位置モードに設定 C00.00=0
    "010611010000",  # 位置プロファイルコマンドを絶対位置決めモードに設定 C11.01=0
    "010603000002",  # 位置指令ソースをステップ増分に設定 C03.00=2
    "0106030D0001",  # 運転速度を1 rpmに設定 C03.0D=1
    "0106030C1388",  # 移動量を5000パルスに設定 C03.0C=5000
    "010604000022",  # DI1を位置ステップ増分有効に設定 C04.00=34 (0x22)
    "010604110001",  # モーターを有効化し運転開始 C04.11=1
    "010604010001",  # DI1有効をトリガー C04.01=1
    "010604110000",  # 緊急停止コマンド、モーター無効化 C04.11=0
    "010604010000"   # DI1無効化 C04.01=0
]

# コマンド説明
descriptions = [
    "ドライブ制御モードを位置モードに設定(C00.00=0)",
    "位置プロファイルを絶対位置決めに設定(C11.01=0)",
    "位置指令ソースをステップ増分に設定(C03.00=2)",
    "運転速度を1 rpmに設定(C03.0D=1)",
    "移動量を5000パルスに設定(C03.0C=5000)",
    "DI1を位置ステップ増分有効に設定(C04.00=34)",
    "モーターを有効化し運転開始(C04.11=1)",
    "DI1有効をトリガー(C04.01=1)",
    "緊急停止コマンド、モーター無効化(C04.11=0)",
    "DI1無効化(C04.01=0)"
]

def calculate_crc(hex_str):
    """16進文字列のModbus CRC16を計算"""
    data = binascii.unhexlify(hex_str)
    crc = modbus_crc(data)
    # CRCをリトルエンディアン形式で返す(下位バイトが先)
    return bytes([crc & 0xFF, (crc >> 8) & 0xFF])

def format_hex(data):
    """バイトデータを16進文字列にフォーマット"""
    return ' '.join([f"{b:02X}" for b in data])

def send_modbus_command(ser, hex_cmd, description):
    """単一のModbusコマンドを送信し応答を処理"""
    try:
        # CRCを計算しコマンドに追加
        crc_bytes = calculate_crc(hex_cmd)
        full_cmd = binascii.unhexlify(hex_cmd) + crc_bytes

        # コマンドを送信
        ser.write(full_cmd)
        print(f"\nコマンド送信中: {description}")
        print(f"データ: {format_hex(full_cmd)}")

        # デバイスの処理を待機
        time.sleep(0.3)

        # 応答を読み取り(Modbus RTUの応答は通常8バイト)
        response = ser.read(8)

        if response:
            print(f"デバイス応答: {format_hex(response)}")
            return True
        else:
            print("エラー: 応答を受信できませんでした!")
            return False

    except Exception as e:
        print(f"コマンド送信エラー: {str(e)}")
        return False

def main():
    # シリアル接続を作成
    try:
        ser = serial.Serial(
            port=PORT,
            baudrate=BAUDRATE,
            parity=PARITY,
            stopbits=STOPBITS,
            bytesize=BYTESIZE,
            timeout=TIMEOUT
        )
        print(f"シリアルポートへの接続に成功しました: {ser.name}\n")
    except serial.SerialException as e:
        print(f"シリアルポートのオープンに失敗しました: {str(e)}")
        return
    except Exception as e:
        print(f"エラーが発生しました: {str(e)}")
        return

    # 全コマンドを送信
    for i, (cmd, desc) in enumerate(zip(commands_without_crc, descriptions), 1):
        print(f"コマンド {i}/{len(commands_without_crc)} を実行中")
        success = send_modbus_command(ser, cmd, desc)

        if not success:
            print("コマンド実行に失敗しました。プログラムを終了します")
            break

        # 重要なコマンドには長めの遅延を適用
        if "Enable" in desc or "Trigger" in desc or "Emergency" in desc:
            time.sleep(1.0)  # 動作関連コマンドには長めの遅延
        else:
            time.sleep(0.5)  # 設定コマンドには標準の遅延

    # シリアルポートを閉じる
    ser.close()
    print("\n全コマンドの処理が完了しました。シリアルポートを閉じます")

if __name__ == "__main__":
    main()

注意事項:

a. このコードはcrcmodライブラリを使用してModbusコマンドのCRC検証を行います。コードを実行する前に、必要なライブラリをインストールする必要があります:

pip install pyserial crcmod

b. デバイスの実際の設定に合わせて、正しいCOMポート(PORT)とボーレート(BAUDRATE)を設定してください。デバイスの応答時間に応じて、遅延パラメータ(time.sleep)を調整してください。

c. 本例のModbusコマンドはStepperOnlineのA6-RSシリーズサーボドライブにのみ適用されます。DSY-RSシリーズサーボドライブ、T6シリーズサーボドライブ、RSシリーズステッピングドライブなど、他のドライブを使用している場合は、各ドライブのマニュアルに従ってModbusコマンドを変更してください。