更新: 2005年12月10日
作成: 2005年12月3日
信号機の各ランプを制御する、制御基板本体を紹介します。設定を、ディップスイッチではなく、赤外線リモコンで行えるようにしたので、回路がたいへんシンプルになっています。リモコンで操作可能な機能は、すぐに信号を変えたり、信号が変わるまでの時間を変えたり、交差点の種類を変えたりと、あれこれありますので、ソフトウエアでいろいろと工夫をしています。
ちなみに、現在はパソコン用のマザーボードの箱の上が、交差点になっています。
こちらが、回路図です。
回路には、次のような特徴があります。
PIC16F628のI/Oピンを、ピン1つあたりランプ1系統にそのまま対応させています。
1つの系統でも、複数のLEDを駆動する必要がある(例えば歩行者用の青・赤はそれぞれ4灯ずつある)ので、トランジスタアレイを用いて、出力を増幅しています。トランジスタアレイは、複数のトランジスタが1つのパッケージに入っているもので、全体の部品数を大幅に減らすのに役立ちます。
LEDの駆動以外のI/Oは、赤外線リモコンからの入力が1系統と、ブザーまたは白色LEDに対する出力が1系統だけしかなく、とてもシンプルな構成になっています。
設定のためのディップスイッチはありませんが、PIC16F628が持つEEPROMに設定内容を保存できるので、いろいろと設定を変えて楽しめるようになっています。設定の操作は、赤外線リモコンからしかできないので、リモコンがないと設定を変えられないようになっています。本体だけでは、勝手にやたらといじれないという点では、本物の交通信号機と似ているかもしれません。
LEDがつながっている端子に、いろいろと名前がついていますが、次の意味があります。
最後の1文字は、色または右矢印を意味しています。
記号 | B | Y | R | X |
---|---|---|---|---|
意味 | 青 | 黄 | 赤 | →(右矢印) |
ちなみに、世間では青のことを「G」(緑)と書く場合もあるようですが、この作品では、交通信号機用の青緑色LEDではなく、真っ青な青色LEDを使っているので、「B」(青)と表記しています。
最初でも最後でもない文字列には、以下の意味があります。
記号 | A | AW | B | BW |
---|---|---|---|---|
意味 | 道路Aの車道 | 道路Aの歩道 | 道路Bの車道 | 道路Bの歩道 |
右矢印の回路にLEDがついていないのは、LED1つだけでは、きれいに見える矢印を作れなかったからです。電子回路としては右矢印用の回路と端子を作ってありますので、灯器さえ作れば、いつでも矢印がつけられるようになっています。
LEDに直列についている抵抗器は、LEDに流す電流を制限します。この作品では、それぞれの灯器の中に組み込んであります。
制御基板は、2階建てになっています。基板はそれぞれ、縦47mm、横72mmくらいの小さいのを使っています。
1階部分は、マイコンのPIC16F628やランプ出力のパワー素子などからなり、信号機の制御機能を担当します。左側のコネクタは、2階部分につなぎます。各ランプへのオン・オフの信号が出ています。
片面にだけ金属がついた、ユニバーサル基板を使いました。
基板からケーブルがのびていて、赤外線リモコンの受光部につながっています。
受光用のデバイスは、38kHz付近の赤外線信号を受信し、検波や波形整形を行った上で、マイコンに信号を届けてくれます。リモコンの光を受けやすい場所に置きます。
2階部分は、28個あるLEDへ向かうケーブルをつなぐためのソケットがメインです。コネクタがたくさん並んでいます。左側には、音響回路も乗っています。
両面に金属がついた、ユニバーサル基板を使いました。表と裏の両方に部品をつけるからです。
裏面には、1階部分とつなぐためのピンが出っ張っています。
1階部分と2階部分を分けた理由は、次の2つです。
基板のレイアウト図を紹介しましょう。グラフ用紙に手書きです。
こちらが、1階部分です。
薄くて見にくいですけれど、右側にマイコンがあって、左側にトランジスタアレイが2個あって、2つのトランジスタアレイに挟まれるように、2階につなぐコネクタが出ています。
小さくまとまったと思いますが、どうでしょうか。
こちらが、2階部分です。
基板の右側では、ひたすら1階から来た信号を横にのばして、コネクタに伝えています。左側が道A、右側が道Bになります。歩行者用の信号は、1本の柱に道Aと道Bの両方の灯器をつける場合があるので、左右でそれぞれ、道Aと道Bの青・赤を両方つないであります。
基板の左側に、音響回路を乗せています。メロディー用と鳴き声用が、1回路ずつあります。
2階のコネクタには、灯器から来るケーブルを取り付けます。ケーブルの先に、エナメル線をピンヘッダに半田付けしたコネクタを作りました。エナメル線を直接基板のコネクタにつなぐよりも、しっかりと確実に固定できます。
こちらが、制御基板本体のソースコードです。制御基板の1階部分にあるPIC16F628に書き込まれているものです。
ソースコード 051203a10.asm
プログラムには、著作権があります。個人的な趣味でしたら、どうぞご利用ください。それ以外の利用をご希望の場合は、事前にお問い合わせください。なお、このプログラムは、本物の交通信号機の制御を目的としたものではありません。実際の交通整理に使うことは、うっかり誤動作するなどして大きな事故につながる可能性もありますので、絶対にやめましょう。(というか、本物の信号機は、一般の人が趣味で作るわけがないので、注意を呼びかけることに意味があるかは不明です・・・。)
信号機としてランプをつけたり消したりする動作をリアルタイムで行い、同時に、赤外線リモコンから指令を受けたり、ブザーで設定の状態を鳴らしたりする内容になっています。
マイクロチップ社純正の開発環境「MPLAB」のバージョン6以降で使えます。
マイコンのコンフィギュレーションビットの設定例が、ソースコードの先頭に書いてありますので、参考にしてください。
ちなみに、制御基板の2階部分にある音声装置のプログラムは、1つ前のページに掲載しています。
一定の時間がたつたびに、信号機のランプをつけたり消したりして、信号機としての表示をする部分です。
特定の時間ごとに、決まった処理があります。
16分の1秒ごと
inctimerルーチンを実行する頻度です。ただし、16分の1秒ごとに必ず行うべき処理は、今のところありません。
8分の1秒ごと
ブザーの状態を更新します。例えば、短くくり返して「ピピピ」と鳴らす場合は、8分の1秒ごとに、オンかオフに切り替えるタイミングがあります(この場合は、1秒に4回鳴ることになります)。
4分の1秒ごと
歩行者用灯器の点滅状態を更新します。4分の1秒ごとに、オンとオフを切り替えるので、1秒に2回の頻度で点滅することになります。本物の灯器も、日本国内では、この頻度で点滅します。(シンガポールでは1秒に1回点滅、など、国によって違います。)
2分の1秒ごと
車道用灯器の点滅状態を更新します。1秒に1回の頻度で点滅することになります。この信号機では、交差点の一方を黄点滅、もう一方を赤点滅とする場合に、黄と赤が交互に光ります。
1秒ごと
信号機は、決められた秒数ごとに、表示する内容が変わります。ある状態が、あと何秒したら次の状態に変わるかを数える必要があり、この信号機では、残り秒数としてカウントしています。
残り秒数を毎秒1ずつ減らし、ゼロになったら、次の状態に信号機を進めます。状態ごとの、秒数や表示の内容は、マイコンのプログラムメモリにデータとして記録されています。
残り秒数が最初から0の場合は、秒数のカウントをせずに、ずっとその状態にとどまる「手動モード」となります。別の状態に変えるには、リモコンを操作する必要があります。
PICマイコンが持っているタイマー機能を使って、時間を計ります。命令の実行数で直接管理しているわけではないのいで、信号の表示を変えるべきタイミングが来ないうちは、リモコンの受信など、別の処理を行えます。
タイマ割り込み機能を使うと、よりプログラムをシンプルにできると考えられますが、このプログラムでは、16分の1秒ごとに発生する「タイマのオーバーフロー」を、条件分岐でときどき調べています。このような、事象の発生をときどき条件判断文でチェックする方法を、「ポーリング」と呼びます。
「シーケンス」は、信号機が、いつどのランプを光らせるべきかを、ど順序だてて記述したデータです。
ちょっとややこしい話かもしれませんが、光る順序などを改造したくなったときなどに、参考にしてください。
1つの状態ごとに、4つの値を持ちます。それぞれの値の詳しい意味は、下のほうに説明があります。
「青になって、黄になって、赤になって、相手の道路が青になって・・・」というように、信号機の動作は、いくつかの状態を順番に進むことで、成り立っています。
具体的には、下の表のような流れになっています。
状態番号 | 道A車道 | 道A歩道 | 道B車道 | 道B歩道 | 時間アドレス |
---|---|---|---|---|---|
0 | ○○● | □■ | ○○● | □■ | 59 |
1 | ●○○ | ■□ | ○○● | □■ | 50 |
2 | ●○○ | □ | ○○● | □■ | 51 |
3 | ●○○ | □■ | ○○● | □■ | 52 |
4 | ○●○ | □■ | ○○● | □■ | 53 |
5 | ○○● | □■ | ○○● | □■ | 54 |
6 | ○○● | □■ | ●○○ | ■□ | 55 |
7 | ○○● | □■ | ●○○ | □ | 56 |
8 | ○○● | □■ | ●○○ | □■ | 57 |
9 | ○○● | □■ | ○●○ | □■ | 58 |
0a | "GOTO 0" |
このように、表示すべき内容とその長さを格納したメモリアドレスを1組にして、連ねることで、信号機としての動作を記述できます。
シーケンスの最後は、先頭に戻る命令で終わります。
シーケンスの先頭は、この例では、0番になります。
状態0aの次、つまり状態0bからは、別のシーケンスが始まります。
スクランブル交差点のシーケンスや、押しボタン信号のシーケンス、点滅信号のシーケンスなど、合わせて8つのシーケンスを持っています。
各状態での表示内容は、プログラムメモリにデータとして記録されています。
1つの状態あたりで、次の4種類のデータを持ちます。
Aポートへの出力内容
マイコンのAポートから出す表示内容です。
ビット番号 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
内容 | - | - | (赤外線入力) | (ブザー出力) | 道A車道青 | 道A車道黄 | 道A車道赤 | 道A車道右矢 |
信号機の状態としてのデータは、ビット0からビット3までです。
シーケンスごとに、最後の状態の次には、そのシーケンスの先頭位置を意味する状態番号が入ります。シーケンスがここまで読み込まれると、記録された状態番号に、すぐジャンプします。
Bポートへの出力内容
8ビットとも、信号機のランプに対応しています。
ビット番号 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
内容 | 道B歩道青 | 道B歩道赤 | 道B車道青 | 道B車道黄 | 道B車道右矢 | 道B車道赤 | 道A歩道青 | 道A歩道赤 |
点滅状態
点滅するランプや、リモコンの赤ボタンによる強制的な状態遷移を許可するかを決めるデータです。値が1のとき、点滅、または許可となります。
ビット番号 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
内容 | 状態遷移許可 | 道B車道赤 | 道B車道黄 | 道B歩道青 | - | 道A車道赤 | 道A車道黄 | 道A歩道青 |
ビット7の赤ボタンによる状態遷移を許可するかのビットは、0になっていると、その状態では一切赤ボタンを受け付けません。この信号機では、黄信号のときなど、人為的にその状態の長さを変えることが、明らかに不適切と考えられるときに、このビットを下げています。
時間記録アドレス
その状態を、何秒間続けるかを記録する、メモリのアドレスが入ります。
16進数でH'50'からH'5c'までの範囲となります。リモコンなどで、各状態の時間を設定すると、設定した時間が、H'50'からH'5c'までの範囲にあるRAMに記録されます。シーケンスを記録しているROMでは、時間の秒数を直接持たず、対応するRAMのアドレスを記録することで、時間を可変としているのです。
アドレスを0とすると、シーケンスの「GOTO文」であるとみなされます。GOTO文は、状態がそこまで来ると、Aポートに出力すべき値に入っている値を、次のシーケンス番号とみなして、すぐにそのシーケンス番号へ状態を移行させます。シーケンスの最後に、そのシーケンスの先頭に戻るために、書きます。
状態ごとに持つデータとは別に、各シーケンスの先頭の状態番号を集めたデータもあります。このデータは、別のシーケンスに切り替えるときに、それぞれのシーケンスの先頭に移動するために使います。
この信号機のプログラムは、赤外線リモコン受信ルーチンがメインルーチン、信号機としての動作がサブルーチンという、ちょっと不思議な書き方になっています。
そうするのが、よいことなのかは定かではないですが、リモコンの受信プログラムを書くのが初めてだったので、そうしたようです。
「点灯したか」「消灯したか」で、ひたすらタイミングを計っています。
タイミングが早すぎたり、遅すぎたりしたら、受信に失敗したとみなして、mainloopに戻しています。
タイミングは主に、タイマTMR0の値がいくつ進んだかで見ています。TMR0は、4096分の1秒(0.244ms)ごとに1進むので、リモコンの信号を解析するには、そこそこ使える精度があります。
値が「1」か「0」かを見極める部分では、こんな処理をしています。
TMR0の値の変化と、実際に経過した時間との対応は、TMR0の値をチェックするタイミングによって、いくらかのずれがあります。そのため、正当とみなす値の範囲は、よく考えて決める必要があります。
このあたりは、割り込みを使うと、もう少し分かりやすく書けるのかもしれません。
リモコンで決めた設定は、リモコン操作により、EEPROMに記録されます。記録された設定内容は、電源投入直後か、リモコンでロードの操作をしたときに、読み込まれます。
記録する値は、0から7まで(ブザーを鳴らす回数としては1回から8回まで)の8種類しかありません。変数の値の確認を、ブザーを鳴らす回数で行っているため、値の上限を小さめにしたほうが、扱いやすいと考えたからです。
この信号機は、液晶ディスプレイなどの文字表示機能を持たないので、操作に対する応答は、ブザー(または白色LED)で行っています。
鳴った回数で情報を伝えるのが基本ですが、「何番の変数がいくつになった」のように、複数の情報を一度にまとめて伝える場合も、あります。
そこで、短く数回鳴らし、次に少し休んで短く数回鳴らす仕組みを作りました。
さらに、電源投入・セーブ・ロードなど、大きなできごとがあったときは、「ピー」と長く鳴らすようにもしました。
ところで、ブザーを鳴らす処理は、信号機の動作と同時並行で行う必要があります。
この信号機では、8分の1秒ごとにブザーを管理するルーチンを呼び出して、少しずつ処理を進めます。1回の呼び出して、8分の1秒ごとに行うべきことだけを処理して、すぐに別のルーチンに進めます。このため、現在の状態を保持する変数を、比較的多く持たせてあります。
信号機のプログラムでは、時間を計る部分が多くあります。
時間の計り方は、主に2つあります。
ループで命令実行数を数える
一定時間待つ必要がある場合などに、使います。ループを作って、待つ必要がある命令数だけ、回します。ループの中にいる間は、他のことはできませんが、決められた命令数を確実に実行すれば、待つべき時間だけ確実に待つことができます。
プログラムを足止めさせることで待つため、待っている間は、別のことができません。
ループ中に割り込みがあったり、ループ中に条件判断を行ってサブルーチンに行けるようにしている場合は、割り込みやサブルーチンに行っている間だけ、待ち時間が余計にかかることになります。
タイマの値を数える
プログラムを足止めせずに、かかった時間が分かる方法です。
PICマイコンには、タイマという特別なレジスタがあります。このレジスタは、値をプログラムから書き換えなくても、一定の時間ごとに、値が上がっていくものです。
ときどきタイマの値を読めば、前回読んだときの値と比べて、進んだ時間が分かります。
あまり長い間タイマを読まずにいると、タイマの値が一周するなどして、正しい時間が分からなくなることもあります。
タイマが繰り上がったときに変化するビットを読んだり、タイマの繰り上がりに対して割り込みを発生させたりすると、特定の間隔ごとに、特別な処理を行うプログラムが書けます。
リモコンを受信しながら、信号機を変えながら、ブザーを鳴らす、というように、この信号機では、3つの処理が同時並行で進んでいます。
でも、マイコンが同時に実行できることは1つだけです。短い間隔で、行う対象を切り替えることで、複数の処理を同時に行っているかのような効果が得られます。
同時並行でものごとを進めるには、こんな方法があります。
1つのことがメインで、暇なときは別のこともする
メインルーチンでやりたいことを集中して行い、暇なときに、別のことをします。
この信号機では、メインルーチンではリモコンの受信をしていて、タイマが繰り上がったときだけ、信号を変えたりブザーを鳴らしたりしています。タイマが繰り上がったかどうかを調べるのは、リモコンの受信で暇になっているときだけです。リモコンからの信号を受け続けていても、十分多くの暇な時間ができるようにしてあります。
特定の間隔ごとに、少しずつ処理を進めていく
一定の間隔ごとに、少しずつ処理を進めていく方法です。やるべきことが複数あっても、それぞれの処理がすぐに終わるようにします。
この信号機では、16分の1秒ごとに、サブルーチン inctimer を呼び出しています。inctimerでは、ブザーを鳴らしたり、信号機の点滅状態を更新したり、信号の状態の残り秒数をカウントしたりといった動作を、続けて行っています。
それぞれの機能は、ずっとその機能だけを実行し続けるのではなく、その時点で行うべきことを終えたら、すぐに次の機能に処理を移すようになっています。
ちなみに、パソコンなどの高度なコンピュータでは、1つの機能だけを実行し続けるようなプログラムを、同時に複数実行できるようになっています。OSと呼ばれる基本的なソフトウエアが、複数のプログラムを次々と切り替えながら実行しています。さながら、複数のコンピュータがあるように見せかけているようです。
おもちゃの信号機を作り、無事に動作させることができました。
街で売られていない交通信号機を部屋の中で楽しめる面白さと、赤外線リモコンで操作できてしまう意外性が合わさり、とても楽しいおもちゃになったと考えています。
実際の交通信号機は、もっと多くのランプを制御できるのも多いです。この作品では、全てのI/Oピンを使い切っていますが、もっと足の多いマイコンを使えば、さらに多くのランプを制御できるようになりましょう。
操作への応答が、ブザーか白色LEDだけなので、扱いにくさを感じるかもしれません。足の数が多いマイコンを使って、液晶ディスプレイをつけてみると、より面白くなるかもしれません。ただし、そのときには、ディスプレイの制御を、別の機能と同時並行で行う必要が出てきます。
本物の交通信号機は、他の信号機との連係プレーを得意としています。他の信号機と連動できるようにする機能や、連動して動作させるための制御装置などを作ってみると、楽しいかもしれません。
この作品では、押しボタン信号の機能を、リモコンの赤ボタンで模擬していますが、押しボタンスイッチや、人間センサーなど、いろいろな入力で信号を変えられるようにすると、面白いかもしれません。
本物の交通信号機は、誤動作を防ぐための機能が充実しているそうです。両方の道が同時に青にならないようにしたり、球切れを検知したりなど、信頼性を向上させるための機能を付け加えてみると、面白いかもしれません。
いろいろと改良の余地はありますが、個人の趣味としては、今くらいが落としどころかなあ、と私は思っています。
おもちゃの信号機を、実際に作ってみましょう。LEDを点滅させる作品は、PICマイコンの入門としてよく出てきますが、この作品は配線がとても多いので、全部作ろうとすると、けっこうはまるかもしれません。
本物の信号機と見間違えられるとたいへん危険ですので、屋外では絶対に使わないでください。
道路交通法第76条では、「何人も、信号機若しくは道路標識等又はこれらに類似する工作物若しくは物件をみだりに設置してはならない。」ことになっています。
この信号機のランプの直径は5mmですが、本物の信号機は1灯の直径が250mm(小)や300mm(中)や450mm(大)もあるので、本当に見間違えるかは、定かではありませんが・・・。
世の中には、珍しい動作をする信号機もあります。(○○●)交通信号機がすべてわかるページなどを参考にしながら、珍しい信号機の動作を模擬するおもちゃを作ってみてはいかがでしょうか。あるいは、身近にある、例えば毎日世話になっている信号機を参考に作ってみるのも、楽しいかもしれません。
みなさまのアイデアを盛り込んで、さらに面白い信号機のおもちゃを作ってみませんか。
前の記事: 音響信号機としての機能を搭載--自作交通信号機「ひかり201号」(2004-11-14)