TOP > 製作日記 > 2月中旬

下の写真はクリックすると大きい写真が見れます。

今月分を全て見る場合はこちら⇒ CLICK

02月11日 金曜日  タイトル: VBで動作を確認  [もうちょいでモーションへ]

▼ホームポジションと各種設定

 ようやく、ホームポジションと他の設定ができるようになりました。ホームポジションの設定はもちろんのこと、出力ポートの変更、ポートごとのRCサーボの選択が可能です。ホームポジションの設定は、スライドバーとテキストボックス、ショートカットキーでの調整の3種類が可能です。
 そして、昨日の時点で各種設定をマイコンへ送信することに成功、今日の昼頃にはマイコンから各種設定の受信が可能になりました。とりあえず、基本が完成したと言ったところですね。これからいよいよモーション製作ができるようにプログラミングします。
 今のところ、あまり考えが固まっていないので、もうちょっと煮詰める必要があるかも。当然VBの方ができれば、マイコン側のCも進めなければなりません。ほぼ交互にやっているような状態なので、時折混乱することも。(^-^;
 モーション作成する方はホームポジションの設定時と同じように、スライドバーやテキストボックスに入力する方式で角度を変えようと考えていますが、その他に表形式で各時間ごとの角度が分かるようにしたいですね。ただ、これについては未だに方法が分からず。どうすりゃいいんじゃ〜!!
 表をセットするところまでしか分からん・・・。
02月13日 日曜日  タイトル: モーション作成部分のプログラミング  [送信まで行かなかったか。]

▼基本部分は完成

 起きたのが正午・・・いかん、寝すぎた。その後、モーション作成部分のコンボボックスの配置やら、テキストボックスの配置を検討する。角度入力するだけのエディターならば簡単なのだが、それだけでは楽ができるとは言えない。
 っと言うのも、今まで、第一回テクニカルカンファレンスにて公開された、行列を使わない逆運動学計算を使って来たので、これは使いたいのです。そんな訳で、角度と逆運動学を切り替えることに決めた。この逆運動学プログラムと睨めっこするのも、相当久しぶりなので、解読するのにだいぶ時間を取られました。
 今までH8でやらせていたので、オーバーフローの処理とか、整数演算部分などVBに不要な部分は全て削除。計算結果がおかしかった部分を修正。なかなか時間がかかった。しかし、ここまで来ると行数がだいぶ増えてくるので、頭が多少混乱気味。フリーズしそう・・・頭が(^-^;

▼限界範囲の設定とか、補完モードの選択とか

 そして忘れてはならないのがコレ、限界範囲の設定。膝とかは-90°〜+90°の設定なんかではやらずに、0°〜180°の設定で行いたいので、VBの表示を変更する設定を追加。操作ミスを防止する目的で製作。こういうのって重要ですよね。
 H8に送るのは、どんな設定であろうと0°〜180°で送ります。だから、実質的には何も変わらない・・・のである。

 で、その他に追加したのが、連動ボタン(通称、なまけボタン)。左端のチェックボックスをクリックし、チェックを入れると、両方のいずれのスライダーを変更しても連動して動きます。当然、増減した数値分だけ動きます。両足に同じ動きをさせたいときとか、両腕に同じ動きをさせたいときに便利。
 補完モードの横にチェックを入れると、一番上の補完モードを変更すると、他の7個も全て同じ物に変更されます。その他に、どの場所で操作していても、ENTERキーを押すと、ショートカット入力ボックスに戻るように設定しました。とりあえず、こんなところです。
 本当は送信するところまで行きたかったんですが、夜が明けてしまったので、一先ず中断(-_- )。
 続きは、目覚めてから・・・おやすみ。Zzzz
02月17日 木曜日  タイトル: 配列のコピーとか初期化とか  [今更だけども、重要。]

▼急にベンチマークしたくなった。

 モーションエディタを作っているのですが、以前にも増して配列を別の配列へコピーしたり、配列を初期化したりする作業が増えてきました。そこで気になるfor文の処理速度を調べて見ようと思い立ったのです。何気なく書いている処理がどのくらい違うのか気になる・・・気になる・・・気になるでしょっ!

▼まずは、今まで使ってきた方法から・・・

 配列Aを配列Bへコピーする際、私はfor文を使います。while文は全く使いません。使い方も3種類ほど思いついたので、どれが早いのかをチェック。条件は、Dummy_Dat[8][64]という配列を作成し、そこに固定のデータ(90とか、100とか)を代入していくようにします。
 データは512個入るので、時間もそこそこ掛かりますね(とは言っても、一瞬ですが)。使用するマイコンは、秋月のH8/3052Fの25MHzタイプ。では、まずはソースから・・・
void FOR_01(void)
{
  int i;
  for(i=0;i<64;i++)
  {
    DUMMY_DAT[0][i] = 90;
    DUMMY_DAT[1][i] = 90;
    DUMMY_DAT[2][i] = 90;
    DUMMY_DAT[3][i] = 90;
    DUMMY_DAT[4][i] = 90;
    DUMMY_DAT[5][i] = 90;
    DUMMY_DAT[6][i] = 90;
    DUMMY_DAT[7][i] = 90;
  }
}

void FOR_02(void)
{
  int i, j;
  for(j=0;j<8;j++)
  {
    for(i=0;i<64;i++)
    {
      DUMMY_DAT[j][i] = 90;
    }
  }
}

void FOR_03(unsigned char n)
{
  int i;
  for(i=0;i<64;i++)
  {
    DUMMY_DAT[n][i] = 90;
  }
}

/* FOR_03関数のみ、メイン関数にて下記のように呼び出す。 */
FOR_03(0);
FOR_03(1);
FOR_03(2);
FOR_03(3);
FOR_03(4);
FOR_03(5);
FOR_03(6);
FOR_03(7);
  
 さて、結果はいかに。個人的にはFOR_03が早いと、メモリは節約できるしプログラムがすっきりするので、期待して実験結果を待つ。そして出た結果は以下のとおり。
関数名 : TCNT μsecへ変換
FOR_01 : 1055 337[usec]
FOR_02 : 1511 483[usec]
FOR_03 : 1691 541[usec]
  
 その結果、関数作った順にどんどん処理が遅くなって行きました・・・。しかも、01と02との開きが大きいし。結論、まとめて書くより箇条書きの方が早い。
悔しいけど、これが現実。受け止めなさい!(-_- )
俺はこんな結果は認めん!
認めたくないものだな。自分自身の・・・(以下略)

▼認めたくないならどうする?

 フフフ・・・あるのだよ。今までのfor文に打ち勝つ最後の手がな!そう・・・その名は。

 第217話 ポインタ

 話数は気にするな。ちょっとした遊び心だ。(ぉぃ)そう、C言語をやるときに壁として立ちふさがるアレである。高速化するにはポインタが使えなきゃダメ。そう聞いたことがあるような気がする。で、改良したのがこれである。
void FOR_04(unsigned char *a)
{
  int i;
  for(i=0;i<64;i++)
  {
    *(a + i) = 90;
  }
}

void FOR_05(unsigned char *a)
{
  int i;
  for(i=0;i<64;i++)
  {
    *a = 90;
    a++;
  }
}

/* FOR_04関数, FOR_05関数共に、下記の方法で配列を関数へ渡す。 */
/* 一番最後の[]を削除すればOKである。 */
FOR_04(DUMMY_DAT[0]);
FOR_04(DUMMY_DAT[1]);
FOR_04(DUMMY_DAT[2]);
FOR_04(DUMMY_DAT[3]);
FOR_04(DUMMY_DAT[4]);
FOR_04(DUMMY_DAT[5]);
FOR_04(DUMMY_DAT[6]);
FOR_04(DUMMY_DAT[7]);


FOR_05(DUMMY_DAT[0]);
FOR_05(DUMMY_DAT[1]);
FOR_05(DUMMY_DAT[2]);
FOR_05(DUMMY_DAT[3]);
FOR_05(DUMMY_DAT[4]);
FOR_05(DUMMY_DAT[5]);
FOR_05(DUMMY_DAT[6]);
FOR_05(DUMMY_DAT[7]);


関数名 : TCNT μsecへ変換
FOR_04 : 1637 523[usec]
FOR_05 : 1192 381[usec]
  
 FOR_04に関しては、先程のFOR_03と大差ない。若干早くなっている程度である。しかし、同じような処理でもFOR_05の処理速度とは天と地の差。先に作ったFOR_01に近づくスピードである。もうちょっとで追いつきそうだ。

▼あの壁を越えろ

 処理を遅くしている原因が、変数iを使っていることだと予想。変数を全く使わない方法で同じ機能を持たせる事に成功した。その際、for文では無理なので、while文を使用した。処理が終わる方法は、現在のアドレスが、(初期のアドレス+64個目)のアドレスよりも少なかった場合、処理を続行ということになっている。
void WHILE_02(unsigned char *a)
{
  int i = 0;
  unsigned char *b;
  
  b = a + 64;
  while(a < b)
  {
    *a = 18;
    a++;
  }
}

/* WHILE_02関数は、下記の方法で配列を関数へ渡す。 */
WHILE_02(DUMMY_DAT[0]);
WHILE_02(DUMMY_DAT[1]);
WHILE_02(DUMMY_DAT[2]);
WHILE_02(DUMMY_DAT[3]);
WHILE_02(DUMMY_DAT[4]);
WHILE_02(DUMMY_DAT[5]);
WHILE_02(DUMMY_DAT[6]);
WHILE_02(DUMMY_DAT[7]);


関数名  : TCNT μsecへ変換
WHILE_02 : 974  311[usec]
  
 予想が的を付いていたのか、見事に箇条書きタイプを超えるスピードを引き出す事に成功した。
やったね!
 さすがに現状で512個ものデータを扱うことはないですが、EEPROMを扱う辺りで大量のデータを処理する必要が出てくると思うので、今回やって良かったかも。これなら、早いし、メモリ消費量も減ったので、モニターデバッガを使用してのRAM上での作業ができそうです。

[BACK] [TOP] [NEXT]

Copyright (C) 2005 U-hirohito All rights reserved.

SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送