2010年12月9日木曜日

5.1 つっつくと動く三輪車




車体をつっつくと動くしかけを作ることにした。車体は前回と同じ三輪車。
センサーは3軸の加速度センサーを使う。車体に直接取り付けようかと思ったが、目立ちやすいように棒を立ててその先にセンサーを取り付けた。
センサーの出力をオシロで見たところ、棒の先につけたので動きが大きくなっており、つっつくと出力が最大値・最小値になることが判明。突っついた方向に向かって動いていくことにし、X軸とY軸の出力の組み合わせで以下のように動きを決めた。
X軸 Y軸 動作
最小 -  前進
最小 最大 右前
最小 最小 左前
最大 -  後退
最大 最大 右後
最大 最小 左後
-  最大 右回転
-  最小 左回転

ソフトウエア
メインループで1ms毎にセンサーの値をAD変換してチェックする。4回連続してX・Yどちらかが最大値または最小値となったらつつかれたと判断し、モーターを1秒間駆動する。駆動中はセンサーはチェックしない。

つっつきの反応
前進・後退・右回転・左回転はうまく反応するが、右前・左前・右後・左後はたまにしか反応しない。X・Y両方が最大値・最小値という組み合わせが起きにくいということだが、調整するほどでもないのでこのままにしておく。

孫の反応
残念ながらあまり興味を持った様子はない。ちょっと突っついてはみたがそれよりもレゴテクニックのバイクやフォークリフトで遊んだり、ブロックで車を作ったりするほうが面白いようである。

2010年12月3日金曜日

5.0 リモコンで動く三輪車




三輪車が偽バイクと同じようにリモコンで動く仕組みを組み込んだ。
また、リモコンの操作イベントをタイムスタンプつきで記録し、それを再生することで記録時と同じ動きを再現できるようにした。
PICにはEEPROMがあるので、操作イベントを4セットEEPROMに記録しておき、それを呼びだして動作を再現する仕組みも組み込んだ。

イベントの時間管理
最初のイベント発生からの絶対時間で管理する。時間の精度は40msとした。時間管理のタイマーは8ビットなので、タイマーが255(約10秒)になったらタイマーオーバーフローを示すイベントを記録し、タイマーを0にリセットする。

記録データフォーマット
1つのイベントを2バイトで記録する。1バイト目は時間を示すタイマー値、2バイト目はコマンドコード。
タイマーオーバーフローのイベントは、0xff, 0xffとする。
イベントの終了を示すため、0xff, 0xfeを最後に記録しておく。

孫の反応
最初はテーブル歩きの車体で動かしてみたところ、あまり気に入らない様子であった。次回は超音波センサーを取り外して多少スッキリした車体にしてみたところ、リモコンを離さず動かして遊んでいた。車体の形で好き嫌いにかなり差があるらしい。

1.2 テーブル歩き修正版




久しぶりに最初に作った三輪車に戻ることにした。
テーブル歩きは角が丸いテーブルなら上手に歩けるが、角がシャープな四角いテーブルだと落ちてしまうことがあったので、まず四角いテーブルでも落ちないように制御を修正することにした。

バージョン2
テーブルの端に来た時、車体の向きがテーブルの端と直角になる方向に後退し、反対方向に回転するようにした。これでほとんど落ちることはなくなったがたまに落ちる。

バージョン3
テーブルの端に来た時、テーブルの端に対してできるだけ直角の角度で後退するよう、回転しながらの後退と前進を繰り返すようにした。落ちることはなくなったが、無駄な動きが多く同じところを行ったり来たりするので美しさは劣る。

孫の反応
動かして見せたところ、ちょっと見た後「もういい」と言って自分でスイッチを切って止めてしまった。どうもこのボディの動きは気にいらないらしい、、、。

2010年11月12日金曜日

4.0 キッチンタイマー




今回は実用品を作ることにした。
レゴの歯車で秒針を作り、1秒毎にモーターで動かす。分と秒の数字表示も欲しいので、7セグメントのLED表示器を載せた基板を新しく作成した。PICはこれまでと同じPIC18F2431。

秒針
モーターを1秒毎に回転させ、歯車で減速して秒針を1分間で1回転させる。
歯車の歯数は8、24、40のものがあったので、3段階で減速することにした。
それぞれの歯数は、
モーター軸:8
1軸目:24->8
2軸目:40->8
3軸目:40
とした。
3軸目が1秒間に40/60歯回転するとき、1軸目の24歯の歯車の動く歯数は、
40/60 * 40/8 * 24/8 = 10
24歯の歯車の動きをフォトインタラプタで測定し、1秒毎に10歯ずつ動かすようにする。

PIC基板
数字表示は3桁の7セグメントLEDを使うことにした。これに合わせて操作用のスイッチを3ヶ実装。音を出すため小型の圧電ブザーも取り付けた。
他はこれまでと同様に電源部、モーター駆動ICなどがある。

時間設定、動作
秒の設定は歯車を回転させて行う。分は一番左のスイッチを1回押すと1分増加する。
60分まで設定できる。表示は3桁なので、10分以内の場合は分1桁と秒2桁を表示し、10分以上の場合は分2桁と秒1桁(10秒の位)を表示する。
一番右のスイッチを押すと動作開始。1秒毎に秒針が動き「ピッピッ」と音が鳴る。カウントが終了すると「ピピピッ、ピピピッ」と音が鳴る、まん中のスイッチを押すと音が止まる。

ソフトウエア
時間管理はTimer0の割り込み(1ms毎)で行う。
フォトインタラプタの測定はメインループで入力をチェックし、入力が1から0に変化したら1カウントする。回転方向はわからないので、歯車を左右どちらに回転させても同じようにカウントする。
歯車の駆動はモーターの駆動をオンにし、フォトインタラプタが8カウントしたら駆動をオフする、モーターは惰性で少し動くのでこれでほぼ10歯ずつ動く。
1秒経過したら、フォトインタラプタのカウント数を-10し、モーターを駆動する。

実用的な使い方
実用上は秒針の動きは必要ない。PIC基板だけでタイマーとして使うのが一番実用的である。分単位の設定で実用上は問題ないが、まん中のリセットスイッチを押したまま左のスイッチを押すと10秒ずつ時間が増える仕組みもいれてある。

2010年10月29日金曜日

3.1 声で動かす偽バイク




DVDのリモコンで偽バイクを動かすようにしたが、孫はそれほど感激した様子ではなかったので別の仕掛けを考えることにした。「孫とおじいちゃんの言うことだけきく偽バイク」、というアイデアを思いつきこれに挑戦することにした。
音声認識をやることになるが、PICではRAMも少ないし信号処理をやるのは難しいため、信号処理はWindowsPCで行い、PCのCOMポートに接続した赤外線リモコンで偽バイクを動かすことにした。
今回は、PC用の赤外線リモコン作成と、音声認識を行うPCのアプリの2つを作成することになった。

3.1.1 PC用赤外線リモコン

使用しているPCはノートブックでシリアルポートはついていない。USBをシリアルに変換するものを探してみたところ、マルツのWebでUSBをTTLレベルのシリアルに変換するボードを発見した。24ピンのICのサイズになっており使いやすそうなのでこれを調達。
リモコンにもレゴとPICを使わないといけないので、シリアル信号を赤外線リモコンのデータに変換するためにPICを使うことにした。最初の散歩のお供で使った8ピンのPIC12F683を選択。

ハードウエア製作
USBをシリアルに変換するボードにピンを取り付け、PICを載せた基板に24ピンのICソケットを取り付け実装した。PIC周りの回路は、赤外線LEDと動作表示用のLEDがつくだけのシンプルなもの。電源はシリアル変換基板からもらう。
PICの基板の下にレゴのブロックをネジ止めし、レゴの車輪を飾りに取り付けた。

ソフトウエア製作
PIC12F683のソフトはアセンブラで作成した。
PCからのコマンドは'f'が前進、'b'が後退、's'が停止、の3つだけとする。

・シリアルデータ受信
PIC12F683にはUARTはないので、ソフトで信号を受信する。メインループで入力信号を監視し、スタートビットを受け取ったら受信を開始する。
調歩同期式なので、本来は入力信号の変化毎に同期をとるべきだが、実際には最初だけ同期をかけ、後は8ビット分のデータを読むまで続ける、というのが一番確実に動作することが判明した。
データ読み込みはTimer0の割り込みで処理する。スタートビット受信後1.5ビット分の時間でTimer0の割り込みをかけ、最初のビットの入力を読み、その後は1ビット分の時間でTimer0の割り込みをかけて続きの入力を読む。8ビット分のデータを受信し、入力がアイドル状態になったら受信完了として、受け取ったデータを処理する。

・リモコン用データ作成・送信
リモコン用の赤外線LEDの点灯はデューティー30%程度のPWMで行うのが普通なので、PICのPWMを使って点灯することにした。シリアル送信の時間管理はTimer1で行う。
データは前回使用したパナソニックのリモコンと同じフォーマットとする。
リーダー部送信後、データを送信し、最後にトレイラー部を送信する。

3.1.2 音声認識アプリ

開発環境
Windows上のソフト開発環境として最も一般的なVisualStudioを見てみたが、10万円以上することが判明。VisualC++だけでも2万円程度ということで困ってしまったが、VisualC++ Express Editionというものなら無料で入手できることを発見。ためらわずにこれに決めた。インストールして試してみたところ、GUIを作るリソースエディターがついていないことが判明。まあ、無料なのでしかたないし、今回のソフトはGUIなしでもできるので、コンソールアプリケーションとして作成することにした。

認識エンジン
ネットを見たところ、Windows環境ではマイクロソフトが提供する音声認識エンジンが使える、ということであったが、今回は「前」「後ろ」「止まれ」の3つの単語だけを認識できればよいし、自分で作るところに意義があると決め、認識エンジンも自作することにした。
分析手法としてFFTは必須と思われるので、まずFFTのソースをネットから調達。

認識手法
まず、「前」「後ろ」「止まれ」の特徴を探してどの単語が特定し、次に基準の倍音構成と比較して話者を特定する、という作戦でトライしてみた。作者の声で3つの単語を認識できるところまでできたので、孫のリー君の声を録音してリー君の声でも認識できるか試してみたところ、声の特性が全く違いうまく認識できないことが発覚。
ゼロからやり直しで、「前」の「ま」の部分、「後ろ」の「う」の部分、「止まれ」の「と」の部分をFFTしたサンプルを用意し、これと入力信号を比較する方法をトライしてみた。サンプルと入力の特定の周波数ごとのデータの差の2乗の和を計算し、これが一定値以下なら単語認識とする。これで3つの単語を認識できるようになった。
単語ごとに1ヶから4ヶのサンプルを用意し、サンプルの数で認識率が変化するか調査してみたが、作者の声だとあまり差がなかったのでサンプルは単語毎に1つとした。これで作者の声で90%以上の認識率が得られた。
リー君の声でサンプルデータを用意して実験してみたが、リー君は叫んだりマイクにかみつきそうになったりしてしゃべったりするので認識率はかなり低い。サンプルも1つではなくて複数用意することにして、サンプルの録音ももっと時間をかけてやり直す必要がある。
また、他の人の声ではほとんど認識できず、当初の目標は達成できた。

アプリの構成
・音声取り込み
PCに接続したマイクから音声を取り込む。アプリ立ち上げ時にAudio Input Deviceをオープンし、取り込みを開始する。入力用のバッファはダブルバッファにしてある。音声の振幅が一定値を超えたら、そこからバッファ1つ分のデータを認識エンジンに渡す。

・認識エンジン
◇入力信号ノーマライズ
入力信号の最大値を検索し、最大値が16ビットの最大値になるようノーマライズ。
◇FFT、サンプルとの差分計算
入力を64サンプル間隔で15回までFFTを行う、FFTのポイント数は1024でハニング窓をかける。その結果とサンプルの比較を行い、サンプル毎に差の最小値を記録しておく。
◇単語特定
差分の最小値を検索し、そのサンプルを認識対象の単語とする。差の値が一定値以下なら認識成功、そうでなければ認識失敗とする。

・コマンド送信
認識成功と判断したら、COMポートから'f', 'b', 's'を送信する。

認識のできばえ
作者の声では9割以上の確率で認識が成功する。リー君はたまに認識が成功する程度。他の人ではほとんど認識失敗となる。

孫のリー君の反応
たまに認識が成功してバイクが動くので、面白がって大声で叫びながら遊んでいる。




2010年7月19日月曜日

3.0 偽バイク







バイクをつくろうと思いネットでレゴテクニックのバイク(Lego Technic 8291)を購入してあったし、逆立ち2輪車が行き詰ったので、気分転換にバイクを作ることにした。まず説明書通りにダートバイクとチョッパーを作ってみたが、チェーンもついていたりしてけっこう気分が出ているし、手で動かすとエンジンのピストンが動く、など面白い。孫はダートバイクのほうが気に入ったようで、動かしてみたりして遊んでいた。
バイクを立たせることができるかに挑戦する。車輪をモーターで動かし、ハンドルもモーターで動くように車体を作った。ハンドルを切るとボディの重心が左右に移動するので、これでバランスが取れないか試してみる。センサーは逆立ちと同じ超音波を使用。ハンドルを切ると重心が移動するように前輪を作ってみたが、ハンドルを切るとボディが左右に傾くことが発覚、しかも普通に作ると重心の移動と傾きが逆向きになる。重心の移動と傾きが同じ方向になるように前輪を調整してみたが、バイクらしくない形になってしまう。
しかたなく、ハンドルを固定して錘を左右に動かしてバランスをとってみようとした。メカをシンプルにするため、錘を歯車に取り付けて円運動で錘を動かしたところ、錘が左右だけでなく上下に動くので錘の動きがスムーズでなくうまくいかない。
こちらも行き詰ってしまったが、せっかくバイクのボディを作ったので、これを走らせることにした。倒れないように補助輪をつけたので偽バイクとなってしまったが、、、。
コントロールはパナソニックの古いDVDレコーダのリモコンを使うことにした。ネットでリモコンのデータフォーマットを探してみたところすぐに見つかった。次にリモコンの信号を受信する受光素子を探してみたところ、ロームの製品で受光素子とアンプなどが一体になっており、38KHzのキャリアも取り除いてくれてデータがシリアルで出力されるものがあるのを発見。マルツで販売していることもわかり、すぐに調達してきた。
受光素子をボディに取り付ける基板を作成し、ソフトの開発にかかる。今回はやればできることが分かっているので安心して進められた。

ソフトウエア:
メインループでリモコンの信号をチェックし、入力が変化したら処理を行う。リーダー部検出、データ検出、エンドマーク検出を行い、エンドマークが検出されたらデータのコードにしたがって処理を行う。

コントロール:
上下のカーソルキーで前進・後退、決定ボタンで停止、再生ボタンでスピードアップ、停止ボタンでスピードダウンを行う。
左右のカーソルキーでハンドルを左右に動かす。モーターが回り続けないよう、約100msでモーターを停止させる。

孫の反応:
バイクを置いてあるのを見つけると、「バイクやろう」と言ってリモコンを持って動かしている。あまり感動している様子は見えないので、他のしかけも考える必要がありそう。

2010年7月16日金曜日

2.0 逆立ち2輪車




次はやはりスリルがあるものに挑戦したいと思い、2輪車を立たせることにした。ネットを見たところ、新しいレゴのマインドストームでは倒立2輪車が走っておりレースもやっているらしいし、他にも倒立2輪車のキットがあり、スムーズに立ち上がったり歩いたりしていることがわかった。車体をモデル化し、運動方程式を解いて制御しているらしいが、当方はそのような難しいことは苦手なので、いきあたりばったりの制御で立たせることができるかに挑戦することにした。

ボディ:
車輪を2つ平行に配置し、それぞれをモーターで駆動する。モーターの上に枠を作り、そこにPICの基板と電池の基板を取り付けた。枠はピンでつなぐようになっており多少ガタがあるので、補強用のブロックを追加してある。

ハードウエア:
散歩のお供で作成したものをそのまま使用する。超音波の送信機を接続していた端子をセンサーの入力に使うことにした。

センサー:
ボディの回転を検出して制御するよう、ジャイロの角速度センサーを調達し実験してみた。ボディの傾きを知るために角速度を積分してみたが、データの扱いがうまくないためかすぐに発散してしまい使い物にならない。次は加速度センサで実験してみた。ボディの重心付近に加速度センサを90度の角度差で2つ取り付け、ボディの傾きを検出して制御しようとしてみたが、これもうまくいかない。
ボディの動きがギクシャクしているせいなのか、データの扱いがうまくないのか、制御のやりかたがうまくないのかわからないが、いきあたありばったりではうまくいかないかとあきらめようとしたが、散歩のお供で使った超音波が使えるのではないかと思いつき、さっそく実験してみた。
ボディの前後にそれぞれ超音波の送信機と受信機を取り付け、床からの反射音で距離を測定し、ボディの傾きを検出して逆方向に車輪を動かすようにした。センサーをチェックするタイミングやモーターを駆動する強さを調整し、なんとか立たせることに成功した。
ボディがどんな動きをしていてもボディの傾きを直接検出できるので、いいかげんな制御でもなんとか立つことができると思われる。

ソフトウエア:
前と後ろの床からの距離の測定、モーター駆動、が主な処理。
距離測定の間隔はボリュームで設定する、10ms程度に設定してある。距離測定のため、前と後ろ同時に40KHzの超音波を3サイクル送信する。タイマーをスタートし、前と後ろの受信信号でそれぞれ割り込みをかけ、それぞれの割り込みでタイマーの値を記録しておく。両方とも割り込みが完了したら記録したタイマーの値を比べると、小さいほうに傾いていることがわかる。タイマーの値の差をもとにモーター駆動のPWMのデューティーを決める。
傾いた方向と逆に動くよう、モーターを駆動する。左右のモーターは同じ条件で駆動している。

課題:
いいかげんな制御なので、立つのがやっとという状況である。ちょっとつつくと倒れるし、歩かせようとしてみてもすぐに倒れてしまう。
また、床からの距離でボディの傾きを検出しているため、床が平らでないと立てないし、カーペットだと超音波が反射せず立てない、などの難点もある。
少し勉強して改善できるか再挑戦してみる予定。

孫の反応:
動かそうとしてみたところ、なにやら気もち悪そうな顔つきだったので、「これは走らないから大丈夫だよ」と言って動かしたところ、「あっ立った立った」「すごいねえ」と喜んでくれた。良かった良かった。

2010年7月15日木曜日

1.1 テーブル歩き

散歩のお供で作ったボディで何か他のことができないか考えてみた。部屋の中を勝手に動き回って障害物に近付いたら避けてぶつからずに歩く、というのも考えたが、これでは平凡でつまらないので、もうひとひねりしてテーブルの上を勝手に歩き回り、端っこにきたら後ろに下がり落そうで落ちない、というのを作ることにした。
センサーは同じ超音波を使用する。散歩のお供では前の車からの超音波を受信するため受信用のセンサーは前方を向けていたが、今回は床(テーブル)との距離を測定するため、センサーの取り付け部を回転させてセンサーが下を向くようにする。前輪の前方・外側のテーブルの距離を測定できるよう、送信機・受信機のセットを左右に配置し、位置も前輪の前方・外側になるよう調整した。

ソフトウエア:
散歩のお供のソフトを修正。動く方向の決定、テーブルとの距離の測定、車輪の駆動、が主な処理。
動く方向は前進のみとし、直進・右・左を一定間隔(約1秒)毎に乱数で決定する。テーブルとの距離の測定は、右・左それぞれ超音波送信の一定時間後に反射音の入力をチェックし、入力がONならテーブル上、入力がOFFならテーブルからはずれた、と判断する。
左右ともテーブル上にある場合は乱数による方向にしたがって車輪を駆動し、左右いずれかがテーブルから外れた場合は約1秒間後退し、その後外れた方向と反対側に動くようにする。

これでなんとか落ちずに歩き回るようになったが、テスト中に油断していたら落ちてしまいボディがバラバラになってしまったこともあり、とてもスリルがあって面白かった。
丸いテーブルならほとんど落ちることなく歩き回るようになったが、四角くて角のあるテーブルだと角の部分に向かっていくと逃げ場を失って落ちることがある。

1.0 散歩のお供







何を作るかあれこれ考えたが、孫の後をついてくる車に決定。センサーはラジコンの無線も検討したが方向の検出が面倒そうなので、超音波を使うことにした。
孫が小さい車を引っ張って歩くとその後をもう1台の車がついてくる、という構成にした。
小さい車は定期的に超音波を送信し、後ろの車がそれを左右2つのセンサーで受信して左右の時間差で方向を検出する。また、後ろの車も超音波を送信し、前の車からの反射音が戻ってくるまでの時間で車の間の距離を測定する。距離がある程度(30cmくらい)に近付くとそこで止まるようにした。

ボディ:
送信側(小さい車)は受信側(後ろの車)からの超音波を反射しやすいように後面と側面後部を平らな面にし、小さい車輪をつけてひもで引っ張るようにした。
受信側は前輪2輪を別々にモーターで駆動する。後輪は曲がりやすくするために1輪とした。後輪が左右に曲がり、車輪がスムーズに回転し、しっかりボディに固定できる形を作るのに結構苦労した。

ハードウエア:
送信側は8ピンのPIC12F683を使用。単4電池2本から5Vに昇圧する電源とPICの他は超音波の送信機をドライブする部分にコンデンサが1つつくだけのシンプルな構成。
受信側は28ピンのPIC18F2431を使用。電源部、PIC、超音波センサー用のアンプ2チャンネル、モーター駆動用のIC(TA7291P)2つ、状態表示用のLED、設定用のボリュームとスイッチ等がある。
電源はPIC用は単4電池2つから5Vに昇圧、モーター用には別の基板に単3電池を4本用意し、ケーブルで接続する。

ソフトウエア:
送信側はPICの理解も兼ねアセンブラで作成した。超音波の発生はソフトのループで行う。
200ms毎に40KHzの超音波を50サイクル発生する。
受信側はCで作成。送信側からの超音波の受信と方向検出、超音波発生と反射音の受信による距離測定、モーター駆動、が主な処理。
方向測定は2つの超音波入力で割り込みをかけ、最初の割り込み時に右だけONなら右、左だけONなら左、両方ONなら中央と判断する、角度は気にしない。また、200ms以上受信信号が来ない場合は方向未定とする。
距離測定用の超音波発生は送信側と同じようにソフトで40KHzの超音波を10サイクル発生する。一定時間(約1ms)後に超音波入力をチェックし、左右どちらかがONなら距離近接と判断する。このアプリケーションでは左右同時測定で問題ないが、次のアプリケーションで左右別々に距離の測定を行う必要が生じたので、このアプリケーションでもまず右の距離を測定し、次に左の距離を測定している。
モーター駆動は、方向不明または距離近接なら停止、方向右なら左だけ駆動、方向左なら右だけ駆動、方向中央なら左右を駆動とする。
動作時に壁などに近付いて止まってしまうことがあり、ここからの救出のため距離近接時に送信側の方向が変化したら少し後ろに下がるようにした。壁で止まってしまったら壁と受信側の車の間に送信側の車を通すと、受信側がいったん後退しその後また送信側を追いかけてくる。

孫の反応:
クネクネ動くのが気持ち悪いのか、追いかけてくるのが怖いのか、「いやだいやだ」「やめてやめて」と言って逃げてしまった、、。嫌われてしまったがめげずに製作をつづけることにする。

開発環境



PICの開発環境はPICkit3をマルツパーツ館で購入。PIC18F4520のデモボードとサンプルプロジェクトが付属しているので、これでPICの勉強をした。
ソフトはMicrochipが提供しているMPLAB IDEを使用。アセンブラ・CコンパイラもMicrochipのものを使用している。コンパイラは試用期間が過ぎオプティマイズが利かなくなっているが構わず使用中。
ハードウエアのデバッグ用にUSBでPCに接続するオシロスコープをネットで調達。2チャンネルでそこそこの帯域があり値段が一番安いHantek DSO-2090 USBを購入。問題なく動作している。