久々にマウスの記事投稿です。俺史上初(マジ)の DC モータを使ったマイクロマウス、じゃき太浪:wq(読み: じゃきたろう, :wqは読まない)を作っています。
実際に動かすとなると、速度制御を行う都合上、何らかの速度目標値を設定する方法が必要です。具体的に僕が知っている範囲内でいうと
- 加速テーブルを生成し、周期割り込みごとに目標値としてそれを用いる(インデックスのインクリメント or デクリメント)
- 加速テーブルは使わず、周期割り込みごとに目標値をマイコンに計算させ、それを使用
というやり方が考えられます。僕はこの内、C++ を使うと実行時コストが圧倒的に少なくなる 1. を採用しています。実装が簡単な台形加速を採用しているところです。
今回はこの加速テーブルを実行時でなく、コンパイル時に生成してしまおうという方法をご紹介します。
理屈の紹介は面倒なので、申し訳ありませんが今回は実装のみの紹介です(中身がない)。
参考サイト
- コンパイル時ルックアップテーブル生成について - in neuro
- 非常に勉強になりました。今日の記事の内容は全てこの記事から持ってこさせてもらいました。感謝感謝。
実装
注意
MSVC(Microsoft Visual C++のコンパイラ)ではコンパイラのバグにより下記のコードのパースが通らず、コンパイルエラーが発生してしまうようです。おおん
なので、良い子は黙って gcc
か clang
を使いましょう。
こんな感じで加速テーブルジェネレータを作ってみました。テンプレート、パラメータパック、constexpr を全力で利用しました。
使用法
このヘッダをどっかにインクルードして、以下のように変数宣言を行えばサクッとテーブルを生成できます。
コンパイラに掛けるときに、PC の方で加速テーブルを生成してしまえるということがポイントです。マイコンでは一切計算を行いません。加速にかかるコストはテーブルのインデックスポインタの加算・減算だけです。O(1) で済むのでとっても嬉しいですね。特に FPU のないマイコンではとてもいいと思います。
// main.cpp
const auto table = AccelarationTableGenerator::daikei::generate<1250, 500, 1>(); // 加速後の速度は500.0mm/sec
基本的に、変数宣言に constexpr
を付けて -O2
以上でコンパイルをすれば、実行バイナリ生成時にはすでに PC にて計算が完了しています。
では PC にてその加速の様子を見てみましょう。
きちんと直線加速できています。
それでは最高速度 500.0mm/sec のもとで、クロソイドスラロームをしてみたらどうでしょう。クロソイドスラロームは途中まで各加速度を台形加速させるという方法なので、上のジェネレータがそのまま使えます。こんな感じでシミュレートしてみます。
このログを gnuplot
に噛ませるとこんなかんじ(std::cerr
と fprintf
が混じっているのは許してください...)。
うん、いい感じにできています。