光波スイッチを再現してみた

今回の回路を使われた場合の、誤動作や故障等に関しては一切責任を負いかねますので、あらかじめご了承ください。また、今回はこちらの環境の都合で "どこでも発車ベル" のソフトを使用せずに再現しています。何か進展あれば随時加筆していきます。

## 発車メロディのスイッチについて...
みなさん。発車メロディお好きですか?発車メロディといえば、車掌さんがこのようなスイッチを押して流しているのは、ご存知の方も多いと思います。特に以下の春日電機の動力開閉器(BSW215B3)が有名で、The 都会な東京や新宿から郊外各駅に概ね設置されています。この記事では、以降当該のスイッチを春日スイッチと呼称します。
※2023年9月記述時点。
[JRE MALL](https://www.jreastmall.com/shop/g/gS248-4573137241418/ "JRE MALL発売分") [Amazon](https://amzn.asia/d/1Mkjmum "Amazon発売分")
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/9f32acd7-3421-a0c5-c2b5-2a6ec3af4014.png"><img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/cefb0cda-1cf8-09e8-d606-9adcb49874f3.png">

#### 光波スイッチについて...
しかし、籠原駅や高崎駅など一部の駅では以下のスイッチが設置されており、製造元の会社名から通称:**光波スイッチ**と呼ばれています。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/e2b0d70a-bd28-4f55-74c7-735a13d29579.png)
#### 光波スイッチの動作
このスイッチは、前述の春日スイッチとは異なり、一つのボタンでON,OFFを兼任し、駅の信号(レピーター/出発信号)が開通(赤以外)していなければ、押してもメロディを流すことができない仕組みとなっています。この装置のボタンはタクトスイッチのように押している間だけ、スイッチがON状態となるものですが、動作的に一度の操作ではON状態を保持し、もう一度の操作でOFF状態となる仕組みとなっています。
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/482b157e-e533-2e31-7490-87f61a2b2019.png"><img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/2f0b7cf8-4cab-8622-8692-1385743c4c19.png"><img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/caeb072f-e5cf-65a2-fa0c-c8230aca2854.png">


春日スイッチは通販なりオークションなりでいくらでも手に入るけど、このスイッチは特注に近く個人での購入は難しい。同じものは無理だけどなんとか似たようなもの、再現してみたいなぁと前から思い、ほぼ似たようなスイッチ単体をアキバで購入したものの、放置プレイかましてしばらくしたある日。「そうだよ、ロジックIC使えばなんとか行けるんじゃないか?状態保持やリセットもロジックICならできそうだし、ググりながらシュミレーションしてまずやってみっか」と思い立ち、やってみたことを拙いながら書いておきます。なお、今回発車メロディ再生および発車放送のプログラムについては、どこでも発車ベルや類似したアプリなんてmac環境で動かすのめんどいので、スイッチの信号をArduinoを介してpcに接続して、 PCでメロディほか再生できる簡単なプログラムを作成しました。

## 部品一覧
※部品のリンク等は、いずれも記述時点のものです。
* OMRON A16-1(照光型)緑 / 回路図上``S1`` *[omronリンク](https://www.fa.omron.co.jp/products/family/1101/lineup.html)*
    * こちらの品は、部品本体にはA16-1としか記載されておらず、LED他部品を組み合わせて型番が確定するようですが購入当時の情報が散失しており、調べても、自分にはよくわかりませんでした...(ただ動作的には問題なさそうなのでここはスルーします。)
* 74HC74/Dフリップフロップ [秋月](https://akizukidenshi.com/catalog/g/gI-10879/)
* 小物ケース/キャンドゥ購入
* 3Pトグルスイッチ / 回路図上 ``SW1`` [秋月](https://akizukidenshi.com/catalog/g/gP-03913/)
* 2SC1815/npnトランジスタ x2
* TC7S14F/シュミットトリガインバータ [秋月](https://akizukidenshi.com/catalog/g/gI-14737/)
* SOT23変換基板 [秋月](https://akizukidenshi.com/catalog/g/gP-03659/)
* 連結ソケット(両端オスピン)6P [秋月](https://akizukidenshi.com/catalog/g/gP-03758/)
* LED x 2(できれば赤/緑1つずつ)
* 抵抗(330Ω x 3, 10kΩ x 3, 30kΩ x 1)
* 0.1μF 積層コンデンサ

## 回路
今回、回路のシュミレーションにはtinkercadを使いました。回路は主に4つの部分で構成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/6b002ccc-651c-05c2-2884-ae7013597609.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/0f221df1-7048-0f83-7003-96db1be2e8b1.png)
#### 信号連動部
まず、ブレッドボード左側のスイッチ``SW1``(シュミレーション上、DIPスイッチを代用)で、信号動作を再現しています。実物にはこのスイッチがリレーに置き換わっており、レピーター等の信号を入れているものと思われます。
このスイッチを<font color="#00ff00">**入れる**</font>ことで、<font color="#00ff00">緑のLEDが点灯</font>し、ロジックICへ信号を送ると(詳細後述)、ロジックICが動作可能となります。逆に<font color="#ff0000">スイッチを切る</font>と、スイッチ``S1``操作(クロック)に関わらず動かなくなります。なお、実物での停止状態では、<font color="#ff00">赤のLEDが点灯</font>するため、今回はこのスイッチの信号(緑のLED)の<font color="#ff00">NOT回路を組んで光らせて</font>ます。
#### スイッチ部
このスイッチ``S1``部分が今回、厄介だったところです。今回使用するボタンは、モーメンタリースイッチ、所謂タクトスイッチのようなものであり、スイッチではチャタリングという、人間感覚では普通に押したものでも、電気信号的には多くの波が立ってしまうという現象が起きます。スイッチ等をArduino等でいじる程度であればソフト側で書き~~誤魔化し~~ますが、今回は後述のロジックICに直接スイッチの信号を与える必要があるので、信号が乱れると誤動作の原因となるため、物理的に対応する必要があります。
* そこで、シュミットトリガ回路を入れることで、波形を安定させることができます(シュミレーション上では74HC14を使用していますが、これは実際つけた7S14Fの1回路だったものが6つに増えたバージョンと考えてください)。なお詳細については、割愛させていただきます。参考→[チャタリングを防止する方法|マルツオンライン](https://www.marutsu.co.jp/pc/static/large_order/1405_311_ph)
* 次に、今回使用しているスイッチS1にはLEDが組み込まれており、このLEDは後述のロジックICの出力(Q)を接続します。

#### ロジックIC部
では、今回の回路の要である74HC74/フリップフロップの動作について、以下の真理値表より見ていきます。なお、今回は上から2、3番目の状態は、使用しないため無視で大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/7e1f78c7-2900-d06b-a76e-27f4077e44c9.png)
回路図にもありますが、CKはスイッチ``S1``の信号、CLRは信号連動部の緑LEDの信号、DはICの前の信号の状態(~Q)をそれぞれ入力します。なお、PRは今回使用しないので、Vccを入れて常に"H"にしてます。
* まず、<font color="#00ff00">CLRの信号連動部のスイッチ``SW1``を開通(ON)状態にすると、下から2,3番目のいずれかの操作を受付状態となり、後述の通り動作させることができるようになります。</font><font color="#ff0000">一方、停止(OFF)状態にすると、CKのスイッチS1状態やQの状態に関わらず、常にOutputのQはL/OFF状態にできます。</font>
* 次にCK/クロックの部分は、通常クロック信号を与えて動作させることが多いですが、今回はスイッチ``S1``の信号を与えます。<font color="#00ff00">一度スイッチS1を押すと下から2番目の状態となり、OutputのQがH/on状態となります。</font><font color="#ff0000">もう一度押すと、先程の出力Qの反転信号がLなので、下から3番目のように、QがL/off状態となります。 </font>いずれの状態も、操作し終わったら、真理地表の一番下のように、その状態を保持してくれます。以下に、[falstad.com](https://www.falstad.com/circuit/circuitjs.html)の回路シュミレーターで簡易的に示したロジックICの状態を合わせて載せておきます。
* Output_QがHの状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/40599f7a-ba23-7bba-3ab6-fd6755a33777.png)
* Output QがLの状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/14940a09-dd0a-b583-90bf-85ce3ab9604e.png)





#### 出力部
ロジックICの出力ピン(Q)を、スイッチ``S1``の組込みLEDに接続し、それをさらに回路図上のT2/トランジスタのベースに接続し、Arduinoの入力ピン(今回はD8を使用)、Vccから持ってきた抵抗をコレクタへ、エミッタはGNDへそれぞれ接続することで、スイッチの状態をArduinoを介してパソコンに送ることができます。なお、シュミレーション/回路図上には記載していませんでしたが、このトランジスタのコレクタに、別途でスイッチを並列で接続することで、今回の光波スイッチの操作関係なく使用できるようになります。

#### PC/プログラム
最後に、Arduino及びmac上で使用したプログラムについてです。Arduinoでは、スイッチ入力をjsonで、シリアルへ出力するようなプログラムで、PC側はメロディ・放送を指定してから、スイッチの状態を受信して音源の再生をするプログラムとなっています。プログラムをそこまで作り込んだわけではないので、打ち返しや立川式他は一切想定してないです。~~(本当は以前別に作ったatos風シュミレーターで動かしたかったのが、なんかうまくいかなくてさじ投げたとは言えない)~~
プログラムについてはかなり適当に作っているのでコメント不足や、PC環境により適宜書き換えが必要な場所もあります。動作不良に関して一切の責任を負いかねます。悪しからず...
Arduino側
``` C:arduino.ino
// ピン指定
#define sw 8
String sw_status = "";
String serial_result = "";

// ピン&シリアル各種設定
void setup() {
  pinMode(sw, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop(){

  // スイッチ状態出力
  if(digitalRead(sw) == LOW){
    sw_status = "{\"sw\":\"False\"}";
    Serial.println(sw_status);
  }else if(digitalRead(sw) == HIGH){
    sw_status = "{\"sw\":\"True\"}";
    Serial.println(sw_status);
  }
  delay(500);
}
```
PC側
```Python:app.py
#ライブラリない場合はpip install xxxを実行
import serial
import pygame.mixer
from threading import Timer
import json
import os
from mutagen.mp3 import MP3 as mp3


arduino = serial.Serial()
arduino.baudrate = 9600

#arduino接続ポート自動判定(mac基準)
#https://qiita.com/usop4/items/9abfa1a4b6bf66a5f8fa
for port_url in os.listdir('/dev'):
	if"cu.usbmodem" in port_url:
		arduino.port = '/dev/' + port_url
		arduino.open()

#音源手前までのパス
moto_url = "~/Desktop/"

#メロディ単体のファイル名
melo = [
    "熊谷市歌A.mp3",
	"HANDS-大きな手から小さな手へ-verA[.mp3",
]
# 発車放送
atos = [
    "saki/3_1.mp3",
    "tuda/4_1.mp3",
]


pygame.mixer.init() #初期化
sw_state = 0
# 仮定義
melo_s = pygame.mixer.Sound(moto_url + melo[0])
atos_s = pygame.mixer.Sound(moto_url + atos[0])

#参考:https://qiita.com/week/items/ab190474eeb7c1fe9fc2
#https://gist.github.com/kekeho/c49bc090d1182eee44d51bc954bff520
#音源再生
def music(s, url, looptime):
	global moto_url
	s.stop()
	s = pygame.mixer.Sound(moto_url + url)
	s.play(looptime)
	return s
	#looptime = 2であれば2回ループ -1であれば無限ループ

#音源一覧表示
def listing_file(list):
	for x in range(len(list)):
		print("[" + str(x) + "]", end="")
		print(list[x])

#atos発車_threading Timer実行用関数
def atos_play():
	global atos_s, y
	atos_s = music(atos_s, atos[int(y)], 0)

listing_file(melo)
#メロディ音源指定
print("input melo num & atos num")
x = input()
old_x = x
listing_file(atos)
#発車放送指定
y = input()


try:
	while True:
        #arduinoスイッチ受信
		value = arduino.readline()
		json_dict = json.loads(value.decode())
		print(json_dict)
		print(json_dict["sw"])
		# time.sleep(0.05)
        #スイッチ状態振り分け
        #スイッチON時
		if json_dict['sw'] == "False":
			#roll_again = "yes"
			if sw_state == 0:
    			#メロディ再生(無限ループ
				melo_s = music(melo_s, melo[int(x)], -1)
				sw_state = 1
			print("sw ON")
			print("melo["+x+"]")
        #スイッチOFF時
		else:
			#roll_again = "no"
			if sw_state == 1:
                melo_s.stop()
                #発車放送再生(offから2秒後に)
				Timer(2, atos_play).start()

                #メロディ再選択
				listing_file(melo)
				print("input melo numbar, if end type 99")
				#print("now melody no is [" + x + "] /" + melo[int(x)])
				old_val = x
				x = input()
				if x == "":
					x = old_val
				elif x == "99":
					break
                #発車再選択
                listing_file(atos)
				print("input atos numbar")
				old_value = y
				y = input()
				if y == "":
					y = old_value
				sw_state = 0
				print(json_dict["sw"])
				print("sw OFF")
				sw_state = 0
			print("sw OFF")

#プログラム停止 Ctrl+C
except KeyboardInterrupt:
	melo_s.stop()
	atos_s.stop()
	arduino.close()
```

## 実機
前述のように、シュミレーション上で思い描く動作に持って来れたタイミングで、部品を回路図をもとに接続して、動作を確認しました。当初はスイッチの信号をそのままICに入れてましたが、実際には思った以上にチャタリングの影響がひどく、後からシュミットトリガについて調べて、回路に入れてたりします。~~この表面実装部品のはんだ付け、キーボードクラッシャーレベルで発狂しながらやってた。~~ また、スイッチの箱は当初は3Dプリンターで作るかなぁとも考えてましたが、色々めんどくなったので百均でサイズ的にいい感じの物入れで代用して穴開けて埋め込みました。
* ブレッドボード実験初期(シュミットトリガ回路設置前)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/d7cdb910-18b6-41b8-b807-349af8d63e57.png)
* シュミットトリガ入れた後のブレッドボード部分拡大。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/d79520ac-1e5d-97e3-407f-9d8f5639503f.png)
* 回路箱内詰め込み途上
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185343/f5c5fb85-d7ad-d0f2-09d6-26a66583209e.png)
* 実際の動作
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">一応の完成かな(LEDの明るさとかもうちょっと手直しいるところもあるけど) <a href="https://t.co/0MQ3sHFknD">pic.twitter.com/0MQ3sHFknD</a></p>&mdash; よーく@旅したい (@yogh8501_720) <a href="https://twitter.com/yogh8501_720/status/1700376226937049146?ref_src=twsrc%5Etfw">September 9, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## その後の追記...

12/8: 上記のpc側のpythonコードを一部修正し、打ち返しに対応

## 制作してみての感想
シュミレーションは比較的簡単に行ったものの、実際に部品で回路を組んでみると、部品のピン配置の勘違いという拙いミスや、チャタリングに関してはロジックIC使っている兼ね合いで舐めており、物理的になんとかしないといけないことがはっきりとわかり、積層コンデンサと抵抗だけで我慢するかこの際シュミットトリガつけるか迷いましたが、チャタリングに対してシュミットトリガーの偉大さを知ることができたのは、自分の中でも成長につながったのかなと思いました。
また、実際の機器では、メロディ再生用の信号以外に、電源、レピーター信号(今回はスイッチSW1で代用)が少なくとも必要となると思われるので、通常の春日電機スイッチに比べて使用コストや保守的にも大変なのかなと勝手に想像しました。先日、籠原の発車メロディのスイッチ故障で流さずそのまま発車するということがありましたが、本家のものの動作音的にレピーター信号のスイッチングにリレーを使用しているものと思われるので、この部分が壊れた可能性があります。そういったことを踏まえると、このスイッチも過去のものになる日が来るのかもしれません。
ただ、前にアキバでomronのスイッチを買ったものの、Arduino等を使ったソフト寄りの回答しか見出せなかったのが、今回物理的に作れたのは大きな達成感を感じました。