目次

積分回路利用

 第8章の内容は、抵抗、キャパシタの接続による
 積分回路を利用した時間差を扱っています。



 キャパシタに電荷を蓄えてから、放電させていき
 電荷がゼロになるまでの時間を計測し、その時間
 を利用します。



 ポートAを利用した次の回路を使います。



 ポートAの0ビット目を出力に設定し、キャパシタに
 電荷を蓄えます。充電が終わったなら、0ビット目を
 入力に設定し、電荷を放電させます。この放電に必要
 な時間をカウンタで計測し、カウンタ値を利用します。

 充放電処理は、とても簡単です。

     /* clear counter */
     cnt = 0 ;
     /* RA0 : output */
     TRISA = 0xF0;
     /* charge */
     PORTA.F0 = 1 ;
     /* wait 10ms */
     Delay_ms(10);
     /* RA0 : input */
     TRISA = 0xF1;
     /* discharge */
     while ( PORTA.F0 == 1 )
     {
       cnt++;
     }
     /* impress */
     PORTB = cnt / 10 ;

 放電時間表示には、LEDを8個並べた2進数表示器を利用。

 キャパシタに電荷を蓄えるので、電荷をいれるバケツに
 相当するキャパシタの静電容量を大きくすると、流す水
 の量が同じなら指定水位まで液面が達するまでの時間は
 長くなります。





 キャパシタの静電容量が同じであっても、流し込む
 水量が少ない場合、バケツの水位が指定液面になる
 まで時間がかかります。抵抗は水量を調整している
 のと等価です。




 例として記されているコードは、次のようになります。

#define OFF 0
#define ON  OFF+1

#define DCNT 10
#define XDIV 10

typedef unsigned char UBYTE ;

/* prototype */
void  usr_init(void);
void  vcharge(void);
UBYTE vdischarge(void);

void main(void)
{
  UBYTE cnt ;
  /* initialize */
  usr_init();
  /* endless loop */
  while (ON) {
    /* charge */
    vcharge();
    /* discharge */
    cnt = vdischarge();
    /* show value */
    PORTB = cnt / XDIV ;
  }
}

void usr_init(void)
{
  /* don't charge */
  PORTA = 0x00 ;
  /* turn off all LEDs */
  PORTB = 0x00 ;
  /* disable analog comparator */
  CMCON = 0x07 ;
  /* set directions */
  TRISA = 0xf0 ;
  TRISB = 0xff ;
}

void vcharge(void)
{
  /* RA0 : output */
  TRISA.F0 = OFF ;
  /* charge */
  PORTA.F0 = 1 ;
  /* wait */
  Delay_ms(DCNT);
  /* RA0 : input */
  TRISA.F0 = ON ;
}

UBYTE vdischarge(void)
{
  UBYTE result ;
  /* clear */
  result = 0 ;
  /* discharge */
  while ( PORTA.F0 == ON ) {
    result++;
  }

  return result ;
}

 充電時間を可変する場合、マクロ定義しているDCNTの値を
 変更すればよいでしょう。そう考えてみると、キャパシタ
 に並列に可変抵抗を入れずに済みます。
 2進数表示は、マクロ定義しているXDIVの値を変更して
 変えられます。

 LEDを1本にして、点灯している時間で放電時間を表現できます。



 ポートBに接続しているLEDの点灯を関数に一任します。

#define OFF 0
#define ON  OFF+1

#define DCNT 10

typedef unsigned char UBYTE ;

/* prototype */
void  usr_init(void);
void  vcharge(void);
UBYTE vdischarge(void);
void  flash_led(UBYTE x);

void main(void)
{
  UBYTE cnt ;
  /* initialize */
  usr_init();
  /* endless loop */
  while (ON) {
    /* charge */
    vcharge();
    /* discharge */
    cnt = vdischarge();
    /* show value */
    flash_led( cnt / 10 );
  }
}

void usr_init(void)
{
  /* don't charge */
  PORTA = 0x00 ;
  /* turn off all LEDs */
  PORTB = 0x00 ;
  /* set directions */
  TRISA = 0xf0 ;
  TRISB = 0xff ;
}

void vcharge(void)
{
  /* RA0 : output */
  TRISA.F0 = OFF ;
  /* charge */
  PORTA.F0 = 1 ;
  /* wait */
  Delay_ms(DCNT);
  /* RA0 : input */
  TRISA.F0 = ON ;
}

UBYTE vdischarge(void)
{
  UBYTE result ;
  /* clear */
  result = 0 ;
  /* discharge */
  while ( PORTA.F0 == ON ) {
    result++;
  }

  return result ;
}

void  flash_led(UBYTE x)
{
  /* turn on LED */
  PORTB.F0 = ON ;
  /* delay */
  Vdelay_ms(x);
  /* turn off LED */
  PORTB.F0 = OFF ;
  /* delay */
  Vdelay_ms(x);
}

 LEDの点灯ができれば、DCモータの回転も可能です。



 LEDの点灯部分を、DCモータの回転に変えるには
 出力ピンの位置を変えるだけになります。

#define OFF 0
#define ON  OFF+1

#define DCNT 10

typedef unsigned char UBYTE ;

/* prototype */
void  usr_init(void);
void  vcharge(void);
UBYTE vdischarge(void);
void  rotate_motor(UBYTE x);

void main(void)
{
  UBYTE cnt ;
  /* initialize */
  usr_init();
  /* endless loop */
  while (ON) {
    /* charge */
    vcharge();
    /* discharge */
    cnt = vdischarge();
    /* motor control */
    rotate_motor( cnt / 10 );
  }
}

void usr_init(void)
{
  /* don't charge */
  PORTA = 0x00 ;
  /* stop motor */
  PORTB.F0 = OFF ;
  /* set directions */
  TRISA = 0xf0 ;
  TRISB = 0xff ;
}

void vcharge(void)
{
  /* RA0 : output */
  TRISA.F0 = OFF ;
  /* charge */
  PORTA.F0 = 1 ;
  /* wait */
  Delay_ms(DCNT);
  /* RA0 : input */
  TRISA.F0 = ON ;
}

UBYTE vdischarge(void)
{
  UBYTE result ;
  /* clear */
  result = 0 ;
  /* discharge */
  while ( PORTA.F0 == ON ) {
    result++;
  }

  return result ;
}

void  rotate_motor(UBYTE x)
{
  /* rotate motor */
  PORTB.F0 = ON ;
  /* delay */
  Vdelay_ms(x);
  /* stop motor */
  PORTB.F0 = OFF ;
  /* delay */
  Vdelay_ms(10-x);
}

 関数flash_ledを関数rotate_motorに置換え
 初期値を変更するだけ。

 Cは関数型言語なので、処理を関数の中に
 押し込めて扱うようにするのがコツ。


目次

inserted by FC2 system