目次

電源タイマー

 自作の夜間点滅器がありますが、午前0時から翌朝6時くらいまでは
 点滅不要なので、電源タイマーを作成しました。PIC16F629を使います。

 点滅器は半田付けしてあるので、接続する電源制御だけを考えます。



 夕方暗くなったことを検出して、4時間電源を入れることに。

 ハードウエアのブロック図は、以下。



 回路図は、以下。



 3V動作リレーがあるので、電源制御はリレーに任せます。

 ファームウエアの構成を考えます。
  1. 明→暗を検出したなら、2へ
  2. カウンタに最大値を設定と同時に、リレーをオンにしたなら、3へ
  3. タイマー割込みからのイベントフラグをとらえて、カウンタをデクリメント、4へ
  4. カウンタ値が正なら3へ、ゼロならリレーをオフして5へ
  5. 1にもどる
 大まかなコードを書きます。 while ( ON ) { /* timer handling (1000ms) */ if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* interval handling */ if ( timcnt > 0 ) { timcnt-- ; } /* shift */ sft <<= 1 ; /* mask */ sft &= MASK03 ; /* update state */ TRISIO.B5 = ON ; /* B5 is input */ if ( GPIO.B5 == OFF ) { sft |= ON ; } /* judge */ if ( sft == 0x01 ) { eflag = ON ; } } /* start timer */ if ( eflag == ON ) { /* clear flag */ eflag = OFF ; /* set count */ timcnt = TIMCNTMAX ; } /* output handling */ if ( timcnt > 0 ) { /* B0 is output */ TRISIO.B0 = OFF ; /* relay on */ if ( GPIO.B0 == OFF ) { GPIO.B0 = ON ; } } else { /* B0 is output */ TRISIO.B0 = OFF ; /* relay off */ GPIO.B0 = OFF ; } }  1000msの経過を、タイマー割込みでイベント通知することにし  それに対応した処理を記述してあります。  内蔵の4MHzを利用し、タイマー0でオーバーフロー割込みを使います。  1000msを生成するために、次のように考えました。
  1. タイマー0の入力クロックは4MHz/4=1MHzなので、プリスケーラで分周
  2. プリスケーラで16分周すれば、62.5kHzとする
  3. 62.5kHzを250分周すると、250Hz(8ビットカウンタの範囲で扱える)
  4. 250Hzを、250分周し1Hzとする
  5. 1Hzでイベントフラグによる通知とする
 割込み処理を定義します。 void interrupt(void) { /* generate 1000ms */ if ( INTCON.T0IF == ON ) { /* clear flag */ INTCON.T0IF = OFF ; /* initialize */ TMR0 = 6 ; /* increment */ timv++ ; /* judge */ if ( timv == 250 ) { /* clear */ timv = 0 ; /* set flag */ tflag = ON ; } } }  まとめます。 typedef unsigned char UBYTE ; typedef unsigned int UWORD ; #define OFF 0 #define ON OFF+1 #define MASKFF 0xff #define MASK30 0x30 #define MASK0F 0x0f #define MASK03 0x03 #define TIMCNTMAX 14400 volatile UBYTE tflag ; volatile UBYTE eflag ; volatile UBYTE sft ; volatile UBYTE timv ; volatile UWORD timcnt ; /* function prototype */ void init_usr(void); /* interrupt handler */ void interrupt(void) { /* generate 1000ms */ if ( INTCON.T0IF == ON ) { /* clear flag */ INTCON.T0IF = OFF ; /* initialize */ TMR0 = 6 ; /* increment */ timv++ ; /* judge */ if ( timv == 250 ) { /* clear */ timv = 0 ; /* set flag */ tflag = ON ; } } } void main(void) { /* user initialize */ init_usr(); /* endless loop */ while ( ON ) { /* timer handling (1000ms) */ if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* interval handling */ if ( timcnt > 0 ) { timcnt-- ; } /* shift */ sft <<= 1 ; /* mask */ sft &= MASK03 ; /* update state */ TRISIO.B5 = ON ; /* B5 is input */ if ( GPIO.B5 == OFF ) { sft |= ON ; } /* send trigger */ if ( sft == 0x01 ) { eflag = ON ; } } /* start timer */ if ( eflag == ON ) { /* clear trigger flag */ eflag = OFF ; /* set count */ timcnt = TIMCNTMAX ; } /* output handling */ if ( timcnt > 0 ) { /* B0 is output */ TRISIO.B0 = 0 ; /* relay on */ if ( GPIO.B0 == OFF ) { GPIO.B0 = ON ; } } else { /* B0 is output */ TRISIO.B0 = 0 ; /* relay off */ GPIO.B0 = OFF ; } } } /* define function body */ void init_usr(void) { /* I/O state */ GPIO = 0x00 ; /* I/O directions */ TRISIO = 0x18 ; /* bit3,5 as input , others as output */ /* disable compare module */ CMCON = 0x07 ; /* pull-up */ /* WPU = 0x10 ; */ /* initialize Timer 0 */ { /* 4MHz/4 = 1MHz -> 1MHz/16 = 62.5kHz prescaler = 1:16 */ OPTION_REG = 0x03 ; /* 256 - 250 = 6 */ TMR0 = 6 ; /* enable timer0 overflow interrupt */ INTCON.T0IE = ON ; } /* enable general interrupt */ INTCON.GIE = ON ; /* clear flags */ tflag = OFF ; eflag = OFF ; /* clear */ sft = 0 ; timcnt = 0 ; timv = 0 ; }

目次

inserted by FC2 system