【編集中】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にしてから電源を入れなおす