回路図での記号 | 型番 | 説明 | 入手先 |
U1 | ATTINY85 | AVRマイコン(DIP 8pin) | DigiKey |
RPM7138-R | RPM7138-R | 赤外線受信モジュール | DigiKey |
IR-LED | OSIR5113A | 5mm赤外線LED | 秋月 |
SW1 | FSM4JH | タクティルスイッチ | DigiKey |
SP1 | PKM13EPYH4000-A0 | ピエゾブザー | DigiKey |
R1 | 10kΩ | 抵抗 | 秋月 |
R2 | 52Ω( | 抵抗 | 秋月 |
No. | 操作名 | コマンド | 説明 |
1 | 送信 | 短押し×[メモリ番号]回 | [メモリ番号]は1~6。単純に短押しすると、押した回数に応じて学習済みのメモリの内容を赤外線送信する(つまりシングルクリックでメモリ1の内容を出力、ダブルクリックでメモリ2の内容を出力...という動作をする)。 |
2* | 学習(モードA) | 長押し×2回+赤外線受信 | 赤外線信号を学習する。記憶先は直前に No.1 で送信したメモリ番号。 |
3* | 学習(モードB) | 長押し×3回+赤外線受信 | 赤外線信号を学習する。記憶先は直前に No.1 で送信したメモリ番号。No.2との違いは、No.3で学習した場合、送信時に同じ信号を約40[ms]間隔で2回繰り返して送信する点。 |
4* | 消費メモリ確認 | 短押し×7回 | 学習済みの信号が消費しているメモリ(EEPROM)量に応じてBEEPを鳴らす。対象は直前に No.1 で送信したメモリ番号。BEEP1回が32バイト。 |
5 | メモリ残量確認 | 短押し×8回 | 全メモリ(EEPROM)残量に応じてBEEPを鳴らす。BEEP1回が32バイト。 |
6* | 固定モード | 短押し×9回 | 固定モードに移行。固定モードでは短押しした瞬間に赤外線が送信される(通常モードでは短押しから赤外線の送信までにタイムラグがあるが、それが解消する)。固定モードにすると、直前に送信した1種類の信号しか送信できなくなる。固定モードは長押しで解除される。 |
7* | メモリ削除 | 短押し×11回 | 学習した赤外線信号を消去する。対象は直前に No.1 で送信したメモリ番号。 |
8 | 完全初期化 | 短押し×12回 | 学習結果を完全に消去して初期状態に戻す。 |
1回 | ピ | 学習予告 |
2回 | ピピ | 起動音(電池を入れた時) |
3回 | ピピピ | 固定モード開始 |
4回 | ピピピピ | 固定モード解除 |
1回 | ピー | 学習スタンバイ(モードA)/学習成功(モードA) |
2回 | ピーピー | 学習スタンバイ(モードB)/学習成功(モードB) |
4回 | ピーピーピーピー | メモリ削除成功 |
5回 | ピーピーピーピーピー | 完全初期化成功 |
1回 | ブ | 学習前に送信しようとした |
2回 | ブブ | ノイズを受信したため学習中断 |
3回 | ブブブ | 受信した赤外線信号が長すぎて RAM 不足のため学習中断 |
4回 | ブブブブ | メモリ(EEPROM)不足のため学習中断/メモリ削除失敗 |
リアルタイム圧縮によって、これまで学習できなかったダイキンと日立のエアコンが学習できるようになった。まだ電源 ON/OFF しか確認していないが、ファームウェアの Version49 として公開した。今のところ試したリモコンは何でも学習できている。
学習中に赤外線信号をリアルタイムでランレングス圧縮するコードができた~。これで相当長い信号も学習できるはず。あとでダイキンと日立のエアコンで試してみよう。72kHz の割り込み期間内(13.9μs)にすべての処理を行わないといけないので、圧縮も含めた学習処理に使える命令数が222ステップしかない。どう書けば実行コードが短くなるのか、コンパイル後のアセンブリコードを眺めながらコーディング。無理かと思ったが、AVR-GCC の最適化のおかげでちゃんとサイズ内に収まった。すばらしい。ただコードを短くするためにトリッキーな書き方をしてしまって、バグを埋め込んでしまっているおそれも。ちゃんと見直そう。
シリアル入力機能を追加して、リモコンを PC からもコントロールできるようにした。学習した生信号を PC のシリアルポートに入力して表示させられるようになってからデバッグがはかどる。むしろいままでその機能なしで(しかもデバッガなども使わずに)開発してきた方がびっくりだが。
エアコンのリモコンの信号が長すぎて RAM に収まらず学習できない問題、どうにかならないか。Tiny85 の RAM は512 バイトしかない。かといって RAM が 1Kバイトの AVR の機種(Mega8など)は、内蔵クロックでの 16MHz 動作ができない。ソフトウェア的に解決したいので、学習中にリアルタイムにランレングス圧縮する方向で検討中。圧縮ルーチンの実行速度が割り込み周期に間に合うかが問題。
ソフトウェア UART を実装した。学習した赤外線信号の生データを PC に出力することはできた。次は PC からシリアルポート経由でリモコンを操作する機能を実装中。
電源問題、だいたい判明。結論としては、新品の LR44*3個を使えば、過負荷ではあるものの正常動作することがわかった。Panasonic 製のいい電池でも、1個10円くらいの電池でも大丈夫だったが、100円ショップのテスト用電池だと問題が発生する。本当にテスト用だった。
自分のまわりにある機器のなかで、ダイキンのエアコンだけが学習できない。エアコンのリモコンの出す赤外線信号の波形を見てみると 320bit 以上あり、AVR の RAM に入りきらないのが学習できない理由のようだ。RAM を節約するために赤外線信号の時間計測の分解能を 1/4 に落として(現在は 76[kHz], 13.16[μs] が最小計測単位)、1パルスを4bitで表現する方法を試してみたが、それでも ATTiny85 の 512バイトの RAM には入りきらなかった。さらに、分解能をそこまで落とすと学習できなくなる機器もあり(ビクターのDVDプレイヤーなど)、この方法はとりあえず断念。
ファームウェアの大改変を行った。改良点は (1)どのリモコンでもモードAで学習できるようにした(モードの切り替えが不要になった)。(2)デバッグモード追加。学習した信号をシリアルに出力できる。(3)デバッグモードを使って各社のリモコン信号を観察して、圧縮アルゴリズムを改良した。新しいファームウェアはまだあまりテストしていないので未公開。テスト後にコードを整理して公開しよう。
赤外線 LED にもいろいろな製品がある。流せる電流、照度、照射角がデータシートに書いてあり、これらのパラメータが大抵トレードオフになっている。今回はボタン電池の非力な電源でできるだけ到達距離を伸ばしたかったので、試行錯誤してみた。結論としては秋月で袋買いした OSIR5113A がよかった。照射角(半値全角)が15度と狭いが、透明なプラスチックのケースを通して発光させると適度に散乱してよい感じだった。ただしケースの不透明な部分でどうしても一部の光がさえぎられてしまう。市販製品のリモコンをよく見ると、赤外線 LED のまわりのケースの形状に工夫がしてあって、できるだけ光をさえぎらない構造になっている。
赤外線受信モジュールは種類が多い。秋月でいろいろ買って試してみたところ、電気的ノイズに弱いもの、蛍光灯に弱いもの、周囲が明るくないとノイズがひどいものなどさまざま。赤外線が入射していないのに出力があることが多くて結構困る。モジュールを使って赤外線のパルス幅をセンシングすると、全体的に点灯時間が長めに、消灯時間が短めになる傾向があるのでソフトウェアで補正が必要。また一見同じ形状のモジュールでもピンアサインが違うことが多いので注意が必要。現在、一番安定して使えているのがロームの RPM7138-R。海外製のモジュールよりは少々お値段が高いが、ノイズに強く非常に使いやすい。
そのうちファームウェアの解説も書きたい。ファームウェアは AVR-GCC でスクラッチから書いたもので、結構頑張っている。頑張っている点は (1)EEPROM が512 バイトしかないので、学習した信号を生のままでなく少し圧縮して保存している。(2)各種フォーマット(家製協、NEC、ソニー、その他外国製の謎のリモコン)に対応するため、アルゴリズムを工夫している。可能な限りビット列として解釈するが、イレギュラーな信号は生のまま記録する。受信した信号の解釈のためにパルスの平均時間を求めたりもしている。(3)RAM も512 バイトしかないので、RAM 上でリアルタイムに処理する学習データは、1~2バイトの可変長フォーマットで処理している(それでもエアコン等の長すぎる信号は RAM に入りきらない)。(4)EEPROM 用の超簡易な独自ファイルシステムを実装してデータを保存している。
12秒間操作しない状態が続くと、赤外線受光モジュールの電源が切られ、マイコンは省電力モードになる(省電力モードからはボタンを押すと回復する)。省電力モード中の消費電流は、実測で2μA以下なので、電池は入れたままでもそれほど消耗しない。...はずだったのだが、なぜか電池が1~2日で消耗してしまう現象が発生した。その状態で電池を外して、一個ずつ電圧を測定してみると、正負が逆になる電池が出てくる。何かおかしい。
また、これも電源電圧と関係しているような気がするが、やはり数日放置するとボタンを押しても反応しなくなる(電池を入れ直すと直ることもある)。
考えられる原因としては、100円LEDライトの動作確認用電池をそのまま使っているのが問題なのかもしれない。または赤外線LEDに大電流を流しているのが問題かも。あるいはウォッチドッグタイマーが発動した時にうまく再起動できていないのかもしれない。リセットピンがオープンのままなのがまずいのかも。
いまだに現象の再現性が確認できないので、電源電圧を測定する実験を開始。新品の電池を入れて、10分おきに別のマイコンのADコンバータで電源電圧を測定して、電源電圧の急低下が発生する条件を探ってみる。
自作記事。まず回路図、操作方法、部品表を書こう。
自分はもう何百回となく学習操作を繰り返しているので無意識にやってしまっているが、赤外線受光モジュールで学習する時には、周囲の明るさ、距離、インバータ式蛍光灯の影響、押す時間などいくつかコツがあるので、忘れずにどこかに書いておかないと。ローム社の製品カタログが、これまでの学習時の感覚と一致していて納得の内容。実際マルツでロームのモジュール RPM7138-R を買って試してみたら、ノイズにも強いし、電池の電圧がかなり下がっても正しく学習できる。ロームのモジュールすごい。
コマンド体系を試行錯誤中。1キーで送信、学習、削除、メモリ残量確認などのコマンドを指定するのはどうするのがベストか。ようやくよさそうな方法が固まりつつあるので、確定していいかな。ただどうやっても完全にマニュアルなしで操作するのは無理そう。
手元にあるリモコンで試してみると、ほとんどがうまく学習できた。ただ日立のエアコンだけはおかしい。学習後に赤外線を出すとハングアップしてしまうようで、8秒後にウォッチドッグタイマで再起動しているようだ(BEEP 音でわかる)。特定の信号でだけハングアップするというのはちょっと奇妙な現象。おかしくなった状態で EEPROM を avrdude で吸い出して、原因を突き止めることにする。
原因判明。この日立のエアコンは赤外線信号が長く、記録できる長さを超えていた。その時の処理がおかしかったので修正。AVR ATTiny85 の RAM 容量の制約で最大 352÷2=176 ビットしか記録できない。RAM の多い MEGA64 で試してみたら学習できたので、信号の長さの問題なのは間違いない。ここまで長い信号を使うリモコンはあまりないと思うが、こればかりはいまのところどうしようもない。
追記: ダイキンのエアコンも新しい機種に買い替えたら、赤外線信号が長すぎて記録できなくなってしまった。