目次

スタートゲートセンサー再考

 mugen2016、mugen2015には、スタートゲートセンサーと
 して超音波センサーを利用してきました。



 この超音波センサーでは、距離をパルス幅で出力してくる
 ので、デジタル回路で計測していました。この計測時間を
 なくすことを考えました。

 ¥50程度で入手できるフォトリフレクタを
 評価してみました。




 フォトリフレクタは、物体までの距離は反射があるのは
 10mmが限度でした。この距離だと、センサーはゲートに
 密着させる程度までにしないと駄目。

 実際に使われているスタートゲートは、以下。




 ゲートの開閉をとらえるためには、象の鼻のように
 センサーを密着させる程度に近づける必要あり。

 データシートには、次の回路をサンプルとしています。



 光の反射があると、'L'レベルであり、反射がないと'H'。
 そのまま利用すると、次の判定をすればゲートの開閉を
 判断できます。

 'L'レベル=ゲートは閉じている
 'H'レベル=ゲートは開いている

 マイコン、FPGAでの論理レベル判定をするためには
 NPN型トランジスタかNchエンハンスメント型MOSFET
 による電圧フォロワを入れて対応すべきでしょう。




 NPN型トランジスタを利用すると、エミッタフォロワの
 出力電圧は、ベース電圧から0.6V程度引いた値になり
 3.3Vを与えると2.7V程度。

 光が入ると、フォトリフレクタのコレクタは0V近くまで
 電圧が下がり、エミッタフォロワの出力電圧も0Vに。

 フォトリフレクタの内蔵LEDは、60mAまでの許容電流が
 あるので、100Ωでは (3.3V-1.8V)/100=15mA 程度です
 から、破損することはないでしょう。

 フォトリフレタは、距離測定が不要なのでシーケンス
 処理をしないで済ませられます。

 光を扱う場合、変調をかけて照射し受光側で整流する
 のが定番なので、その回路を考えます。

 変調は単純なON/OFF信号を与え、受信側では2倍圧整流
 してみます。回路構成は、以下。



 ゲートの開閉をデジタル値で出力すればよいので、シリコン
 ダイオードを利用した2倍圧整流で対応します。
 変調用クロックは、1kHz前後でよいと判断しました。
 クロック生成は、555のような発振ICで簡単に生成。



 555は、抵抗値の組み合わせで任意の周波数を指定できます。

 低消費電力にするためには、CMOSタイプの555を選定すべきでしょう。

 CMOSタイプの555は、3種程度もっているので、次の基板で
 抵抗値の組み合わせを調べられるようにしてます。




 ダイオードで、変調波を復調して直流に変換するので
 1kHzから100Hzの矩形波でよいとわかりました。

 555は、8ピンなのでPIC12F1501を利用して
 常にスタートゲートまでの距離を測定して電圧
 で出力する基板も作成しました。



 回路図は、以下。



 VOUT、VOUTXが距離に相当する電圧を出力し
 TOVER、TOVERXが距離が範囲外の場合、'1'とします。

 PICが動作していることを、TOTからパルスを出力して
 アナログマルチメータでは、電圧を積分したカタチで
 固定電圧で判断できるようにしました。

 LEDを接続すると、薄ぼんやりと点灯するので、LEDを
 接続しても、動作していると判断できます。

 PIC12F1501のファームウエアは、以下。

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

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

volatile FLAGSP xflags ;

volatile UBYTE xcnt ;
volatile UBYTE ycnt ;
volatile UBYTE dh ;
volatile UBYTE dl ;
volatile UWORD xtim ;
volatile UBYTE xlen ;

#define EFLAG xflags.BIT.B0
#define SFLAG xflags.BIT.B1
#define OFLAG xflags.BIT.B2

#define OFF 0
#define ON  OFF+1

#define CNTBEGIN 6

#define DEFX 588

#define TOVER PORTA.F1
#define DMON  PORTA.F2
#define ECHO  PORTA.F4
#define TRG   PORTA.F5

/* function prototype */
void  init_usr(void);
void  dac_write(UBYTE x);
void  dac_init(void);

/* interrupt handler */
void interrupt(void) 
{
  /* generate trigger 1ms interval */
  if ( INTCON.T0IF == ON ) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize */
    TMR0 = CNTBEGIN ;
    /* increment */
    xcnt++ ;
    /* judge */
    if ( xcnt == 100 ) {
      xcnt = 0 ;
      EFLAG = ON ;
    }
  }
  /* echo handling */
  if ( PIR1.TMR1GIF == ON ) {
    /* clear flag */
    PIR1.TMR1GIF = OFF ;
    /* set flag */
    SFLAG = ON ;
  }
  /* echo handling (overflow) */
  if ( PIR1.TMR1IF == ON ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* set flag */
    OFLAG = ON ;
  }
}

void main(void)
{
  UBYTE i ;
  /* user initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* sensor handling */
    if ( SFLAG == ON ) {
      /* clear flag */
      SFLAG = OFF ;
      /* stop timer1 */
      T1CON.TMR1ON = OFF ;
      /* get timer counter */
      dl = TMR1L ;
      dh = TMR1H ;
      xtim = dh * 256 + dl ;
      /* calculate distance 100mm : 588 us */
      xlen = (UBYTE)((32.0 * xtim) / DEFX) ;
      /* upper limiter */
      if ( xlen > 21 ) { xlen = 21 ; }
      /* calculate voltage */
      dac_write(xlen);
    }
    /* sensor handling (overflow) */
    if ( OFLAG == ON ) {
      /* clear flag */
      OFLAG = OFF ;
      /* impress */
      TOVER = ON ;
    }
    /* execute */
    if ( EFLAG == ON ) {
      /* clear flag */
      EFLAG = OFF ;
      /* monitor counter increment */
      ycnt++ ;
      if ( ycnt & ON ) { DMON = ON  ; }
      else             { DMON = OFF ; }
      /* clear */
      TMR1L = 0 ;
      TMR1H = 0 ;
      /* start timer1 */
      T1CON.TMR1ON = ON ;
      /* indicator */
      TOVER = OFF ;
      /* send start trigger */
      TRG = ON ;
      for ( i = 0 ; i < 160 ; i++ ) ;
      TRG = OFF ;
    }
  }
}

/* define function body */
void init_usr(void)
{
  /* select 16MHz */
  OSCCON = (15 << 3) | 0x03 ;
  /* disable A/D converter */
  ADCON0.ADON = OFF ;
  ADCON2      = 0 ;
  ANSELA      = 0 ;
  /* initialize D/A converter */
  dac_init();
  /* disable compare module */
  CM1CON0.C1ON = OFF ;
  CM1CON0.C1OE = OFF ;
  /* I/O state */
  PORTA = 0x00 ;
  /* I/O directions */
  TRISA = 0x18 ; /* bit0,1,2,5 as output , others as input */
  /* pull up */
  WPUA = 0x10 ;
  /* initialize timer 0 */
  {
    /*
       16MHz/4 = 4MHz (Fosc)
       Fosc/4 = 1MHz
       1MHz/4 = 250kHz prescaler = 1:4
    */
    OPTION_REG = 0x01 ;
    /* 256 - 250 = 6 */
    TMR0 = CNTBEGIN ;
    /* enable timer0 overflow interrupt */
    INTCON.TMR0IE = ON ;
  }
  /* initialize timer 1 */
  {
    T1CON = 0x24 ;
    T1GCON = 0xc0 ;
    /* select RA4 */
    APFCON.T1GSEL = OFF ;
    /* enable peripheral TMR1GE */
    PIE1.TMR1GE = ON ;
    /* enable TMR1 overflow interrupt */
    PIE1.TMR1IE = ON ;
    /* enable peripheral interrupt */
    INTCON.PEIE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
  /* clear flags */
  xflags.DR = 0 ;
  /* initialize variables */
  xcnt = 0 ;
  ycnt = 0 ;
  xtim = 0 ;
  xlen = 0 ;
}

void  dac_write(UBYTE x)
{
  DACCON1 = (0x1f & x);
}

void  dac_init(void)
{
  /* reference Vdd */
  DACCON0.DACPSS = OFF ;
  /* enable DAC output #1 */
  DACCON0.DACOE1 = ON ;
  /* use DAC */
  DACCON0.DACEN = ON ;
}


目次

inserted by FC2 system