目次

ゲート制御スケッチ

 角度を制御するには、サーボモータを利用します。
 サーボモータの動きが最もよくわかるのは、駐車場
 の出入口にあるゲートでしょう。



 サーボモータのワイヤーは、3ピンになっています。
  (電源、GND、信号の3ピン)



 サーボモータを動かすには、パルスを与えます。



 20ms周期で1ms〜2msの幅のパルスを利用し
 角度を制御します。従ってPWM波形を出力
 することになります。

 Arduinoには、サーボモータを利用するための
 ライブラリが用意されています。



 どういう関数を利用するか、回路図等は
 次のページで詳しく説明されています。



 ページの右にある関数リストは、ライブラリServoを
 利用することを宣言したときに使えます。

 サーボモータの信号ピンに、パルスを出力する
 には、analogWrite関数を使います。

 ライブラリServoを利用すると、1つのサーボモータを
 1つのオブジェクトとして扱います。Javaの仕様と同じ
 と考えれば、わかりやすいでしょう。

 端末から与えた角度で、サーボモータを0〜180度の
 任意の角度を形作るスケッチは、以下となります。

#include <Servo.h>

// pin assignment
#define SERVOPIN 9

#define DMAX 179
#define DMID 90
#define DMIN 0

#define INTERV 200

// create servo object to control a servo
Servo oneservo;

int  val;
char cmd ;
int  xinterval ;

void setup()
{
  // serial
  Serial.begin(9600);
  // attaches the servo
  oneservo.attach(SERVOPIN);
  // place 90 degree
  val = DMID ;
  oneservo.write(val);
  // delay counter
  xinterval = INTERV ;
}
 
void loop()
{
  // serial handling
  if (Serial.available() > 0) {
    // get command
    cmd = Serial.read();
    // judge increment
    if ( cmd == 'i' ) {
      // increment
      val++ ;
      // upper limitter
      if ( val > DMAX ) { val = DMAX ; }
    }
    //  judge decrement
    if ( cmd == 'd' ) {
      // decrement
      val-- ;
      // lower limitter
      if ( val < DMIN ) { val = DMIN ; }
    }
  }
  // impress
  oneservo.write(val);
  // delay
  delay(xinterval);
}

 90度の位置に動かし、コマンド'i'、'd'により
 角度を増減します。



 シリアルでの動作を確認できたなら、スイッチを
 利用して、ゲートの上げ下げを考えます。



 2つのスイッチをTOP、BOTTOMに対応させ
 0度か90度かを指定させます。

 バーの上下動を制御するようにスケッチを
 作成します。

 基本となる内容を考えます。

 スイッチの変化をとらえる
  スイッチを2つ利用するとして、押したときに
  ゲートバーの状態が変化させたいもの。

  シフトレジスタを利用して、スイッチの状態に変化
  があったとき、それを通知するようにします。

  タイマー割込みで、スイッチの状態を読み込んで
  シフトレジスタのLSBに付加してやります。

  ms単位のタイマー処理は、次のページに解説が
  あります。



  ライブラリをダウンロード後、ArudinoIDEのある
  ディレクトリのサブディレクトリlibrariesに
  展開して入れておきます。



  このページの情報から、タイマー割込みハンドラを
  定義して、そのハンドラが使えるようにすればよい
  ようです。タイマー割込みハンドラを定義します。

#define OFF 0
#define ON  OFF+1

#define MASK01 0x01
#define MASK03 0x03

void update_sw() {
  // shift
  tsft <<= 1 ;
  bsft <<= 1 ;
  // mask
  tsft &= MASK03 ;
  bsft &= MASK03 ;
  // get switch state
  if ( digitalRead( TBUTTON ) == LOW ) { tsft |= ON ; }
  if ( digitalRead( BBUTTON ) == LOW ) { bsft |= ON ; }
  // judge
  if ( tsft == MASK01 ) { tflag = ON ; }
  if ( bsft == MASK01 ) { bflag = ON ; }
}

  タイマー割込みハンドラの周期を設定し、割込みが利用
  できるようにsetup関数の中で、setとstartの2メソッド
  を使います。

    // 100ms period
    MsTimer2::set(100,update_sw);
    // enable 
    MsTimer2::start();

 状態管理
  タイマー割込みハンドラからフラグで状態変更が
  通知されるので、loopの中でサーボモータへの
  角度を指定します。

    フラグを監視し、対応するフラグでの通知が
  来たなら、角度数値を再設定します。

  処理は、非常に単純で、以下のようにします。

    // rise bar 
    if ( tflag == ON ) {
      // clear flag
      tflag = OFF ;
      // set 90 degree
      val = DMID ;
    }
    // fall bar
    if ( bflag == ON ) {
      // clear flag
      bflag = OFF ;
      // set 90 degree
      val = DMIN ;
    }

 必要な情報が整ったので、スケッチを定義します。

#include <MsTimer2.h>
#include <Servo.h>

// pin assignment
#define SERVOPIN 9
#define TBUTTON  10
#define BBUTTON  11

#define DMAX 179
#define DMID 90
#define DMIN 0

#define INTERV 200

#define OFF 0
#define ON  OFF+1

#define MASK01 0x01
#define MASK03 0x03

// create servo object to control a servo
Servo oneservo;

int  val;
char cmd ;
int  xinterval ;

byte tsft ;
byte bsft ;
byte tflag ;
byte bflag ;

// MtTimer2 interrupt handler
void update_sw() {
  // shift
  tsft <<= 1 ;
  bsft <<= 1 ;
  // mask
  tsft &= MASK03 ;
  bsft &= MASK03 ;
  // get switch state
  if ( digitalRead( TBUTTON ) == LOW ) { tsft |= ON ; }
  if ( digitalRead( BBUTTON ) == LOW ) { bsft |= ON ; }
  // judge
  if ( tsft == MASK01 ) { tflag = ON ; }
  if ( bsft == MASK01 ) { bflag = ON ; }
}

void setup()
{
  // pin assignment
  pinMode(TBUTTON,INPUT);
  pinMode(BBUTTON,INPUT);
  // attaches the servo
  oneservo.attach(SERVOPIN);
  // place 0 degree
  val = DMIN ;
  oneservo.write(val);
  // delay counter
  xinterval = INTERV ;
  // clear shift registers
  tsft = 0 ;
  bsft = 0 ;
  // clear flags
  tflag = OFF ;
  bflag = OFF ;
  // 10ms period
  MsTimer2::set(10,update_sw);
  // enable 
  MsTimer2::start();
}
 
void loop()
{
  // rise bar 
  if ( tflag == ON ) {
    // clear flag
    tflag = OFF ;
    // set 90 degree
    val = DMID ;
  }
  // fall bar
  if ( bflag == ON ) {
    // clear flag
    bflag = OFF ;
    // set 90 degree
    val = DMIN ;
  }
  // impress
  oneservo.write(val);
  // delay
  delay(xinterval);
}


目次

inserted by FC2 system