TOP > 製作日記 > 2月

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

02月07日 月曜日  タイトル: モーションエディタ  [進まん!(いつも同じじゃん)]

▼Visual Basic 6.0

 ゼミにて、たしなむ程度にVBを扱えるようになったので、モーションエディタをVBで作ってみる事にした。その際、RCB1を参考に作っているが、既に似て非なるものとなりつつある。(^-^;
 とりあえず、このモーションエディタの役目は、今までマイコンにガリガリ書いていたエディタを独立させることにある。機能も大切だが、そんなに時間をかけていられる場合でもないので、似たような機能を移植して、多少使いやすくしようと考えている。
 何にせよ、ハイパーターミナルでは1行しか(プログラムの仕様上)表示できない。その「1行をいかにして表示するか?」に今まで時間を割かれていたようなものなので、今回やってみようと思い立った訳である。

▼バイナリ通信失敗

 バイナリを送ったり、受信するのにChr関数を使ったが、129や250と言った値を送るとマイコン側からは0を返すし、ChrB関数を使うと何も帰ってこなかったりする。PCの受信側は、受信した値を数値で表すAsc関数や、16進数で表すHex関数を使っている。
 このまま時間を食っていても仕方が無いので、現状ではこれ以上無理と判断し、16進数を一桁ずつ文字として送るようにした。考えてみれば、今までバイナリの通信など行っていなかったので、できないのは当然かもしれない。X-MODEMを行うプログラムを作った時も、バイナリではなく3桁の数字を送っていたのだから。

02月09日 水曜日  タイトル: バイナリ再び  [戦いには負けたが、勝負には勝った!(何・・・)]

▼いしかわさんの書き込みから

 先日、「バイナリなんて、無理だ〜!できるかこんなもん!」っと、さじを投げてしまった訳ですが、いしかわさん(*1)から書き込みがあった「StrConv関数(*2)」が何なのか分からなかったので、HELPとネット探索。すると、VisualBasic初心者掲示板というのを発見。
 ここで、バイナリの送信方法とかを調べた結果、Byte定義した配列に数値を入れていき、送信するだけでよい事が分かる。具体的には以下のような方法である。

Public Sub test()
  Dim A(0) As Byte, i As Integer
  
  For i = 0 To 255
    A(0) = i
    Form1.MSComm1.Output = A
    Call wait(100)
  Next i
End Sub

Public Sub wait(n)
  Sleep n
  DoEvents
End Sub
  
 「なんだ・・・簡単じゃないか。」っと上記のプログラムを実行するとi=128にて、無限ループに入ったのか分からないがフリーズし、強制終了。「なんじゃこりゃー!?」っと誰もが思ったに違いない。(いや、あんただけだから(-_- ))

*1 知らぬ人はいないだろう。WEBページ、思い立ったが吉日を運営しているのが、いしかわさん。愛機えんぱくの状況が気になる。(^-^;
*2 大文字を小文字にしたり、UnicodeをAsciiに変換したりする関数。StrConv(対象の値とか, 引数)という使い方をする。ちなみに、UnicodeをAsciiに変換したいのならば、引数の部分に128という値を代入するか、vbFromUnicodeという定数を代入すればよい。他の引数については、HELPで確認しよう。

▼戦いの果てに

 先程の掲示板でさらに調べていくと、ある設定を忘れていたことに気づく。それは、MSComm1.InputModeの設定である。これをバイナリモードにしていなかったので、ダメだったらしい。つまりは・・・。
Private Sub Form_Load()
  With MSComm1             'With(*3)
    .PortOpen = True
    .Settings = "38400,n,8,1"
    .InputLen = 0
    .RThreshold = 1
    .SThreshold = 1
    .InputMode = comInputModeBinary    '←ココが抜けていた
  End With
End Sub
  
と設定しなければならなかったのだ。この設定をやらないと、初期値が0(comInputModeText)になっているので、テキストデータしか送れないのだ。まぁ、タネが分かればこんなもんですな。
 そんな訳で、問題なくバイナリによる通信が可能になった。いやぁ・・・楽で良いですな。余計な処理書かなくて良いし。(-_- )フッフッフ

*3 「With 省略したい名前」とすることで、End Withまでの名前などを省略できる。これを使うと書くのも楽だし、読み返すときも楽になる。(っと自分は思う。)

▼最終的に

 いろいろとやった結果、以下のような感じで落ち着いた。
'標準モジュールにて宣言
Public DTX(16) As Byte

'これは好きなフォームなどにて
Private Sub Port_Output()
    Dim i As Integer
    
    DTX(0) = &H55
    DTX(1) = &H1
    For i = 0 To 3
        DTX(i + 2) = PORT_N(i)
    Next i
    Call Check_Sum(6)
    Call D_TX2(7)
    Call wait(2)
End Sub

'以下は標準モジュールにて
Public Sub Check_Sum(n)
    Dim D_CS As Integer
    
    D_CS = 0
    For i = 0 To n - 1
        D_CS = DTX(n) + DTX(i)
        If D_CS > 255 Then D_CS = D_CS - 256
    Next i
    DTX(n) = D_CS
    
End Sub

Public Sub D_TX2(n)
    Dim A() As Byte, i As Integer
    ReDim A(n - 1)
    
    For i = 0 To n - 1
        A(i) = DTX(i)
    Next i
    
    Form1.MSComm1.Output = A
End Sub
  
 最後の「Form1.MSComm1.Output = A」は、このように書くとA(0)〜A(n-1)までの配列を連続して送れるようになる。しかし、普通にこれをやると、前回よりも少ないデータを送ろうとすると、過去のデータが残っているのでそれすらも送ってしまう。
 そのため配列を再定義して代入し、それらを送信することにしている。自分自身もあんまり良く分かってないので、この辺の解説はこの辺で・・・(^-^;
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上での作業ができそうです。
02月25日 金曜日  タイトル: 無線コントロールユニットで悪戦苦闘  [やっと受信機が・・・]

▼配線まだなのに・・・

 配線完了率65%というところで、無線機のマイコンへの接続を試み早3日。かなりの時間を消費して通信が可能になりました。使う予定の無線機は近藤科学製です。これの通信に関わって、色々と経験の足りなさを痛感致しました。成功した瞬間ホッとした訳ですが、現実逃避のごとく受信機とマイコンの接続に関する記事を書き上げてしまった。所要時間5時間。(げっ)
 詳しくは、こちらの方でご覧ください。 ⇒見に行く  とりあえず良い息抜きになったので、また配線を再開しなければ。相変わらず悩ませます・・・どのように配線するのか。今日中には配線を終えて、火を入れたいところ。果たして、予定通り行くのだろうかっ!?

▼エントリー番号

 塗装後の配線が結局間に合わなかったので、上半身は仮組み状態で撮影し23時59分(自分のPC時刻)に提出。もちっと早くするつもりが、画像を縮めたり、回転させるのに時間がかかってしまった。ROBO-ONE委員会の皆様、ご迷惑をおかけ致します。
 で、エントリー番号は159番でした。今回は、多いですね〜。お近くの方、よろしくお願いします。って、後輩のチームが近場だ。がんばれ〜。

[BACK] [TOP] [NEXT]

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

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