秋葉原のパーツショップ「秋月」の 「シリアル制御液晶表示モジュールキット」を Linux から使用しました。 ハードウェアの改造と、ソフトウェアの作成が必要だったので、 その手順をここに報告します。
手っ取り早く使用したい人のために、変更点を先に書きます。
これだけの変更で、液晶に文字を表示することができます。
この写真が、製作したものです。 iMac なんてスケルトンコンピュータが販売される10年以上前から、 私が製作するハードはアクリルケースに収納しています。 放熱やシールドの関係でアルミケースを使うこともありますが、それは例外です。
基板が斜めに傾いてついていますが、 私の工作精度はこんなものです。
ここからは、 私がキットを使用できるようになるまでの試行錯誤の過程を書きます。 似たようなことを試みる人の参考になればさいわいです。
このキットは、 ホストの RTS 信号が ON になったときの 12V を利用して、 動作するように設計されています。 しかし、Linux では、RTS 信号をこまめに ON/OFF するので、 安定した電源として使用することができません。 そこで、外部電源として 006P 乾電池から電源供給することにしました。
最初はキットのダイオードを接続したまま使用していましたが、 ひんぱんにキットが暴走するので、ダイオードを外してしまいました。 キット暴走の理由として、以下の仮説を立てたからです。
仮説 |
---|
RTS がON/OFFを繰りかえすたびに、 3端子電源の電源供給端子の電圧が変化して、 PIC の 5V 電源にノイズが乗っている。 |
ダイオードを外したら、暴走はピタリと止まりました。 ダイオードがあると RTS が 12V になったときに、 乾電池に逆方向電流が流れるので、それを避けるためでもあります。
外部電源を 006P 乾電池から、AC-DC 9V アダプタに切替えました。 理由は、006P が数日で空になってしまったからです。
このキットは、RxD 信号をドライブするトランジスタの電源に RTS を利用しています。 つまり RTS が ON にならないと、 いくら PIC が RxD を操作してもホストに信号が伝わらないのです。 ホストから write(), read() を交互に繰りかえすと、 write() の間は RTS が OFF になり、 PIC が応答を始める前に RTS を ON にすることができないために、 結果として read() に失敗します。
少々 unix の知識がある人なら、 write() と read() を別プロセスにしたら良いのではないかと思うでしょう。 でも、それはうまく行きません。 read() バッファが無限に無いかぎり、 いつかは read() システムコールから帰って、 受信処理をしなければなりません。 その間は RTS が OFF になるので PIC が送信したらアウトです。 write() の前に必ず read() システムコールが実行される保証が無いかぎり、 read() が保証されません。 write() 側がカーネルメモリを調べて、 read() 側が read() システムコールでブロックしていることを確認した後 write() すればうまく行くかも知れません。 手間の割に、得るところが少ないので、 そのようなプログラムは組みませんでした。 そのため、PIC からの返信は無視しています。
まず試しに
% echo -n "abcd" >/dev/cua0 |
を実行してみました。
その結果、液晶には
ac |
と表示されました。
キットの説明書には、1文字送信する毎に内部処理に時間がかかるため、 連続送信はできないとあります。 そのとおり、1文字おきに処理されました。 説明書には、1文字送信するたびに、キットからの返信を待って、 次を送るように指示されています。 しかし、上に書いたような理由で、返信を受信することができません。 以下に書くようなプログラムで送信を試みました。
while ( 送信文字列がある限り ) { write( fd, 文字のポインタ, sizeof(char) ); usleep( 適当な時間 ); } |
このプログラムで "abcd" を送ってみたところ、
aaaaaaaa |
と表示されました。
どうも、キット側でシリアルのハンドシェークを行っていないため、 TxD に出る無効なパルスを拾って誤動作しているようです。 本当は、何がおきているか確実に知るため、 測定機器で調べるべきなんでしょうが、 我が家にはオシロスコープもシリアルアナライザもないので、 仮説を立てるしかありません。
次に、
% echo -n a >/dev/cua0 % echo -n b >/dev/cua0 |
の様に1文字ずつ送信してみました。
この場合は、うまく行きます。 というところで、障害回避策はわかりました。 1文字送信する毎に、デバイスを close() すれば良いのです。
以上を踏まえて試作した送信プログラムが、 serial.c です。
今までは、少ない手間で目的を達成する方法を書いて来ました。 とりあえず、私の目的だったシリアルに液晶表示器を接続することは、 達成されました。 でも人によっては PIC の入力端子を使用して、 外部情報を入力したいかもしれません。 そのような人のために、さらなる改良のヒントを書きます。
このキットは、 前にも書いたようにシリアルのハンドシェークを行いません。 また、電源供給のため RTS が常に ON であることを期待しています。 キットに付属のプログラムは、 MS-DOS 環境でダイレクトにシリアル LSI を制御して、 このキットを使用するものでした。 Linux でも、シリアル端末のドライバを外して、 I/O ポートを直接叩いてシリアル LSI を直接制御すれば、 MS-DOS と同様の使用方法をとれます。 私は最近のシリアルチップの資料を持っていないので、 この方法はとりませんでした。
現実的な解決策は、 キットに正しいシリアルのハンドシェークを行わせることです。 どうせ外部電源を供給するのだから、 シリアル端子との間にレベル変換ICを入れてしまいましょう。 その上で、PIC の余った入出力端子を利用して、 正しいハンドシェークを行わせるのです。 PIC プログラムの変更も必要ですね。
秋月には、「PICマイコン開発キット」というものもあります。 これを買ってみたのですが、ハードウェアは全部揃っているのに、 PIC に液晶表示させるプログラムは自分で書き込む必要があります。 「液晶表示キット」にレベル変換IC を入れて、 ハンドシェークは適当にごまかすのが一番安上がりなようです。 大量に同じ物を作るなら、「PICマイコン開発キット」を買って、 自分でプログラムを書き込むのが簡単でしょう。
Linux でシリアルの使い方を調べたい方が、 検索エンジンでこのページにたどりつくことが多いようです。 ここに記述してある内容は、PICLCD の制御に特化してあるので、 その他の目的には向かないかもしれません。 ネット上に http://www.linux.or.jp/JF/JFdocs/Serial-Programming-HOWTO.html という優れた解説文があるので、そちらを参考にしましょう。
2001年12月11日 初出
2003年8月11日 追記