実験用AGVの作成 - (3) - オリエンタルモーターをCANopenで回す

# はじめに

AGVの実験台車の作成に向けてgazeboシミュレータを使って機構の検討を行ってきました。

https://qiita.com/yamamoto-kazusige/items/531ecc4f699f3c8ad306

検討した結果を元に実際の台車の設計をしていますが、最近立て込んでいてなかなか進められません（本業はソフト開発なのでメカの設計はちょっと骨が折れます）。

気分を変えて駆動用モータードライバの作成を先に着手しました。

# モーターの選定

モーターを選定するにあたり下記の基準で探しました

1. 入手性が良いこと
2. コントローラからデジタルIFで制御できること
3. 同じ制御方式で小型から大型モーターまで対応できること
4. 価格が手頃なこと

特定の商社を通さないと購入できないとか、まとまった数量でないと購入できないものは、お手軽に試したい今回の用途には不向きです。また、Amazon等で購入できる安価なモーターは次回に同じものが入手できないこともあります。

また、試作したものをベースに大型の搬送車を開発しようとした時に、異なった制御方式だったりするとドライバうソフトのメンテナンスも増えていきます。

上記の選定基準で探したところオリエンタルモーター製のBLVシリーズRタイプを選定しました。

# オリエンタルモーター BLVシリーズRタイプ

オリエンタルモータのブラシレスモーターBLVシリーズRタイプは軽量小型のDCブラシレスモーターです。
専用のドライバと組み合わせて使用し60W/100W/200W/400Wのラインナップがあり、減速比のギヤヘッドと
組み合わせることで広い速度制御範囲と高可搬質量の搬送車両を設計できます。

バッテリー駆動できる小型軽量をコンセプトにした「mobi モバイルオートメーション」対応製品です。
(弊社の自律移動ソフトパッケージ@&#xFFF0;mobiと微妙に名前が似ているのは偶然です。本当に。)

https://www.orientalmotor.co.jp/products/mobileautomation/

今回は小型AGVの駆動用に一番小型の60W並行ギアヘッドの「BLMR460SHK-15」を選定しました。

|項目|スペック|
|--|--|
|定格出力|60W|
|減速比|15|
|定格回転速度|3000rpm|
|速度制御範囲(モーター軸)|1～4000rpm|
|出力軸回転速度|0.067～267rpm|
|分解能|0.01°(36000パルス/回転)|

出力軸の最高回転速度267rpmなので、0.15mの車輪を取り付けた場合の最高速度は
2.09m/sec(約7.5km/h)となります。前述の選定基準への対応状況は次の通りです。

- 入手が容易（オリエンタルモーターのオンラインストアやミスミで購入できる）
- CAN bus/RS485 busに接続してコントローラーから制御できる
- 400Wまでのラインナップもあり、大型の搬送車にも同じ制御系で対応できる
- モーター＋モータードライバの左右２セットで15万円程度

購入して触ってみると次のような特長があることもわかりました
- DCブラシレスモーターなのに、サーボモーターのように角度指定の制御ができる
- 1rpm（減速後は0.067rpm）という低速での動作に対応している
低速での回転ができることや、角度指定での制御ができることは台車の位置合わせに有利です。

## 参考資料

オリエンタルモーターのホームページからダウンロードできる下記の資料を参照しています。

|資料No|ファイル名|タイトル|内容|
|---|---|---|--
|1|HP-5139J.pdf|BLVシリーズ Rタイプ 設置・接続編|モーターとドライバ、コントローラの接続方法について|
|2|HP-5141J.pdf|BLVシリーズ Rタイプ 機能編|
|3|HP-5143E.pdf|BLV Series R Type Driver CANopen Communication Profile|BLVD-KRDに関するObject Directory情報|

以下、説明内の引用資料は特に断りがない場合上記資料からの抜粋です。

## 購入品一覧

|製品|品名|単価(税込)|数量|
|---|---|---|---|
|ブラシレスモーター|BLMR460SHK-15|32,500|2|
|ドライバ|BLVD-KRD|37,800|2|
|接続ケーブル|CCM003B1ABF|3,200|2|
|モーター取付金具|SOL4M6F|2,800|2|
|電源ケーブル|LC03D06A|1,600|2|

価格は記事作成時点でオリエンタルモーターのWEBショップでの価格です。

# 接続方法

### モータードライバの入出力コネクタピンアサイン

![CN4_PIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/b6d1c7a5-9dc5-85e8-98f1-7a46b0a128ed.png)

参考資料No.1に従って今回はCANによる制御を行うので次のコネクタを接続します。

5 : CAN_L
6 : CAN_H
7 : CAN_GND
20 : NET_VIN 通信用電源
21 : NET_GND 通信用電源

### 通信用電源の電源電流容量

|電源電流容量|入力電源電圧|
|---|---|
|0.2 A 以上|DC24-48 V|

### 上位システムとのCAN接続例
![CAN_CONNECT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/79a3705f-576c-262c-f3ae-941e882f09b3.png)

### CAN通信仕様

![CAN_SPEC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/b033641f-1f1f-e0ca-aa30-fb6fa1f75848.png)

# モーターを MEXE02 で回す

BLV-RはModbusとCANopenを使った外部からの制御ができますが、CANopenを使っての制御方法については解説の資料が少なく、次の記事を参考にさせていただきました。

https://qiita.com/jamjam/items/9da1912a9870f09f5b71

上記記事ではサポートソフト「BLST01」を使ってモーターの設定を行うようになっていますが、現在は「MEXE02」に変わっているようです。

https://www.orientalmotor.co.jp/download/software/mexe02/

- 上記サポートーページからMEXE02をダウンロードしてWindowsPCへインストール
- miniUSBケーブルを用いてPCとモータードライバ(BLVD-KRD)を接続
- MEXE02を起動し「BLV-R」を選択

制御を行うに当たり、モータードライバのCAN NodeIDと通信速度を設定します。
- 簡易通信設定画面を開いて、上部の「簡易設定を開始します」チェックボックスをチェックする
- 「CANopen通信設定」の項目から「ノードID　10」「Bitrate　1000kbps」を選択しドライバへ反映クリック

「リモート運転」画面からモーターを実際に動かしています。
- 画面上部の「リモート運転モード」チェックボックスをチェックする
- リモート運転→S-ONを「ON」にする（モーターが励磁状態になり、ジリジリと音がする）
- 速度命令での動作、移動量指定での動作を行う

リモート運転ができれば、電源やドライバの接続はOKです。

# CANopenで回す

ここからが今回の本題、今回AGVの自律移動はROSの制御ソフトで行う予定です。BLVD-KRDに対応した作動二輪のROSドライバを探したところRS485 modbusに対応した次のものがありました。

https://github.com/hijimasa/blvr_ros_samples

ただ、今回使用予定のコントローラPCはCANのIFが有るのでCANOpenで制御してみようと思います。（今までCANOpenは使ったことがなかったのでかじってみたいのもある）

## CANopen

CANopenはCAN通信の物理層、ネットワーク層の上に定義されたプロトコルでアプリケーション層に該当します。
株式会社ソフテック様のサイトにわかりやすく解説されていました。

![CAN_LAYER.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/4f00df08-9793-2b41-7edb-818d1e3e51eb.png)
引用：株式会社ソフテック https://www.softech.co.jp/mm_130904_plc.htm

使用できそうなプロトコルスタックの実装としては次の３つ
- https://canopen-stack.org/
- https://github.com/CANopenNode
- https://opensource.lely.com/canopen

Linux用のサンプルソフトが付属しているCANopenNodeを使ってみることにしました。

## CANopenNode

https://github.com/CANopenNode/CANopenDemo
にLinux用のサンプルがあります。READMEに従ってダウンロードしてビルドします。

### ダウンロード＆コンパイル
```shell
$ git clone https://github.com/CANopenNode/CANopenDemo.git
$ cd CANopenDemo
$ git submodule update --init --recursive
$ cd CANopenLinux
$ make
```

### canopendの起動

プログラムはCANopenのプロトコルスタックを実装する canopend とコマンドラインのフロントエンド cocomm から構成されます。

CAN IFの設定
```shell
$ sudo ip link set can0 up type can bitrate 1000000
```

canopendは標準入出力、UnixDomainSocket、TCP-Scoketの方法でフロントエンドと通信します。UnixDomainSocketでの通信指定は次のように指定してcanopendを起動します。
```shell
$ canopend can0 -i 1 -c "local-/tmp/CO_command_socket"
```
-iで指定するのは canopend に割り当てるnode idです。

## デバイスの読み出し

参考資料No.3によるとBLVD-KRBのObject Directory 0x1008 は "Manufacturer device name" です。

![1008h.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/0e394a2c-fdea-86b1-3735-2ac5a7dd4c39.png)

cocommを使って0x1008の情報を読み出します。

```shell
$ cocomm "10 r 0x1008 0 vs"
[1] "BLVD-KRD"
```
上記のように表示されればCANopenによるモータードライバとの通信はできています。最初の"10"はMEXE02で設定したBLVD-KBDのnode idです。

### Object Directory

CANopenでは通信パラメータ、データが標準定義されており、Object Directory(OD)と呼ばれます。ODは16bitのインデックスと8bitのサブインデックスで定義されています。
前記の例では、インデックス1008hのサブインデックス0です。規格では次の様の定められています。

|インデックス|オブジェクト|
|---|---|
|1000～1FFF|通信プロファイル|
|2000～5FFF|メーカー固有プロファイル|
|6000～9FFF|標準化されたデバイスプロファイル|

現在のモーターのポジションの取得はの6064hで定義されています。

![6064h.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/aed723f1-e9ef-a80a-df2a-24c0313cfab7.png)

int32で定義されているようですので次のようにして読み出します。
```shell
$ cocomm "10 r 0x6064 0 i32"
[1] -2888
```
モーターの軸を手で少し回して再度コマンドを入力すると次のように値が変化します。
```shell
$ ./cocomm "10 r 0x6064 0 i32"
[1] 40819
```

## デバイスの書き込み

CANopenではNMTという状態遷移モデルで通信状態を管理しています。

![NMT_state.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/284a576b-4600-5a72-be13-bd615280cb85.png)
(参考資料No.3 4.1より)

また、デバイス状態は参考資料No.3 5.1の状態遷移モデルで管理しています。

![DEV_state.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/c31b7250-efb2-8c9a-f8c0-ae1547a32ea1.png)
(参考資料No.3 5.1より)

モーターを回すためには、通信状態を"operational"、デバイス状態を"Operation enabled"に設定する必要があります。

この状態は MEXE02 の「CANopen通信ステータスモニタ」画面で確認できます。

### 通信状態

cocommコマンドでは"start"コマンドで通信状態を"operational"、"preop"コマンドで"Pre-operatonal"に変更することができます。

```shell
$ cocomm "10 start"
```
通信状態が"operational"に変化します。(MEXE02で確認)

### 運転状態

参考資料No.3 6040h : controlwordの設定により運転状態を変えることができます。参考資料No.3の6章 Status Machine control commandsを参考に状態を変えます。

#### Switch on disabled → Ready to switch on

> $ cocomm "10 w 0x6040 0 x16 0x6"

#### Ready to switch on → Switched on

> $ cocomm "10 w 0x6040 0 x16 0x7"

#### Switched on → Operation enabled

> $ cocomm "10 w 0x6040 0 x16 0xF"

"Operation enabled"状態に遷移しモーターが励磁状態になります。

#### 速度指令で回す

速度指令は60FFhです。
![60ffh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112366/ad0c275a-224b-628a-4e65-bf67c5346c84.png)

1000rpm(モーター軸)で回します。
> $ cocomm "10 w 0x60FF 0 i32 1000"

逆方向に1000rpmで回します。
> $ cocomm "10 w 0x60FF 0 i32 -1000"

MEXE02の「ステータスモニタ」画面で回転指令値と現在の回転速度を確認できます。

モーターがちゃんと回れば成功です！ここまで来たらもう「Hello World.」ができたぐらいの達成感です。もうできたも同然と思ってしまいました。しかし、ここから先が長かったので次回に続きます。

---
**Next**

https://qiita.com/yamamoto-kazusige/private/955b1ca4f17ad3c405ba