reiunivのアイコン画像
reiuniv 2020年12月30日作成 (2020年12月30日更新)
製作品 製作品 閲覧数 4355
reiuniv 2020年12月30日作成 (2020年12月30日更新) 製作品 製作品 閲覧数 4355

リレー80個とESP8266を使ってニキシー管時計を作った

リレー80個とESP8266を使ってニキシー管時計を作った

はじめに

リレー80個で構成したデコーダ回路でニキシー管の表示を制御する「リレーデコーダ式ニキシー管時計」を作りました。
だいたいの仕様はこちらです。

  • ニキシー管IN-14を8つ並べ、8桁の時計としました。
  • 表示モードは3種類あり、
    時刻モード(hh.mm.ss)、
    日付モード(yyyymmdd)、
    そして某アニメで登場したダイバージェンス風モード(1.048596)としました。
    また、モードの切替は側面のスイッチで切り替えるようにしました。
  • ESP8266のWROOM-02を使用しました。これは、Wi-Fi接続が可能であるためインターネットに接続しNTPサーバーから時刻を取得した。

※180 V近くの高電圧を扱うため、取り扱いには十分に注意しましょう。感電注意!

以前にYouTubeニコニコ動画に投稿した解説動画を元に記述しています。画像などはそのまま流用しています。

使用部品

2019年11月でのものであるため、販売が終了している部品もあります

部品名 型番/容量 秋月通販番号 個数
ニキシー管 IN-14 eBayで購入 8
抵抗 1/4W 680Ω R-25681 1
1/4W 1kΩ R-25102 2
1/4W 2.2kΩ R-25222 1
1/4W 470kΩ R-25474 1
0805 10kΩ 千石電商で購入 5
0805 22kΩ 千石電商で購入 8
0.15Ω 千石電商で購入 1
コンデンサ 400 V 100μF P-10604 1
400 V 4.7μF P-10600 1
0805 0.1μF P-13372 2
0805 330pF 千石電商で購入 1
0603 0.1μF P-12928 30
ダイオード 1N4148 I-00941 1
UF2010 I-00124 1
GS1010FL I-06014 80
インダクタ 220μH P-03059 1
トランジスタ 2SA1015 I-06734 1
TBD62783 I-11082 4
FET 2SK3234 I-00244 1
リレー 941H2C12D P-01228 80
IC NJM2360 I-12365 1
74HC595 I-10077 4
ピンヘッダ 両端ロング2x40 C-12180 2
2x40 C-00082 2
ピンソケット 2x20 C-00085 6
連結2x20 C-02485 4
足長10 mm 1x10 C-07199 4
丸ピンICソケット 1ピンSMD P-12368 744
スイッチ 縦タクト P-08077 3
横スライド P-08789 2
その他 WROOM-02 K-13646 1
DCジャック C-06568 1
3.3 VDCDCコンバータ K-09980 1
USBシリアル変換 M-08461 1

回路

ブロック図

簡単に示したブロック図はこちらです。
キャプションを入力できます
ACアダプタから12Vの電源を供給し、そのままの電圧でリレーに、180Vまで昇圧してニキシー管に、3.3Vまで降圧してWROOM-02にそれぞれ供給します。
ここからは、電源(昇圧、降圧回路)、制御、リレーロジック回路について解説をします。

昇圧,降圧回路

昇圧回路の回路図はこちらです。
昇圧回路
NJM2360を使用したチョッパ方式の回路を作りました。
出力付近の2kΩの可変抵抗を操作することで出力の調節が可能です。
この回路の入出力の関係(計算値)は以下の表になります。

入力電圧 12 V
出力電圧 180 V
出力電流 13.9 mA

ニキシー管は1つあたり1~2 mA程度の電流があれば十分ですが、8桁全てを同時に点灯させるスタティック点灯にしたかったため出力電流を13.9 mAと多めに取りました。

降圧回路は秋月電子のLXDC55を使用した3.3 V出力のキットを使用しました。
降圧回路のモジュール

制御

メインの制御にはWROOM-02を使用しました。
これはArduinoIDEで開発ができWi-Fiが使えて安価(秋月でDIP変換版が650円)なマイコンです。
WROOM-02
駆動には3.3 V電源が必要なため、降圧回路を用意しました。

マイコンからは、シフトレジスタ74HC595へ信号を送信し、トランジスタアレイTBD62783で信号のレベルを変換してリレーへ送ります。
信号は4ビットがニキシー管の1桁に対応しており、後述するリレーで構成されたデコーダ回路を通して変換されます。
WROOM-02への書き込みは、秋月電子のUSBシリアル変換モジュールを使ってPCからUSB接続で行います。
モード変換の際に使用するタクトスイッチを3つ用意し、それぞれでプルダウンしました。
制御部分の回路図はこちらです。
WROOM-02周りの回路
シフトレジスタとトランジスタアレイ

リレーロジック

リレーとは?

今回の回路で最も規模の大きい部分がこのリレーロジック回路です。
リレーとは、コイルを用いて電気信号を機械的な動きに変換し接点を物理的に開閉する部品です。
また、接点が移動する際に「カチッ」という音が鳴るため、今回のような時計に用いると秒針のような音が再現できます。
下の図はリレーの動作を表しており、矢印で示したコイルに電流を流すと接点が移動し赤色の接点同士が導通します。
リレーの動作
今回は、C接点2回路の941H-2C-12Dを使用しました。
C接点とは、先程の図のようにコイルがOFFで導通する接点とONで導通する接点の2種類がある形式です。これが2つあるため、C接点2回路のリレーと呼ばれています。
また、このリレーはコイルが12 Vで駆動するため「制御」でトランジスタアレイを通して3.3 V出力のシフトレジスタの出力を12 Vに変換しました。

ニキシー管を扱う際にはリレーを使わずにドライバICを使う方法もありますし、こちらのほうが主流です。
わざわざリレーでロジック回路を組むには以下のようなデメリットがあると考えます。

  • 物理的に接点が移動するため動作に時間がかかる

  • 音が鳴る

  • ハンダ付けの箇所が多い(ICをが16箇所なのに対して、ほぼ同じ動作をするデコーダ回路は合計で80箇所)

  • サージ保護のダイオードが必要
     
    しかし、リレーを使って回路を組むことのメリットとして、

  • ロマンがある

  • 音も見方を変えれば大きなメリット

があると考えています。

サージとは、リレーへの入力をONからOFFにした際にリレーに入っているコイルから発生する逆起電圧のことであり、高電圧なため半導体素子などを壊してしまう恐れがあります。
そのため、回路をサージから保護するために並列でダイオードを接続するなどの対策が必要になります。
サージ保護

リレーで論理ゲート

今回のリレーでは、NOTゲートとANDゲートを簡単に作ることが出来ます。

NOTゲート

コイルを入力、コイルOFFで導通する接点を出力とするとNOTゲートを作ることが出来ます。
リレーNOT[0]
リレーNOT[1]

ANDゲート

コイル部分を入力A、その他のリレー端子を入力B、出力とします。
リレーAND[0,0]
リレーAND[0,1]
リレーAND[1,0]
リレーAND[1,1]
図のように、入力A(コイル)と入力Bが同時にONになった時のみ出力に電流が流れます。
NOTゲートとANDゲートを組み合わせることでNANDゲートが作れますので、理論上ではあらゆるロジック回路を組むことが出来ます。

ニキシー管IN-14

今回使用したニキシー管IN-14は、入力電圧が180 Vのアノードコモンです。そのため、デコーダ回路は表示したいピンをGNDに落とすことで制御します。
また、0~9の表示の他に左右にドットがありこちらも制御できるようにします。

リレーでデコーダ回路

真理値表

論理回路を設計するにあたって、まずは真理値表を書いてどのような動作にするのかを決定しておきましょう。
入力をD,C,B,Aの4ビット、出力を1つとしたときのデコーダ回路の真理値表を以下に示します。

D C B A 出力
0 0 0 0 0
0 0 0 1 1
0 0 1 0 2
0 0 1 1 3
0 1 0 0 4
0 1 0 1 5
0 1 1 0 6
0 1 1 1 7
1 0 0 0 8
1 0 0 1 9
1 0 1 0 ドット左
1 0 1 1 ドット右
1 1 - - 消灯

このとき、「-」はドントケアとしました。

この表から直接リレーの回路を考えようとしても、ちょっと難しいです。
そこで、表を図のようにDC,BAで分割し同じ入力の組で色分けをしてみました。
分割した真理値表
分割した表を元に、それぞれのグループの動作をするロジック回路を構成します。

リレーロジックその1

DCグループでの動作をするリレー回路を図に示します。
DCグループ[0,0]
DCグループ[0,1]
DCグループ[1,0]
DCグループ[1,1]
BAグループにおいても、「12 V」の部分をGNDに置き換えたのみで全く同じです。

リレーロジックその2

DCグループの回路とBAグループの回路を分割した真理値表を元に組み合わせることで各入力に対する出力を決定します。
例を挙げると、入力が[0,1,1,0]のときDCグループの[0,1]の出力とBAグループの[1,0]の出力をANDゲートで組み合わせることで、[5]の出力が得られるようにします。
こうして作成したデコーダ回路は以下の図の動作をします。
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます
キャプションを入力できます

このデコーダ回路をニキシー管の桁数分用意しました。
デコーダ回路1つでリレーが10個、デコーダ回路を8つ作ったので全部で使用したリレーは80個です。

リレー部分の回路図はこちらです。
リレーロジックの回路図

プログラム

プログラムの全体の流れは[起動]→[Wi-Fiに接続]→[NTPサーバーで時間取得]→[シフトレジスタに送信]となります。
以下にプログラムを示しますが、あくまで手元の環境で探り探りで動けばいいやといった感じなので記述やアルゴリズムがめちゃくちゃだったりします。

ニキシー管時計のプログラム

#include <ESP8266WiFi.h> #include <time.h> #include <Arduino.h> #include <Ticker.h> #include <FS.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #define JST 3600*9 //標準時設定 Ticker ticker1; //割り込み設定 Ticker ticker2; int latchPin = 13; // SRCLK int clockPin = 12; // RCLK int dataPin = 14; // SER int sec0 = 0; int sec1 = 0; int sec2 = 0; int min0 = 0; int min1 = 0; int min2 = 0; int hour0 = 0; int hour1 = 0; int hour2 = 0; int year=0; int mon = 0; int day=0; int year1=0; int year2=0; int year3=0; int year4=0; int mon1=0; int mon2=0; int day1=0; int day2=0; int ran =0; int ranstart = 0; int rancheck=0; bool btnflg=false; int nixienum=0; int delaytime[20]={198,165,137,114,95,79,66,55,50,50,50,50,50,50,50,50,50,50,50,50}; time_t t; struct tm *tm; const char *ssid = "SSID"; //接続するWi-FiのSSID const char *password = "PASSWORD"; //接続するWi-Fiのパスワード void myshift(int bit,unsigned long val ){ //シフトレジスタ用 for( int i = 0; i < bit; i++ ) { if((val>>(bit-1-i))&1){ digitalWrite(dataPin,HIGH); }else{ digitalWrite(dataPin,LOW); } digitalWrite(latchPin,HIGH); digitalWrite(latchPin,LOW); } } void myclock(){ if(!btnflg){ if(nixienum==0){ t = time(NULL); tm = localtime(&t); //時間取得 sec0 = tm->tm_sec; sec1 = sec0%10; sec2 = sec0/10; min0 = tm->tm_min; min1 = min0%10;; min2 = min0/10; hour0 = tm->tm_hour; hour1 = hour0%10; hour2 = hour0/10; Serial.print(hour2); Serial.print(hour1); Serial.print("."); Serial.print(min2); Serial.print(min1); Serial.print("."); Serial.print(sec2); Serial.println(sec1); digitalWrite(clockPin,HIGH); myshift(4,hour2); myshift(4,hour1); myshift(4,10); myshift(4,min2); myshift(4,min1); myshift(4,10); myshift(4,sec2); myshift(4,sec1); digitalWrite(clockPin,LOW); }else if(nixienum==1){ t = time(NULL); tm = localtime(&t); //時間取得 year=1900+tm->tm_year; mon=tm->tm_mon+1; day=tm->tm_mday; year1=year/1000; year2=(year-year1*1000)/100; year3=(year-year1*1000-year2*100)/10; year4=year%10; mon1=mon/10; mon2=mon%10; day1=day/10; day2=day%10; digitalWrite(clockPin,HIGH); myshift(4,year1); myshift(4,year2); myshift(4,year3); myshift(4,year4); myshift(4,mon1); myshift(4,mon2); myshift(4,day1); myshift(4,day2); digitalWrite(clockPin,LOW); }else if(nixienum==2){ digitalWrite(clockPin,HIGH); myshift(4,1); myshift(4,10); myshift(4,0); myshift(4,4); myshift(4,8); myshift(4,5); myshift(4,9); myshift(4,6); digitalWrite(clockPin,LOW); } } } void randomout(){ for(int i=0;i<20;i++){ digitalWrite(clockPin,HIGH); myshift(4,random(0, 9)); myshift(4,random(0, 9)); myshift(4,random(0, 9)); myshift(4,random(0, 6)); myshift(4,random(0, 9)); myshift(4,random(0, 9)); myshift(4,random(0, 9)); myshift(4,random(0, 9)); digitalWrite(clockPin,LOW); delay(delaytime[i]); } } void numwrite(int num){ digitalWrite(clockPin,HIGH); for(int i=0;i<8;i++){ myshift(4,num); } digitalWrite(clockPin,LOW); } void setup() { //SPIFFS.begin(); //SPIFFSを開始 Serial.begin(115200); delay(10); pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); // prepare GPIO2 pinMode(16, INPUT); pinMode(5, INPUT); pinMode(4, INPUT); //digitalWrite(16, HIGH); //ticker2.attach_ms(200, randomout); numwrite(0); //ここからテンプレ Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println(WiFi.localIP()); //ここまでテンプレ Serial.println("getTime"); configTime( JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");//ntpサバにアクセス delay(1000); myclock(); Serial.println("WriteTime"); //ticker2.detach(); ticker1.attach_ms(100, myclock); //1秒毎に時間取得(ntpには1時間に1回(?)) } void loop() { if(digitalRead(16)==HIGH){ if(nixienum!=0&&!btnflg){ btnflg=true; randomout(); } nixienum=0; myclock(); } if(digitalRead(5)==HIGH){ if(nixienum!=1&&!btnflg){ btnflg=true; randomout(); } nixienum=1; myclock(); } if(digitalRead(4)==HIGH){ if(nixienum!=2&&!btnflg){ btnflg=true; randomout(); } nixienum=2; myclock(); } btnflg=false; delay(10); }

モード切り替えのボタンは側面に配置し、それぞれのボタンを各モードに対応させました。
側面のボタン
モードを切り替える際に、グラフのようにニキシー管のランダム表示の時間を変化させ段々と早くなるようにしました。
演出のディレイ

基板発注~組み立て

今回、回路図をKicadで作成したのでそのままPCBの設計に移りました。
基板をリレーロジック回路の層、電源&制御の層、ニキシー管を並べる層の3つに分けました。
発注先はFusionPCBで、$112ほどお金がかかりました。
基板が到着するまで10日ほどかかりました。
電源&制御の層
リレーロジック回路の層(裏面)
これらを組み合わせることでニキシー管時計の完成です。
キャプションを入力できます
動作している動画はこちらです。
https://youtu.be/xO3bj8Syb4U

あとがき

このニキシー管時計は構想から完成まで1年ほどかかり、PICマイコンでの制御やRTCモジュールを使用した回路を考えてみたりと試行錯誤の繰り返しでした。完成は1年以上前ですが、まだまだ沢山の人に見てもらいたくこの記事を書くことにしました。
こういった解説記事を書くことは初めてなので分かりづらい部分が多いと思いますが見つけ次第適宜修正していきたいと思います。

1
3
reiunivのアイコン画像
履歴書に「基本情報技術者」と書けるようになった大学院生
  • reiuniv さんが 2020/12/30 に 編集 をしました。 (メッセージ: 初版)
  • reiuniv さんが 2020/12/30 に 編集 をしました。
  • reiuniv さんが 2020/12/30 に 編集 をしました。
  • reiuniv さんが 2020/12/30 に 編集 をしました。
  • reiuniv さんが 2020/12/30 に 編集 をしました。
  • Opening
    3duilabのアイコン画像 3duilab 2021/01/17

    一個一個は簡単でもまとめて設計して組み立てるのは難しいし技術力が必要、デザインもいいです。リレーの音が時計っぽくていいです⏰😍

    0 件の返信が折りたたまれています
ログインしてコメントを投稿する