【編集中】ODrive試験装置を作ってBLDCモーターをSPI接続アブソリュートマグネットエンコーダで位置制御、速度制御できるよう設定した

はじめに

ODriveというオープンソースのブラシレスDC(以下BLCD)モーターのコントローラ(モータードライバ?)を使って、マルチコプター用のセンサレスBLDCモーターとマグネットエンコーダを組み合わせて使ってみました。

配線してPCからUSB接続で設定してモーターを回せるようになるまでの手順を記録しました。

自分用のメモですが、誰かがODriveを使い始めるときの参考になれば幸いです。

必要な物

ODrive基板を公式から購入

適当なBLDCモーターをAmazonなどから購入

エンコーダをMouserやDigikeyなどから購入

ブレーカーをAmazonなどから購入

安定化電源が無ければAmazonなどから購入

USB2.0か3.0があるWindowsPC


配線

後で書く

【注意】電源電圧は12V以上必要!


odrivetoolをWindowsPCにインストール

公式ドキュメントの通りにインストールします

ODriveパラメータ設定

WindowsPCでpythonを起動します。ここから先のコマンド入力はpythonターミナルで行います。[enter] はEnterキーを押すという意味です。

Odrivetoolに入る

odrivetool [enter]

Please connect your ODrive.
You can also type help() or quit().

ODrive基板に電源を入れてUSBケーブルでPCに繋ぐ。PCが認識すると以下のように表示される。1回目にOdrive基板にPCを接続したときだけ1行目の表示が出て1分程度の待ち時間があります。

Downloading json data from ODrive... (this might take a while)
connected to ODrive 2053368D424D as odrv0 

一度odrivetoolを抜ける

exit [enter]

まずFirmwareバージョンを最新にする。1分程度かかります。

odrivetool dfu [Enter]

ODrive control utility v0.5.1.post0
Waiting for ODrive...
Found ODrive 2053368D424D (v3.6-56V) with firmware v0.5.1-dev
Checking online for newest firmware... found v0.5.1

Warning: you are about to flash firmware v0.5.1 which is older than the firmware on the device (v0.5.1-dev).
Do you want to flash this firmware anyway? [y/N] y
Downloading firmware v0.5.1...
Putting device 2053368D424D into DFU mode...
Erasing... done
Flashing... done
Verifying... done
Waiting for the device to reappear...
Device firmware update successful.

Odrivetoolに入る

odrivetool [enter]

Please connect your ODrive.
You can also type help() or quit().

基板に供給されている電圧を確認する

odrv0.vbus_voltage [enter]

15.00146484375

安定化電源で15Vを供給いれば15に近い数字が表示されるはずです。

エラーが無いのを確認する。起動しただけなのでエラーは無いはずです。

dump_errors(odrv0) [enter]

axis0
 axis: no error
 motor: no error
 fet_thermistor: no error
 motor_thermistor: no error
 encoder: no error
 controller: no error
axis1
 axis: no error
 motor: no error
 fet_thermistor: no error
 motor_thermistor: no error
 encoder: no error
 controller: no error

motor config 設定

モーター電流制限を11Aに設定する

odrv0.axis0.motor.config.current_lim = 11 [enter]

モーターキャリブレーション電流制限を5Aに設定する。この値が大きすぎると小さいモーターではキャリブレーションに失敗する場合あり

odrv0.axis0.motor.config.calibration_current = 5 [enter]

速度リミット設定を300turn/sに設定する

odrv0.axis0.controller.config.vel_limit = 300 [enter]

ブレーキ抵抗の値を0.05に設定する

odrv0.config.brake_resistance = 0.05 [enter]

モーター極ペアの値を7に設定する

odrv0.axis0.motor.config.pole_pairs = 7 [enter]

モータートルク定数を8.27/KV値(1200) = 0.00689に設定する

odrv0.axis0.motor.config.torque_constant = 0.00689 [enter]

モーターのresistance_calib_max_voltage を12Vに設定

odrv0.axis0.motor.config.resistance_calib_max_voltage = 12.0

キャリブレーションの速度リミット設定?

odrv0.axis0.controller.config.vel_limit = 5

Encoder config 設定

CSnが繋がっているGPIOピンを4に設定する


odrv0.axis0.encoder.config.abs_spi_cs_gpio_pin = 4 


エンコーダのパルス数を4000にする(これ必要?SPIならいらない?)

odrv0.axis0.encoder.config.cpr = 4000

エンコーダーモードをSPIのABSのAMSにする。今使っているAS5047PはAMS


odrv0.axis0.encoder.config.mode = ENCODER_MODE_SPI_ABS_AMS


config.cpr を 2**14に設定。AMT232A とAMT233Aの場合は2**12らしい?

odrv0.axis0.encoder.config.cpr = 2**14

これをやっておくと電源を落として次回起動したときに今回のキャリブレーションの値でキャリブレーション済みとして起動するはず。

電源落ちてる間にモーターやエンコーダが変わってたりしない限りは無事起動するはずです。

odrv0.axis0.motor.config.pre_calibrated = True
odrv0.axis0.encoder.config.pre_calibrated = True

設定(configuration)を保存して再起動

odrv0.save_configuration()
odrv0.reboot()


ODriveの電源を落としてから入れなおす。これをしないとSPIのエラーがリセットされない模様。再起動コマンドではダメなので必ず基板の電源を入れなおす

位置制御モードにする(デフォルトは位置制御のはずだけど念のため)

odrv0.axis0.controller.config.control_mode = CONTROL_MODE_POSITION_CONTROL

エンコーダオフセットキャリブレーション実行

odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION

正常ならモーター軸が両方向に1回まわるはず。(モーターキャリブレーションを先にしないと動かないかもしれない)


エラー確認


dump_errors(odrv0)

モーター確認


odrv0.axis0.motor


エンコーダ確認


odrv0.axis0.encoder

問題なければ設定保存

odrv0.save_configuration()


問題なければフルキャリブレーションシークエンス実行


odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

エラー確認


dump_errors(odrv0)




クローズドループを開始する


odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

あれ?なぜかクローズドループを開始すると2Aが流れて振動する???

パラメータ設定する

integrator_gain を0に設定して保存、フルキャリブレーション

odrv0.axis0.controller.config.vel_integrator_gain = 0
odrv0.save_configuration()
odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.save_configuration()

クローズドループを開始してみる

odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

同じように振動したので、pos_gainを適当に下げてみる

odrv0.axis0.controller.config.pos_gain = 1
odrv0.save_configuration()
odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.save_configuration()

クローズドループを開始してみる

odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

状況変わらず。下げるべきゲインはpos_gainじゃなくてvel_gainだった

odrv0.axis0.controller.config.vel_gain = 0.0075
odrv0.save_configuration()
odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.save_configuration()

クローズドループを開始してみる

odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

クローズドループを有効にしても振動しなくなった!

位置制御やってみる。入力する単位は回転。正方向に1回転、逆方向に-10回転、最後に初期位置(0)に戻す

odrv0.axis0.controller.input_pos = 1
odrv0.axis0.controller.input_pos = -10
odrv0.axis0.controller.input_pos = 0

振動はしなくなったけど、追従が非常に弱い。pos_gainを適当に上げてみる

odrv0.axis0.controller.config.pos_gain = 4
odrv0.save_configuration()
odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.save_configuration()

クローズドループを開始してみる

odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

さっきと同じ位置制御やってみる。多少は追従性が良くなった気がする。制御ゲインの追い込みはここではしない。

odrv0.axis0.controller.input_pos = 1
odrv0.axis0.controller.input_pos = -10
odrv0.axis0.controller.input_pos = 0

今度は速度制御モードにして速度制御してみる。まずは速度制御モードに設定する

odrv0.axis0.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL

続いて速度の指令地として1rpm,100rpm,1000rpmを与えてモーターを回し、止める

odrv0.axis0.controller.input_vel = 1 
odrv0.axis0.controller.input_vel = 100
odrv0.axis0.controller.input_vel = 1000
odrv0.axis0.controller.input_vel = 0



電源入れなおすと、起動すぐにクローズドループが有効にならずエラーが出る。

odrv0.axis0.motor.config.pre_calibrated = True

odrv0.axis0.encoder.config.use_index = False

odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

odrv0.save_configuration()

電源入れ直し


エラーがなければ、ここまでで初期設定が終了。次回電源を入れたときに同じ状態で起動するはず。

これをやっておくと、電源投入と同時にクローズドループがはじまるらしい。電源入れてすぐトルクONは怖いので、私はこれはやっていない。

odrv0.axis0.config.startup_closed_loop_control = True

ODrive動作命令

あとで書く

位置制御の加減速フィルター設定

 odrv0.axis0.controller.config.input_filter_bandwidth = 6.0 [1/s]

位置制御フィルターモードに設定

odrv0.axis0.controller.config.input_mode = INPUT_MODE_POS_FILTER

自分用ヒント

モーターが回らなかったり何か問題がありそうならdump errorでエラーを確認する!

Encoderにエラーがあったら詳細確認、Motorにエラーがあったら詳細確認

エンコーダにエラーがあるときはrebootコマンドじゃなくてODriveとエンコーダの電源を一度OFFにしてから電源を入れなおす



サポートしていたけたらスーパーロボット開発資金として有効活用致します。 人が乗って歩いて変形して空を飛んで合体するようなスーパーロボットの実現が少し近づきます。