目次

Go/Stop装置

 Go/Stop装置は、ミニ四駆やマイクロマウス等の
 タイムトライアル競技でスタートの合図を送る装置。



 写真のGo/Stop装置は、ある工業系大学で開かれた
 ロボットコンテストで使われていました。

 予選会場が複数ある場合、同じような装置が
 多数必要になり、ワンチップマイコンで実現
 できるかを考えてみました。

 Go/Stop装置の動作は、次の状態遷移図で表現可能。



 ボタンスイッチ、4個のLED、圧電ブザーをPICに
 接続して、Go/Stop装置を実現します。

 LEDはデコーダICの74HC139に接続し、ピンの割り当て
 を以下とします。



 利用するPICは、PIC12F629。

 8ピンのワンチップマイコンなので、4LEDを直接
 接続する余裕がなく、デコーダICを使いました。

 I/Oの設定を、Cの関数の中に入れておきます。

  /* I/O state */
  GPIO = 0x10 ;
  /* I/O directions */
  TRISIO = 0xe8 ; /* bit0,1,2,4 as output , others as input */

 点灯するLEDは、74HC139への出力で選択するので
 次のように制御します。

  /* clear 74HC139 control bits */
  GPIO = GPIO & 0xfc ;
  /* turn on LED_3 */
  if ( x.F0 == ON ) { GPIO = GPIO | 3 ; }
  /* turn on LED_2 */
  if ( x.F1 == ON ) { GPIO = GPIO | 2 ; }
  /* enable LED_1 */
  if ( x.F2 == ON ) { GPIO = GPIO | 1 ; }




 状態遷移図で描いた状態を遷移させるために
 シーケンスで、LEDの点灯を制御します。
 音を入れると、次の関数で実現。

void plc(UBYTE x)
{
  /* judge */
  if ( x > 8 ) return ;
  /* default */
  xf = XCNTMAX ;
  /* clear 74HC139 control bits */
  GPIO = GPIO & 0xfc ;
  /* turn on LED_3 */
  if ( x.F0 == ON ) { GPIO = GPIO | 3 ; }
  /* turn on LED_2 */
  if ( x.F1 == ON ) { GPIO = GPIO | 2 ; }
  /* enable LED_1 */
  if ( x.F2 == ON ) { GPIO = GPIO | 1 ; }
  /* judge */
  if ( x.F3 == ON ) { xf = YCNTMAX ; }
  /* calculate */
  TMR1L = xf & 0xff ;
  TMR1H = xf / 256 ;
  /* enable decoder */
  XENA = OFF ;
  /* send sound 500ms */
  T1CON.TMR1ON = ON ;
  delay_ms(500);
  T1CON.TMR1ON = OFF ;
  /* disable decoder */
  XENA = ON ;
  /* delay */
  delay_ms(250);
}

 シーケンサで、LED点灯と音だしを処理したので
 シーケンサを動かすトリガーをボタンクリックで
 与えられるようにします。

 ボタンの状態に変化があったことを
 シフトレジスタを使って検出。

    if ( eflag.F0 == ON ) {
      /* clear flag */
      eflag.F0 = OFF ;
      /* shift */
      sft = sft * 2 ;
      /* mask */
      sft = sft & 3 ;
      /* get switch state */
      if ( XPSHS == OFF ) { sft = sft + 1 ; }
      /* judge */
      eflag.F1 = OFF ;
      if ( sft == ON ) { eflag.F1 = ON ; }
    }

 利用するブロックを定義したので
 ステートマシンを扱うコードを作成。

void main(void)
{
  /* user initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* shift register */
    if ( eflag.F0 == ON ) {
      /* clear flag */
      eflag.F0 = OFF ;
      /* shift */
      sft = sft * 2 ;
      /* mask */
      sft = sft & 3 ;
      /* get switch state */
      if ( XPSHS == OFF ) { sft = sft + 1 ; }
      /* judge */
      eflag.F1 = OFF ;
      if ( sft == ON ) { eflag.F1 = ON ; }
    }
    /* LED handling */
    if ( eflag.F1 == ON ) {
      /* run */
      plc(1);
      plc(2);
      plc(4);
      plc(8);
      /* exit */
      eflag.F1 = OFF ;
    }
  }
}

 音出しには、タイマー1のオーバーフロー割込みを使います。

 PIC12F629は、内部に4MHzのクロックジェネレータをもつので
 1MHzがタイマー1に入力されます。周波数を、タイマー1の
 オーバーフローで処理するとして、使う周波数を以下に設定。

#define XCNTMAX 65398 /* 450Hz */
#define YCNTMAX 65466 /* 900Hz */

 LED0を点灯したときに、高い周波数を出力し
 他では低い周波数を使います。




 シーケンサは、イベントフラグを利用して
 回すようにしておきます。これだとフラグ
 値を見るだけで、どのLEDを点灯するかが
 わかるので、ワンホットコーディングが
 できます。




 LEDは別基板にする条件で半田付けすると以下。



 スピーカとアンプを集めて、実装すると
 次のようにまとめられます。



 ファームウエアとしてまとめます。

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

#define OFF 0
#define ON  OFF+1

#define XSND  GPIO.B2
#define XENA  GPIO.B4
#define XPSHS GPIO.B5

#define CNTBEGIN 131

#define XCNTMAX 65398
#define YCNTMAX 65466

volatile UBYTE eflag ;
volatile UBYTE sft ;
volatile UBYTE loop ;
volatile UBYTE scnt ;
volatile UWORD xf ;

/* function prototype */
void init_usr(void);
void plc(UBYTE x);

/* interrupt handler */
void interrupt(void)
{
  /* timer 0 generate 1kHz */
  if ( INTCON.T0IF) {
    /* clear flag */
    INTCON.T0IF = OFF ;
    /* initialize */
    TMR0 = CNTBEGIN ;
    /* set flag */
    eflag.F0 = ON ;
  }
  /* timer 1 overflow */
  if ( PIR1.TMR1IF ) {
    /* clear flag */
    PIR1.TMR1IF = OFF ;
    /* initialize */
    TMR1L = xf & 0xff ;
    TMR1H = xf / 256 ;
    /* increment */
    scnt = scnt + 1 ;
    /* default */
    XSND = OFF ;
    /* sound out */
    if ( eflag.F1 == ON ) { XSND = scnt.F0 ; }
  }
}

void main(void)
{
  /* user initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* shift register */
    if ( eflag.F0 == ON ) {
      /* clear flag */
      eflag.F0 = OFF ;
      /* shift */
      sft = sft * 2 ;
      /* mask */
      sft = sft & 3 ;
      /* get switch state */
      if ( XPSHS == OFF ) { sft = sft + 1 ; }
      /* judge */
      eflag.F1 = OFF ;
      if ( sft == ON ) { eflag.F1 = ON ; }
    }
    /* LED handling */
    if ( eflag.F1 == ON ) {
      /* run */
      plc(1);
      plc(2);
      plc(4);
      plc(8);
      /* exit */
      eflag.F1 = OFF ;
    }
  }
}

/* define function body */
void init_usr(void)
{
  /* I/O state */
  GPIO = 0x10 ;
  /* I/O directions */
  TRISIO = 0xe8 ; /* bit0,1,2,4 as output , others as input */
  /* disable compare module */
  CMCON = 0x07 ;
  /* pull-up */
  WPU = 0x20 ;
  /* initialize Timer 0 */
  {
    /*
       4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
       125kHz/250 = 500Hz
    */
    OPTION_REG = 0x02 ;
    /* 256 - 131 = 125 */
    TMR0 = CNTBEGIN ;
    /* enable timer0 overflow interrupt */
    INTCON.T0IE = ON ;
  }
  /* initialize Timer 1 */
  {
    /*
       4MHz/4 = 1MHz -> 1MHz/8 = 125kHz
       125kHz / 880 or 440
    */
    T1CON = 0x30 ;
    /* enable timer1 overflow interrupt */
    PIE1.TMR1IE = ON ;
    INTCON.PEIE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
  /* clear flag */
  eflag = OFF ;
  /* others */
  sft = 0;
  scnt = 0 ;
}

void plc(UBYTE x)
{
  /* judge */
  if ( x > 8 ) return ;
  /* default */
  xf = XCNTMAX ;
  /* clear 74HC139 control bits */
  GPIO = GPIO & 0xfc ;
  /* turn on LED_3 */
  if ( x.F0 == ON ) { GPIO = GPIO | 3 ; }
  /* turn on LED_2 */
  if ( x.F1 == ON ) { GPIO = GPIO | 2 ; }
  /* enable LED_1 */
  if ( x.F2 == ON ) { GPIO = GPIO | 1 ; }
  /* judge */
  if ( x.F3 == ON ) { xf = YCNTMAX ; }
  /* calculate */
  TMR1L = xf & 0xff ;
  TMR1H = xf / 256 ;
  /* enable decoder */
  XENA = OFF ;
  /* send sound 500ms */
  T1CON.TMR1ON = ON ;
  delay_ms(500);
  T1CON.TMR1ON = OFF ;
  /* disable decoder */
  XENA = ON ;
  /* delay */
  delay_ms(250);
}

 パンケースの中に入れて使いやすくできます。




目次

inserted by FC2 system