LEDシーリングライト用赤外線リモコンの製作(5)アイリスオーヤマ用

pic1

今回でアイリスオーヤマLEDシーリングライト用リモコン送信器(仮)は一応の完成です。

●処理概要

今回は前回作成したプログラムに、コマンド種別を増やしてスイッチ入力の処理を追加したものです。

●スイッチなどの配線

配線図と周辺写真を示します。スイッチボードWSN285を使用しています(CQカチャduinoのセットに付属)。単独のタクトスイッチなどで製作する場合は、スイッチにプルアップ抵抗が必要です(プログラムでAVR入力ポートの内蔵プルアップを有効にしても可)。なお、WSN285にはプルアップ抵抗が既に内蔵されています。そのため、このボードに電源とGNDを接続し忘れないように注意してください。

配線図remo_cir

WSN282とLED、トランジスタ回路周辺

pic3

プログラムを書き込んだ後はWSN283(USB/電源部)は不要です。5V電源を用意すればWSN282単独で作動します。単三~単四の乾電池3本を直結しても使えると思います。
赤外線LEDにはOptoSupply OSI5LA5113A(φ5) 半値角:±7.5°  (秋月電子)を使用しています。

ブレッドボード全体。電源は右側のWSN337で5VのACアダプタより供給

pic2

●プログラム概要

全灯、常夜灯のリモコンコマンドを追加して4コマンドにし、4つのスイッチの入力で切り替えるようにしました。

●プログラム(irRemo.ino)

キー入力ドライバに筆者作成のライブラリw4SwitchとwCtcTimerを使用しています。この両ドライバを組み合わせてスイッチ入力時のチャタリングを除去しています。割り込みを使用していないため、リモコンパルス出力中(ごく短時間)はキー入力を受け付けませんが、これは逆に、パルス出力中に割り込み処理が発生しないためパルス出力に影響が出ないとう点で好都合です。

このドライバは無情公開しています。書籍「Arduino実験キットで楽ちんマイコン開発 」にも記事を掲載しています。

コードを次に示します。

/*
  アイリスオーヤマ LEDシーリングライト用赤外線リモコン評価

    copyright (c) 2013 www.wsnak.com

    13/10/20 新規作成

    スイッチ入力によりコマンド切り替え
    メモリ点灯、消灯、全灯、常夜灯

*/

/*
    ディジタル・ポート・アサイン
      スイッチポート D2-D5
      IR発光(LED)  D8
*/

// ライブラリのリンク
#include <wSwitch.h>            // スイッチ用ライブラリ(w4Switch)
#include <wCTimer.h>            // タイマ・ライブラリ(wCtcTimer2A)

#define ON HIGH
#define OFF LOW

#define IR_OFF digitalWrite(8, LOW);    // IR LED(D7)
#define IR_ON  digitalWrite(8, HIGH);   // IR LED(D7)

// ライブラリのインスタンス生成
w4Switch sw;                    // スイッチオブジェクトの実体化
wCtcTimer2A tm;                 // タイマオブジェクトの実体化

//
// 初期化
//
void setup(void) {
  int i;

  tm.init(125);                 // タイマ初期化
  sw.SwitchInit(2, 3, 4, 5);    // SW用ポート定義

  sw.onKeyPress(KeyPress);      // スイッチが押された時に呼び出される関数の登録

  pinMode(8, OUTPUT);   // IR発光 (IR-LED)
  IR_OFF;

/*
  delay(500);
  for(i = 0; i < 4; i++) {
    irOut(i);         // 消灯
    delay(2000);
  }
  while(1);   // halt
*/
}

//
// リモコン コマンド出力
//
void irOut(byte sw) {
  int i, k;

  // (C)
  for(i = 0; i < 74; i++) {
    IR_ON;
    delayMicroseconds(9);
    IR_OFF;
    delayMicroseconds(10);
  }
  delay(1);

  // ********* リピート部分 ************
  for(k = 0; k < 3; k++) {

  // 共通部分
  // (D)
    for(i = 0; i < 205; i++) {
      IR_ON;
      delayMicroseconds(9);
      IR_OFF;
      delayMicroseconds(10);
    }
    delay(1);

    pulseB();       // (E)
    pulseA(7);
    pulseB();
    // 共通部分終わり

    // コマンド依存部分
    switch(sw) {
      case 0:     // 消灯
        pulseA(4);
        pulseB();
        pulseA(19);
        pulseB();
        pulseA(1);
        pulseB();
        pulseB();
        pulseB();
        pulseB();
        pulseA(1);
        pulseA(1);
        break;

      case 1:     // メモリ点灯
        pulseA(6);
        pulseB();
        pulseA(17);
        pulseB();
        pulseA(1);
        pulseB();
        pulseB();
        pulseA(1);
        pulseB();
        pulseB();
        pulseA(1);
        break;

      case 2:     // 全点灯
        pulseA(3);
        pulseB();
        pulseA(20);
        pulseB();
        pulseA(1);
        pulseB();
        pulseA(2);
        pulseB();
        pulseA(2);
        break;

      case 3:     // 常夜灯
        pulseA(5);
        pulseB();
        pulseA(18);
        pulseB();
        pulseA(1);
        pulseB();
        pulseB();
        pulseA(4);
        break;
    }
    delay(9);
  }
}

//
// パルス(A)出力
//
void pulseA(int n) {
  int i, j;

  for(j = 0; j < n; j++) {
    for(i = 0; i < 19; i++) {
      IR_ON;
      delayMicroseconds(9);
      IR_OFF;
      delayMicroseconds(9);
    }
    delayMicroseconds(520);
  }
}

//
// パルス(B)出力
//
void pulseB(void) {
  int i;

//  for(i = 0; i < 57; i++) {
  for(i = 0; i < 55; i++) {
    IR_ON;
    delayMicroseconds(9);
    IR_OFF;
    delayMicroseconds(10);
  }
  delayMicroseconds(520);
}

//
// メインループ
//
void loop(void) {
  if(tm.checkTimeup()) {
    // 8ms周期
    sw.KeyProc();     // キーセンス処理
  }
}

//
// キー入力ハンドラ
//   スイッチが押された時に呼び出される関数
//
void KeyPress(byte keyval) {
  switch(keyval) {
    case 1:           // SW1(上) メモリ点灯
      irOut(1);
      break;
    case 3:           // SW3(下) 消灯
      irOut(0);
      break;
    case 2:           // SW2(右) 全灯
      irOut(2);
      break;
    case 4:           // SW4(左) 常夜灯
      irOut(3);
      break;
  }
}

20、21行目でライブラリをリンクし、30、31行目でインスタンスを作成しています。

39行目はタイマライブラリのタイマ周期を指定して初期化しています。設定値は125ですが、64us単位なので、ここでは64us×125= 8msということになります。

40行目はスイッチ入力に使用するディジタルポートを定義しています。

42行目はキーが押された時に呼び出される関数(ハンドラ)を定義しています。この定義により、キーが押されると”KeyPress()”という関数(194行目)がコールされます。

キー入力ドライバを使用するためにメインループの中で周期的にプロセス関数”sw.KeyProc()“を呼び出す必要があります(186行目付近)。”tm.checkTimeup()"はAVR内蔵のCTC(タイマ)により周期的にtrueになる関数です。

●応用

従来の照明器具のように、スイッチを1つにして、メモリ点灯→全灯→常夜灯→消灯とサイクリックに作動するようにもできます。マイクロスイッチなどにひもを付けて、照明近くに設置し、従来照明のようにひもでスイッチ操作するようにもできます。ひもの方が便利なこともあるので。

そのほか、時計機能を付けてタイマ動作や指定時刻に照明をON/OFFさせるとかもできますね。外出時に防犯用にON/OFFさせるとか応用できます。

それと、再調整が必要になると思いますが、CQカチャduino(WSN282)のクリスタルを8MHzにしてファームを書き換え、8MHz 3.3V仕様にすれば省電力になります。そうすれば乾電池2本で駆動できます。

5V電源でアイドル時の消費電流は16mAでした。リモコン操作時(赤外線LED発光時)は40~50mAぐらい流れていると思います。乾電池で駆動する場合は電源スイッチをつけないときついですね。アイドル時はArduinoがスリープにして、スイッチ操作でウェイクアップできればよいのですが、8MHz化も含めて今後の課題です。(13/10/21追記)

●最後に

製品付属のリモコンは水平方向に向けていても制御できますが、本機では赤外線LEDを照明器具の方へ向けないと反応しませんでした。使用するLEDの違いだと思います。製品版は3つLEDを使っているのと、恐らく、指向性の低いタイプを使用して強めに発光させているのだと思います。このあたりは用途により改造する必要があるかもしれません。指向性に関しては、現状ではパワーを上げても製品のようにはならないと思いますので、そういう場合には赤外線LEDを適当なものに変える必要があります。

LEDを上向きのままにして机の上に置いて使う分には現状のものでいけると思います。

(一応、完)


参考文献
ここで使用した筆者作成のライブラリは、書籍「Arduino実験キットで楽ちんマイコン開発」で紹介したものです。よろしければこちらもごらんください。なお、ライブラリはCQ出版のサポートサイトから無償でダウンロードできます。

コメントは受け付けていません。