サーボモータを使って踏切の遮断機を動かしてみる!

電子工作

今回は、踏切の動作の要素として最後です。サーボモータを使って遮断機を動かします。

1.回路図

早速ですが回路図は以下になります。前回のものにサーボモータを追加しました。

サーボモータを動作させるのに、あまり理由はないですがライブラリを使わずに行おうと思って試行錯誤したのですが上手くいかず、さっさと諦めてライブラリを使うことにしました。

ライブラリはservo.hというのを使用しました。検索して多く出てくるのがこれでした。今回の踏切ではサーボモータは2個使う予定ですが、このライブラリを使うと複数個扱えるようです。(I/Oポートの数だけ?)

回路図上サーボモータを9ピンにつないでいますが、どこでも良いらしい?先に書いたようにライブラリを使うつもりがなかったので、ATmega328のTimer1(16bit)を使おうと思って、9ピンにしています。2個目は10ピンの予定でした。

2.踏切動作スケッチ ほぼ完成

ライブラリを使うとかなり楽ですね。あまり悩まずスケッチができました。それが以下です。

/*    踏切動作確認スケッチ
  *    Arduino Pro Mini 上位互換使用 (秋月電子)
  *
  *    警報灯と警報音の動作確認用
  *      ・警報灯はLED*2
  *      ・警報音はDFplayer mini を使用
  *      ・サーボモータで遮断操作
  *    
  *    2022年3月6日
  *    ~想・作★小・路~/シーゲル
  */

#include "DFRobotDFPlayerMini.h"
#include "SoftwareSerial.h"
#include <Servo.h>

const int DIN_PIN1 = 2;  //TSCから信号入力ピン想定:D2ピン
const int DIN_PIN2 = 3;  //TSCから信号入力ピン想定:D3ピン
const int LED_PIN1 = A2;  //LED出力ピン設定:A2ピン
const int LED_PIN2 = A3;  //LED出力ピン設定:A3ピン
     
long previousMillis1 = 0;    //前回時間1(初期値0)
long previousMillis2 = 0;    //前回時間2(初期値0)
long servo_on_timer = 4000;    //servo onまでの時間(msec)
long interval = 500;      //LED点滅間隔(msec)
volatile int flg = 0;     //フラグ
int ledState = LOW;       //LEDのON/OFFステータス

Servo servo;
  long count;
  long min_val = 60;      //サーボモータ回転角度
  long max_val = 120;     //サーボモータ回転角度
  int interval2 = 80;     //サーボモータの回転速度調整
  int servo_on = 0;
  unsigned long lastUpdate;

volatile int val1 = 1;    // 読み取った値を格納する変数(踏切入側センサー入力ピン状態)
volatile int val2 = 1;    // 読み取った値を格納する変数(踏切出側センサー入力ピン状態)

SoftwareSerial mySoftwareSerial(5, 6); // UART通信ピン(RX, TX)
DFRobotDFPlayerMini myDFPlayer;

void setup() {  
  mySoftwareSerial.begin(9600);    //シリアルポートの転送速度を9600bpsに設定
  myDFPlayer.begin(mySoftwareSerial);   //ソフトウェアシリアル通信開始

    pinMode( DIN_PIN1, INPUT );  //TSCから信号入力ピン
    pinMode( DIN_PIN2, INPUT );  //TSCから信号入力ピン
    pinMode( LED_PIN1, OUTPUT );  //LED出力ピン出力設定
    pinMode( LED_PIN2, OUTPUT );  //LED出力ピン出力設定

    myDFPlayer.volume(5);    //ボリュームの設定(設定値は0から30まで可)ここでは設定値5
}

void loop() {        

val1 = PIND & _BV(2);   //踏切入側センサー入力ピン状態
val2 = PIND & _BV(3);   //踏切出側センサー入力ピン状態

    /* 開始処理 */
    if(val1 == 0 || flg == 1){

        unsigned long currentMillis = millis();            //現在時間の取得
        
          if (flg==0){              //最初の1回目に再生開始、フラグを1(在線有り)にする
            myDFPlayer.loop(1);     //DFplayer on
            flg=1;
            previousMillis1 = currentMillis;   //サーボタイマー開始(4秒待ち)
          }

      /* 4秒待ち後サーボON */
      if(currentMillis - previousMillis1 >= servo_on_timer) {
         servo.attach(9);         //サーボモータ出力9ピンに設定
          servo_on = 1;
      }

      if(currentMillis - previousMillis2 >= interval) {     //現在時間から前回時間の差がimtervalの時間を超えると以下の処理を行う
        previousMillis2 = currentMillis;
        
        if (ledState == LOW){
          ledState = HIGH;
        }else{
          ledState = LOW;
        }

        digitalWrite(LED_PIN1, ledState);
        digitalWrite(LED_PIN2, !ledState);
      }
    }
   
    if(val2 == 0 && flg ==1){
        digitalWrite(LED_PIN1, LOW);   //LED_OFF
        digitalWrite(LED_PIN2, LOW);   //LED_OFF
          
          myDFPlayer.pause();   //警報音停止
          ledState = LOW;
          servo_on = 0;         //サーボモータ処理フラグを0にする
          val2 = 1;
          flg = 2;
    }

  if(servo_on == 1){                            //サーボモータ処理フラグが1だったら以下処理
    if((millis() - lastUpdate) > interval2) {
      lastUpdate = millis();

        if(count > min_val){
            count--;
            servo.write(count);
        }          
    }
  }
  
  if(servo_on == 0){                            //サーボモータ処理フラグが0だったら以下処理
    if((millis() - lastUpdate) > interval2) {
      lastUpdate = millis();
      
      if(count < max_val){
          count++;
          servo.write(count);
          if(count == max_val){
            flg = 0;
          } 
      }
    }
  }
}

実際に線路に組み込んで動作テストをします。

今回の動画を作成しました。ぜひご覧ください。

3.まとめ

これで踏切の一通りの動作が行えるようになりました。まだ単線一方通行しか対応できていません。これを複線で使えるようにさらにスケッチの追加が必要ですね。

ご覧いただきありがとうございました。次回は、TOMYTECのジオコレの踏切のLED点灯化、サーボモータを遮断桿とつないで開閉動作させる改造をしてみたいと思います。

コメント