2011年3月2日水曜日

IR受信のプログラムを整理


サンプルプログラムを整理した。

display_xxxx() という下請け関数が3つあるが、処理の本質には関係ないので、
基本的には、byteの配列でバッファをつくって、receive()を呼ぶ。

receive() は 受信ステータスが立つのを待って ir_rx.getData()で
データを取り出す。

LCD には 上段にフォーマットとステータス。
下段に 受信データが表示される。

リモコンのボタンをいろいろ押すと、受信データが変わるので、
この値を比較して、対応する処理を呼び出すようにすると、
リモコンでコントロール出来る車ができたりする。

ややこしくなるので、このプログラムでは対応処理を呼び出す部分を書いていないが、
ボタンとコードの対応を調べるために、とっておくと良い。


#include

#include "ReceiverIR.h"
#include "TextLCD.h"


ReceiverIR ir_rx(p10); //GEMMY IR RECEIVER

TextLCD lcd(p11, p12, p27, p28, p29, p30); // rs, e, d4-d7


/**
* Receive.
*
* @param format Pointer to a format.
* @param buf Pointer to a buffer.
* @param bufsiz Size of the buffer.
*
* @return Bit length of the received data.
*/
int receive(RemoteIR::Format *format, uint8_t *buf, int bufsiz, int timeout = 100) {
int cnt = 0;
while (ir_rx.getState() != ReceiverIR::Received) {
cnt++;
if (timeout < cnt) {
return -1;
}
}
return ir_rx.getData(format, buf, bufsiz * 8);
}

/**
* Display a current status.
*/
void display_status(char *status, int bitlength) {
lcd.locate(8, 0);
lcd.printf("%-5.5s:%02d", status, bitlength);
}

/**
* Display a format of a data.
*/
void display_format(RemoteIR::Format format) {
lcd.locate(0, 0);
switch (format) {
case RemoteIR::UNKNOWN:
lcd.printf("????????");
break;
case RemoteIR::NEC:
lcd.printf("NEC ");
break;
case RemoteIR::NEC_REPEAT:
lcd.printf("NEC (R)");
break;
case RemoteIR::AEHA:
lcd.printf("AEHA ");
break;
case RemoteIR::AEHA_REPEAT:
lcd.printf("AEHA (R)");
break;
case RemoteIR::SONY:
lcd.printf("SONY ");
break;
}
}

int bit2CharLen(int bitlen) {
return bitlen / 8 + (((bitlen % 8) != 0) ? 1 : 0);
}


/**
* Display a data.
*
* @param buf Pointer to a buffer.
* @param bitlength Bit length of a data.
*/
void display_data(uint8_t *buf, int bitlength) {
lcd.locate(0, 1);

const int n = bit2CharLen(bitlength);

for (int i = 0; i < n; i++) {
lcd.printf("%02X", buf[i]);
}
for (int i = 0; i < 8 - n; i++) {
lcd.printf("--");
}
}



//void getStr(uint8_t *buf, int bitlength)


/**
* Entry point.
*/
int main(void) {


lcd.cls();
lcd.printf("IR RECEIVE TEST.");

/*
* Execute.
*/
while (1) {
uint8_t buf1[32];
memset(buf1, 0x00, sizeof(buf1));

RemoteIR::Format format;

int bitlen = receive(&format, buf1, sizeof(buf1));

if (bitlen < 0) {
continue;
}


display_status("RECV", bitlen);
display_data(buf1, bitlen);
display_format(format);

}
}

2011年3月1日火曜日

GEMMYの赤外線受光部 しょうもないことでハマってしまった。


焦電センサーで失敗して悔しいので、赤外線つながりでGEMMYについている受光部を使ってみることにした。

RemoteIR というライブラリを使う。
使い方が書いていないので、ソースを読んであたりをつけるが、
めんどくさくなって とりあえず 作者の作成したサンプルプログラムを
コンパイルして動かしてみる。

ありゃ動かない。

家じゅうのリモコンを持ってきて試すが、これはフォーマットうんぬんではなくて、
全然入力がきていない。

例えば、サンプルプログラムとは使うピンが違っているので、ディレクションやアナログ、デジタルモードの設定をしなければならないのか・・・・などなど 2時間ほど格闘。

受光デバイスの出力波形を当たってみようかな~~と 眺めていると気がついた。

あ~電源ね!

mbed USBからの給電でLCDも表示されるし、ボード上のものは動くと思い込んでしまった。

電源をつなぐと正常に動作。
リモコンを向けてボタンを押すと、コードが表示された。

--------------------------
ライブラリのソースを見るとSONYとNEC などが出てくるので、
最初、SONYとNECしかつかえないのかいね~?
と思ったのだが調べると、
IRリモコンの下位レイヤーのフォーマットとして NECタイプ SONYタイプ AEHA タイプ
などがあり、家電のリモコンは概ねこれのどれかに属するということだ。
この上位レイヤーにメーカー識別や独自のコードが乗るということらしい。

焦電センサーに敗北す


焦電センサーというのは自動ドアやセンサー付きライトに入っていて、人間の発する赤外線に反応する。
これを振るとか、左右に2個付けて差を見るとかしたら人の動きを追うようなことができないかと考えた。

実験キットを取り寄せた。センサー付きライトそのままの回路で、アンプと一定時間リレーをオンにする回路が入っている。リレー部分は不要なので、アンプ部分だけ利用する。

組み立ててオシロをつなぐと反応するのだがどうも思うような結果にならない。
変化量しか検出していない感じ。
まあ、用途を考えれば当然だ。センサーライトに適した動きをするように、フィルターが入っているのだろう。
アナログはあまり良くわからないのだが、アンプ部分に2段階に微分回路があるらしい。
これを外してみる。入力には積分回路らしきものがあって細かい変動もキャンセルしているらしいので、これも外す。
状況は変わってノイズっぽい変動も出てくるのだが、以前大勢は変化量しか検出しないことに変りなし。

ひと休みして
焦電センサーについて調べてみる・・・・・

ええええ~~~ そうなんだ~~

なんてこったい。デバイスそのものが変化量しか検出しないものらしい。

センサーを振れば変化するのだが、どうも出てくる出力を見ると、
位置検出できるような安定した結果は得られそうにない。

ということで、GEMMYにつなぐまでもなく失敗である。

もちろん、人が近づいたら何か動着始めるといったセンサーライトまがいのことは簡単にできる。