照明開発(18) 人感センサライト

今日は、一日中雨がザブザブ降ってたので、久しぶりに電気工作。MOSFETのドライブ回路の調整は、少しおやすみして、先日eBayで入手した焦電型人感センサを利用したセンサライトの制御回路を造ってみた。

以前造ったものを1Fのトイレで使っているのだけど、今回は、2Fのトイレと洗面所用の2つ。

入手したモジュールには、照度センサを追加するパタンも準備されておりそこにCdSセルを載せるだけで、CPUを使わずに照度センサ付人感センサができる。しかし、それだと、明るいときには電気が付けられなくなってしまう。

洗面所だと、明るくても電気を付けて更に明るくしたい場合もあるので、それだと困ってしまう。いろいろと検討した結果、CPUにはPIC12F629という、以前購入してあったチップを使うことにした。

現在利用中のものは、PIC12F629でアセンブラでプログラムを記述した。当時は、まだCコンパイラが無償になっていなかったから。今回は、最新のMPLAB-XにXC8という組合わせ。全て無償の開発環境。

F629は、ちょっと前のチップで割込みを使う場合、レジスタをいちいち待避させなければならない。アセンブラだと、全部自分で書かなければならないのだが、Cでは、コンパイラが自動的に挿入してくれる。非常にありがたい。

F629は、内部オシレータで4MHz発振するのだけど、電力消費をとことん抑えるためにRC回路を外付けしてどんな発信周波数になるか試してみることも含めて検証した。外部発信を利用すると、スリープ中に割込みを受けられるという利点もある。処理をちょろちょろとやってすぐにスリープという制御論理を構成すれば、生じ電力がかなり抑えられる。

試してみると、抵抗22kHz、コンデンサ0.1μFで約4kHzの発振。Foscは1/4なので、1kHz。CPUクロックとしては、超のろいのだけど、消費電力はFosc32kHzで35μAだから、それよりも少ないことになる。ちなみに20Mkzで動かすと24mAと700倍程度。大きな省電力効果が認められる。

プログラムは、mainではPICの初期設定の記述のみ。あとは、割込みハンドラで、ちょいちょいと記述してあるだけ。いたってシンプル。これだけで、照度センサ付の人感センサができあがり。

<前へ>                   <次へ>

#include <xc.h>
#pragma config BOREN = OFF, CPD = OFF, FOSC = EXTRCIO, MCLRE = OFF, WDTE = OFF, CP = OFF, PWRTE = OFF #define LED GP1
#define MDS GP2
#define CDS GP4
#define RST_TMR1 64286 // 10秒カウンタの初期値
//****************************************
/* 割込みハンドラ
INT割込みでセンサー検知信号を受信
TMR1割込みで消灯タイミング処理
*/
void interrupt handler( void ){
      unsigned char sleep_flag;
      // 非同期動作のためカウント値を保護するためカウンタ停止
      TMR1ON = 0;                                         // TMR1カウンタ停止
      sleep_flag = 0;
      // TMR1割込み(180s周期)の場合
      if(TMR1IE&&TMR1IF) {                        // TMR1割込み
           TMR1IF = 0;                                     // TMR1割込みフラグクリア
           LED = 0;                                           // LED照明消灯
           sleep_flag = 1;
      }
      // INT割込み(人感センサ検知)の場合
      if(INTE&&INTF) {                                 // INT割込み
           INTF = 0;                                          // INT割込みフラグクリア
           if(CDS) LED = 1;                               // 周囲が暗かったらLED照明点灯
           TMR1 = RST_TMR1;                        // カウンタリセット
           TMR1ON = 1;                                   // TMR1カウント再開
      }
      // 割込み終了処理
      GIE = 1;                                                  // 割込み許可
      if(sleep_flag)SLEEP();                             // スリープモードに
}
//#################### main ####
void main(void){
      //Initialization
      OPTION_REG = 0b11000000;                  // Pull up Off,
      CMCON=0x00000111;                            // ComperlatorOFF
      // 入出力指定
      TRISIO = 0b00011100;                            // GP0,1,5:Output GP2,3,4:Input
      // 出力ポート状態初期化
      GPIO = 0b00000000;                               // 0b00000000 = all off
      // TMR1初期化
      // TMR1割込みでSleepからWakeUpさせるためにはXtalが必要で今回は断念
      // TMR1:(1kHz)*8*22500=180s(3m) 毎にタイマー割込みが発生する
      // 65536-22500=43036が初期値となる
      T1CON = 0b00110000;                            // クロック源外部(2pin),プリスケール1:8,TMR1停止
      LED = 1;                                                 // 電源が入ったときは先ずは点灯
      // タイマ設定
      TMR1 = RST_TMR1;                              // TMR1初期化
      TMR1ON = 1;                                         // TMR1カウント開始
      // 割込み設定
      PEIE = 1;                                                // 周辺機器割込み許可
      INTE = 1;                                                // 外部割込み許可
      TMR1IE = 1;                                           // TMR1割込み許可
      GIE = 1;                                                  // 割込み許可
//———————————————————
      while(1){}
}

Y.Sさん、K.Oさん、M.Sさん、他14人が「いいね!」と言っています。

タイトルとURLをコピーしました