Blog Archives

マイクロマウス研修(kora編)[38] 第40回全日本マイクロマウス大会

こんにちは。koraです。

今回は、2019年12月1日に開催された全日本マイクロマウス大会について報告します。

会場は昨年と同じ、東京工芸大学の厚木キャンパスでした。

マイクロマウス競技

全国大会のマイクロマウス競技はファイナルとセミファイナルに分かれており、参加者のうち地区大会で獲得したポイントが多い人はファイナルに出場します。今回は3ポイントがボーダーラインだったらしく、運よく3ポイント獲得していた私はファイナルに出ることになりました。

ファイナルは32×32区画のサイズで、今までの迷路の4倍の面積があります。手ごわい相手ですが、これまでの改良で走破できるだけの性能はあるはずです。

実際の結果がどうだったかというと…

  • 第1走:多少ふらついていはいましたが、壁を読み違えることなく完走できました。
  • 第2走:南回りのルートで最短走行を試みるも、途中で壁に引っかかってリタイアしてしまいました。
  • 第3走:再度最短走行を試しましたが、同じ場所で引っかかってリタイアしました。迷路の段差とカーブが重なって曲がりきらなかったようです。
  • 第4走:重ね探索で他のルートを探すことにし、北回りのルートを見つけてゴールしました。
  • 第5走:最後に北回りの最短走行にトライしたが、残念ながらこれも壁に引っかかって終了となりました。


結果としては、第4走の「00:53.301」が記録として残り、成績は14位となりました。

技術交流会

競技の後は技術交流会が開かれました。毎度のことですが、皆さん作り込みはすごいです。見比べると自分のマウスの改良すべき点に気づかされます。車体自体もっと小型化できるはずですし、車軸のブレも直せるはずです。ブザーはあったほうが良かったし、欲を言えば吸引機構も欲しいです。

おわりに

今回で、社員研修としてのゴールであった「全国大会での完走」は達成することができました。
これにてマイクロマウス研修は修了となります。

しかし、この大会で最短走行を決められなかったのは心残りです。また、ハードウェアから作り直したい部分がたくさんあって、このまま終わらせることはできそうにありません。まだまだマウスは続けていこうと思います。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[37] STM32F7のFlashにマップデータを保存する

こんにちは。koraです。

前回までの投稿で迷路探索ができるようになりました。今回は迷路の壁情報をFlashメモリに書き込む方法についてまとめます。
マイコンのRAMに保存されている情報は電源を切ると消えてしまいますが、Flashメモリに保存しておけば電源を入れなおした後でも読み込むことができます。

STM32のFlashメモリの基本的な使い方は、idさんのブログを参考にさせていただきました。

STM32F7のFlashメモリについて

私のマウスはSTM32F7を使用しているので、公式のマニュアルを参照します。68ページ目にFlashのSector表が記載されていました。STM32F732には、全部で7つのSectorがあり、Sector 0~3は16Kbyte、Sector 4は64Kbyte、Sector 5~7は128Kbyteのサイズになっていることがわかります。

ただし、どのSectorでも自由に使えるというわけではなく、Sector 0にはシステムによって割り込みベクタテーブルが配置されるそうです。なので、Sector 1にマップデータ、Sector 2以降に実行プログラムが書き込まれるようにリンカスクリプトを編集します。

リンカスクリプト

STM32CubeMXとSW4STM32を使った環境では、プロジェクトディレクトリの直下にある.ldファイルがリンカスクリプトです。

MEMORYコマンド

リンカスクリプトではMEMORYコマンドでメモリ領域を定義しています。デフォルトではRAM領域とFLASH領域のみ定義されていますが、まずこの部分を変更します。
RAM領域はそのまま、新たにFLASH_SECTOR0とFLASH_SECTOR1を追加します。また、元のFLASH領域の開始アドレスをSector 0の0x80000000からSector 2の0x8008000に変更し、領域のサイズを512Kから480Kに変更します。

SECTIONコマンド

次に以下のSECTIONSコマンドを変更します。

.isr_vectorは割り込みベクタテーブルを表していて、STM32CubeMXで生成されたコード内で定義されています。先ほどFLASH領域をSector 2~7に変更したので、割り込みベクタテーブルがSector 0に配置されるようFLASHをFLASH_SECTOR0に変更します。

.backup_flashが今回マップデータを保存するセクションです。これをFLASH_SECTOR1に配置します。また、_backup_flash_startという変数にこのセクションの開始アドレスを代入します。この変数は実際にFlashへ書き込む際に使用します。

マップデータの書き込み・読み込み

大まかな流れは次の通りになります。ソースコードはidさんのものとだいたい同じになるのでここでは割愛します。

書き込みの流れ

  1. あらかじめRAM上にマップデータ受け渡し用の領域を確保しておく
  2. マップデータをRAM上の一時領域に展開
  3. HAL_FLASH_Unlock関数でFlashの制御を許可
  4. HAL_FLASHEx_Erase関数でFlash上の指定Sectorのデータを消去
  5. HAL_FLASH_Program関数でRAMに展開されたマップデータをFlashにコピー
  6. HAL_FLASH_Lock関数でFlashの制御をロック

読み込みの流れ

  1. memcpy関数でFlash上のデータをRAM上の領域にコピーする
  2. コピーしたメモリから、マップデータの構造体に落とし込む

おわり

これで探索後のマップデータを保存できるようになりました。電源を入れなおしても重ね探索や最短走行にトライできるので、かなり便利になりました。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[36] 迷路探索

こんにちは。koraです。

前回はモーター制御を実装して、軌道に追従できるところまでやりました。今回は実際に迷路を探索させてみます。

軌道生成

探索中は、1区画ごとに「直進」あるいは「90度スラローム」の軌道を生成して迷路内を走ります。複数区間をまたがるような複雑な軌道を作ることも考えられますが、今回は確実に完走することを目指してこの2つだけに限定しました。

ちなみに「直進」の場合は角速度ゼロで直進方向のみ台形加速、「90度スラローム」の場合は一定速度で角速度のみ台形加速にします。

迷路探索

探索アルゴリズムは足立法を実装しました。ソースコードはHM-StarterKitのサンプルプログラムを参考にしています。

これで1区画ごとに、

  1. 壁を認識
  2. マップを更新
  3. 次の軌道を決定
  4. 軌道に追従
  5. (以下ループ)

という順でプログラムが実行されるようになります。

テスト

軌道追従のパラメータとモータ制御のパラメータを調整して、実際に迷路を探索させてみた動画です。
4×4の小さな迷路ではありますが、ゴールして戻ってくるまで動いてくれています。
本番の大会に向けて、もっと速度と安定性を上げていきたいと思います。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[35] 九州地区大会・中部地区大会

こんにちは。koraです。

今回は、マイクロマウス九州地区大会と中部地区大会について報告します。金曜日から熊本に前日入りして、土曜日は九州大会、日曜日は中部大会と密度の高い週末となりました。

九州地区大会


九州地区大会は熊本高専・熊本キャンパスで開催されました。学祭との同時開催だったようで、校内は賑やかな雰囲気でした。

さて今回出場した私のマウスですが、前回参加した北陸信越地区大会からの改良点は主に2つです。

  • 軌道追従によって走っているのですが、前回まで軌道追従のコードが雰囲気で組まれていたのでコントロールを失うとねずみ花火のように暴走しがちでした。そこをこちらの記事で解説したような追従方法に変更しました。
  • 足立法の探索では1区画ごとに歩数マップを更新しますが、マップ作成に時間がかかっていたため区間の終わりで一瞬足を止めるような動きをしていました。そこで、マップ作成の範囲を必要な区画に限定することで高速化を図りました。


こちらが本番の迷路です。探索時にあっちこっち行かされる作りになっていましたが、第1走~第3走は目立ったトラブルもなく完走できました。また、最短走行のタイムは6秒234で、13人中5位の記録となりました。今回改良した部分は上手いこと機能してくれたようです。

ただし、第4走~第5走は壁にぶつかって止まってしまったので、最短走行のパラメータには改良の余地があることも分かりました。

中部地区大会


中部地区大会は名古屋工学院専門学校で開催されました。九州地区大会の翌日だったのでマウスに改良は加えられなかったのですが、会場の迷路は壁材の劣化が少なく照明環境も安定していたので、試走では昨日よりいい走りだったと思います。


しかし本番の迷路を見ると試走の安心は吹き飛んでしまいました。中部地区にはつよつよなマウサーが集うので上級者向けな迷路になると聞いてはいたのですが、噂通りのひどい迷路です。櫛、密林、連続180度ターンなど、難易度の高い構成です。

壁にかすりながらもかろうじて完走できました。タイムは14.255秒で33人中11位の速さです。こんな難しい迷路でも上位陣は2~3秒で走ってしまうから恐ろしいものです。少しでも近づけるよう、参考にさせていただきながら改良を重ねていくしかありませんね。

総評

両大会で完走できたとはいえ、まだまだ安定性には課題を感じました。エンコーダは目に見えるほど偏心していますし、光センサも信頼できるとは言えません。全国大会まで約1ヶ月ありますので、安定性に重きを置いて改良していきたいと思います。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[34] モータ制御の実装

こんにちは。koraです。

今回は、指示した通りにマウス本体を動かせるようにモータを制御するモジュールを追加します。

CubeMXの設定

左右のモータを制御できるように、2つのPWMを出力できるようにします。使用するタイマをTIM3として、チャンネル1と2をPWM出力に設定します。

PWMのクロックにはAPB1 Timer clockが供給されるらしいので、108MHzになります。

以前使用していたHM-StarterKitでは48MHzで240階調 = 200kHz周期のPWMを出力していました。同じモータとモータドライバを使っているので、周期を同じにするため108MHzで200kHzになるよう539(540階調 – 1)に設定します。

PWMを出力

HALを使ってPWMのパルス幅を変更するには、TIM_OC_InitTypeDefという構造体を使用します。この構造体のメンバPulseに0~539の値を設定してHAL_TIM_PWM_ConfigChannel関数に渡すことで、パルス幅が変わります。

設定をするだけではPWM出力が開始されるわけではありません。開始するには以下のHAL_TIM_PWM_Start関数を呼び出します。

モータ制御モジュールの追加

指定される目標速度と目標角速度に対して、エンコーダとジャイロで測定される車体の速度と角速度を一致させるよう、モータに掛ける電圧を調整します。単純なPID制御を使って実装しました。

テスト

実際にスラロームの軌道に追従させてみました。あまりなめらかな動きとは言えませんが、一応意図した動作はしてくれているようです。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[33] 目標軌道への追従方法の検討

こんにちは。koraです。

前々回までにマウスの自己位置を推定できるようになったので、今度はマウスに辿らせたい目標軌道を生成していきたいと思います。

目標軌道の生成方法

マウスは目標点に追従するものとして、その目標点を移動させることで軌道とします。
速く走るためには斜め走行や180度ターンなど多様な軌道を考えるべきですが、今回は確実に動かすことを目標として、直進と90度のスラロームの2つだけ考えます。

目標軌道の追従方法

目標軌道から、目標点の速度(Vr)と角速度(ωr)が分かりますので、これをマウスで再現させます。ただしこの際、目標点とマウスのズレをフィードバックさせることで、より目標軌道に近い経路を走行できるようにします。

考え方はシンプルです。マウスから見て目標点の前後のズレをXe、左右のずれをYe、角度のズレをθeとしたとき、ズレを反映した目標速度(V)と目標角速度(ω)を以下の式で求めます。

V = Vr * cos(θe) + Kx * Xe
ω = ωr + Vr * (Ky * Ye + Kθ * sin(θe))

ただし、Kx、Ky、Kθはそれぞれ前後、左右、角度のズレに掛けるゲインです。
この追従方法はKanayama Control Methodというそうです。こちらを参考にさせていただきました。

ここで求めた新しい目標速度と目標角速度に対し、マウスの速度と角速度を一致させるようにモーターの出力を決定してマウスを追従させます。

軌道追従の実装

以下の手順で軌道追従できると思います。②~⑤を1ms周期で繰り返し、目標点が目標軌道の終点に達したら①に戻って新たな目標軌道を設定します。

①目標軌道を設定
②オドメトリによりマウスの位置と速度を取得
③目標軌道に沿って目標点の位置を更新
④上式で目標速度と目標角速度を計算
⑤目標速度と目標角速度に追従するようモーター出力を決定

次回

今回考えた軌道追従を実現するには、速度と角速度を追従させる制御が必要です。次回はこれを実装したいと思います。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[32] 東日本地区大会・北陸信越地区大会

こんにちは。koraです。

今回は、東日本地区大会と北陸信越地区大会の参加レポートです。

マイクロマウス東日本地区大会


東日本地区大会は、9月7日~8日にパシフィコ横浜で開かれたロボットのイベント「ロボフェス」の一環として開催されました。

7月の関西地区大会に挑んだときはバグだらけで暴走しがちだった自作マウスでしたが、そこから改良を重ね、スラローム探索も安定してこなせるようになっています。前日の試走会もそこそこ安定した走りを見せてくれました。

しかし、思えばこれで慢心してしまっていたのでしょう。翌日の本番では、序盤こそ調子よさそうに走っていたものの、ゴール手前で壁を読み間違えてしまい、残念ながら完走することはできませんでした。

敗因は本番のフィールドに合わせた光センサの調整ができていなかったことのようです。前方の光センサの閾値を上げるだけで解決できたのですが、ルール上、競技中はソフトウェアを変更することはできないため、なすすべもなく壁を読み間違えるマウスを見守ることしかできませんでした。

マイクロマウス北陸信越地区大会


東日本地区大会の1週間後、北陸信越地区大会がNCC新潟コンピュータ専門学校で開催されました。

全国大会への出場権を得るためには、地区大会での完走が条件になっています。確実に完走を決めることを目標に参加しました。

1走目、タイヤが汚れていたのか直進距離にズレが生じ、壁に衝突してしまいました。
2走目、タイヤを丁寧に拭いてから挑戦したところ距離は正確になりました。が、前回の大会と同様に壁の誤認が発生して迷子になってしまいました。
3走目、こんなこともあろうかと光センサを調整できるようにしておいたので、ほんの少し閾値を上げて走らせた結果、上手いこと認識できるようになり、ついに完走を決めることができました。おまけにスタートへ戻る際に最短経路を見つけてくれたようです。
4走目と5走目は、先ほど見つけた最短経路を通り、壁にぶつかることなくゴールすることができました。

結果、タイムは00:12.313で5位の成績になりました。
入賞は逃しましたが、ようやく全国大会への出場権を得ることができたので大満足です。

次の大会ではさらに安定性を上げて、タイムを縮められるよう、工夫を凝らしたいと思います。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[31] オドメトリの実装

こんにちは。koraです。

今回はオドメトリ(自己位置推定)をできるようにします。
以前の制御では迷路の壁に沿って進んでいたので、正確な自己位置を把握する必要はなかったのですが、今回は目標軌道に追従させるような制御をしたいので実装することにしました。

オドメトリの実装
計算方法

制御周期を1msとしますので、制御周期ごとに車体の角度と移動距離を計算して積算していけば、ロボットの自己位置を推定することができます。

  1. ジャイロの出力値から[度/秒]の車体の角速度が得られるので、単位を[rad/ms]に変換して1ms前の車体の角度[rad]に足し合わせることで、現在の車体の角度[rad]になります。
  2. エンコーダ出力値(タイヤの絶対角度)に対して、1ms前の値との差分をとるとタイヤの角速度[rad/ms]が得られます。これにタイヤの直径[mm]を掛けると車体の進行方向の移動距離[mm/ms = m/s]が得られます。
  3. 車体の角度と進行方向の移動距離から、X方向、Y方向の移動距離をそれぞれ求めます
    • X方向の移動距離 = 車体の進行方向の移動距離 * cos(車体の角度)
    • Y方向の移動距離 = 車体の進行方向の移動距離 * sin(車体の角度)

実際には1ms間も角度が変わり続けているのですが、ここでは計算を簡単にするため角度一定と仮定しています。また、タイヤの滑りなどで誤差が出ますので、後々補正を入れる必要があります。

モジュールの実装

エンコーダのモジュールを作ります。Srcフォルダにodom.cを、Incフォルダにodom.hを作って、上記の計算を実装します。また、タイマ割り込みで制御周期ごとに呼び出されるようにします。

動作確認

実際にマウスを動かして、角度と座標を計算できていることを確認できました!

次回

次回から、目標軌道の生成とその追従制御に取り掛かりたいと思います。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[30] タイマ割り込みの実装

こんにちは。koraです。

今回はタイマ割り込みを設定します。
以前HM-StarterKitを使ったときも実装していましたが、一定周期でセンサ値の取得と車体の制御ができるようになります。

タイマ割り込みの設定

マウス本体は1kHzで制御する予定ですが、この中で4つの光センサと1つの電源電圧のAD変換を行いたいので、1kHzの5倍の5kHzで割り込ませたいと思います。

CubeMXの設定

まず、CubeMXのClock Configurationタブを開いて、クロックを確認します。
STM32には複数のタイマがありますが、今回はGeneral-purpose timersの1つであるTIM2を使います。
STM32F72x/3x Reference Manualの5章によると、APB1 Timer clocksがのTIM2に供給されるようです。

次に、Pinout&Configurationタブを開いて、タイマを設定します。
左側のタブからTimersをクリックし、TIM2を選択して、TIM2 Mode and Configurationウィンドウを表示します。

  • 上段のModeの”Clock Source”を”Internal Clock”に変更します。
  • 下段のConfigurationのParameter Settingsタブを開いて割り込み周波数を設定します。
    割り込み周波数 = クロック周波数 / ((Prescaler + 1) * (Counter Period + 1))
    APB1 Timer clocksが108MHzですので、”Prescaler”を200-1に、”Counter Period”を108-1にすれば、割り込み周波数が5kHzになります。
  • NVIC Settingsタブを開いて”TIM2 global interrupt”にチェックを入れることで、割り込みが可能になります

タイマ割り込みのプログラム

割り込みが発生したときに呼び出される関数は、CubeMXで生成されるファイルのstm32f7xx_it.cにある、TIM2_IRQHandler()です。ここから各モジュールを呼び出すようにします。
5kHzで発生する割り込みに対し、前回設定したADCを順番に実行し、全体を1kHzで更新します。また、ジャイロとの通信、エンコーダとの通信、現在位置の計算(未実装)、目標軌道の計算(未実装)、モータの制御(未実装)も順番で実行し、これも1kHzで更新します。
なお、実際にタイマ割り込みを開始するには、main関数内に次の行を追加しておく必要があります。

次回

センサが一通りそろって、タイマ割り込みもできるようになりましたので、次から現在位置の計算をさせてみます。最終的には目標軌道に追従させるような制御をさせるつもりです。

続きを読む ›

Posted in DCマウス研修


マイクロマウス研修(kora編)[29] 光センサの動作確認

こんにちは。koraです。

今回は光センサを設定します。

光センサの動作確認
STM32のADC

光センサとバッテリー電圧の読み取りにSTM32のADC (アナログ・デジタル・コンバータ)を使用します。STM32F732にはADCモジュールが3つあり、今回使用するのはADC1です。
配線は次のようになっています。

  • 右前光センサ: ADC1_IN0
  • 右光センサ: ADC1_IN1
  • 左光センサ: ADC1_IN2
  • 左前光センサ: ADC1_IN3
  • バッテリー電圧: ADC1_IN4

CubeMXの設定

次のように設定します。

ADC_Settings

  • Scan Conversion Mode: Enabled … 複数のチャンネルを変換するためEnabledにします。
  • Continuous Conversion Mode: Disabled … 連続で変換するわけではなく、光センサのLEDの発光と同期させる必要があるのでDisableにします。
  • Discontinuous Conversion Mode: Enabled … ADCを開始後、下のNumber of Discontinuous Conversionで指定する数のチャンネルだけ変換してADCが停止するようになります。
  • Number of Discontinuous Conversion: 1にします。

Scan Conversion Modeでは、変換する順番を指定します。
各光センサは、LED消灯時に1回、LED点灯時に1回、ADCを実行し、その差分を取るようにします。バッテリー電圧は1回だけにします。つまり、①右前LED消灯時、②右前LED点灯時、③右LED消灯時、④右LED点灯時、⑤左LED消灯時、⑥左LED点灯時、⑦左前LED消灯時、⑧左前LED点灯時、⑨バッテリー電圧、という順でADCを行います。
ADC_Regular_ConversionModeを次のように変更します。

  • Number of Conversion: 9にします。
  • Rank: 1
    • Channel: Channel 0 … 一番最初に読み取りたいチャンネルを指定します。0を指定するとADC1_IN0が読み込まれます。
  • Rank: 2
    • Channel: Channel 0 …

続きを読む ›

Posted in DCマウス研修