ブレッドボードでの大体の実験を終え、実際の製作に取りかかっています。
まず、基板。秋月で買った超大型両面ガラス・ユニバーサル基板はこれでもサイズが足りないので大型両面ガラス・ユニバーサル基板これも購入。んで連結。
超大型の方は横、大型の方は縦にしてくっつけていますが、微妙に縦幅が違うので基板が変な格好になってます。
下にある緑色の基板はFoneraの基盤です。ヒートシンクの下にあるのがたぶんCPUでしょう。電源は共用できそうです。下敷きになっているのは450mm×300mmの塩ビ板です。基板の横幅はほぼぴったり、45cmあります。
LED以外の部品はすべて裏面に実装します。
裏面(部品面)から見たレイアウトはこんな感じ。
LEDをいくらか取り付けてみたらこんな感じ。
表面は表示が際だって見えるように黒くマジックで塗りつぶしました。なんか汚いですが、上からスモークの塩ビ板をかぶせる予定なので気にならないと思います。
左下にあるのは丸七というところが輸入した(?)100円ショップで買った中華製ステレオスピーカーから取り出したスピーカー本体。ものすごく安物な代物でコーンがプラスチックフィルムでできていますが、鳴らしてみたらなかなかいい音で鳴ってくれて、しかもちっこいのでこれを使うことにしました。秋月にあったこれよりも全然いい音で音量も出ます。これだけちっこいので低音はさっぱりですが。ステレオスピーカーなので二個入り。
FONとPICの間はUARTによるシリアル通信なのですが、USB-to-Serial経由でパソコンをつないでデバッグしたいときに配線を切り替えて使うのが面倒かなと思ったので、というか買った12F629を何かに使ってみたかったので、UARTのリダイレクタを作りました。
12F629は8ピンなので、電源を除くと6ピンしか余っていません。三つの機器のRXとTXそれぞれで6本使いきります。なので外部オシレータを使えないので内蔵オシレーターを使います。
条件によってピンとピンの間をハードウェア的に結線するなんていう芸当はこのPICには難しいので、ソフトウェア的に中継を行います。入力端子をとにかくとにかくポーリングしまくってそれを出力端子に出す感じ。
9600bpsで通信を行うと、マークやスペースの幅は約0.1msになるのですが、最低でもこの間に3点はサンプリング&出力を行いたいですね。PICの命令サイクルは内蔵オシレータ4MHzの場合は1μsなので、すると約33サイクルで1回はサンプリング&出力を行わないとなりません。さらには機器が切断されたかどうか、接続されたかどうかの検知も行わないとならないのでやや面倒です。
結局は、いろいろ最適化したら10~15サイクルでサンプリング&出力するようにできました。シリアル通信の波形はややタイミングがずれたような、タイミングが一定しないような信号になるはずですが、問題ないようです。19200bpsぐらいまでは対応できるようです。
歩調同期方式のシリアル信号は、接続されているけどデータが来ない時は、データの代わりにストップビットが連続して来ています。ストップビットはレベルとしてはHになります。入力端子はプルダウンしておくので未接続の場合はLになります。これで接続を検知します。データが来るとLにもなりますが、歩調同期の場合は連続してデータが送られてきても必ずストップビットが途中にはいるので、適切にタイムアウトを設けておけば切断を誤検出することはありません。ブレーク信号 (Lが長期間続く) を中継することも考え、切断検出のタイムアウトは2.6秒にしてあります。
音を鳴らすにあたっては、ゴーンという鐘のような音をならしたい訳です。前からFM音源が金属音の表現に適していることは知っていたので、じゃあFM音源でいこう!ということになりましたが、FM合成の原理をしりません。しばらくWebでお勉強。
アルゴ算法堂 - PICピコピコ やPIC AVR 工作室 実験くん マイコンでFM音源がとても参考になります。
今回は8ピンのPICを使ってみることにしました。

PIC12F683です。ちなみに初回電源投入時に僕にVSSとVDDを逆に扱われて臭い匂いを発しながらも壊れなかった偉い奴です。
PICですからそんなにまともな計算はできません。PCMの時点で 8bit, サンプリング周波数はタイマー1の周期である約20kHzぐらいならばいいかなーと。PWM周期は、精度8bitの場合は78kHzぐらいになるようで、十分可聴周波数外なのでOKです。20kHzの方はギリギリ可聴周波数なので、出力にはナイキスト周波数付近である10.6kHzあたりにカットオフ周波数を持つ簡単なLPFを入れます。
音が鳴るぜ!
まぁ最初からいきなり簡単になったわけではありませんでしたorz
まず、最初、音がすごい汚い。何でだろうなーとおもっていろいろ調べていると、どうもちゃんとPWMがベースにしているタイマー2にちゃんと同期したタイミングでPWMのデューティー比を設定してやらないとノイズが乗るようです。これはデューティー比を設定する前にTMR2のオーバーフローまで待つことで回避。
そして、やっぱりPICの出力ぐらいだとダイナミックスピーカーを駆動するには足りないようです。2SA1015と2SC1815で適当にプッシュプル増幅回路を組んでやったらある程度大きくなりました。
んで、どうせ一時間に一回ぐらいしかならない時報、PICがずっと動いてるのももったいないので、外部から「鳴れ!」の信号が無いときはsleepしてるようにしたのですが、そのときに、それまでデューティー比50% ( すなわち 無音、0V ) で動いてたPWMも停止してデューティー比 0% になるので、sleepするときに「ブツッ」という音が入ってしまいます。これはsleepに入る前に徐々にデューティー比をゆっくり0%に落としてからsleepすることで回避。
こんな音がなります (OggVorbis)。スピーカーへの出力端子から録音したものです。
なんか意図した音と違いますが、それっぽい音になってるのでよしとしましょう。
それと、八潮にある秋月電子に行ってきました。本店と違って広くて静かで空いてます。車でもいけます。うちからだと車でも1時間かかるので微妙ですが。
LEDにかぶせる光拡散キャップを買ってきました。
右がかぶせた物、左がかぶせないものです。横から見てもはっきりと光ってるのが見えるようになります。Good.
うめさんはPICが結構電流ながせるから、PICをドライバにしたら?とか言ってましたが、つい先日それをやめたばかりですwwww
たしかに110円とかで手に入るPICやAVRはいい選択肢になるとはおもいます。標準ロジックの8回路入りラッチを探しに千石にいったら130円とかしてるんですわね。んで先日秋月でAVRのATTINY2313-20PUが100円だったので10個買っておいたのを思い出して買うの止めました…ちなみに4017も100円でした。
まあ、それはともかく、回路はカソードコモンにして、カソード側には1.5Aまで流せるMOSFETであるTND012NMを、アノード側には2SA1015を使うことに。
買ってきたLEDはこんなやつ。まるで宝石見たいですね。
この駆動回路で点灯させるとこんな感じ。
このLEDは秋月で100個単位で安売りされているやつなんですが、かなり指向性が高くて、光軸がずれると写真のように極端に輝度が落ちます。
時計なので正面だけではなくて横から見てもちゃんと読めることが重要な訳なんですけどね。
横からみたかんじ。まあ光ってるのが見えなくもない。
これを嫌って、表面を擦ろうかと紙ヤスリをかってはみたものの……256個のLEDを擦りきれるきがしません。LEDにかぶせるカバーなどでなんとか工夫しようかなと思います。
光拡散キャップ あー。一個4円だったか。LED本体と同じだw 4円だったら使っちゃおうかな。
次は。音だ。時報をスピーカーからならしたい。ベルの音で。
前までは、メインのPIC16F887でドットマトリクスLEDの制御とFonからのコマンド受付を、PIC16F716かPIC16F628Aを6つつかって、時分秒の7セグLEDの制御をスタティック駆動で行おうと思っていましたが、何となくかっこ悪いと思ったので、7セグLEDをダイナミック駆動にしてメインのPIC16F887に統合してしまおうと考えました。
前までは、ドットマトリクスLED(16×8)の行に8ピン、桁に16ピンを使っていたため、A/Dコンバータ関連やUART関連を含めると、さらに7セグLED用のピンを出すのがちょっと難しかったのです。
で、ドットマトリクスLEDの行制御用の8ピンなんですが、8ピンがそれぞれ順番に1になるのを繰り返すだけなのでちょっと無駄なわけです。製作例でよく見かけるのが74138や74154 (それぞれ3-to-8 decoder, 4-to-16 decoder) を使ったやつですが、僕は昔から大好きな4017を使って見ました。
4017はクロックを入れるとその度に10本あるピンが一つずつ順番にHになり、他はLになってるICです。
なのでPIC16887からの信号線は1本でよく……とはならなくて、いちおう4017をリセットしてやらないと4017の状態を制御できないのでリセット用の信号と合わせて2本になります。上の写真で左のPIC16F887から右のちっこい4017に二本伸びてるのがそれ。
おかげで7セグ駆動用のピンを空けることができました。
4017はドットマトリクスLEDの行制御にも、7セグの桁制御にも使います。
「木」と「雲」です。う○こではありません。
4017 が8本のピンを一回りするのは一秒間に76.2回です。要するにこれが垂直同期周波数みたいなものです。ほんのちょっと、視線を動かした時とかにチラつきが気になる感じですが、これ以上周波数をあげられません orz
というのも、さらにPWMで輝度制御を行っているからです。
今のところ輝度は33段階で制御を行ってます。PICは20MHz駆動、この場合タイマは最高で約20KHz周期で割り込みをかけることができるのですが、この割り込みごとに点灯制御をおこなうとなると、人間の目にチラつきが見えにくくなる大体60Hz以上をキープするとなると、キリのいい数値が76.2Hzということになります。76.2Hz×8(ライン)×32(PWM制御のステップ数)≒20kHzということです。
これ以上周波数をあげるとPWM制御を荒くしなければならなくなります。ということでこの形に落ち着いています。
ちなみにタイマ割り込みでプロセッサ時間の90%ほどを使ってしまってるようです。最適化したいけどsdccでC言語で書いてるうちはこれ以上は無理。

PWMでは、LEDのクロスフェード表示と、部屋の明るさによる輝度調整を行うつもりです。上はそのためのCdSセル。
ということでいろいろ機能を詰め込んだらPIC16F887のRAMが足りなく…orz
sdccやめてアセンブリ言語で書けばいいのかも知れませんが死にます。嫌です。
次は7セグLEDのドライブ回路の実験に入ります。
何せ一つの桁で7*6=42個のLEDがつきます。一つのLEDに8mA流したとしても、全点灯させると336mA流れるので、2SC1815ぐらいだと足りないようです。ってか16×8のドットマトリクスLEDぐらいでも足りませんでした(ので2SC2120を使ってます)。
僕は論理回路はそれなりに分かるのですがトランジスタとかアナログ回路とかさっぱりなのでうめえもんに聞きながら頑張ります……。
秋月でCMOS温度センサーを買っておいたのでいざつけようとしてデータシートを読んだら、出力が大体1〜2Vの間なんですね。
PICのADコンバータは、VREF+とVREF-として外部から上限と下限の基準電圧をあたえ、その間を計測することができるので、この基準電圧をまずつくらなければ、となりました。
最初ツェナーダイオードを使おうかとおもったんですが、うめさんが三端子レギュレータでいいんじゃね?というので3.3Vの三端子レギュレータを買ってきました。
1Vと2Vは酸化金属皮膜抵抗による抵抗分圧回路で作ろうと思いました。1V側を 10k + 22k 、2V側を10k + 16k で作ろうと思ったのですが10kを一本しか買ってこなかったorz
秋月のセンサーに100kと200kの抵抗がついていたのでそれで1V側を作ることにしました。
しかしPICにつないでもADコンバータの出力の値がふらふらして、ぜんぜん安定しない。ちゃんとセンサICの出力をテスターで測っても温度に応じた数値がでてくるのに。おかしーなー、プログラムのせいかなー、とかいろいろ考えているうちに、ふと温度センサの出力とGNDの間に0.1μFをいれてみたら、見事に安定しました。基準電圧の方も同様に入れたらさらに安定しました。なんと。
センサまわり。結局、分圧用の抵抗は100k程度の値の物でもよいようです。
温度計モードです。読み出した値をfloatで処理しようとしたらRAMがあふれてしまったので固定小数点数で計算してます。
校正はしてません。まあ、校正値はEEPROMにでも突っ込めるようにしておけばいいですね。
ふー
疲れた。
マトリクスLEDのテストをするために配線をしました。これがつかれるorz 上の写真は、マトリクスLEDを取り外したブレッドボード。
以前H8で32x16(しかも二色LED)のマトリクスLEDを制御しようとして配線した時はワイヤリングペンで配線しましたが、さながら配線面がスチールウールになってました。それよりは今回はマシですが、ブレッドボードに実装した時点でもうこれでいい気分になります。もうやりたくない、みたいな。
表示させてみるとこんな感じです。
日付の表示と
曜日と天気の表示を交互にさせたいとおもいます。天気はインターネットから自動的に取得して。
マトリクスLEDを制御するプロセッサはPIC16F887を使っています。メインプロセッサとして使い、UARTによる通信機能を持っています。
とりあえずコマンドを叩くと反応するようになっています。こんな感じで。
> get-version
Revision: 13
ok
> seasdfasdfa
error
> set-week-weather 4 5
ok
> show-matrix 30
ok
> set-week-weather 3 3
ok
> show-matrix 30
ok
> set-date 12 23
ok
> show-matrix 39
ok
> set-date 12 21
ok
> show-matrix 39
ok
ブレッドボードではパソコンとつないでデバッグをやっていますが、本番ではFoneraとつながって、Foneraから表示コマンドを受け付けるようにします。
いまのところのソースはこちら。修正BSDライセンスにしました。
んまあカオスってほどじゃないんですが……。
PICを3つ使って見ました。
上の二つはまったく同じプログラムが書き込まれているPICです。今回は6桁分の7セグLEDを制御するためにPICを6個使います。メインのプロセッサからの通信はシリアル通信でバスを形成するようにしようとおもっていますが、そうなるとそれぞれのPICを識別するIDが必要になります。が、それぞれに一個一個違うIDを書き込むとか面倒くさくてやってられなさそうなので、起動時に隣同士のPICで通信してIDを自動的に決定するようにしてます。それぞれのPICは、隣同士の通信のために入力と出力のピンを持っていて、隣同士で数珠つなぎになります。末端のPICの入力はVDDにつながっています。写真だと、上の二つのPICの間にくにゃりとまがった黄色いラインがありますが、それが通信線です。右側のPICにだけ7セグメントLEDが接続されていますが、左側のPICも同じプログラムが書き込まれた物です。
下のPICは左端のシリアル-USB変換アダプタにつながっていて、パソコンからのコマンドをPICのシリアルのバスに流すだけのテストプログラムが書き込まれています。バスといってもまだ右側のPICにしかつないでませんが……。シリアルのバスはなんちゃってシリアルです。なんちゃって、っていうのは特に何かの規格に沿っているわけでもない独自のシリアルプロトコルと言うことです。まあうごきゃいいんだ、うごきゃ。
タイトルのとおりですが、なぜか読み込もうとしてもプログラムワードがすべて0x3fffになってしまいます。エラーすら出ません。当然書き込んでも動作しません。一体どこが悪いのかわからず、、、hexファイルみても何がおかしいのかわからない。
こちらをみるかぎり gputilsの出力hexファイルを秋月のPICプログラマver.4で読み込むことには成功しているし、確かにそこにおいてあるhexファイルは秋月のそれで読み込める。何が違うのだろう。
改行コードの問題でしたorz そういやここで言及されていたのにすっかり忘れていた...
また買いました。PIC16F716-I/Pにライターが対応するのを待ってるのも面倒だし、そう高くもないのでPIC16F628A-I/Pをたんまり買ってきました。あとこれ、ちゃんとしたUARTついてるので、なんちゃってシリアルじゃなくてちゃんとしたシリアル通信にできます。んでもって、シリアル通信のデバッグ用にUSBシリアル変換モジュールも。こー言うのが気軽に使えるってのは便利だなー。