創るたのしみを応援

Pololu ハイパワーシンプルモータコントローラG2

Linux シリアル Pythonサンプル(Raspberry Pi)

シンプルモータコントローラG2のTTLシリアル通信を使い、Raspberry Piでモータ制御をします。

シリアル動作モード

  • ボーレート 9,600 bps
  • バイナリコマンド方式
  • CRC無効モード

Pythonでは、pySerial ライブラリを使用しています。

コードを実行したときに、“ImportError: No module named serial” や “ModuleNotFoundError: No module named ‘serial’”と表示されるときは、pySerialライブラリがインストールされていませんので、インストールをしてください。

Raspberry Piと接続

USB(仮想シリアル)接続

Raspberry Piとシンプルモータコントローラを、USBで接続します。USBドライバが自動的にロードされ、仮想シリアルポートとして動作します。

USBで接続したとき、Raspberry Piのシリアルポートは、/dev/ttyUSB0 になります。複数つないでいる時は、/dev/ttyUSB1と最後の数字が増えていきます。

TTLシリアル接続

Raspberry Piとシンプルモータコントローラを、Raspberry Pi拡張ポートからTTLシリアルで接続します。

  • シンプルモータコントローラG2 Rx / Raspberry Pi TXD (GPIO14)
  • シンプルモータコントローラG2 Tx / Raspberry Pi RXD (GPIO15)
  • GND

18v15/24v12と18v25/24v19で配置がすこし違いますが、ボードの左にあるRX/SDA、TXとGNDへ接続します。

ハイパワーシンプルモータコントローラ G2 18v15 と 24v12 のピン配置
ハイパワーシンプルモータコントローラ G2 18v25 と 24v19 のピン配置

TTLシリアルで接続したとき、Raspberry Piのシリアルポートは、/dev/ttyAMA0 になります。

Raspberry Piから、TTLシリアルをアプリケーションで使用するために、次の設定をRaspberry Piで行ってください。

  • sudo raspi-config
    • Interfacing options sudo raspi-config から、P6. Serial を選択
    • login shellに使用するか聞かれるので、No を選択
    • ハードウェアシリアルポートを有効にするか聞かれるので、Yes を選択
  • BluetoothのUART設定の解除(pi3-disable-bt)
    • sudo systemctl disable hciuart

シリアル通信へ設定

Simple Motor Control Center G2から設定します。 インストールがまだの時は、導入編をご覧ください。

Input settingsタブを開き設定していきます。

  1. Input ModeでSerial/USBを選択
  2. TTL Serialの Fixed baud rate: を選択し 9600を入力
  3. Apply Settingsをクリック

サンプルコード中で、baud rateを指定しているため、9600にしてください。他の速度で使用する場合は、サンプルコードの速度指定を変更してください。

サンプルコード

基本的な、正転と逆転制御するサンプルコードです。

# pySerialライブラリを使用し、シンプルモータコントローラG2から送受信を行います。
#
# 注意: シンプルモータコントローラG2の入力モードを Serial/USB に必ずしてください。
# 注意: "port_name =" の行をシリアルポートに応じて変更する必要があります。

import serial

class SmcG2Serial(object):
  def __init__(self, port, device_number=None):
    self.port = port
    self.device_number = device_number

  def send_command(self, cmd, *data_bytes):
    if self.device_number == None:
      header = [cmd]  # Compact protocol
    else:
      header = [0xAA, device_number, cmd & 0x7F]  # Pololu protocol
    self.port.write(bytes(header + list(data_bytes)))

  # セーフスタート終了コマンド送信
  # モータを動作させるために必要
  def exit_safe_start(self):
    self.send_command(0x83)

  # SMC ターゲット速度設定 (-3200 ~ 3200)
  def set_target_speed(self, speed):
    cmd = 0x85  # Motor forward
    if speed < 0:
      cmd = 0x86  # Motor reverse
      speed = -speed
    self.send_command(cmd, speed & 0x1F, speed >> 5 & 0x7F)

  # 指定した変数IDの値を 符号無し整数 で取得
  def get_variable(self, id):
    self.send_command(0xA1, id)
    result = self.port.read(2)
    if len(result) != 2:
      raise RuntimeError("Expected to read 2 bytes, got {}."
        .format(len(result)))
    b = bytearray(result)
    return b[0] + 256 * b[1]

  # 指定した変数IDの値を 符号付き整数 で取得
  def get_variable_signed(self, id):
    value = self.get_variable(id)
    if value >= 0x8000:
      value -= 0x10000
    return value

  # ターゲット速度取得 (-3200 ~ 3200)
  def get_target_speed(self):
    return self.get_variable_signed(20)

  # 異なるエラーの各ビット表示の数値を取得
  # ビットが「1」の時は、現在もエラーが有効
  # エラービットの定義はユーザガイドを参照
  def get_error_status(self):
    return self.get_variable(0)

# シリアルポート名の指定
# Linux USB example:  "/dev/ttyACM0"  (see also: /dev/serial/by-id)
# Raspberry Pi USB example:  "/dev/ttyUSB0"
# Raspberry Pi TTL example:  "/dev/ttyAMA0"
# macOS USB example:  "/dev/cu.usbmodem001234562"
# Windows example:    "COM6"
port_name = "/dev/ttyUSB0"

# ボーレート設定 (bits per second). 
# USB経由でSMCに接続しているときは、この値は関係ありません。
# Tx/Rxラインで接続している場合は、SMCのシリアル設定のボーレートと同じにしてください。
baud_rate = 9600

# SMCのデバイス番号を0~127の間で変更してください。
# 複数のSMCをシリアルに接続し Pololu Protocolを使用しているときに使用します。
device_number = None

port = serial.Serial(port_name, baud_rate, timeout=0.1, write_timeout=0.1)

smc = SmcG2Serial(port, device_number)

smc.exit_safe_start()

error_status = smc.get_error_status()
print("Error status: 0x{:04X}".format(error_status))

target_speed = smc.get_target_speed()
print("Target speed is {}.".format(target_speed))

new_speed = 3200 if target_speed <= 0 else -3200
print("Setting target speed to {}.\n".format(new_speed));
smc.set_target_speed(new_speed)