SVX日記
2005-04-05(Tue) PICのウォッチドッグタイマ機能の翻訳、実装ッ!!
まず、昨日の文字化けの原因である。結論からいうと4.3MHz近かったPICの動作クロックが本来の4MHzに戻ったために、補正してあったボーレートが再び狂ったのが原因であった。再び一昨日の「秘伝の0.1秒×n-αループルーチン」法によって動作クロックの実測を行ったところ、5:02.86、5:02.93と、4MHzより1%弱遅いという結果が得られたのだ。7%近く速かった状態から回路に施した変更といえば、0.1uFのパスコンを追加したくらいなのだが、これが思いのほか効いたようだ。USBシリアル変換基板側にはタンマリとパスコンが載ってるので、省略してもイイやと思っていたのだが、やはりコンデンサを「至近に配置」するというのは重要な要素なのだろう。パスコンの役割の大きさを痛感した次第である。ちなみにSPBRGの設定値は、補正値の27から推奨値の25に戻した。まっとーである、至極、まっとーである。PICちゃん、不良扱いしてゴメンね。
次は電源の話。気持ち的にはUSBバスパワーで動かしたいが、やっぱり電源容量が足りないのである。プリンタは公証4Wであるから、4W / 5V = 800mA、余裕をみたらUSBの2ポート分の1000mA程度の電流容量は欲しい。でもって、まさにそーゆーケーブルが実際に売られているのだ。現在の自分の環境では使えないのだが、だからといって非対応にするのはもったいない。この際であるから、両対応にするのが吉というモノであろう。
で、切り替えスイッチで対応するかといえばノンノンである。この状況に以前にハマりの教訓を生かさなくてどうする。多くのDCジャックは3極になっており、そのうち2極はジャックを抜いた状態で導通するのだ。これをうまく利用すれば、ジャックを抜いた状態ではバスパワー、挿した状態ならACアダプタという自動切換えが可能になるのである。
しかしちょっとまて、一般のACアダプタのジャックは内側がプラス、外側がマイナスである。フツーはマイナスが切り替わることを利用して、こんな具合に使うのだろうと思うが、おいらはこんな具合に使いたいのだ。困る。これじゃ、ひッじょーに困る。
結局、プラスが切り替わるように、ジャックの極性を逆に使うことで対応することにした。もちろんACアダプタ側も、既存のプラグをチョン切り、極性を逆に新しくプラグを付け直す。アダプタの表記と実際の配線が逆になるので、誤って挿すとひッじょーに危険だが、既にウチには同じプラグで電圧が違うアダプタがひしめいているので、プリンタ専用のアダプタとして割り切るコトにする。もちろん、ちゃんと表記も正しておくつもりだが。
あとは、バスパワーとACアダプタの給電順、ポートへの漏れ電流やノイズなど、どんな状態でPICが起動したにせよ、数秒後には正常動作に復帰できるように、ウォッチドッグタイマによるリセット機能を組み込むコトにした。現状、プリンタが沈黙すると、つられてPICもロックアップしてしまうという問題(手抜き)があるのだが、これも同時に解決することができる。
14.7 ウオッチドッグタイマ(WDT)_
ウオッチドッグタイマは、外付けの部品が一切不要の完全自立の内蔵RCオシレータです。このRCオシレータはCLKINピンのRCオシレータとは独立しているため、例えばSLEEP命令の実行によりOSC1とOSC2ピンのクロックが停止しても、WDTの動作は続くようになってます。PICの動作中にWDTがタイムアウトすると、リセットがかかります。PICがスリープ中の場合にWDTがタイムアウトした場合は、PICはスリープ状態から復帰します(訳注: SLEEPの次の命令から実行を開始する)。なお、WDTはコンフィグのWDTEビットをクリアに設定することで、完全に無効にできます(節14.1 Configuration Bits参照)。
14.7.1 WDTのタイムアウト_
通常、WDTのタイムアウトまでの時間は18msです(プリスケーラ不使用の場合)。タイムアウトまでの時間は温度や電源電圧などによって変動します(表17-7 DC Specifications参照)。長めのタイムアウトが必要ならば、コード内でOPTIONレジスタを自ら操作し、ポストスケーラをWDTに割り当て、その分周率を1:128まで上げることで、2.3秒程度まで伸ばすこともできます。
WDTのタイムアウトによるリセット発生を防ぐには、CLRWDTまたはSLEEP命令の実行によって、WDTとポストスケーラ(WDTに割り当てた場合)をクリアすることで行います(訳注: メインループ内で周期的にクリアするのが一般的)。
なお、WDTがタイムアウトすると、STATUSレジスタのTOビットがクリアされます(訳注: TOビットは読み出し専用で、起動時とCLRWDTまたはSLEEP命令の実行時にセットされる)。
14.7.2 WDT使用上の注意_
最悪のケース(最低電圧、最高温度、WDTプリスケーラが最大設定)では、WDTがタイムアウトするまでに5〜6秒かかる場合もあることを考慮に入れておくべきです。
訳注: ポストスケーラ、プリスケーラが(原文でも)混在しているが、減速する歯車が前に位置しようが後ろに位置しようが結局は同じように、実質は同じと考えて差し支えない。
その反対側。以前にUSBプラグの差込口用に穴を空けようとして、空ける位置を間違えた穴があるのだが、それを動作確認用のLEDの取り付け穴として流用してみた。プリンタの正面から見るとUSBプラグのちょうど裏にあたり、動作確認用として非常にセンスのない実装位置といわざるを得ないが、なにせ間違えた穴であるから仕方ない。今後は間違えるにしても、もう少し熟慮した末にうまく間違えるよう努力しよう。
何気なく基板のアップ。LEDは秋月で買った黄色を使ってみたが、フツーなら制限抵抗として470Ωあたりをハサむのが定番であるトコロを、今回はバスパワー動作を考慮して電流が1/3で済むように1.5kΩをハサんでみた。室内なら十分に光って見えるのでヨシとする。なお、点灯タイミングはパラレルポートの非BUSY確認前から、BUSY確認後まで。要するにプリンタ側の処理を待っている期間に点灯するようにした。
動かす。今度は調子よく印字が行われる。文字化けもない。と、ここでさっそくLEDが面白い反応を示した。印刷を始めて最初の一瞬だけは点灯間隔が短く、それ以降は1文字印刷ごとにLEDが比較的長く点灯するのである。どうやらこのプロッタは十数バイト程度ながら、データキュー(スプーリングエリア)を持っているようだ。たぶん、1チップマイコンである6805内のメモリで実現しているのであろう。劇的に遅いプリンタのクセに、なかなかニクい作りである。
ウォッチドッグタイマ関係のコードを入れたので、プリンタのBUSYをGNDに固定してタイムアウトリセットのテストをしてみた。プリスケーラを1:128に設定したので、印刷データを送るとLEDが点灯しっぱなしになり……2.3秒後に……2.3秒後に……おいッ!! 2.3秒経ってもリセットされんやんけ。なんでや。あいやぁ!! コンフィグのWDTEビット立てるの忘れとったわ。立てて書き込みなおして……よっしゃ!! リセットされるようになったわッ!! 完璧じゃッ!!
つーわけで、一応の完成コードである。これは別にプロッタプリンタ専用でなく、一般的なUSB→パラレル変換I/Fであるから、パラレルポートの付いていないノートPCなどに、USB経由でセントロニクス仕様のプリンタを接続する時に有用であろう。Windowsならばプリンタをシリアルポートに接続したモノとして扱えばよい。例によってGPLとする。GPLだから気をつけろッ!! エレコムッ!!
で、今後の課題はふたつ。ウォッチドッグタイマを実装してイキナリではあるが、2.3秒という短いタイムアウト時間では、一番右から一番左までペンが改行動作をするだけでギリギリだというコト。そもそもプリンタをグラフィックモードで使った場合、縦に長い線を描いたら一撃でタイムアウトするのは目に見えているからこれは問題だ。できればタイムアウトまで10秒くらいは欲しい。
もうひとつの問題は、紙が切れた場合にゴムローラにガンガンと印字してしまうコト。こーゆータイプのプリンタなのであるから、ペーパエンプティくらいは当然のように検知して、ハード的に動作を止めてほしいくらいのモノだが、ないものねだりをしても仕方ない。しかしながら、このプリンタを自宅サーバにつないで24時間稼動で各種情報を印刷するように使うとなると大問題になる。そうなのだ、実はオイラはそーゆー用途に使おうと考えていたのだ。家に誰もいない間に紙が切れ、ゴムローラにガシガシと印刷されたら大変なダメージである。やはり、なんらかの検知機構を追加する必要だ。