TFT LCDによるアナログメーター 2
<カテゴリー:PICマイコン>
8bitのPICマイコンでは容量不足で、まともにLCDの表示が出来なかった為、マイコンを16bitに替え、かつLCDも一回り大きな2.4インチサイズにして、実用サイズのLCDアナログメーターを実験中です。
マイコンはi/oに不足がありますが、とりあえず簡単に実験できそうな、PIC24FJ64GA004という16bit品と、前回と同じメーカーDisplaytechの、DT024CTFTという、320x240ピクセル2.4インチサイズで作ることにしました。 マイコンが16bit品になったので、コンパイラもXC16に変更必要です。そこで、開発環境も、MPLAB Xに変更する事にしました。 しかし、これが、くせもので、従来のやり方では、全く動きません。 すでに通り過ぎた方は、問題ないにしても、これから、XC16やMPLAB Xの環境でPIC24xxxの開発を始めようと思っている方に多少なりとも、役にたつならと、失敗と対応方法を紹介します。
まず、MPLAB Xですが、エジターの日本語が文字化けして読めません。 WEBで調べていくと、プロジェクトを作るときにEncodingの指定をやるのだそうですが、それを見落としてプロジェクトを作ってしまっているので、後から、Encodingを変更する方法を探す必要がありました。
プロジェクトをオープンして、プロジェクト名の周りが青色になっている状態で、マウスを当て、右クリックすると、一番下にPropertiesがありますので、これをクリックします。出てきたダイアログの一番上にるGeneralの文字をクリックすると、中央下にEncodingの設定ランがあります。その中から、Shift_JISを選択すると、文字化けは直ります。
初期段階として、PICのソースファイルにConfig事項を書き並べて、チップの初期設定をおこないますが、HI-TECH CとXC8やXC16では全く書式が異なります。
HI-TECH Cによる16F1939のConfig記述例
__CONFIG ( FOSC_INTOSC & WDTE_OFF & PWRTE_ON
& MCLRE_OFF & CP_OFF & CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF
& FCMEN_OFF);
__CONFIG ( WRT_OFF & VCAPEN_OFF & PLLEN_OFF & STVREN_OFF & BORV_LO
& LVP_OFF );
これに対して、XC16で24FJ64のconfig記述例
// コンフィギュレーション設定 Fosc=20MHz Xtal
#pragma config POSCMOD = HS, I2C1SEL = PRI, IOL1WAY = ON
#pragma config FCKSM = CSDCMD, FNOSC = PRI
#pragma config WUTSEL = LEG, IESO = OFF, WDTPS = PS1
#pragma config FWDTEN = OFF, ICS = PGx1, COE = OFF, BKBUG = OFF
#pragma config GWRP = OFF, GCP = OFF, JTAGEN = OFF
XC16をデフォルトでインストールすると、以下のホルダーの中に、各PICの品種ごとに、どのように設定するか説明があるのですが、書いてある単語が何を意味するのか判らず、結局、該当チップの英文データシートを読む必要が生じます。それも大変な作業で、今回のPIC24FJ64の設定がなんとなく判るまで2日間もかかりました。 それでも上の設定が正しいのかは?です。とりあえず動いいていますので、良しとします。
C:\Program Files (x86)\Microchip\xc16\v1.24\docs\config_docs
最近のPICマイコンは、i/oピンの多重化がすさまじく、何もしなければパラレルポートを使う事が出来ません。このマイコンも、端子機能はピン配置図に書かれている名称の左から順に優先度が高いと説明されていますが、一番右側に書かれたパラレルi/oをそのまま使う方法が判りません。
ほとんどのi/oで一番左側に書かれている機能はADです。 ADを使うか使わないかを最初に設定しないと、i/oをHに設定したのに、いつのまにかLになっているとかの異常動作に遭遇します。 HI-TECH CでもADは最初に設定する事が必要でしたが、16bitになって、ほとんど全てのi/oがAD対応になっていますので、面倒がらずに、全部設定が必要でした。 ADの設定を行うと、各ピンの一番右側に書かれた端子機能をそのまま使う事ができました。
次にHI-TECH CではLATB1などのようにi/oのビット指定が出来るのですが、この単語ではエラーになります。これらの定義はincludeファイルの中にあるはずですが、そのファイルを見つける事ができませんでした。結局、WEBで調べてLATBbits.LATB1のように記述したら良いと判るまで、またまた2日間もかかってしまいました。 16bitをパラレルで一挙に書き込む場合はLATB = 0xFFFFでOKでした。
とりあえず、マイコンはソフトで書かれた通りi/oのH,Lの設定が出来るようになりましたが、今度は、LCDがまともに動作しません。 このメーカーのホームページにサンプルコードがありますが、このクラスのLCDは8bit RGBドライブオンリーで、マイコンからのパラレルドライブやシリアルドライブの実働例はありません。FAQなどを調べていくと、世界中のユーザーが困っているようです。 私の実験では、マイコンからのパラレル8bitドライブはなんとかなっても、シリアルドライブは全く不可というのが実態のように思えます。多分、自社でもテストした事がないのでしょう。
このような環境で、案の定、16bitドライブにしてもまともにカラーが出ません。悪戦苦闘の末判った事はRGBモード時設定するように説明されたカラーコードフォーマットの指定をマイコンからのパラレル接続でも行わないとダメという事でした。
このLCDは以下の初期設定で16bitパラレルドライブの基本的な動作は可能となります。
IM0をHとして、IM1-IM3はL(GND)にしておき、ハードリセットをかけた後のイニシャル処理です。
void init_LCD() {
lcd_CMD(0x01);//ソフトリセット
__delay_ms(120) ;
lcd_CMD(0x11);//Sleep Out
__delay_ms(120) ;
lcd_CMD(0x13);
lcd_CMD(0x0036);//Memoryアクセス(画面のスイープ方向設定)
lcd_DATA(0x0048);//画面は縦置きOnly
lcd_CMD(0x3a);//カラーモード書式設定
lcd_DATA(0x55);//16bit(5-6-5) この設定が必要でした。
lcd_CMD(0x002A);//カラムアドレスセット
lcd_DATA(0x0000);//SC[15-8] 0から
lcd_DATA(0x0000);//SC[7-0]
lcd_DATA(0x0000);//EC[15-8] 319まで
lcd_DATA(0x00EF);//EC[7-0]
lcd_CMD(0x002B);//ローアドレスセット
lcd_DATA(0x0000);//SP[15-8] 0から
lcd_DATA(0x0000);//SP[7-0]
lcd_DATA(0x0001);//EP[15-8] 239まで
lcd_DATA(0x003F);//EP[7-0]
lcd_CMD(0x0029);//Display ON 検討中はこのタイミングで。
lcd_CMD(0x002C);
__delay_ms(200) ;
}
今回の配線図を下記からダウンロードできます。
マイコンとLCDは専用ラインでつながっていますので、CE端子は常時Lで良く、またLCDの内部情報の読み出しも行いませんので、RD端子も常時Hとしております。
開発開始してから約1週間経過した時点で左のようなアナログメーターの表示に成功しました。
前回のドット数は160x128でしたが、今回は320x240でそれなりに分解能も向上しておりますが、単純に約4倍の面積に拡大しただけでは、このような綺麗なグラフィックにはなりません。
まず、JW CADを使い、正確な目盛板を作成します。 JW CADのフォントは限られていますので、グラフィックの部分のみを作画して、これをスクリーンショットでGIF画像に変換します。 この時のサイズは面積比で16倍以上あります。 この画像をWindows標準のペイントで読み込み、文字を入れます。フォントも色も豊富にありますので、デザインは簡単です。
デザインが終わったら、実際のLCDに表示するピクセルサイズまでペイントで縮小します。 この状態での各ピクセルのカラーデータをそのまま取り込むという手法で実現できます。
PCでの画像処理は、その豊富なアプリのおかげで、簡単に実現できますので、これをマイコンが扱えるデータに変換する為に、変換プログラムを作る必要が生じます。 PICのマイコンとLCDをにらみながら、ちまちまソフト開発をやるはずでしたが、 このSWRメーターの目盛が表示できたのを境に、マイコンプログラムの開発ではなく、PCのアプリ開発がメインになってしまいました。
そして、さらに、1週間くらい過ぎた時点で、PCアプリが完成しました。
下の画像は、PCの画面上に表示された、LCD表示用カラーコードジェネレーターです。 LCDと同じピクセルサイズに縮小したグラフィックデータを読み込むと、C言語で扱えるLCDへ表示する為のデータファイルを出力します。 出力されたファイルを#include命令で読み込み使う事ができるようになります。 バグだらけのアプリでしたが、なんとか動作するようになりました。
このアプリはTcl/TKと呼ばれるインタープリンターで作られておりますので、動作は遅いですが、コードジェネレーターですから、たとえ1分かかろうが問題ありません。 実際のところは数秒で出力されます。
バグだらけですが、ソースをダウンロードできます。Ccord_Generator4.tclをダウンロード
defaultcolor.txt を同じディレクトリーに置いてRUNさせて下さい。defaultcolor.txtをダウンロード
グラフィックデータをC言語で出力するのはOKですが、フォントデータを出力させる場合、都度ソースを微調整していましたので、このままでは機能しません。 取説が無いので作った本人も、もう忘れてしまいました。
このアプリはTcl/Tkというインタプリンターをインストールする必要があります。インストールの詳細は「Tcl/Tk」で検索してください。 ダウンロード元は全部英文で、個人情報の登録が必要です。
メーターの振れ角を66度として、0.5度きざみで指針データを作り、これをROM上に配置して指針の動きを表現するもので、PC上でのシュミレーションではうまくいってましたが、いざPIC24Fのマイコンに書き込む作業をしたところ、ROM不足でエラーとなってしまいました。
なぜなら、この指針用データが90Kバイトくらいあり、完全なメモリー不足でした。 本来は、もっと早く気付くべきところですが、アプリが完成して、コードを出力したら、そのファイル容量が170Kバイトくらいを示しましたので、やっと判った次第です。 データのスパンを1度ごとにして、容量を半分にしてみましたが、指針データ以外で24Kくらい使っていますので、やはり足りません。
現在のROM容量64Kに収まる範囲で可能な方式として、指針データは常に計算で出し、指針より少しだけ広い四角い範囲のグラフデータに、指針データを重ねると、ちょうどドット数の多いフォントと同じようなデータが作れますので、これをグラフ画面上に上書きすることにしました。
左の画像は、そのようにしてメーター目盛の上に、指針とその周囲の目盛画像を上書きしたものです。最初の案より指針データを計算する分だけ動作が遅くなっています。
この目盛のSWR1.0から無限大までの指針移動時間は実測で、約3.3秒ありました。指針位置の計算はsin()と平方根で出していました。
Y座標は、半径やXの値を2乗してから、平方根ですから、かなり時間がかかりそうです。 そこで、平方根を止め、Xはsin()で、Yはcos()で計算させると、指針の速さは約2.7秒まで改善しました。
三角関数は時間がかかると思われますので、sin()の0度から90度までを予め、PCで計算し、その結果を10000倍した数値を整数として、配列に記憶させ、sin(deg)はそのまま取り出し、cos(deg)はsin(90-deg)で取り出す事にしました。 結果は約1.3秒まで改善しました。
関数のなかを見渡して、繰り返しループの中で、初期設定など、結果が変化しない処理事項を取り出し、ループの外に置くとか、見やすくするために置いた変数を固定値に変えるとかの作業を行った結果SWR1.0から無限大までの指針移動時間は約1秒まで改善出来ました。
次に、一部、浮動小数点(double)を使用していた計算式を10000倍の整数計算した後、四捨五入した整数に直す方法で、全ての計算を整数で行った結果、ゼロからフルスケールまでの時間は約0.65秒となりました。
左の画像はその速さで指針が動いている時のショットです。動きが速いので、指針もボケて写っていますが、見た目のチラツキは少ないです。
アナログメーターの指針移動時間で違和感が無いのはゼロからフルスケールまで0.3秒くらいの移動時間ですから、あと半分くらいは短縮必要です。
しかし、 現在はメータードライブだけしかやっていませんので、例えば、SWRメーター以外にインピーダンスメーターも同時に表示したり、周波数カウンターの周波数表示など、負担が増えるばかりで、指針の移動スピードもどんどん遅くなってしまいます。
また、この方式の場合、チラツキは最少に抑えられますが、指針の移動スパンは1度以内に限られます。VUメーターではないので、かなり遅い追従時間でも問題は無いと思われますが、実際に作ってみないと、何とも言えません。
次回は、LCDの全画面表示にトライします。
TFT LCDによるアナログメーター 3 に続く。