踏切に必要なLEDと警報音を動かしてみる!

電子工作

前回は、車両の検知のセンサーを動かしてみたのですが、今回は警報灯(LED)の点滅と警報音を鳴らしてみようと思います。

それと前回書かなかったのですが、踏切、信号機を今後作るにあたり使用するのは、Arduino Pro Mini上位互換機(秋月電子)かArduino UNOで、最終的には基板を作って、AVRマイコン単品で動かそうと考えています。

また、踏切の電動化にあたっての最終目標は、

  • レイアウトに組み込む。
  • 複線使用するためのスケッチにする(逆走は対応しない)
  • サーボモータはレイアウト下に配置し見えないようにする。
  • ユニバーサル基板で作らず専用基板を起こす。

です。なおコストと手間は天秤にかけて判断します。

1.踏切の動作シーケンス

始める前に、踏切動作のシーケンスを考えてみたいと思います。言葉で書くと分かりづらくなるので図式にしてみました。こんな感じだと思います。

 今回の警報灯の点滅と警報音について、まず警報灯は赤いLED2個を交互に点滅させます。次に警報音ですが、ICで警報音を作り出す、録音して再生するの大きくは2パターンあるようですが、ICで作った音は好みではないので、録音したものを再生することにします。再生方法はマイコンでコントロールするのに比較的容易そうだったので、DFplayer miniというものを使用することにしました。DFplayer miniについては、Arduino Uno で動作させるブログも多く出ています。ユーザーが多い方が困ったときに調べやすいのでメリットと思います。

2.踏切の警報灯の点滅(LEDを交互に点滅)させてみる

警報灯の点滅の実験から行います。と言ってもLチカのちょっとした応用?でなので、大したスケッチではありませんが、以下に載せます。

お試し回路はこんな感じです。LEDは抵抗入りのものを使用します。動作のON、OFFは、タクトスイッチで、押すたびにON、OFFするようにして動作の確認を試したいと思います。(実験中にタクトスイッチがブレッドボードとの接触不良でうまく動作しないので、途中からワイヤーでスイッチ代わりにしています。)

/*    踏切動作確認スケッチ
  *   Arduino Pro Mini (秋月電子上位互換)  使用
  *
  *    警報灯の動作確認用
  *      ・警報灯はLED*2
  *    
  *    2022年2月27日
  *    ~想・作★小・路~/シーゲル
  */

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ピン
int flg = 0;  //フラグ

void setup()
{
    pinMode( DIN_PIN1, INPUT );  //TSCから信号入力ピン
    pinMode( DIN_PIN2, INPUT );  //TSCから信号入力ピン
    pinMode( LED_PIN1, OUTPUT );  //LED出力ピン出力設定
    pinMode( LED_PIN2, OUTPUT );  //LED出力ピン出力設定
    attachInterrupt(digitalPinToInterrupt(2),tcs1_vect,FALLING); //ピン変化割り込み設定:D2ピン
    attachInterrupt(digitalPinToInterrupt(3),tcs2_vect,FALLING); //ピン変化割り込み設定:D3ピン
}

void loop()
{
   if(flg == 1){                  //フラグが1だったら以下の処理を行う
  //LEDを交互に点灯
  digitalWrite( LED_PIN1, HIGH );  //LED点灯
  digitalWrite( LED_PIN2, LOW );   //LEDを消灯
  delay(500);                     //500ms経ったら
  digitalWrite( LED_PIN1, LOW );   //LEDを消灯
  digitalWrite( LED_PIN2, HIGH );  //LED点灯
  delay(500);                     //500ms経ったら
   }

   if(flg == 0){                  //フラグが0だったら以下の処理を行う
  //LEDを消灯
  digitalWrite( LED_PIN2, LOW );   //LEDを消灯
  digitalWrite( LED_PIN1, LOW );   //LEDを消灯
   }
}

/* ピン変化割り込み処理 */
void tcs1_vect(void)
{
 flg = 1;     //フラグを1にする
}

void tcs2_vect(void)
{
 flg = 0;     //フラグを0にする
}

3.踏切の警報音を追加して、警報灯と一緒に動かしてみる

DFplayer miniは、動作はマイコンとUARTとという通信方式で制御します。Arduinoだと簡単に制御できそうです。値段は秋月電子で1000円/個ちょっと、Amazon(300円/個程度)などで購入できます。Amazonだと安く買えるのですが、今回は秋月電子で購入しました。

それからDFplayer miniとの接続はUARTを使用しますが、マイコンからDFplayer mini、DFplayer miniからマイコンへの往復2線で接続します。

ですが、今回は、再生と停止の操作しかしないので、マイコン(TX)からDFplayer mini(RX)の接続のみにしています。また、マイコン、DFplayer miniとも5Vで駆動しますが、信号線は3.3V駆動らしいので、間に1kΩの抵抗を入れています。この辺りは多くの方がブログで説明されていますのでそちらを参照してください。

スケッチはこんな感じです。警報音を動作させるスケッチを書くにあたり、LED点滅だけの場合と比較してピン変化割り込みをやめています。理由はうまく反応しなことが度々ありました。原因はよく追えていません。あくまで対処療法です。(かなり適当・・・)

 /*    踏切動作確認スケッチ
  *   Arduino Pro Mini (秋月電子上位互換)  使用

  *
  *    警報灯(点滅はDelayを使用)
  *       ・警報灯はLED*2
  *    警報音
  *       ・DFPlayer miniで再生する
  *    
  *    2022年2月27日
  *    ~想・作★小・路~/シーゲル
  */


#include "DFRobotDFPlayerMini.h"
#include "SoftwareSerial.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ピン
volatile int flg = 2;  //フラグ

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

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

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

    mySoftwareSerial.begin(9600);    //シリアルポートの転送速度を9600bpsに設定
    myDFPlayer.begin(mySoftwareSerial);   //ソフトウェアシリアル通信開始
    myDFPlayer.volume(5);    //ボリュームの設定(設定値は0から30まで可)ここでは設定値5
}

void loop()
{
  val1 = digitalRead(2);           //D2ピンの状態を読む
  val2 = digitalRead(3);           //D3ピンの状態を読む
     
   if(val1 == 0){                  //踏切入側センサー入力ピン状態がLOW(0)だったら以下の処理を行う
  myDFPlayer.loop(1);              //DFPlayer mini 1Trk再生
  flg = 1;                         //フラグを1にする
   }

   if(flg == 1){
  //フラグが1の間、LEDを交互に点灯
    digitalWrite( LED_PIN1, HIGH );  //LED点灯
    digitalWrite( LED_PIN2, LOW );   //LEDを消灯
    delay(500);                      //500ms経ったら
    digitalWrite( LED_PIN1, LOW );   //LEDを消灯
    digitalWrite( LED_PIN2, HIGH );  //LED点灯
    delay(500);                      //500ms経ったら
   }

   if(val2 == 0){                    //踏切出側センサー入力ピン状態がLOW(0)だったら以下の処理を行う
    flg = 2;                         //フラグを2(1以外)にして、LED点滅停止
    digitalWrite( LED_PIN2, LOW );   //LEDを消灯
    digitalWrite( LED_PIN1, LOW );   //LEDを消灯
    myDFPlayer.pause();              //DFPlayer mini 1Trk一時停止
   }
}

実配線は、以下のような感じです。(注:いろいろ検討しながらだったので、余分な配線、抵抗がついたままになっています。)

ここで動作確認して問題が発覚!動作をさせるときは良いのですが、動作を止める際に何度かOFF動作をしないと動作停止しません。今回ピン変化割り込みは使っていないのでそれとは別要因です。憶測ですがLEDの点滅にDelayを入れています。Delayしている間はマイコンが動作を受け付けないことになるので、その為だと思われます。

なので、Delayをやめてmillisを使うように変更しました。これでOFF動作が確実に行えるようになりました。以下がmillisに置き換えたスケッチです。

/*    踏切動作確認スケッチ
  *   Arduino Pro Mini (秋月電子上位互換)  使用
  *     
  *    警報灯(点滅はmillis関数を使用)
  *       ・警報灯はLED*2
  *    警報音
  *       ・DFPlayer miniで再生する
  *    
  *    2022年2月27日
  *    ~想・作★小・路~/シーゲル
  */


#include "DFRobotDFPlayerMini.h"
#include "SoftwareSerial.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ピン
volatile int flg = 2;  //フラグ

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

unsigned long startTime;  
unsigned long currentTime;
const unsigned long interval = 500;
int ledState = LOW;

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

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

    mySoftwareSerial.begin(9600);    //シリアルポートの転送速度を9600bpsに設定
    myDFPlayer.begin(mySoftwareSerial);   //ソフトウェアシリアル通信開始
    myDFPlayer.volume(5);    //ボリュームの設定(設定値は0から30まで可)ここでは設定値5

    startTime = millis();  //initial start time
}

void loop()
{
  val1 = digitalRead(2);           //D2ピンの状態を読む
  val2 = digitalRead(3);           //D3ピンの状態を読む
     
   if(val1 == 0){                  //踏切入側センサー入力ピン状態がLOW(0)だったら以下の処理を行う
  myDFPlayer.loop(1);              //DFPlayer mini 1Trk再生
  flg = 1;                         //フラグを1にする
   }

   if(flg == 1){
  //フラグが1の間、LEDを交互に点灯
    currentTime = millis();
    if (currentTime - startTime >= interval)
    {
        startTime = currentTime;

      if (ledState == LOW){
        ledState = HIGH;
      }else{
        ledState = LOW;

      }

      digitalWrite(LED_PIN1, ledState);
      digitalWrite(LED_PIN2, !ledState);
   }

   if(val2 == 0){                    //踏切出側センサー入力ピン状態がLOW(0)だったら以下の処理を行う
    flg = 2;                         //フラグを2(1以外)にして、LED点滅停止
    digitalWrite( LED_PIN2, LOW );   //LEDを消灯
    digitalWrite( LED_PIN1, LOW );   //LEDを消灯
    myDFPlayer.pause();              //DFPlayer mini 1Trk一時停止
   }
  }
}

4.まとめ

今回警報灯と警報音の動作スケッチを作成しました。これで一歩踏切の実現に近づきました。ピン変化割り込みがうまく使えなかったのがよくわかりませんでしたが、今後原因が何かを見ていきたいと思います。それとDelayは使い方を考えないとマイコン動作に影響を与えるので、今後はそこをよく考えながらスケッチを書くという教訓になりました。

最後に上記のお試し実験を行っているところと、実際にTOMIXのTCSセンサーを使い、エンドレスのレールに組み込んだ動画を作成しました。こちらもご覧ください。

ご覧いただきありがとうございました。次回は、踏切の遮断桿(サーボモータ)の動作を見ていこうと思います。

コメント