STM8Sでグラフィック液晶に漢字をスクロール表示する
ハングアップするSTM32F107の気圧計を修理する(4/13/2013)
STM8Sでグラフィック液晶に日本語フォントを表示するプロジェクトは一段落したが、実は前から気になっていることがある。一年ほど前、O-Familyさんの掲示板で知ったのがきっかけで作ったグラフィック気圧計がまともに動かなくなってしまった。
この気圧計のMPUはSTM32F107で気圧センサーは秋月のMPL115A2、Aitendoの2.4インチのカラーTFT液晶(YHY024006A)に2日間の気圧の変化をグラフィックに表示する。気圧データは、毎秒測定した気圧を1分ごとに平均化し、10分に一回、I2CのEEPROMに蓄積する。
RTC(リアルタイマークロック)を内蔵しているので、実際の年月日を表示したグラフ枠に直近の2日間の気圧遷移が折れ線グラフで表示される。予報ロジックの組み込みや、ケースに実装する工程が残っているが、とりあえずここ数日の気圧の変化が一目で確認できるので、このままで結構重宝していた。
当初この基板にはソケットの接触不良があって、長時間稼動させると(2~3日以上)、止まってしまう持病があったのだが、直接ピンとピンの間を別配線してしまうことなどで、トラブルは解消していた。ところが、最近になってまた止まるようになった。しかも動いている期間がどんどん短くなり、このところは数時間が限度である。これでは実用にならない。
止まる要因で疑われるのは、TFT液晶の描画と、気圧センサーMPL115とフラッシュROMの読み書きに使っているI2Cインターフェースである。最初、液晶の描画ルーチンを疑っていたが、詳細にコードを調べて、このプロセスでは、少なくともMPU側にはループする要素が見当たらないことがわかった。
とすると、残るはI2Cである。このI2Cのドライバーは、例の弁護士さんの書いた「STM32マイコン徹底入門」でも紹介されたSTマイクロの標準I2Cライブラリーを殆どそのまま使っている。久しぶりにEclipseを立ち上げて、ソースを見る。
他のウェブや、この本にも書かれているとおり、このライブラリの信頼性は余り高くない。しかし、これに換わる適当なコードはないので、とりあえず仔細にソースコードをチェックする。何だ、何だ、ソースコードには、たくさんwhileでイベントが終わるのを待っているところがある。4箇所もある。しかも無限ループだ。これでは沢山のところでハングアップする可能性がある。
無限ループをやめて、エラーexitをつけたのに止まらなくなった(4/14/2013)
回数を数えて、一定の回数以降はそのループを抜けるようにソースを書き換えた。ところが、MPL115が正しい値を返さないようになって測定値が乱れる。うーむ、1000回程度ではだめなのか。
クロックを計算してみたら数十μsだ。こりゃいかん。MPL115はまだ測定を終えていない。
60000回以上(1ms近辺)でループを抜けるようにして、様子を見る。これが不思議なことに、何時間経っても、エラーexitもせず、しかも全く止まらなくなってしまった。2日間でも止まらない。???である。
要するに少しソースに手を入れただけでタイムアウトもせず(エラーメッセージも出ず)、無限ループにも入らず直ってしまったのである。逆に、UARTの切断/接続でハングする。えー、UARTルーチンにイベントを待つプロセスなどはないぞ。これも謎である。暫く様子を見ることにする。
それにしても最近の物忘れの程度は度を越えていて、自分でも笑ってしまうほどだ。STM32の開発手順を見事に忘れている。この気圧計の開発を盛んにやっていたのは、わずか1年前である。それが統合環境のEclipseでのソースのコンパイルはともかく、ファーム書き込みの具体的な手順が思い出せない。
さすがに、どういうツールを使うか(中華製のシリアルローダーMCUISPを愛用している。他のプログラマーの出番なし)くらいは覚えているが、どういう手順でプログラムをロードするのかブートモードが0だったか1だったかも忘れている。見事なものだ。
エラーが起きないので、これ以上のデバッグは出来ない。デバッグというより、I2Cがエラーで帰ってきたときにどうするかを考えておく方が合理的かもしれない。測定は毎秒やっているのでひとつくらい読めなくても大きな差は出ない。EEPROMの書き込みでも2日間のグラフなので、1回や2回データが欠けても大勢には影響がない。
ハードウェアのスクロールは難しい(4/15/2013)
気圧計のエラー発生待ちで手が空いたので、いよいよSTM8Sの最後の課題、ハードのDisplay Startコマンドを使った漢字のスムーズスクロールを実装する作業に入った。
問題は、縦64ラインある画面に12X12ドットの漢字を表示し、これをなるべく乱れなくスクロールしていくことである。これまでの検討では漢字フォントを分割して(画面の最下部と最上部に分けて)描画できればスムーズスクロールが出来るはずである。
つまり、縦(Y軸)0ラインから、12ドットの漢字を5行表示し、余白になっている画面の60ラインから一字の4 ドット分描画し、画面の0ラインに戻って残りの8ドット分を描画する。さらに4ラインの空白を表示し、ここにハードウエアの描画開始アドレスを移動すれば、全体の漢字の位置は全くずれずに、1行分スクロールされることになる。
このやりかたは、漢字描画の縦の物理スタートポイントが、決まった位置になく少しづつずれて行き(次の行の開始アドレスは12ではなく8。16回廻って一周)、スクロールのスタートアドレスも、それに合わせてずれるので、コーディングには細心の注意が必要だが、今のところ、この方法以上のやり方は見当たらない。複雑だがこれを実装することにする。
まず、必要なのはフォントの分割表示のための、グラフィックライブラリの中の日本語フォント関数LcdChr_Kanji())への機能追加だ。これまでは画面の最下部にかかる文字の描画は、エラーリターンしていたのを、折り返して最上部に残りのフォントを描画するようにロジックを追加する。
この改良は、相当厄介だろうと覚悟していたのだが、思いのほか追加するステップが少なく、簡単に完成した。Y方向(縦)のドットのアドレスを画面の最大幅になったときに0に戻すだけである。こんなにうまくいったのは、最初のプログラムの構造が良かったからだと自画自賛する(動いてから自慢するべきだろう)。
実際にスクロールを制御するところは、ライブラリではなくmain.cの中である。SRAMが残り少なくなっているので、変数を増やすのは気を遣う。手持ちの変数を使いまわして、描画のスタートポイント、スクロール開始位置のシフトを考える。
やっぱり一筋縄では動かない。擬似コードを何度もやりなおす。なんとかコーディングを終了した。いよいよテストである。苦労が多いほどこの瞬間はわくわくする。最初は連続ではなく、スペースバーを押すたびに、一字づつ表示するようにする。
順調に画面の最上部から、漢字が出てくる。スクロールしないときの表示は順調だ。まあ、ここは前と変わっていないので表示されて当たり前なのだが、ついに画面の最後まできて、スクロールするところに来た。
思い切って先へ進む。おお、画面全体が上に上がった。しかし文字は、表示されない。消し残しのようなラインが出るだけである。さらにキーを押して次の文字を出す。おっ、今度は文字が出た。コードを確かめる。出るべき正しい文字だ。スクロールした最初の文字だけが出ないが、分割したフォントは正しく文字になっている。良かった、この部分はうまく行っているようだ。
さらに文字を出していく。何とかスクロールが動いているようだが、周辺にはゴミが出るし、行換えした直後の文字が出てこない。一字づつを止めて連続表示をしてみると、文字が乱れたりループしたりして不安定だ。しかし、とりあえずスクロールはしている。とはいえ完成にはまだ程遠い。
すこしづつスクロールが出来てくるが連続はまだ無理(4/16/2013)
最初の文字が出ないのは、画面の更新をするときの領域の設定ミスとわかった。描画領域の定義は、仮想の描画スタートアドレスではなく、物理的なVRAMの範囲なので、分割して表示する時は結局、全部を描画領域にするしかない。
これを直して、スクロール直後の文字もめでたく画面に表示された。しかし、スクロールの幅がおかしい。思ったように下の余白が止まっていない。表示が4ドット分上がったり下がったりするので、連続して表示するととてもスムーズなスクロールにはならない。それに画面にゴミが残って、それがスクロールに合わせて動く。
メモに図を描いては、画面の動きを確かめ、UARTにドットアドレスを表示したり、デバッグを進める。スクロールの幅は常に12ドット(文字フォントの幅)で良いはずだ。それなのに何故、4ドットの余白が移動するのだ。そのうち思い違いをしているのを発見した。
ハードスクロールのスタートアドレスを新しく表示する文字のスタートアドレスに合わせている。ああ、これでは駄目だ。スクロールの開始アドレスは、0ラインから12ラインづつ動かしていけば良いのだ。このままでは空白は最上部に行ってしまう。まさしくプログラムは書いたようにしか動かない。
面のゴミは原因不明だ。スクロールのあと、表示するまえに1行分全体を消去しているのだが、このあたりは並木算の世界である。0オリジンか1オリジンか、最後の部分は含むのか、含まないのか。画面の途中ならそう難しくはないが、折り返すところがどうしても計算が合わない。
ライン0を表示しないのは元の関数の仕様だった(4/17/2013)
ゴミが出るのは、折り返しのところだけなのは間違いない。しかし、消去する幅や、起点を調整しても、ゴミがとれない。どうも今開発しているプログラムに誤りはなさそうだ。となると下部関数に何か不具合があるのではないかという疑いが出てきた。
そら。さんから頂いたこのグラフィック液晶(GLCD)ライブラリのオリジナルは、外国でNOKIAの液晶用に開発されたようだ。グラフィックの部分は、このGLCDではコメントアウトされて使われていなかった。こちらが勝手にコメントをはずして動かしているので、このGLCDで動く保証はない。
グラフィック関数は階層構造になっていて、新規に開発した特定の行を消去する関数、LcdFill()は、LcdLine()で直線を引き、LcdLine()はLcdPixel()という1ドットを描画する関数を使っている。
LcdLine()から見ていく。特におかしいところはない。次は、LcdPixel()を調べる。あ、あ、あ、画面の0アドレス(Y軸)は何も処理せず帰っている。何だ、何だ。0ラインにはドットが描けないのか。スクロールは0ラインにもドットが描けなければ正しい字にならないのに。
不具合でも何でもない。元からこういう仕様だったのだ。やれやれ大山鳴動鼠一匹である。もっと早くここを確認すべきだったのだ。0ラインも描画するようにして今まで汚かった画面は一掃された。漢字フォントだけが綺麗に表示される。一字づつ表示していくだけでは問題なく漢字が表示されて行く。よーし、大分進んだ。
しかし、連続するとまだ途中でループしたり、画面の位置が変わったりする。まだ何かがおかしい。トラブルシューティングは終わらない。
連続してスクロールが出来ないのも大きな勘違いだった(4/19/2013)
連続スクロールは、入力されたシフトJISの漢字コードに1バイトづつ足し上げ、漢字コードのときのみ(LcdChr_Kanji()は有効な漢字コードでないときはエラーで帰る)画面上に漢字を出すようになっている。
待ち時間を入れないで連続表示させると、表示が速すぎて、画面全体が白くなり、字そのものが殆ど読めなくなってスクロールの意味がなくなるので、一字あたりに30ms程度の待ちを入れて表示する。
ところが、連続しているうちにスクロールの位置が変わったり、ある時点でループに入ってしまう。 一字づつでは問題なく、連続してエラーが出るのは、ハードが疑われる。表示位置を変更するコマンドの前後に待ち時間を入れたり、表示そのものの関数にも待ちを入れたり、時間調整してみるが全く改善されない。
GLCDのSPIインターフェースが早すぎてデータをとりこぼしているのかもしれない。現在のSPIクロックは、2MHzである。データシートを確かめてみる。何とこのGLCDは20MHzくらいまでサポートしており全く問題ない。
そのうち一字づつ表示を続けているうち、全く同じところで表示が乱れることがわかった。うはあ、これはハードではない。ソフトだ。非漢字領域をスキップしているところで、どうもエラーが起きているようだ。
漢字コードでないときのエラー処理がおかしい。念入りに調べる。あっあっあー、わかった。非漢字コードのときは、文字をずらすところをスキップしているのだが、肝腎のスクロール処理がこのループからはずれているではないか。これではたまたま表示が左端で非漢字コードが来た時、無意味なスクロールをしてしまう。
何というお馬鹿なコードだ。非漢字領域のコードの描画が画面左端から始まるときのみ、おかしくなるので発生がランダムに見え、ハードを疑っていたが、何のことはない、単純なソフトのバグだった。今まで疑っていたGLCDさん大変失礼いたしました。悪いのは全部私です。
この解決で、グラフィック画面は、延々と漢字を表示し続ける。いやあ、良かった。良かった。これで動画が公開できる。この画面では、漢字一字に30msの待ちを入れて表示している(スクロールは待ちなし)。これより少ないと、表示が速すぎて液晶の残像で満足に字が見えなくなる。
これでSTM8SとGLCDの当面のテーマはすべて完了した。この日本語表示を何に使うかが今後の課題である。音声合成チップとあわせてネットワークを経由したメッセージボードのようなことが出来ると面白いかもしれない。
ここに例によって上記のソース一式をSTVDのプロジェクトごとzipファイルにしたものを置きます。STM8のライブラリはこれまでどおり同梱されていません。以前の記事を参考に所定のディレクトリに設定してビルドしてください。容量の関係でフルビルドが必要です。
本格的なFETスイッチの実験(4/22/2013)
このあいだ秋月から買ってきたMOSFET(FKV575)のスイッチの実験の続きである。ブレッドボードにCRとトランジスターの遅延回路を組み込んで、FETでLEDを1秒ほど遅らせて点灯する実験は成功した。しかし実際のスピーカー切り替え用の2つのFETを組み合わせた本格的なスイッチはまだ組んでいない。
前回にも書いたように、2つのFETで構成されたスイッチの導通抵抗がどうも寄生ダイオードによってミリΩ台になっていないような気がする。ウェブを見ているとACのスイッチには、何と4つのFETでスイッチを構成しているものもあり、その回路図を探していたが見つからなかった。
迷っていても仕方がない。現物があるのだから実際に試してみるのが手っ取り早いのではないか。まずは最初組んだFETひとつの回路に、オシロと秋月のファンクションジェネレーター(FG)で導通を調べてみることにした。
FGの出力は、AC(±1V)なので、FETひとつなら、片側が半波整流のような波形になるはずである。ところが、これがおかしなことに、ACが完全に通るのである。所長のFETの知識は、トランジスターのアナロジーで、ドレイン(コレクタ)からソース(エミッタ)に流れる(N型のとき)電流をゲートが制御し、ソースからドレインには電流がそもそも流れないというものである。
寄生ダイオードは、この逆電位のときに流れるもので(これはトランジスターにはない)、スイッチに使うときは、これが効かないよう、FETを背中合わせにするのだと思っていた。
ところが、前回の記事に、久しぶりにkugaさんからコメントがあり、自分が勘違いしていることがわかった。FETはゲート電位が上がって導通状態になれば、たとえドレインがソースより電位が低くなっても(NMOSのとき)、寄生ダイオード以外のところでも電流が流れると言うのだ。
どうも勘違いをしていたらしい。それなら本番用を実験してみよう。ブレッドボード上に背中合わせにFETをつけた回路を組む。たいした手間ではない。FGの出力を、このスイッチを通してオシロにつなぐ。導通は?うむ、全く問題ない。では、ゲートの電圧を0にする。ありゃあ、切れてないぞ。矩形波はサグの出る波形に、正弦波は殆ど減衰せずにそのまま出ている。
負荷抵抗を入れると切れた。うーむアナログは難しい(4/23/2013)
えー、どうして切れないのだ。良くわからない。ウェブで同じような実験をされているページの回路図を確認した。あ、そうか。負荷抵抗がいるのだ。微小電流ではFETは遮断できないらしい。
今ひとつ理屈はわからないが、本来はスピーカーという数Ωの負荷を切るスイッチである。この状態で調べるべきだろう。しかし、現在のFGは、内部抵抗が高く、とても数Ωの負荷抵抗をドライブすることは出来ない(出力は0になってしまう)。
とりあえずFGが何とか出力を出す(0.5V)くらいの負荷抵抗、300Ωを入れてスイッチを調べてみた。よし、わずか脈流は残るが、出力は殆ど0になった。スイッチは機能したようだ。しかし、正弦波は切れたが、矩形波は立ち上がり(下がり)に鋭いパルスが残る。
これは結局、実際の音で確かめるしかないか。使用を予定しているメインアンプの切り替えは少しおおごとなので、手元にあるカマデンデジタルアンプで試してみることにした。スピーカー端子は幸いこのあいだワンタッチの端子板に換えてあるので接続は簡単だ。
これはFETが持つ内部寄生容量で一瞬導通するからではないかと思うが、これを解説しているところは見つけられない。この症状は0.01μFくらいのコンデンサーを負荷に並列に入れるとパルスはおさまり、何とかスイッチの役目を果したようだ。
ブレッドボードからジャンパーを出し、念のためオシロもつないで片チャンネルだけスイッチをつける。問題なく入り切りができた。全くの無音になる。音は変化したか。この程度のスピーカーやアンプで、これを判別するのは無理と言うものだろう。
ウエブでも、機械リレー方式との音の違いを追及している人がいるが、まあスペックを信用するしかない。矩形波の残留パルスはMhzの世界で、少なくとも可聴周波数域での違いは全くないと言ってよいのではないか。
ウェブをさまよった挙句、4つのFETを使ってスイッチする理由がわかったような気がする。FETのオン抵抗(Rds)が入力電圧(ゲートソース電圧)によって大きく違うので、レールツーレールにするため、P型とN型を並列にして特性を相殺しているためではないかと思われる。 http://www.analog.com/jp/content/cu_ad4505jp/fca.html
まあ、ここまで心配ならリレーを使えば良いと思うけれど。
実験はそろそろ良いだろう。これを実装する工程が待っている。いずれにしても、スピーカーのミュートスイッチは、一般のFETのスイッチング特性とは全く別の世界(スイッチング周波数は全く無関係)なので参考になるウェブサイトは意外に少ない。以下は、スピーカーのFETスイッチに関して参考になったサイトのURLである。ご参考まで(勝手リンクご容赦)。
そもそもフォトボル型カプラーを知ってFETスイッチを作ろうとしたきっかけのサイト。
http://easyaudiokit.hobby-web.net/bekkan/MOSFETrelay/MOSFETRELAY.html
スピーカーのミュートをリレーからFETにしたときの考察。切れていたら()内のホームから。
http://members2.jcom.home.ne.jp/2060bl/21review/18ftrly/01vrfctn/vrfctn1.html
(http://members.jcom.home.ne.jp/4120blaudio/index.html)
マルツのFETスイッチの基礎的な解説。FETの一覧表もある。わかりやすい。
http://www.marutsu.co.jp/user/fet_3.php#mos-fet3
| 固定リンク
| コメント (2)
| トラックバック (0)
最近のコメント