電子工作シリーズ。MSP430 マイコンで赤外線コントロール Q-STEER を動かす実験。先日思いついたネタだ。「Q-STEER赤外線信号解析[STEAR home page]」の情報を元に赤外線 LED を点滅させるのだが、この仕様の微妙に間違えて解釈していたために少し手間取ってしまった。同サイト内にある PIECE 用赤外線リモコンソフト「Multiform Remcon Ver1.10」のコードを元に仕様を解析し、修正することで Q-STEER を動かすことができた。
「Q-STEER 赤外線信号解析」の説明から、キャリア周波数38KHz、0.425msを on/off の時間隔単位として on-off でビット0を、on-onでビット1を表現すると解釈したのだが、PIECEソフトのコードによるとビット1はon-on-offとなるようだ。またon-on-on-onのヘッダの後にもoffが入る。自前で信号の解析をすれば良いのだろうが、そこは「適当も甚だしい電子工作研究所」と言うことでひとつよろしく。赤外線LEDは不要のリモコンを分解して取り出したもの。赤外線は肉眼では見えないからオシロスコープでモニタ。デジカメのモニタを通すと確認できたりもする。
プログラムはTimerA3により38KHzのキャリア周波数でLED点燈をおこない、0.425ms毎のWDT割込みでコマンドに応じて信号のオンオフをする。とりあえず最小限の動作確認ができただけで、スイッチなどによるコマンドインターフェース等はまだ無い。続く、かも。
[2007.03.18]
サンプルプログラム。このままだとひたすら前進のみ。動作を変更する場合は next_cmd に設定する。UI は適当によろしく。赤外線LEDはP1.2に付けたが、これは学習用マザーボードに実装されているLED(緑1)との差し替え。電流制限抵抗も適当に付けておく。
実際の Q-STEER リモコンではコマンドボタンを離した時に停止コマンドが出されるそうだ。このプログラムでは WDT 割込みでコマンド処理をおこなっているが、メインルーチンあるいは別の割込み処理でコマンドを送るときには cmd == next_cmd を待って next_cmd に次のコマンドを設定すること。//****************************************************************************** // MSP430-CQ // P1.2 に赤外線LED をつないで Q-STEER を動かすサンプル // 2007.03 masato@bird.email.ne.jp //****************************************************************************** #include "msp430x42x0.h" // QSCMD: Q-STEER の信号パターンを bit で表現する typedef struct _QSCMD { unsigned int cmd; // MSB から 1/0 パターンを埋める unsigned int len; // 有効ビット数 } QSCMD; const QSCMD cmds[] = { { 0x0000, 0 }, // dummy // ヘッダとバンド指定 { 0xf500, 9 }, // Header - Band A { 0xf580, 10 }, // Header - Band B { 0xf680, 10 }, // Header - Band C { 0xf6c0, 11 }, // Header - Band D // 操作コマンド { 0xaa00, 8 }, // 0000 reserved { 0xab00, 9 }, // 0001 forward { 0xad00, 9 }, // 0010 backward { 0xad80, 10 }, // 0011 left { 0xb500, 9 }, // 0100 right { 0xb580, 10 }, // 0101 dash forward { 0xb680, 10 }, // 0110 forward / left { 0xb6c0, 11 }, // 0111 forward / right { 0xd500, 9 }, // 1000 dash / left { 0xd580, 10 }, // 1001 dash / right { 0xd680, 10 }, // 1010 back / left { 0xd6c0, 11 }, // 1011 back / right { 0xda80, 10 }, // 1100 dash back { 0xdac0, 11 }, // 1101 dash back / left { 0xdb60, 12 }, // 1111 stop }; enum Command { CMD_NONE = 0, CMD_HDA, CMD_HDB, CMD_HDC,CMD_HDD, // ヘッダとバンド指定 CMD_RSV, CMD_FW, CMD_BK, CMD_LT, // コマンド CMD_RT, CMD_FF, CMD_FL, CMD_FR, CMD_FFL, CMD_FFR, CMD_BL, CMD_BR, CMD_FB, CMD_FBL, CMD_FBR,CMT_STP }; #define BITON(X) ((X) & 0x8000) // bit on / off 判定 #define LEDON P1DIR |= 0x04 // LED on #define LEDOFF P1DIR &= ~0x04 // LED off unsigned int tick = 0; // 0.425ms 単位ステップカウント unsigned int tick2 = 0; // 127ms 単位ステップカウント(テスト用) enum Command band = CMD_HDA; // バンド指定 enum Command cmd = CMD_FW; // コマンド enum Command next_cmd = CMD_BK; // 次コマンド int gap = 19; // 信号セット間隔 Band-A:19 tick, B:47, C:75, D:104 // void main(void) { /* WDT により 0.425ms 毎に LED の on/off 制御をする。*/ SCFQCTL = 38 - 1; // 38 * ACLK = 1.246MHz - 38KHz キャリアと 0.425ms 割込周期を作りやすそうに WDTCTL = WDT_MDLY_0_5; // 0.5ms@1MHz → 0.421ms@1.246MHz 細かいずれには目をつむる。 // P1.2 に赤外線 LED をつなぐよ P1DIR |= 0x04; // P1.2 as output P1SEL |= 0x04; // P1.2 as TA1 output /* Timer_A3 を用いてキャリア周波数(38KHz)で赤外線 LED を点燈 */ CCTL1 = OUTMOD_7; // Reset on EQU2(TAR = CCR2), Set on EQU0(TAR = CCR0) CCR1 = 16; // on time CCR0 = 33; // interval time : 38KHz TACTL = TASSEL_2 + MC_1; // source:SMCLK, up to CCR0 IE1 |= WDTIE; // WDT 割込み許可 _BIS_SR(LPM0_bits + GIE); // LPM0 } #pragma vector=WDT_VECTOR __interrupt void WDT(void) { const QSCMD *hp = &(cmds[band]); const QSCMD *cp = &(cmds[cmd]); int t; if (cmd == CMD_NONE) return; // no-op if (tick < hp->len) { // Header - Band if (BITON(hp->cmd << tick)) LEDON; else LEDOFF; } else if (tick < hp->len + cp->len) { // Command t = tick - hp->len; if (BITON(cp->cmd << t)) LEDON; else LEDOFF; } else if (tick < hp->len + cp->len + gap) { // Gap LEDOFF; } else if (tick < hp->len * 2 + cp->len + gap) { // Header - Band (2) t = tick - (hp->len + cp->len + gap); if (BITON(hp->cmd << t)) LEDON; else LEDOFF; } else if (tick < hp->len * 2 + cp->len + gap) { // Command (2) t = tick - (hp->len * 2 + cp->len + gap); if (BITON(cp->cmd << t)) LEDON; else LEDOFF; } else { LEDOFF; // nop } tick++; if (tick > 300) { // 127ms 周期で連続させる。 tick = 0; tick2++; #if TEST // テスト用に 1.27s 周期で前進(CMD_FW)と前進+左(CMD_FL)を切り替え t = tick2 / 10; next_cmd = (t % 2)? CMD_FL: CMD_FW;; #endif if (next_cmd != cmd) cmd = next_cmd; } } /* EOF */
信号の on/off 制御をもっと汎用的にして UI を工夫することで他の赤外線リモコンにも使える、かも知れない。なお、デジQは信号の仕様が異なり、このプログラムでは動かない。
[2007.04.01]
制御プログラムについては hamayan さんのページの方法がスマートなので参照されたし。これは以前のオルゴールも同様だが、割込みルーチン内ではなるべく処理量を減らすようにしたほうが全体として処理に余裕ができる。PC などの GUI プログラムと同じような考えではよろしくない場合も多いのだ。
うほ!面白そうな事を始めていますね。
私も随分前におもちゃ屋の処分セールで似たようなラジコンカーを購入したので、いつかコードを解析してマイコンで操作してみようと思って、しかし放置していたら、動かなくなっていましたOTL。ちなみに私の車はインプレッサWRC仕様です(*´ー`) 。
しょうがない、アマゾンでQ-STEER買おうかな。
デジカメで赤外線が見れるのは本当ですね。
勿論コードまでは判りませんが、出ているのは判る。
ワタシのは無印ランエボでございます。
それはともかく、こうしたものにはやはり解析ツールが無いことには辛いですね。当初、まるっきり Q-STEER が反応しなくて悩みました。
ストレージ無しの中古オシロでは、なんか似たようなパターンが出ているな、くらいしか判りません。
とりあえずUI無しのいい加減なソースも公開しました。
Posted by: masato%管理人 at 03/18, 2007 05:13 PMおそらく携帯電話等からは投稿できません。日本語文字列を含まないコメントやトラックバック、および当サイトへの言及を含まないトラックバックは御遠慮いただいております。また、90日以上経過した記事へのコメントはできません。