ロボットの本質は同じ…
別プロジェクトの基本的なプログラムがなんとか完了した。まだ、改良や追加すべき点は多々あるが、UIであるPCソフトに移ろうと思う。UI部分は今回のプロジェクトとBlueMarionetteで共通して使える。ロボットの本質は同じなんだなと感じたところ。ここへ来て開発のペースが少し落ちたような感じだが、完成度が高まってくると実際のブツが無いと先に進みにくくなってくるなぁー。
別プロジェクトは今週中にナントカしよう。
« 2006年04月 | メイン | 2006年06月 »
別プロジェクトの基本的なプログラムがなんとか完了した。まだ、改良や追加すべき点は多々あるが、UIであるPCソフトに移ろうと思う。UI部分は今回のプロジェクトとBlueMarionetteで共通して使える。ロボットの本質は同じなんだなと感じたところ。ここへ来て開発のペースが少し落ちたような感じだが、完成度が高まってくると実際のブツが無いと先に進みにくくなってくるなぁー。
別プロジェクトは今週中にナントカしよう。
後先も考えずにオーダーした VAIO U であるが、キャンセルした。理由は納期が遅いのと、ロボの資金繰りがショートしてしまったからだ。
とりあえず、手元のPCでロボは色々と仕込んでみようと思う。今回のVAIO Uは成功するような感じなので、改良版が遠からず出るだろうとも睨んでいる。
さてさて、別プロジェクトであるがちょっと難航した。LPC2138 で GPIO を使おうとしたが、一部うまく使えないポートがあったのだ。プログラムを作るまで、わからないのが痛かった。仕方がないのでポートをOn/Offする短いプログラムを RoboShell のディスパッチャに記述して、On/Offの動作を確認してから本格的なプログラム開発を行った。ソフトの開発に手間取ったので、回路製作は明日以降だな。明日もソフトの改良は続けなければいけないので、やはり今週いっぱいはかかってしまうと思う。
ロボを作るための模索は今日も続く…。先日、これを買ったと報告したばかりだったけど、今度はこれを買ってしまった…。まだ、RoboShell Console は検討段階だと言うのに…。コントローラは Saitek で統一できたので、良しとしよう。次はドライバをインストールして、モーション用のコマンドの割り当てでも行えるようにしておこう。
ロボと平行して行っている別プロジェクトのための部品をいくつか購入してきた。大物は例によって一番最後になるけど導入したら即使えるように今から入念に準備をしておくのだ!!
色々と資料を検討しながら、回路設計。一応、出来上がったので時間を作って製作する予定。早ければ今週中には回路は出来上がりそう。ソフトは先に作る予定。入出力が決まれば、ソフトはすぐに出来るのだ。
外は雨だし、体の調子も良くない。こういう時は仕方なしに思索に耽る事になる。ほとんど妄想に近いが、思わないものはカタチにならないし、強く思えば願いも叶うような気がする。
今思っているのは、ロボの機体製作だ。機械設計・金属加工の領域なのでほとんど未知の領域だ。ただ、やるべきことはぼんやりとだが見えてきた。
まだ、はっきりした事は言えないけど、道筋も少しだけど見えてきた。RoboShellは金属とシリコンの塊から、生命に昇華できるのではないかと考えている。機械と生命の違いは、生命は自分自身をコピーする能力を有していることだそうだ。そう、自分で自分を生み出せるのではないか…?種を明かすとがっかりするので、黙っておく…。予備実験が終わり次第、作業を本格化させることにする。
各所で絶賛のKRS-4014HVを買ってみた。制御電圧が+5V必要みたいなんだけど、ロジック的には3.3Vでもいけるのではないかと言うことで試してみることにしたのだ。現在のRoboShellのシステムでは3.3Vに統一している。サーボはCPLDの出力を100Ω(ダンパ抵抗)を直列に入れて3.3KΩ(プルアップ抵抗)で吊ってあるのだ。そこに接続してみると問題なく動作した。これで3.3Vのままで良さそうだ。このモータはシリアルでも角度設定が出来るみたいなんだけど、コマンドが書いていない…。困ったもんだ。
ついでにRoboShellの動作を見直すことにした。GyroDistributionの結果をSetPWM で加算するようにした。これにより、コードが短縮できた。
そろそろ、機体製作も考えないと…。
ジャイロ信号を シグナルコンディショニングを施した後に、各種の補正を行いサーボモータの角度設定パルスに値を足し込んだり、引いたりするわけだ。各サーボモータによって補正係数は当然異なるので、これらの補正係数は個別に設定できるようにした。ゲインとオフセットの設定はターミナルから変更可能だ。実際に動作させながら、変更も可能。設定用に RoboShell Composer を拡張する予定。
うーん、勢いというか…、とりあえず注文してしまった VAIO Type U。ロボリモコンとか、通勤電車の映画鑑賞とか…色々と夢が広がるけど…。これ、今のデスクトップの置き換えに狙っている。そう、サブ機じゃなくてメインマシン。大丈夫かな?次に狙っているのが、PS3。これがまともなデスクトップ機として使えれば、これをメインマシンにする予定。ソニーで統一されてきたな…。ソニーに踊らされているなぁー。うーん。こういうのを
ソニーダンシングチーム
と言うんだろうな…。
まぁ、いいや。しばらく踊り狂うことにしよう。
ジャイロ搭載に向けて、色々な仕掛けを組み込んでいる。その中の一つが、シグナルコンディショニングだ。ADCから取り込んだデータはそのままだと、使いにくい場合がある。対象物(今回はジャイロ)に合わせた信号の前処理を行っておくと何かと便利だ。そこでフィルタ後のADCの値をシグナルコンディショニングする。やり方は…
gSignalCondition = gFilteredADCValue * gain + offset;
となる。現在、利用できるADCのチャンネル数は8ch。その全てのチャンネルにおいて上記の処理をおこなう。処理タイミングは 5msec タイミングだ。これはADCの入力、フィルタと同期している。
次はいよいよジャイロだ。ジャイロの回路はまだ出来ていないが、10ビットADCで取り込んだ場合は0−1023の値が来る。これを適切なダイナミックレンジに設定して、PWMの値として足したり、引いたりすればフィードバック制御になるわけだ。
RoboShell のモーション再入防止のメカニズムと、RoboShell Composer での Export 時の変数名指定機能が実装出来たので、今度は RoboShell Console の検討を始めた。
RoboShell Composer は当初はこの名前だったが、役割が大きく変わったので RoboShell Composer になったわけだ。RoboShell Console はロボットを動作させるためのUIを司るシステムだ。現在、UIはジョイスティックと FPS 用キーボードの組み合わせを考えている。
現在利用しているジョイスティックは、Saitek Cyborg Evo である。これを右手で操作しロボの歩行を制御しつつ、FPS用のキーボード Cyber Snipaで指定したモーションを呼び出すわけだ。
だんだん、面白くなってきた。
RoboShell, RoboShell Composer ともに基本的な機能の実装は終わったので、後は使い勝手の向上を図るようにする。それとは別に RoboShell Console の検討も始めることにする。
RoboShell:
モーションの排他的な処理:
同一優先順位のモーションが重なったときは、後から来たモーションはキャンセルされる。キューに入れることもしない。これはモーションの応答性を高めるためである。ただし、転倒時の起き上がりなどのモーションは通常のモーションより優先順位を高める。起き上がりのモーションは自動起動だが、マニュアルでも起動できるようにする。
RoboShell Composer:
プレイバック機能に任意の Move から Move までの実行機能を付加する。具体的なUIは、プレイバック機能を選択したときにどの番号からどの番号までを入力するダイアログを表示して、プレイバックを実行する。
その他、UIの見直しを行い使い勝手を向上させる。
RoboShell Console:
操作系のPC側のソフト。ジョイスティックやキーボードの読み取りを行い、コマンドに変換した後にシリアル出力を行う。たくさんのモーションを効率的に誤操作なしに行えるUIを構築する。
RoboShell Composer で作成したモーションデータを RoboShell 本体に移すための Export 機能が出来た。これにより、RoboShell Composer のデータを手間なしに移すことが出来る。RoboShell で確認したデータをそのまま、Cのソースリストに変換できる。
懸案だった A/Dコンバータの読み取りルーチンが完成した。けっこう、完成するまでに時間がかかってしまった。現在は10KΩのポテンショメータを5個、取り付けてその数値を読み込ませている。読み取らせると、最小値は0で最大値は1023と返ってくる。10ビットの精度だからこれでばっちりだ!!スケジューラの中に配置してあるので、2.5msec 単位でサンプリング時間を設定することが可能だ。現状は 5msec に設定してある。このスケジューラに配置するところで、ひとつ大きなミスを犯してしまった。タスクの登録を行うのだが、モーションタスクをコピペして使ったためにタスク登録がモーションタスクとADCルーチンでかぶってしまい、どうしようもないバグが発生した。最初はどうしてそうなっているのかが、わからずにかなり試行錯誤してしまった。現在はキチンと動作している。AD変換値に様々な味付け(ゲインやオフセット調整の機能)を盛り込んでいく。
やっと基板が到着しました。長いこと待たされましたが、その間に作業も進んでいたのでちょうど良いタイミングといえるでしょう。とりあえず、試作したので少し使ってみて改良を加えます。今までのロボコントローラに無いパフォーマンス(ARM7-60MHz)と柔軟性(CPLD)を備えています。CPLDの中身はバーニング・宮田さんのLBC機能に近藤サーボレッドバージョンのポジションキャプチャやキャラクタリスティックチェンジなどが付加されています。ROMも512KBの大容量なので、様々な仕掛けを取り込んでいくつもりです。基板の供給にあわせて、作成したファームウェア(RoboShell)もオープンソースで公開します。
レッドバージョンのサーボの取り込みがかなり良い感じになってきた。かつてはモータがおかしくなったり、暴力的に何度もデータを読み出さねばならなかったのが、かなり安定してきた。以前からの懸案だったキャプチャ切り替え時にショートパルスになってしまう問題も解決できた。入れた命令は
出るわ、出るわ、いやになる位バグが出まくった。プレイバック機能は複数のムーブが登録でき、セーブとロードが出来たつもりなので実装に入ったわけであるが、このセーブとロードの機能が極めてあやしい。ロードしたサーボ角もこれまた、どこに格納されるのか?って悩むほどデータ構造がおかしかった。
これをすっきりさせて、セーブとロードとデータ確認が必要だった。各種のテストを繰り返し、どうにかカタチになった。
プレイバック機能はROM焼きをしなくても、PCから逐次データを送りつけることにより、モーションを実行させる機能だ。モーションの試作が簡便になるのだ。短時間で色々なモーションを試すことが出来る。これも挙動がおかしかった。シリアルでコントローラと通信しているわけだが、以前に作成した角度キャプチャも挙動がおかしかったのだが、適当な待ち時間を設けることにより、この不具合を回避していた。キャプチャモードのはずが、PWM出力モードになっている。これはコントローラにリセットがかかり、PWMモードに戻ってしまったことを意味するのだ。ターミナルで手打ちで行っている分にはあまり顕在化しなかったが、PCから大量に短時間に連続的にデータを送ると途端におかしくなる。これはコントローラのシリアル部分がおかしくなっていることを意味する。
いつ、どのタイミングでエラーが発生するかを調べることにした。こういうときにはTeraTermは便利だ。RoboShellのコマンド列に相当するテキストを用意して、ガンガン送りつける。案の定、バッファオーバーフローのようだ。この部分を直して、再び送りつけてみる。全然、大丈夫だ!!素晴らしい!!調子に乗って、通信速度を速くしてみる。57.6Kbps でも問題なし!!でも、サーボの回る感じは 38.4Kbps の方が良い感じ。という事で 38.4Kbps にした。
キャプチャも連続して、取り込めるようになった。前よりも高速だ。ソフトは32chまで作ってあるが、プロトタイプは16chしかない。案の定、16、17chで1,2chのゴーストが出てきた。設計どおりだな。
プレイバックも安定している。これなら、十分使えるレベルだな。まだ、UIがこなれていないのでその部分の修正を加えることにする。
あとは Export 機能。これは純粋にPCプログラミングなので、なんとかなりそうだ。
ジャイロの回路において、オペアンプを NJM2114 にすると先のブログで書いたがこれはとんでもない間違いかもしれない。と言うのも NJM2114 は両電源のアンプで NJM2115 は片電源だ。すぐに手に入りそうな片電源タイプのオペアンプをとりあえず、購入して試してみるつもりだ。もちろん、配線には違いはないのでソケットに出来れば 2114 も試してみるつもり。いずれにしてもこの辺りは、経験値が物言う領域だ。精進する。
前口上
ここんとこ、ひたすらジャイロの活用について考えている。アナログ回路であるジャイロ基板を自作することにはかなりの緊張感を禁じえないが、ジャイロは RoboShell の標準コンポーネントなので避けては通れないし、これが無いとロボの精度向上は望めない。
ハードウェア
基本的にはムラタのサンプル回路のとおりだが、一部の部品は変更する。これは入手性と再現性を考慮したものだ。具体的には OP-AMP NJM2115 を NJM2114 に代えて、実験してみるつもりだ。NJM2114 なら秋月電子で入手できる。実際の基板の製作と搭載は本基板到着後に行う。本基板の搭載可能エリアはかなり小さいので、高密度実装になる。この辺はきっちり作りこむ予定。
ソフトウェア
ジャイロはラジコンで使っているように直接 PWM信号の増減を行うわけでなく、A/D 変換後に各サーボモータにジャイロのフィードバック信号をソフト的に増減する方式を採用しようと考えている。具体的には…
ダイナミックレンジの設定
現在のサーボモータの角度設定のパルス幅は 最小値が 1100, 最大値は 4400程度になっている。これには単位があるわけでなく、サーボモータの特性とPWMコントロールサブシステムのクロックの分周比に依存する。ジャイロの出力もこれに合わせて正規化する。つまり、ジャイロのダイナミックレンジを 1100〜4400 にソフト的に変換してしまうわけだ。正確にはこの中心値である± 1650 にする。あとはジャイロの出力応じた値をサーボモータの設定パルスに足しこんでやればOKだ。もうひとつはムーブやモーションで使われているサーボモータのパルス幅に応じてのレンジの変更だ。各ムーブやモーションはすべてのダイナミックレンジを使い切っているわけではないので、利用幅に対応してダイナミックレンジを変更してはどうだろう?というアイデアだ。
ソフトウェアフィルタの設定
あまりにもセンシティブはフィードバック制御はサーボのピクつきが発生する原因となるのは、自動制御理論においての定説である。静止状態ではフィードバックを切ってしまったり、あるいは長い時定数を設定するのが有効であると思われる。
設定ツール
上記はロボの動作中に設定出来るとわかりやすい。RoboShell Composer に適合ツールチックな機能を付加し、RoboShell もこれに対応する。設定項目は
1.ジャイロ分配のON/OFF
2.モーションダイナミックレンジ変更のON/OFF
3.ゲイン設定(2と連動)
4.ソフトウェアフィルタ設定
ちょっとずつ、実装していく。
やるべきことが次から次へと出てくる。この手の開発は後のほうになればなるほど、まとまった量の実装をしないと効果が見えにくくなる(そう、一気に進めないとまったく動作しないのだ…)。少し、まとめてみると…、
RoboShell
1. A/D 変換ルーチンの作成
2.5msec ルーチンに割り当てて、8ch分まとめて取る。
2. ソフトウェアフィルタの作成
4, 8 個程度のサンプリングの平均値を求める
3. スケジューラの強化
同一優先順位のタスクが複数起動したときには、各種のスケジューリングをおこなう(タスクの再入防止など)
4. ジャイロ関連
別BLOGにします
RoboShell Composer
こちらは PC ソフトであるので、UI に凝りだしたら完全に泥沼である。節度を持って開発の優先順位を付ける
1. Export 機能
入力したモーションデータから、RoboShell 用の C言語のソースを生成する。モーションデータは RoboShellComposer で管理する。
2. プレイバック
モーションデータを ROM 化しなくてもロボで直接実行できるようにする。モーション番号の呼び出しにより、通常はモーションに入る。モーションは一塊の動作なので、モーション番号とどのムーブから実行するかを指示するだけだが、ROM化したデータが前提になっている。
これをワーク変数への書き込み、ムーブを逐次、行うことにより「オン・ザ・フライ」でモーションの動作確認が出来るようにするのだ。
現在、PC側のソフトでは各サーボモータの特性を管理できるようになっている。プレイバックや Export ではこのデータを最大限に活用する。つまり、ロボットへの教示やモーションデータを生成するときは各種の修正データを加味した上で、データを生成するのだ。これにより、より高精度のサーボモータの管理が行えるのだ。
RoboShellConsole から RoboShellComposer になった。Composer にしたのは主として、モーションを作るために用いるからである。懸案だったシリアル受信(サーボ角を RoboShell が取った後、PCにシリアル経由で送信する)もインターネットで見つけたこのクラスライブラリを用いることにより可能になった。作者の方に RoboShellComposer での試用許諾と公開許諾をお願いすると快諾を得ることが出来た。これで完成の暁には何の問題もなく公開できそうだ。
現在の課題は大きく分けて、2つ。
1.サーボの動作に必要な完全なパラメータの管理
2.Export 機能により、1のデータをC言語のソース化
これで完全なモーションデータが作成できるようになる。完成を急ごう。
ロボットのコントロールは Bluetooth を使った遠隔制御を考えているんだけど、やっぱゲーム機でコントロールしたいから、いくつか方法を考えてみた。
TeamKNOx 的には NDS を直接ハックして、リモコンに仕立て上げてしまう方法もある。でも、加齢のせいか最近はこういう「ぐいぐい」はあまりしたくない。
で、ちがう方法を考える…
6月に発売される NDS用の Opera を使う。あ、そうか?PSPならブラウザ内蔵だから、今でも出来るな…。
ロボのほうは
WiFiアダプタを使うんだけど、自分でCFのWiFiカードのTCP/IPのプロトコルスタックとカードドライバを書ければ完璧だけどそこまで男前じゃない。
で、仕方がないから市販品を使う。市販品としては…
1.アルファプロジェクトの EZL-80C
2.WiPort
がある。
ブラウザを使うのでWEBサーバ機能が必要になる。
1.に問い合わせしてみたところ、WEBサーバの機能はないそうだ。今後も搭載予定はないとのこと。残念だね。
商売の機会を逸している…。
2.はリンク先を見たところ、その機能はあるみたいだ。ただ、どの程度カスタマイズできるかが不明だ。ロボのコントローラが一段落したら、やってみますよ。
問題点はいくつか考えられるので、練りこんでおきます。面白くなってきた!!
構造体などを記した ヘッダーファイルの共有化は RoboShell と RoboShell Composer の間で行うことが出来た。これで、保守性と可読性(同じファイルなので頭の切り替えが不要)が向上した。
Composer は 現在、機能拡張中。いろいろとやらせたいことがあるので、どれを優先的に実装しようか非常に悩ましい。
モーションのデータ構造は既に固まってきたので、RoboShell Composer が出来たらモーションを色々と作り始めようと思う。
現在、製作しているのは RoboShell が動作するサーボモータコントローラ、モーション作成のための RoboShell Composer である。RoboShell Composerはモーションデータを作成するわけだから、RoboShell のモーションデータを理解していなければならない。両方ともに C(++) で記述されたソフトウェアである。そこで、データ構造とコマンドの記述がされたヘッダファイルを共有化することにした。これにより、データ構造が常に同一に保たれる。
この試みは初めてではなく、鬼吸いでも行われている。ただ、鬼吸いではコマンドの共有化にとどまっているが…。
もう一度、両方のソフトを見比べて切り分けていく。
レッドバージョンのサーボはサーボ角が取得できることは何度も書いた。サーボ角を取得するためには一旦、サーボの出力を止めるわけだが、この止め方が非常に重要。
と言うのも、出力パルスが出ているうちに止めると、短いパルスと同じことになりサーボモータが動いてしまう。現在の保持している角度と短いパルスには差が生じるので、サーボが動いてしまうと言うわけだ。つまり、より狭い角度方向に動くことになる。
今度は実際のサーボ動作に移行させるときだが、これも注意が必要。現在、保持しているサーボ角(メモリの値)と実際のサーボ角が違うとその差分だけ動作してしまう。これを防ぐためには動作移行時に実際のサーボ角をメモリの値に上書きして、その差分をなくす処理が必要になる。ここで問題になるのが、取得したサーボ角と実際にサーボを動作させる角度に少し差があることだ。この差は直線で表せないので、テーブルが必要になる。全点のテーブルは持てないので代表値か特異点がある場合はその周辺を多く持たせる必要がある。
実装
では、どのような実装が必要になるかを考察してみる。
通常モード→キャプチャモード
キャプチャモードに移行する前に、サーボモータ切り替えカウンタを初期化する。初期化すると当然、0になるのでch00が出力され、この信号がフィードバックされる。このフィードバック信号を監視して0になっているところでサーボの出力を完全に止める。
これはコントローラ側の実装で可能になりそうだ。ただ、フィードバック信号はCAPに割り当てられているので、単なるデジタルI/Oと平行して使えるかどうかは調査が必要だ。(途中で動作モードを切替えるのは、バグの温床になるので、キライである。)
キャプチャモード→通常モード
予め全てのモータで支持角と取得角の差分のマップを作成するモードが必要になる。これがないとティーチングの結果が常に微妙にずれることになってしまう。どの程度のずれかはサーボモータに依存するので、なんとも言えない。(何点か取れば、傾向がわかるかもしれない。)
そんな感じかな…?
ロボットなんかもそうだけど、組み込みシステムで重要なのがタイミング。RoboShell もタイミングがキモだったりする。
RoboShell は全てが割り込みで動作する非同期なシステムだからタイミングをうまく設定しないと所望の動作が得られなかったりする。今はシーケンスを書いているところ。でも、ひとつ山を越えたと思ったら、すぐに次の山が現れる感じがするよ。結構大変。出来るところから攻めていくしかないな…。
当分は PC の RoboShellComposer (名前を変えました。)を改良していくことにする。
先のダサい実装もなんとか改修できた。scheduler と同様に関数ポインタを使って、各タスクを配列に押し込んだ。コマンドに応じて、動作させる場合はその配列をスキャンして処理を呼び出す。すごく、すっきりしたプログラムになった。
現在、コントローラで残っている作業は…
プログラムの拡張に備えて、RoboShell の中身を整理した。シリアルコンソールからの入力要求を処理する dispatcher() と 時間軸制御をおこなう scheduler にわけた。
今後はリアルタイム制御が必要なものは、scheduler に、処理要求の低いものは dispather に分けていけばよい。dispatcher に書き方には、少しダサイ実装が使われているので、この辺も修正していく。
さてDCC だが割り込み駆動では無い様なので、現在の RoboShell で利用している uart0GetCh の代わりに使うには少し工夫が必要そうだ。
現在の RoboShell もバックグランドタスクが整理されていないので、この辺を整理した上で DCC を組み込んでみる。ただ、DCC が持っている pritn 命令は非常に便利なので、デバッグで役に立つだろう。
Optimize から DCC の概要がリリースされたことは先に書いたけどなんとか実装が終わった。
まだ、シリアルのシェルの代わりに使えるところまでは行っていないけど、少しずつポートしていく。まずはWindows版の自作ソフトだ。ソケットを開くクライアントを作ってみようかと思っている。
USBが本格的に通信に使えると、現在使っているシリアルを別の用途にできる。たとえば、BTのHCIのプロトコルなどの実装による BT ネイティブサポートのロボットだ。あるいはシリアル制御のサーボモータなら、そのまま接続すれば良い。
使い道は色々とありそうだ。
コントローラに使えそうなネタはないかと WEBサーフィンしていたら、こんなサイトを発見した。
ロボットの開発記が載っているのだが、やっぱり開発しているプロセスは非常に似通っている。その中でスケジューラを発見した。
WEBの方はPICで行っているが、こっちはARMでGCCで開発している。PICのコンパイラだと関数ポインタの使い方がうまくないらしいけど GCCなら問題ない。
ということで最軽量TCBとそれを使ったスケジューラを早速搭載してみた。ちょっと冗長だった 10msec ルーチンが非常にすっきり書けるようになった。普段はこういうのはOSとかに隠れているけど、たまには剥き出しのスケジューラも良いね!!なにしろ、軽い!!
安定して動作しているようなので、しばらくこのまま使っていこうと思う。
そうこうしている内に、OptimizeからDCCを使ったコンソール出力が発表された。現在のロボシェルのコンソールは、そのままシリアル出力を使っている。
DCCだとUSBが使えるので大変スマートだ。とりあえず、ソースを読んで問題無さそうなら実装してみようと思う。
以前に制作した RoboShellConsole に若干の改良を施して、スライダーからの出力をリアルタイムでサーボに伝えられるようにした。スライダーの値とサーボのPWM値が正確にマッピングされていないので、不感帯があるがとりあえず、サーボは動くようになった。
現在のコントローラはモーションまでサポートしているので、モーション作成をサポートするソフトも作る必要がある。現在の RoboShellConsole で足りない機能は
10msec タスク(サーボモータの直線補間)のメインルーチンへの実装が完了した。当初の目論見(しかし、リストはみにくくなるなぁ〜)どおり、スタックの使用量が激減したのでかなり良い感じになった。(当社比:75%減)
残すはA/Dコンバータの実装だ。A/Dコンバータにはロボに必要なセンサである、
BlueMarionette のコントローラのモーション生成プログラム時に、原因不明のバグが発生したこととその解決策を講じたことは既に本Blogに書いたとおりだ。
これで解決。めでたし、めでたしなのだろうか?一般に割り込み中に処理を重ねることは、あまり誉められたことではない。今回のように CPUの実行速度に比べて、今回のシステムのように比較的遅いサイクル(2.5msec)であれば問題ないが、早くなってくるととたんに苦しくなってくる。あるいはスタックをかなり増量しないと成立しないシステム設計はあまり良いとは言えない。割り込みというのは、現在の状態をスタックに退避して、割り込み終了後にそれを戻すことの連続だからだ。
このような処理はメインループに移すのが定石だ。10msec 毎の割り込み通知のみを割り込み処理ルーチンにて行い。その割り込み情報を元に実処理はメインループ中にて処理する。
気を付けなければいけないのは、10msec に一回だけ処理を行うということだ。フラグは立ち上がり/立下り(所謂、エッジ)のみを捉えることが肝要だ。
if(g10msecTask == TASK_ON){
if(g10msecDone == TASK_DONE){
}
else{
Task10msec();
g10msecDone = TASK_DONE;
}
}
割り込みルーチン(2.5msec 毎に入る)
if(gIntCounter % 4){
g10msecTask = TASK_OFF;
}
else{
g10msecTask = TASK_ON;
g10msecDone = START_TASK;
}
こんな感じだろうか?
現在のコントローラではロボットの動作は下記のように定義される。
Motion = Move(0) + Move(1) + ... Move(n)
Move から 次の Move へ遷移するときに、インターバルタイムを設けた。全て Move で逃げようかとも思ったが、現在のMove では PWM 時間(4byte) x 32ch + 分割数(4byte) を消費する。全て Move で処理すると、実Move毎に無駄な Move が間に入ることになる。
これを防ぐために、インターバルタイムを Move に持たせることにした。これにより、最小限の記憶容量でインターバル時間を Motion に反映させることができるようになった。
少し、野太い声も遠ざかったような気がする。
最近は頭の中でコードを廻している。組込みシステムでは、まともなデバッガは使えないので自分の論理だけがデバッガになるのだ。I/Oデバイスに現れる様々な事象を通してのみ、的確なデバッグができる。
コードを廻しているせいか、少しずつCPUの気持ちがわかってきた。ちょっと、やばいかも…。汚いコード(論理の反転が高頻度に起きたり、同じような用途の変数、意味のないグローバル変数など)があると、「直せぇ〜、直せぇ〜。」とどこからか声がする。
特に現在使っているCPUはARMだ。組み込み用途という極めて、ガテンな仕事で使われているし、名前がアームって言う位だから、腕っぷしもかなり強いのだ。そう、野太い声で、「直せぇ〜、直せぇ〜。」が聞こえるのだ…。
かなり、やばいなこれは…。
そろそろ、PCのソフトの開発をするかな…。
昨日からテンパッているMotionの実装だが、どうにか完成した。Move もかなりシェイプアップして、冗長なところは削ぎ落とした。
現在の実装ではなるべくブロッキングファクターを無くす実装を心がけている。Move/Motion の実行中であっても、通信機能は生きている。ほとんど、全てを割り込みで実装しているからだ。
Motion の実装は久々に手こずった。Moveは問題なく、動作しているのにそれの集合体である Motion はうまくいかない。割り込みを考慮して、割り込みのワンサイクルで一回だけ実行するようにしているのに関わらずである。自分がCPUになった気持ちで、頭の中で1ラインずつ実行してみる。論理に破綻は無いはずだ(って誰でも言うんだよねW)。
ヒントになったのは本当に時々動作すること。ただ、その再現条件がどうしてもわからない。もうひとつは、本来は出ないはずのエラーメッセージがなぜか出ること…。
このことから…、
時々、動作をするということはMotionのロジックは完成している。変なエラーメッセージが出るとはメモリ周りがおかしくなっている…。
これらの現象から、プログラム実行時のスタックを消費しつくしていることが考えられた。そこで、よくわからないながらも boot.s のスタック記述を増量してみた。
結果はばっちり。
これで、Motion を実装することが出来た。後はA/Dコンバータの部分を実装すれば、ロボットに必要なコントローラの基本的な実装が完了する。
後はひたすら、テストとチューニングで品質を上げていく。
もう少しだ!!