目次

食器乾燥機タイマー

 15年以上使っている食器乾燥機のタイマーが
 おかしくなりました。




 ゼンマイを利用した、超アナログ式メカタイマーなので
 カム部分が摩滅して使えなくなりました。

 食器乾燥機は、3度の食事の後に使うので、マイコンを
 利用して、スイッチを押すと通電し、10分後に切断と
 いう仕様を考えました。

 AC100Vの電源を接続、切断するのでリレーを利用し
 通電の音が聞こえるようにします。

 手持ちの部品をかき集めて簡単に作りたいので
 ブロック図を描いて考えます。



 ブロック図から回路図を作成。



 回路ができたなら、基板上に部品を半田付けしました。
 (リレーは接点容量が2倍以上のデバイスを利用)



 ファームウエアは以下。

/* redefine data type */
typedef unsigned char UBYTE ;
typedef unsigned int  UWORD ;

#define XCOUT PORTA.F0
#define LTICK PORTA.F1
#define ITICK PORTA.F2

#define OFF 0
#define ON  OFF+1

#define MASKFF 0xff

typedef union {
  struct {
    unsigned B7:1;
    unsigned B6:1;
    unsigned B5:1;
    unsigned B4:1;
    unsigned B3:1;
    unsigned B2:1;
    unsigned B1:1;
    unsigned B0:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP xflags ;

#define XFLAG xflags.BIT.B0
#define EFLAG xflags.BIT.B1
#define TFLAG xflags.BIT.B2

volatile UWORD xcnt ;
volatile UBYTE ycnt ;
volatile UBYTE zcnt ;
volatile UWORD xinterval ;

volatile UBYTE ssft ;
volatile UBYTE tmp ;

/* function prototype */
void init_usr(void);

/* interrupt handler */
void interrupt(void)
{
  /* generate 2ms */
  if ( INTCON.TMR0IF == ON ) {
    /* clear flag */
    INTCON.TMR0IF = OFF ;
    /* 256 - 250 = 6 */
    TMR0 = 6 ;
    /* increment */
    xcnt++ ;
    ycnt++ ;
    /* impress */
    if ( (ycnt & 1) ) { ITICK = ON ; }
    else              { ITICK = OFF; }
    /* set TFLAG (2ms) */
    TFLAG = ON ;
    /* judge */
    if ( xcnt == 500 ) {
      /* set flag */
      XFLAG = ON ;
      /* clear */
      xcnt = 0 ;
    }
  }
}

void main(void)
{
  /* initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* timer handling (2ms) */
    if ( TFLAG == ON ) {
      /* clear flag */
      TFLAG = OFF ;
      /* shift register */
      ssft <<= 1 ;
      /* mask */
      ssft &= 3 ;
      /* get trigger */
      tmp = PORTA ;
      tmp ^= MASKFF ;
      /* ? click */
      if ( tmp & 0x20 ) { ssft |= 1 ; }
      /* judge */
      if ( ssft == 1 ) {
        if ( EFLAG == OFF ) {
          /* set flag */
          EFLAG = ON ;
          /* set signal */
          XCOUT = ON ;
          /* 10x60 = 10 minutes */
          xinterval = 600 ;
        }
      }
    }
    /* timer handling (1sec) */
    if ( XFLAG == ON ) {
      /* clear flag */
      XFLAG = OFF ;
      /* decrement */
      if ( EFLAG == ON ) {
        xinterval-- ;
        if ( xinterval == 0 ) {
          EFLAG = OFF ;
          XCOUT = OFF ;
        } else {
          /* monitor */
          zcnt++ ;
          if ( (zcnt & 1) == ON ) { LTICK = ON  ; }
          else                    { LTICK = OFF ; }
        }
      } else {
        LTICK = EFLAG ;
      }
    }
  }
}

/* define function body */
void init_usr(void)
{
  /* select 1MHz */
  OSCCON = (0x0b << 3) | 0x03 ;
  /* disable A/D converter */
  ADCON0.ADON = OFF ;
  ADCON2      = 0 ;
  ANSELA      = 0 ;
  /* disable D/A converter */
  DACCON0 = 0 ;
  DACCON1 = 0 ;
  /* disable compare module */
  CM1CON0.C1ON = OFF ;
  CM1CON0.C1OE = OFF ;
  /* I/O state */
  PORTA = 0x00 ;
  /* I/O directions */
  TRISA = 0x38 ; /* bit0,1,2 as output , others as input */
  /* initialize timer 0 */
  {
    /*
       1MHz (Fosc)
       Fosc/4 = 250kHz
       125kHz/4 = 125kHz prescaler = 1:2
    */
    OPTION_REG = 0x00 ;
    /* 256 - 250 = 6 */
    TMR0 = 6 ;
    /* enable timer0 overflow interrupt (500Hz) */
    INTCON.TMR0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
  /* clear flags */
  xflags.DR = 0 ;
  /* initialize variables */
  xcnt = 0 ;
  ycnt = 0 ;
  zcnt = 0 ;
  xinterval = 0 ;
  ssft = 0 ;
  tmp = 0 ;
}

 スイッチの状態は、500Hzのインターバルで取り込んでL→Hと
 変化したならば、クリックと判断しています。

 10分間のカウントは、変数xintervalの値を1秒ごとの
 割込みで−1して実現。

 スイッチと一体化されているLEDを、動作中に点滅させています。

目次

inserted by FC2 system