PICマイコン Feed

2024年11月 3日 (日)

LCD NFP190B-21AF PICで表示

TFT LCDはaitendoから仕入れる事が多かったのですが、理由はPICでドライブできそうな情報が見つかりやすかった事です。 最近3Dプリンター用の部品をAliExpress経由で買う事が多くなり、その中で、かなり安価なTFT LCDも見つける事ができます。 ただし、ここでの買い物は商品説明も少なく、またWEB上でも使い方を公表しているブログも少ない為、二の足を踏んでいましたが、SPI仕様で700円台で手にいるNFP190B-21AFというLCDが目に留まり、ST7789でドライブしているとの事。 同じSPIドライブですがIC名はST7796というGMT024-08-SP18Pという品番のLCD各1個を入手しました。

過去、ST7789をドライバーに使ったLCDは使用した事は有りませんでしたが、コマンド系がST7735とコンパチのILI9163CによるLCDは沢山使ってきた関係で、情報が少なくても、動作出来るかも知れないと購入しました。

事前にドライバーICの仕様書を入手し、すでにPICで実績のあるプログラムと同じで有る事を確認できましたので、実際に試作開始してから2日目にはグラフや文字の表示が出来るようになりました。

以下、その時の配線図とPIC用のプログラムを紹介します。

プログラムの検討はNFP190Bにて始めました。 LCDに表示するのは文字とグラフィックを含めた静止画ですから、LCDのイニシャライズも必要最低限にとどめています。

Nfp190b_1

左が、ディスプレーが成功したサンプル画面です。 新しいLCDの表示テストを行う時、RGBの構成が仕様書と異なる問題に遭遇しますが、今回も、仕様書上ではRGBの順序でカラーコードを設定するように書いてありましたが、実際はRBGの順序でした。 しかもこのLCDドライバーはRBG「255,255,255」が黒色で「0,0,0」が白色になっており、過去のどのドライバーと比較して正反対でした。 データシートを詳しく見てみると、縦長に置いた状態で上から、左からのスキャンなら、通常のRGBですが、横長に置いた時のスキャンモードなら、このようになるみたいです。  また、LCDのピクセル構成も書いた資料が無く、表示が出来るようになって調べたら320X220ピクセルという結構密度の高いLCDでした。

下は、検討用に製作したPIC18F14K50を乗せた実験基板と実験中のLCDです。

Nfp190b_2

配線図は以下の通りです。 インターフェースがSPIですから、回路図は単純です。 ただし、応答速度はパラレル接続より目に見えて劣ります。 デバッグが完了したらクロックの限界を確かめる事にしますが、今は1MHz以下での検討です。 このドライブ操作を高速にするため、SPIのSSPBUFにデータを書き込んだ後、2usecのディレーを設けていますが、これを1usecにした途端LCDは表示しなくなります。 2usecと1usecの間に動作OK/NGの境界線があるのですが、それがいくらなのかは判りませんでした。 ただし、このディレー時間はクロック周波数にも大きく関係しますので、最初は20usecくらいに設定して置き、うまく表示できるようになりましたら、次第に小さくして、NGになる時間を見極めた後、その時間の2倍くらいに設定するのが良いようです。

Nfp190b_schema

テスト用プログラム LCD_NFP190B_test.cをダウンロード

テストに使ったフォント Font6.hをダウンロード

上のプログラムはNFP190B用ですが、ピクセルサイズを320X240としたGMT024用に修正した時の表示画面は以下のようになりました。

Mt02408

所で、XC8でconstを使ってデータをプログラム領域に埋め込もうとしますが、全部RAMエリアに配置されすぐに満杯となりエラーになります。 PIC24Fでは32Kバイトを超えるデータをプログラム領域に配置できたのに! WEBをぐぐるとXC8でのconstは256バイト以下に限るとの情報が見つかりました。 グラフィックを仕込めなかった原因はこれですね。 

色々情報が得られたところで、通常のGIF画像のカラー情報をそのまま表示できる仕様に変更しました。 カラー構成は「RGB」とし、黒色は「0,0,0],白色は「255,255,255」としたプログラムに書き替えました。

また、SPIのクロックの最高周波数の見極めができましたので8MHzに設定してあります。 

修正したプログラム LCD_NFP190B_test2.cをダウンロード

使ったフォント Font7.hをダウンロード

このプログラムで表示した状態は以下です。

Nfp190b_3_2

さらに、GIF画像の表示にトライしました。 320x240ピクセルの画像データをPICで扱えるフォームに変換したのですが、メモリー不足でエラー。240x180ピクセルもエラー、やっと160x120ピクセルのデータなら、なんとかPIC24FJ128GB106のデータメモリーの中に納まりましたので、ひまわりの写真とペナン風景を160x120の画像に縮小し表示にトライしました。

Himawari160x120

Penang160

最初、LCDを横長にして、表示にトライしましたが、カラー画像がどうしても再現出来なく、困りはて、LCDの標準置きとなる縦長にし、かつ、カラーモードを6-6-6bitの18bitモードしして、やっとオリジナルのカラーモードに設定できました。 その後で横向きにしてもちゃんと色を再現しています。 ただし、元がGIF画像ですので、色は最大で256色しかなく、このふたつの画像とも256色中の110色くらいでしか描画していません。

この画像は、PC上で表示されたGIFの画像のピクセルデータを読み取り、一度6-6-6bitのカラーデータに変換した後、互いに異なるカラーコードに連番のindexを付け、各ピクセルに対応するindexとindexが対応するカラーコードのみをPICのデータメモリー(const指定なので、実際はプログラム領域に配置されている)を確保し、このカラーコードを6-6-6bitのモードでLCDメモリーへ転送したものです。 左の写真では、かなり粗く描画されているようですが、実物を目で見た場合、結構綺麗に再現しています。 今後、サイズの大きな画像表示にトライする事にします。 

GIF画像表示のプログラム GIF_display_test3.cをダウンロード

GIFピクセルデータ penang160_data.hをダウンロード

GIFカラーコード penang160_cord.hをダウンロード

実験用配線図 LCD-TEST_pic24FJ.pdfをダウンロード

配線図にはSDカード用ソケットも描かれていますが、まだソフト上では対応していません。

 

INDEXに戻る

2024年4月13日 (土)

LCD ZJM161A PICで表示

aitendoの福袋の中に、1行16文字表示のLCD ZJM161Aが有りましたので、PICによる表示テストを行いました。

入手したLCDは左右両端の文字がコントラスト不足になっていましたが、在庫処分の福袋でしたので、しょうが無いと思っています。 正規品はお一人様2個までの条件付きで199円で売られています。この正規品はもしかしたら、コントラストのムラは無いかも知れません。 なお、正規品もLED照明は有りません。

このLCDに使われているICは一般的な1602BタイプのLCDドライブICと同等品で、秋月で扱っている8文字2行タイプの青色LCD ACM0802C-NLW-BBHと同じ構成で、私の実験では、このLCD用のプログラムでちゃんと表示できました。 ただし、秋月のLCDは2行が上下に並んでいますが、このLCDは1列8文字がふたつ1列に並べられており、文字の大きさが大きくなっています。

Zjm161a_lcddisp

表示テストは、いつも検討に使うPIC16F1939で行いました。 

回路図 LCD_ZJM161A.pdfをダウンロード

サンプルプログラム ZMJ161Atest.cをダウンロード

コントラストを調整する半固定抵抗が5KΩですが、これは手持ちが20個くらいあって使っているもので、抵抗値に他意は有りません。 今回のLCDは半固定抵抗のセンター端子の電圧は0Vで、最大のコントラストになりました。

 

INDEXに戻る

2024年4月 1日 (月)

エレキーの製作(PIC16F1827) コンテスト用

メインのHFリグをFTDX-101Dに変更して、CWのコンテストに参加した時、送信用のキーはCTESTWINからの自動送信としていたのですが、キースピードを25WPMに設定していると、時々、早すぎて取ってくれない事があり、手動のエレキーでゆっくり打電しようとしても、リグ内蔵のキーファンクションをエレキーに切り替える必要がありました。 この切り替えがわずらわしく、自作の外付けエレキーとCTESTWINからのキー信号をパラに接続して交信していましたが、自作のエレキー回路にはキースピードの表示が無く、一度キーを打ってみて、目標のスピードになるよう調整する必要があり、非常に不便でした。

そこで、キースピードがWPM単位で表示できて、CTESTWINと共存できるエレキー回路を作る事にしました。 手元に、PIC16F1827があり、8文字、2行表示のLCDもありますので、これを使い、以前製作した、PIC12F675によるエレキー回路を改造して実現する事にします。

エレキー回路配線図 elekey4test.pdfをダウンロード

せっかく作りますので、モニターTONEも正弦波で出力させ、小さなスピーカーを鳴らせるように、PWMオーディオアンプも付けました。 モニタートーンの周波数は500Hzくらいから1500Hzくらいまで、可変出来るようにし、可変中は、モニタートーンのみ1.5秒くらい聞こえるようにしてあります。この場合、キー出力は出ませんので、いちいちトランシーバーの送信を禁止する必要は有りません。 モニター音量調整の為、470KΩの可変抵抗を使っていますが、これは100KΩの可変抵抗が最適なのですが、手持ちが無かったのでやむなく使っているものです。

また、1.2Kとか12Kの抵抗を多用していますが、本来は1Kか10Kで済ませる抵抗ですが、この値の抵抗は他の工作でも沢山使い、すぐに手持ちが無くなってしまいます。 その為、秋月で2500個単位で買いますが、工作する方の思いは同じで、2500個リール売りの1Kと10KΩの抵抗は売り切れており5000個リールしか無かった為、2500個リールの在庫が有った1.2Kと12Kを買った為です。この辺の定数は8.2から12くらいの値であれば何でも使えます。

エレキーの可変スピードの範囲は2WPMから40WPMまでとしましたが、実際に使われるのは18WPMくらいから28WPMくらいです。

従来のエレキーでは、マニュピレーターの動作を周期的にチェックする時間は16msecで、一応チャタリング対策は出来ておりましたので、今回も16msecとしました。

FTDX101Dをキーイングする信号はフォトカプラーで完全にGNDを分離し、PCやエレキーの誤動作防止としました。 PCからこのエレキーに接続するのはUSBからRS232Cに変換するアダプターを使い、PCとこのエレキーの間にフォトカプラーを入れ、PCとエレキーのGNDも絶縁してあります。

Elekey1827_1

760hz_tone

上は、出来上がったバラック状のエレキー回路です。 左は、モニタートーンの波形で、5bitのDACから出力したものです。 完全な正弦波ではありませんが、レベルゼロの位置からスタートし、レベル0の位置で終了するようにしてありますので、キークリックは全くでません。

TONE信号を作る為に、1サイクルを20分割した5bitのデータを作り、タイマー2が割り込みする間隔を指定して、TONE周波数の可変を行っています。 表示される周波数はこの割り込み周期から計算されたもので、実際の周波数とは、若干ずれている場合があります。

これをケースに入れる為、ケースを発注しましたので納品され次第、組み込むことにします。

マイコンプロブラム Elkey4ContestV102.cをダウンロード

やっとケース加工が完了しました。 以前作成した160m用SSB/CW送信機と横幅がほぼ同寸法になりましたので、シャックの中でも納まりがいいです。 FTDX101DのCW符号は、CWの設定規則通りのキータイミングでしたので、今後は、私なりのキーイングスタイルで、CWコンテンストを楽しめそうです。

Elkey4testcasein

 

INDEXに戻る

2023年11月22日 (水)

ADCの動作が時々おかしい

PIC18F47K42を使いATUを作成しましたが、SWRを計算する為に内蔵ADCで、CM結合器から取り出した進行波電圧と反射波電圧を読みだしています。 しかし、この読出し値が時々大きく狂う現象が有りました。 その原因が判らず5か月以上ああでもない、こうでもないと、悩んでいたのですが、やっとその原因が判明しました。 判ってしまえば当たり前の事なのですが、PICを使ったソフト開発を10年以上続けてきた後だけに、過去のADCを使った製作も全て間違っていたという事が判り、がっくりです。

今回問題が発生したのは、CM結合器から漏れる高周波がマイコンに混入しないようにCM結合器とマイコンのAD入力端子との間にバッファアンプやCRによるLPFを設けたのですが、このCRによるLPFのコンデンサがAD入力端子とGNDの間に直接接続され、かつその容量が0.1uFで有った事でした。

下のブロック図はPIC18F47K42のADC入力回路の原理図ですが、AD変換する為に必要なサンプルホールドコンデンサが入力端子に直接接続されています。

Pic19fadc

このPICの中に内蔵されたコンデンサの容量は5PFで、設定により最大31PFの容量を追加できますので、最大36PFの容量のときでも、正確なAD変換が行われるよう、クロックで必要なタイミングを確保していました。 この状態で、このADCの入力端子とGND間に36PFよりはるかに大きい0.1uF(100,000PF)のコンデンサを追加した事により、ADCがPICの仕様通り動作しなかったものです。

これが判った時点で、上のブロック図のごとくRs=1.2KΩのみにしたところ、今まで頻繁に起こっていた誤変換がぴたりと無くなりました。

常に誤変換するなら、調べようも有ったのでしょうが、時々誤変換する事と、他にバグが有ったりして、なかなか発見出来なかったのが実情でした。 また、この入力端子に0.01uFを追加した過去の事例も有ったのですが、ADCの動作頻度がATUの1/10か1/100くらいしかなく、実害が無かったのではと推測されます。

今、思い出せば、昔作成したバリコン式のATUがなかなか収束しない事が時々発生していましたが、その原因もこれでは無かったのかと推測します。 (この昔のATUはすでにお役御免でジャンク箱行きとなっています)

この事に気づいて、ADC入力とGND間にコンデンサを接続しているSSBジェネレーターはなぜうまく変換しているのかと、改めてデータシートを見てみると、下のブロック図のごとく、サンプルホールドコンデンサと入力端の間に、バッファアンプがあり、サンプルホールドコンデンサの容量が外付け部品で影響しないようになっていました。

Dspicadc

今後ADCを使う時は、注意する事にします。

INDEXに戻る

2023年4月23日 (日)

PIC18F25K42 IOC異常

PIC18F25K42のバグ情報です。

IOCによる割り込みにて、立下りでの割り込みを設定したとき、IOCIEの設定に関係なく、立下りで割り込みフラグがセットされるのは正常ですが、IOCIE=0でも割り込みが発生する。

立ち上がりでの割り込み設定の場合、異常なし。

対策は、立ち下がりによる割り込みを使わない事。 この割り込みの使用場所がロータリーエンコーダーによるアップ・ダウンの検出ですので、どっちでもソフト対応できました。

平行して、ソフト開発をしているPIC18F47K42は、異常なしです。

確認したXC8のバージョン:V2.40  PIC18F-K_DFP 1.8.249

 

Indexへ戻る

2021年10月25日 (月)

dsPIC33CH トラブル事例

<dsPIC33CH Trap Reset モジュロアドレッシング atpack>

New_sdr211025

左は、dsPIC33CH64MP202を使い、SDRを開発しているスナップですが、この開発中に遭遇したトラブル事例を紹介します。

①モジュロアドレッシングの為にワーキングレジスタを専用割り当てした時は、このレジスタをコンパイラーが勝手に使わないように処理する必要がある。

FIRフィルターを2種類設定しリングメモリーを構築する為に、モジュロアドレッシングの設定をおこないますが、ひとつのリングメモリーのコントロールの為に、ひとつのワーキングレジスタを専用に割り当てます。 このワーキングレジスタはW8とかW10が良く使われますが、一旦、この専用レジスタを割り当てた後、他の目的に同じレジスタを使用すると、トラップが発生し、RESETがかかってしまいます。 コンパイラーの説明によると、このように専用レジスタを設定した後は、コンパイラーがこのレジスタを使わない様にユーザー側で設定する必要があると説明されております。

その方法は、MPLAB X XC16 GCCのオプション欄に以下のように記述します。 この例では、W8とW11をコンパイラーは使用しなくなります。

-ffixed-w8  -ffixed-w11    

全て小文字で記述する事。  最初wを大文字にした為、全く効果がなく焦りました。

 

②割り込みにて、トラップが発生し、RESETされる。特に、32bitや64bitの演算のとき、16bit単位の演算途中に割り込みが発生した場合、直前のデータの回復ができなくなる事があり、演算結果に誤りが発生したり、ひどい時はトラップが発生するもの。

特に、C言語で複数の演算式を1行の命令文として記述した時に発生しやすい。演算式をひとつづつに分解して、かつ途中に中継用の変数をおけば、かなり改善される。 それでも、10usecに1回くらいの頻度で割り込みがかかるような場合、かなりの頻度でトラップが発生する。

対策としては、割り込みの周期を変えても良い場合、トラップの発生する演算の期間中、割り込みを遅延させる。 割り込みを遅延させる方法で一番簡単な方法は、該当する演算命令の直前に割り込みの優先順位を0にして、演算が終わったら優先順位を元にもどせば良い。

ただし、ADCのタイミングなどのように周期をずらせない場合、対応不可なので、あきらめる事になります。

この現象はdsPICに限らず、PIC24FJでもFFT処理時、発生していました。その場合、一旦周期的な割り込みを禁止して、FFTの計算をやらせていました。

これらの事が理解できるまで1か月以上かかりました。結局 dsPIC33CHの場合、10usecの割り込みはスレーブ側だけにし、浮動小数点の計算やlong intを扱う演算などは、定期割り込みがかからないマスター側のみで行う事にします。 実際に実現できるかトライした結果OKとなりました。

 

③ レジスタ変数の禁止

古い資料には、ワーキングレジスタを16bitの変数に指定すると、そのワーキングレジスタはコンパイラーが専用と認識し、他の用途には使用されないと説明されていますが、これは当時から非推奨となっていました。 そして、現在は、そのような記述をするとエラーになります。

 

④ Slaveという文字の非推奨

XC16 V1.50で、エラーに近いワーニングが出て、コンパイラをアップデートしろと怒られます。 そこで、V1.70に変更しましたら、今後 Slave という文字は secondary に変えろとコメントが付きます。 この変更を実施したら、コンパイラの出力から赤文字がなくなりました。

 

⑤ 発振回路とPLL設定

SDRとして使う為に、クリスタルによる発振をベースとしたクロック回路を構築しようとしましたが、なぜか、Foscが生成されません。 通常、以下のようにコンフィギファイルを設定しますが、クリスタル発振回路は正常に動作しているのに、PLL回路への信号が途中で途絶えているみたいで、動作しません。 

#pragma config FNOSC = PRIPLL     //プライマリ-オシレーター、PLLモード     
#pragma config POSCMD = HS    //8MHz以上のクリスタル発振

何日も原因が判らず、先へ進めなくなりましたので、クリスタル発振を外部発振回路に変え、コンフィギファイルを以下のように書き換え、OSCの出力にFosc/2が出てくるようにしましたが、信号は有りませんでした。

#pragma config POSCMD = EC           // 外部クロック
#pragma config OSCIOFNC = OFF     //

結局解決できず、再度マニュアルを読み直すと、どの説明も、最初FRCモードで立ち上げ、その後で、外部発振やクリスタル発振モードへ移行する例しか書いてありません。 そこで、そのサンプル通りに設定すると、晴れて、正常にFosc/2が出力され、プロブラムが実行されるようになりました。 このFosc/2がFRCによるものか、外部クリスタル発振器によるものかは、接続した周波数カウンターで簡単に見分けがつきます。 FRCの場合、周波数が1000Hz以上ばらつきますが、クリスタルの場合、バラツキは1Hz以内です。 以前、dsPIC33FJにて、SSBジェネレーターを作った時は、従来のやり方で問題無かったのに、と焦りましたが、動き出しましたので、とりあえず、納得です。

最終的に、コンフィギファイルを以下のように設定した上で

#pragma config FNOSC = FRC           // Oscillator Source Selection (Fast RC Oscillator with PLL module (FRCPLL) )
#pragma config IESO = ON               // Two-speed Oscillator Start-up Enable bit (Start up with user-selected oscillator source)

// FOSC
#pragma config POSCMD = EC     

Mainプログラムの中で、以下のように記述することで、動作OKとなりました。

 // POSCとPLLの設定 FRCで起動して、外部clockのPLLモードへ切り替える

 PLLFBDbits.PLLFBDIV = 100 ; // M FPLL=819.2 Fosc=204.8
 CLKDIVbits.PLLPRE = 3;  // N1 1/3 Xtal=24.576MHz
 PLLDIVbits.POST1DIV = 2; // N2
 PLLDIVbits.POST2DIV = 1; // N3
   
 // Initiate Clock Switch to FRC with PLL (NOSC=0b001)
    __builtin_write_OSCCONH(0x3);
    __builtin_write_OSCCONL(OSCCON | 0x01);
 // Wait for Clock switch to occur
 while (OSCCONbits.OSWEN != 0);//Clock SW 切り替え完了
 while (OSCCONbits.LOCK != 1); //PLL Rock 完了

ちなみに、この設定をdsPIC33FJで行った所、Foscは生成されませんでした。 

 ⑥CCP3の怪

周期割り込み用のタイミングを取る為に、CCP1 CCP2と単純なタイマー仕様で利用していましたが、さらに割り込みが必要になり、同じようにCCP3を設定しました。 設定した割り込みタイミングは約6KHz程度の周期でしたが、出てきたタイミングは、周期が乱れた約850KHzくらいの異常周期でした。 設定が間違ったかと、何度もチェックしましたが、間違っていません。 試しにCCP3の3の数字をすべて4に変えたら、設定通り6.25KHzの周期で割り込みが発生します。

CCP3の異常の原因はわかりませんでしたが、とりあえずCCP4で正常に動作していますので、そのままです。

<半年後に追記>この原因は多分Timer3をADコンバーターのサンプリングレート設定に使っている事が原因かも知れません。

 

⑦DACがsigned intで動かない。 unsigned intオンリーです。

どこかに設定があるかもと、日本語、英語、類似dsPIcの資料を読みあさりましたが、結局、極性付整数によるドライブが出来るという説明は見つかりませんでした。 多分、極性付整数は扱えないのでしょう。 FIRフィルターなどをデジタル処理する上で極性付きはマストですから、DSPの計算部分は極性付きで実行させ、DACに出力する直前にsignedからunsignedへ変換すれば良いようです。

Singned_int

Unsingned_int

左上は、signed intのデータをそのままDACに出力したものです。 右は、DACに出力する前に、データに2048を加算したものです。 12bitのDACですから、その半分のオフセットを加えてやれば、データが全部正の値になりますので、正常に出力出来ています。 ただし、この状態を作る為には、DSP内のデータは整数で有る事が必要で、TAP係数もADCの設定もすべて、signed intにしておくことが必要でした。

  

⑧配列変数の要素数が確保した要素数をオーバーしてもコンパイルエラーがでず、ハングアップする。

通常、配列変数の宣言を要素数を指定して行いますが、誤って、その要素数をオーバーしても、コンパイラはエラーをはかずに、そのままリンク完了してしまいます。 その為、いざRUNさせると、ハングアップを起こし、動かなくなります。 どこでハングアップしているのかを、LED点灯を目印に調べていくと、その原因が要素数のオーバーらしいという事がわかりました。 エラーなしでコンパイル完了したのに、プログラムが止まった場合、最初に疑えば、解決がはやくなりそうです。 XC8では、ちゃんとエラーが出たような記憶でしたが。

 

⑨2021年12月の時点でXC16 V1.70がインストールされている状態で新規にプロジェクトを作ると、Configの記述が変更されており、XC16 v1.50の記述のままではエラーになる。

I/OポートをMasterが使うかSlaveが使うかを記述するときの記号が変更されている。

MSTR → MAIN            SLV1 → SEC1

どうやら、マスターとかスレーブという語句を全て禁止したみたい。 なにもエラーにしなくても、ワーニングにして変更を開示すれば良いのに。   この変更を加えた事により、エラー表示は無くなり、コンパイルが成功するのですが、マスター側は正常に動作しているのに、スレーブ側がランしていません。 まだ、何か変更事項があるらしい。

Microchip.dsPIC33CH-MP_DFP.1.10.223.atpackというファイルをMicrochip(US)のホームページで見つけ、これを下記のようにインストールしたら、スレーブも動き出しました。

Atpack_install ターゲットファイルは、USBメモリーの中にダウンロードしてありましたので、そのファイルを選択するだけです。

Atpack_tgt

 後で判ったのですが、MPLAB Xのupdateリストを調べたら、このatpackもリストの中に含まれていました。 updateファイルは自動的にインストールされる事はなく、MPLAB Xのバージョンアップ時、それまでのatpackはアップデートされるみたい。 このatpackがリリースされたのが2021年11月3日だったようで、マニュアルによるインストールが必要なようです。 このatpackをインストールした後、プロジェクトのプロパティを開き、以下のようにPacksをセレクトすると、このupdateが適用されます。 MainもSecondも両方設定必要です。

After_atpack

これらの設定で、一応スレーブは起動できたのですが、IQミキサーを構成して、IとQの信号を引き算して、DACへ通すと、出力はゼロになります。 これは、IQ信号に90度の位相差が無い事を意味し、以前と同じ状態で、正常に動作していない事を示しています。 さらに、この対応する前はFIRフィルターは機能していましたが、今回の設定でハングアップするようになりました。 これらのソースプログラムは、すべてdsPIC33FJ用として作成され、このdsPIC上では正常に動作し、トランシーバーを実用しているものですが、このdsPIC33CH上では正常に動かないようです。

MicrochipのXC16のバージョン履歴を見ますと、V1.61というのが存在し、これはV1.60のバグフィックス版と説明されていますので、XC16 V1.70またはdsPIC33CHのファームウェアにバグがあるのかも知れません。 しばらく、このICを使うのは延期した方が良さそうです。

一方、かろうじてミキシング動作だけはOKのIQミキサーですが、DACがPWM方式しかなくサンプリング周波数の1/4くらいの信号をクロックを完全に取り除く事は困難で、送信用信号を取り出すには、外付けのDACが必要であろうと推察されます。従い、受信機に利用出来ても、送信機には使えないという事がはっきりしました。

バンドスコープから始めたこのマイコンの検討でしたが、最終的に、400KHzくらいのキャリアをもつSSBジェネレーターを目標としていましたので、これできっぱりと諦めがつきました。 このマイコンによるSDRの開発は中止する事にします。

 

INDEXに戻る

2021年8月28日 (土)

PICでFFT (XC16でFFTにトライ)

<バンドスコープ、自作,PIC>

デジタルオシロスコープが基本動作としては、可能になり、ADCでデータを取り込む方法、そのデータをTFT LCD上に表示する方法が可能になりましたので、次はいよいよFFTにトライします。 WEB上で色々検索した結果、FFTのいろはも良く判っていない輩にとっては、どれも思考がついていかない為、PICで実行が可能かも知れない大浦先生のC言語によるパッケージを検討する事にしました。 このパッケージは、標準的なC言語で作成されており、該当する変換関数を1回実行すれば、回転因子の作成や、ビットリバースなど全部関数の内部でやってしまい、処理完了したら、入力した同名の配列にFFT結果を返すというもので、中身をよく知らない私には打ってつけのソースです。

さっそく、先生のホームページから、zipファイルをダウンロードし、解凍すると、沢山のファイルとテスト用のサンプルまで同梱されていました。

fftsgと言われる、大浦先生のソースは、XC16でも問題なくコンパイルできます。 動作テスト以前の問題として、全ソースがXC16でコンパイルできるか試したところ、すべてOKでした。

今回、これらのソースをインストールするのは、PIC24FJ64GA002です。 プログラムメモリーは64Kありますが、RAMが8Kしかなく、PICKit3経由でターゲットPICを決め、いざ、コンパイルすると、データメモリー不足で即エラーになります。 トライしたのは、沢山のプログラムの中で、一番高速だと言われるfftsg.cでした。 浮動小数点がdoubleで表現されているので、これをすべてfloatに置換してトライしましたが、やはりダメでした。 そこで、プログラムをfft4g.cに代えてトライすると、メモリー使用量88%でやっとコンパイル成功しました。 大浦先生の解説では、このプログラムが有名なCooley-Tukey 型 FFTで基数型とも言われるものらしく、コンパイルに失敗したソフトはこれより高速なSplit-Radix型と言うものらしい。

高速に越した事はありませんが、コンパイル出来なければ話になりませんので、今回はfft4g.cで進める事にします。

先に、FFTが成功し、例の320x240TFT LCDに表示できたところを紹介し、そこまでの工程を以下説明します。

2ksqw_with_windowfunc

Wg_2k_sqw

左上が、2KHzの矩形波をFFTして、そのスペクトルを表示したものです。 源信号は矩形波ですので、奇数次の高調波がきれいに並んでいます。 右上が、ウェブジェネレーター(WG)で発生させた2KHzの源信号です。 左上の画像で、水平方向は、2KHzスパンでメモリを合わせましたが、垂直方向は校正されていません。単位はdBです。

このc言語のパッケージは、オリジナルがdoubleの浮動小数点形式で作成されており、小規模なマイコン用ではなく、windows95が出たころのPC用に作られていると思われ、メモリーはかなりセーブしているように見えますが、16bitのPICには、まだ無理があります。 そこで、浮動小数点をfloatに代えて、メモリーの量とスピードをなんとかカバーしなければなりません。

FFTを実行する場合、サンプリング数が最小分解能を決めますが、この数は2のn乗でなければなりません。 今回は、LCDの横のピクセルサイズが320しかありませんので、これ以上多くしても表示は同じになります。 そして、320以内に収まる2のn乗の最大値は256ですので、FFTも256個のサンプル数で進めます。 また、サンプリング周波数ですが、バンドスコープで表示しようとしているIF帯域のキャリア周波数が約9.8KHzですから、最高で20KHzまで表示出来たらよいので、サンプリング周波数はその2倍の40KHzくらいで良い事になります。

従い、PICのADCはタイマー3から40KHzの周期で割り込みをかけ、そのたびにADCから10bitのデータを取り出し、これを256個だけメモリーに格納し、割り込みを中止した後、このデータをFFT関数に渡してFFT処理してもらいます。

FFT関数はa[]という配列変数に、「実数」「虚数」「実数」「虚数」・・・の順にサンプル数の2倍の配列数となっており、今回はa[512]の配列となります。 今回のFFTでは、虚数は使いませんので、ADCで得られたfloatのデータを実数部分に、0.0のデータを虚数部分に代入したあと、FFT関数に渡してやれば良いわけです。 下のfor文がそれを実行しているところです。 ADCの出力は符号付きintで取得し、これを512で割って、floatに変換し、a[]に代入しています。 途中のadfloatの変数は、CASTの不安定さを取り除くために、挿入したダミー変数です。これを中継して行わないと、時々プログラムがおかしくなります。

for (k=0;k <256;k++) {
adfloat=(float)ADdata[k]/512;
adfloat = adfloat * hanning256[k];
a[k*2]=adfloat;
a[k*2+1]=0.0;
}

2ksqw_no_windowfunc

 hanning256[k]はハニング窓関数で、この処理をしていないと、左の画像のごとく、低い周波数のすそ野が広がってしまいますので、必ず実行します。

このハニング関数は、エクセルで計算し、それをhanning256.hというファイルに編集してあります。

エクセルファイルの実物は、後で、ダウンロードできるようにしておきます。

このパッケージの中には、FFTの関数として、以下の2つの関数が紹介されています。

cdft: 複素離散フーリエ変換
rdft: 実離散フーリエ変換

両方とも実験したところ、スペクトルが細くなるのがcdftの方で、rdftの場合、窓関数を掛けても左上の窓関数なしのcdftくらいにしかなりませんでした。 また、両方ともメモリーの使用量は同じくらいでしたが、rdftの方が、処理速度が速いようです。 しかし、この実験ではcdftで進行します。

FFTを実行すると、a[]の中に結果が格納されて終了しますが、このデータの中で周波数スペクトルを表す実数はプラスとマイナスが有り、256ポイントの0から127ポイントまでが正の周波数を表し、128から255ポイントまでが負の周波数を表します。 今回の目的は0から20KHzまでの周波数スペクトルを256ピクセルのグラフで表す事ですので、負の周波数のデータが必要ありません。 従いa[]の0番目から127番目までの実数データだけを二乗平方根して、これを256ピクセルに棒グラフで表せれば良いのですが、グラフ画面のチラツキが激しく、安定したスペクトルを見る事が出来ません。 ちなにみ、実数の隣にある虚数を含めて二乗和の平方根とすると、かなり安定した、グラフが得られます。 バンドスコープとしては、この安定した状態のほうが見やすいので、この方法でグラフ表示する事にします。

用意したLCDの表示ピクセルは256ですから、結果的にふたつのピクセル列に同じデータを書き込む事になります。256のピクセルを有効活用しようとすれば、ADCのサンプリング数を512にすれば良いのですが、それを実行すると、即メモリー不足でエラーになりますので、このPICでは出来ません。

この、グラフの縦の目盛は対数としますので、二乗和は行いますが、平方根は実行しません。 この結果対数計算値は平方根を実行した場合の2倍になりますので、この結果に10を掛け算すると電圧レベルのdB値になります。

for (k = 0;k <= 127;k++) {//FFT結果の負の周波数は無視する。
j0=a[k*2];j1=a[k*2+1];
lvl=(int)4*(10*log10f(j0*j0+j1*j1));

lvl = Goffset - lvl;
if (lvl > DSdata[k]) {
      write_HVline(m,DSdata[k],m+1,lvl,backcolor);//xs<=xe ys<=yeの事
     }
     write_HVline(m,lvl,m+1,208,linecolor2);//xs<=xe ys<=yeの事
     DSdata[k] = lvl;
     m=m+2;
    }

 
この辺の計算式は1行で済ませるより、一度変数に格納してから、処理させると、実行時間が早くなるようです。

また、X方向に2ピクセルだけグラフデータを棒グラフで書き込む前に、前回書き込んだデータを消しますが、消す範囲は、今回のレベルより前回のレベルが高い場合のみで、かつ今回分から高かった表示のみ消していますので、グラフ画面全体のチラツキも最小限になっています。

ここまでやって先に紹介したようなスペクトルグラフが得られるわけですが、その処理時間は、実用レベルとはかけ離れていました。

FFTの計算時間は約78msecかかりました。

FFTの計算を含んだLCD描画時間は約120mescでした。

この時間では、実用は無理です。少なくと、現在の120msecを30msec以下にしないとダメでしょう。

結局、Tcyが16MHzの16bitマイコンでは、無理と判りましたので、もっと早く実行できるPIC用のソフトをさがすか、32bitマイコンに乗せ換えるか考えねばなりません。

今回の配線図です。

Fft_test_schema

2ksqw_final

上は、表示レベルを拡大したもので、縦方向のメモリが10dB/divくらいになっています。

この実験に使ったすべてのソースファイルです。 MPLAB Xのプロジェクトは左のようなファイル構成になっています。

Mplab_x0

bandscorp_float.cをダウンロード

fft4g_float.cをダウンロード

FFTexec_float.cをダウンロード

Hanning256.hをダウンロード

Font5.hをダウンロード

Font6.hをダウンロード

ハニング窓関数を作成するエクセル Hanning_coef.xlsxをダウンロード

 

 

 

 

  

 

7mhzband_scrp_0

完成ではありませんが、20KHzまでのスペアナができましたので、自作のSSBトランシーバーの2nd IFの出力につないでみたのが左の画像です。 使ったプログラムは上のソースファイルとは異なる実験用なので、上のソースファイルで左の画像が得られるわけでは有りません。

キャリア周波数が9.766KHzですから、その周波数を中心に+/-4KHzくらいは、反応があるはずと見てみると、LSBとUSBが反転しています。 これは、その通りで7MHzのLSB信号は、2nd IFでは反転し、USBになっていますので、この場合、負の周波数を表示しないと、グラフの周波数が逆になってしまう事を納得。

また、真ん中より少し上に淡い水平一直線のオビが見えますが、これは、ウォーターフォールのディスプレイを実験的に行ったものです。 たった5行のウォーターフォールですので、何がなんだかわかりませんが、このPICの残り少ないRAMを使って作りましたので、これが限界です。 それと、ウォーターホールを含めた、MAINルーチンの1周時間は140msecくらいになってしまい、スペクトルが見慣れたPCのバンドスコープのようには見えません。 この第2IF信号を使ったバンドスコープをしばらく見ていましたが、表示される範囲は、ルーフィングフィルターとなる24MHzのクリスタルフィルターの帯域内のみで、+/-3KHzが表示されるだけです。 HDSDRを経験した身としては、面白くありません。 せっかく作るなら、せめて+/-50KHzくらいはカバーしたい。

 

これらの課題を抱えて、実用的なバンドスコープをどうやって作るか再検討する事にします。

 

INDEXに戻る

2021年8月22日 (日)

PICでオシロスコープ 2

このプロジェクトを始めたのは、自作のトランシーバーにバンドスコープを追加する目的でしたが、その途中のオシロスコープが中途半端に出来上がると、せめてオーディオ信号くらいは、表示できるオシロに仕上げられないかと、開発を継続する事にしました。

前回、PIC24FV32KA302というマイコンで、オシロスコープの基本動作を確認し、LCDに描画された波形を静止する検討を行いましたが、RAMが2Kバイトしかなく、静止する事はできましたが、その頻度が少なく、画面のチラつきが目立つ状態でした。 そこで、RAMが8Kバイトある、PIC24FJ64GA002に変更して、再挑戦です。

Oscv2_schema

 

上が、今回の回路図です。PICは変更してあります。 そして、描画された波形を静止させるためのトリガレベルの調整機能を半固定抵抗で追加してあります。 このレベルはLCD画面の左側に赤色のラインで位置を示し、かつ左下に、ADCの出力レベルをそのまま数値で表示してあります。 この数値はソフトを変更する事により電圧値の表示に変更は可能です。

Osc2_1khzsin

Osc2_10khzsin_2

左上が、Seep時間 500usec/divでの1KHz、右上が100usec/divの10KHzの波形です。

このマイコンのADCは最高500KHzspsのスピードまで可能ですが、右上の時は、457KHzspsくらいでスイープしており、10KHzの波形もなんとか見れる状態になりました。 まだ、スイープタイムの可変機能が有りませんので、プログラムを書き換えて取ったデータです。

この改良型オシロは、デジタルデータを1024ポイント分取り込み、その中で、予め設定したトリガレベルを10番目から712番目までの中から探し、そのメモリー位置から255メモリー分のみLCDへ表示します。 前回のオシロの実験中にも、この機能を入れて検討を行いましたが、検索できるメモリーの範囲が先頭から69番目くらいしか出来ず、たまに、描画できる波形を検出して、LCDに表示しますが、その頻度が1秒間に数回程度でした。 今回は712番目まで検索範囲を拡大しましたので、前回より10倍の頻度で静止波形を描画できるのですが、実際は5倍くらいにしかなりませんでした。 原因を調べるも、良くわからず、不明のまま、完成度を上げていく事にします。(原因が判りました。後述します。) それでも、トリガレベルを起点にきれいに静止した波形を見る事が出来ます。 このソフトは立ち上がりのトリガレベルしか検出していませんが、ソフトをスィッチで選択できるようにし、立ち上がりも、立下りのエッジも検出可能にする事は可能です。

このテストボードには、スイープタイムや入力レベルの設定回路は、付いていませんが、ソフト的には、未使用i/oを使用して取り込み可能です。

また、前回のソフトでは、格子メモリを描画する為に、かなりの時間を必要としていましたので、以前、アンテナアナライザー開発時に得たいくつかの高速描画手法を取り込みました。 斜めのラインは従来のままですが、水平、垂直のラインに限っては、前回のソフトより4倍以上速くなっています。 その上で、波形を3回書き換える毎に格子目盛を再描画して、全体の描画速度を上げてあります。 また、LCDへの書き込みもLCDのWindow機能を最大限に生かすべく、手直ししてあります。

デバッグの為、ADCが出力したデータを数値でLCD上に表示させてみると、同じ数値が二つならんで表示されています。1024ポイントのデータを取得したつもりでしたが、実際は512しか取得していない事が判りました。 原因はADCをスキャンして、入力信号とトリガーレベルを同時に取得した為に発生したようです。 トリガーレベルの取得をやめると、データの取得数は1024になります。 トリガがかかる頻度が予想の半分くらいしかないのはこれが原因でした、

Osc3_1khzsin


そこで、タイマー3による割り込み時は、入力信号のみ取得し、トリガーレベルは、タイマー3による割り込みがかからない時間に、単独で取得する事にしました。 データの更新がほんの少し長くなりますが、LCDに表示される波形が滑らかになりました。 

左の画像は、対策後の波形で、以前の波形より滑らかになっているのが判ります。

 

トリガーレベルの検出頻度が上がって、描画回数は増えたのですが、旧波形をバックグラウンド色で再描画する事により一旦全部消して、新しい波形を再描画するプログラムでは、波形のチラツキは解消されませんでした。 そこで、以前、アンテナアナライザのアナログメーターの指針描画の手法を取り入れ、旧波形のひとつの直線を消したら、同じ列に新たな直線を即書き込むようにプログラム変更しました。 すると、うそのようにチラツキはぴたりと止まり、きれいな静止波形が描画され続けます。 

斜めの線の描画速度を高める為に、線の太さを1ピクセルに限定した高速関数をふたつ作り、従来の関数との描画時間の比較を行いました。

斜め線は開始点がx=20,y=50 終点がx=250,y=150で、左うえから右下へ斜めに走る線です。

① write_Line(m,j0,m+1,j1,0,linecolor);//開始x,y 終了x,y 線幅(0or1) 色
② write_HSLine(m,j0,m+1,j1,linecolor);//開始x,y 終了x,y 色
③ Bresenhamline(m,j0,m+1,j1,linecolor);//開始x,y 終了x,y 色

従来の線幅を変えられる①の関数の場合、描画時間は6.5msec

高速描画の②の関数では、 2.8msec

ブレゼンハムの③の関数では、2.3msec

でした。ただし、③はまだ完成度が低く、線が連続せず、破線としか描画出来ていません。

下の画像は左が①の関数、右が②の関数です。、

 

Normalspeed2khz

Highspeed2khz_2

右側の正弦波はピーク付近で、うまく描写出来ていない波形となっております。 また、チラツキはほとんど無く、差はありません。 結局、オシロスコープの波形表示としては、描画速度より、線の太さを変えられる①の方がメリットがありそうです。 ちなみに、線幅を2ピクセルとした時の先の斜め線の描画時間は8msecで2倍になることはなく、波形がきれいに見えます。

従来の①のみのソース oscillo_64GA_1.cをダウンロード

②と③を選択できるソース oscillo_64GA_hs1.cをダウンロード

Font5_6.hをダウンロード

 

斜め直線では、上記のような描画時間となりましたが、実際の正弦波を描画させた時の時間を検討してみました。

検討に使ったソース oscillo_64GA_hs2.cをダウンロード

この中で、次の6つの関数を計測しました。 いずれも2KHzの正弦波を1画面描画する条件です。

① write_Line(m,j0,m+1,j1,1,linecolor);//開始x,y 終了x,y 線幅(0or1) 色// 
② write_HSLine(m,j0,m+1,j1,linecolor);//開始x,y 終了x,y 色
③   write_HS2Line(m,j0,m+1,j1,linecolor);//開始x,y 終了x,y 色
④   Bresenhamline(m,j0,m+1,j1,linecolor);//開始x,y 終了x,y 色
⑤   write_oscline(m,j0,j1,linecolor);
⑥   write_osc2line(m,j0,j1,linecolor);

①はLCDの全画面に、かつ斜め線の角度の制限なしで線幅を指定できる関数で線幅1ピクセル時の時間は49msec、X及びY方向に各2ピクセル、計4ピクセル描画時63msec。1ピクセルの場合、他の1ピクセル描画の関数と変わりませんが、2ピクセルの場合、X,Y各方向へ2ピクセルなので、水平、垂直いずれの線幅も2ピクセル分となり、特に水平が含まれる矩形波の描画は一番きれいです。

② LCDの全画面に角度の制限なしで描画する線幅1ピクセル専用の関数です。描画時間は22msec。

③ ②の線幅2ピクセル版です。 描画時間は31msec。 2ピクセルはY方向だけで、斜め線や水平直線は2ピクセルで描画しますが、垂直線は1ピクセルの線となります。

④ ブレゼンハムの関数で、線幅1ピクセルのみです。描画時間は10msec。 ただし、破線にしかなりません。 多分、ソースの詰めがまだ甘いのでしょうが、破線を実線に改善すると、当然時間も増えますので、単純見積もりで②と同じくらいにしかならないと思われます。

⑤ オシロスコープの描画ではX方向は常に1ピクセルしか増えないので、その理屈を利用して、掛け算と割り算を無くした関数で、線幅1ピクセル専用です。 時間は12msec。 

⑥ は⑤のアルゴリズムのままで、2ピクセルの線幅にしたものです。描画時間は23msec。2ピクセルはX方向のみで、水平線は1ピクセルにしか描画されません。

Originalline

Original2line

左の画像の内、左側が①の関数による線幅1ピクセルの2KHzです。 右側は、同じく①の関数で線幅2ピクセルです。

この①の2ピクセルが一番きれいに波形を描画出来ています。

Hsline

Hs2line

 この列の左側が②の関数、右側が③の関数になります。③の関数は2ピクセルの線幅なので、斜め線はきれいですが、水平線は1ピクセル時と同じとなります。

 

 

Oscline

Osc2line

この列の左側は⑤の関数による線幅1ピクセルの波形です。1ピクセルの波形では一番きれいに見えます。

右側が⑥の線幅2ピクセルの波形です。③よりラインが滑らかですが、水平線は1ピクセルでの描画です。

 Brezenline

最後の左の1枚が④のブレゼンハムのラインで破線になっています。

結局、実用的オシロスコープの描画関数は波形のきれいさを追求したい場合、①の2ピクセルが最適。 描画の速さを追求したいときは⑤という選択がありそうです。

 

 

Osc2y_2ksq

Osc2_2ksq

気になって、⑥のX方向に2ピクセルした時の矩形波と、Y方向に2ピクセルした時の波形を確認してみました。 左がX方向、右がY方向を2ピクセルにしたものです。 クローズアップすれば、差が判りますが、遠くから見るとどっちもあまり変わりませんでした。

 

これらの検討結果は、本格的なデジタルオシロを自作するときの参考にする事にします。 

 

PICでFFT (XC16でFFTにトライ)へ続く

  

INDEXに戻る

2021年8月14日 (土)

PICでオシロスコープ

「デジタルオシロ 自作 TFT LCD」

自作のSSBトランシーバーにバンドスコープを追加する為には、デジタルオシロスコープで、タイムドメインのデータを収集し、このデータをFFTにて、周波数ドメインに変換して、TFT LCD上にそのスペクトラムを表示させる必要がありますが、前回、このTFT LCDをPICマイコンで制御できるところまでできました。 今回は、アナログ信号をADコンバーターで取り込み、デジタルデータとしてメモリーに記憶させる部分の検討を行います。

バンドスコープの構成上は信号波形をLCD上にグラフィックで表示する必要はないのですが、デジタルデータが目標通り取り込めたかどうかを確認する為に、取り込んだデータをLCD上に表示する事で目標達成とします。

使用するPICマイコンはLCDの駆動に使ったPIC24FV32KA302をそのまま使います。 このマイコンのADコンバーター(以下ADC)は12bit対応ですが、最高サンプリング周波数は100KHzとなっています。 バンドスコープの対象周波数範囲は最高で20KHzであり、100KHzのサンプリング周波数でも十分なのですが、内蔵するRAM容量が2Kバイトしかなく、本格的なデータ収集器にはなり得ません。 その為、基本機能を実現する為のテストバージョンとして、デジタルオシロスコープを作る事にします。

Oscv2_schema_2

 

上が、今回のデジタルオシロテストバージョンの回路図です。 PICの品番はPIC24FV32KA302でRAM2Kバイト品です。

デジタルオシロを安いPICとLCDでいかに実現するかは、実際にやりながら、カットアンドトライしていく事にしました。

AD変換は12bit対応のままで、最高速度で変換させるように設定すると、約75nsecで変換完了する事が判りました。ただし、この場合、AD入力に接続される側の出力インピーダンスを極力小さくして、リニアリティの確保をしなければなりません。実際は低出力インピーダンスのOPアンプで駆動必要ですが、実験では、最高レベル付近でのリニアリティが悪化する事を承知で、発振器の出力を直結です。 発振器の出力インピーダンスは、多分120Ωくらいですので、大きく悪化する事は無いと予想しています。

私は、実際のデジタルオシロがどのような構成で動作しているのか知らないので、表面上の動きから推測した以下の工程で、実現する事にしました。

① ADCはタイマー3によるトリガーで、サンプリングを開始するようにし、タイマー3の周期を変えて、サンプリング周期を設定する事にします。

② タイマー3の割り込みで得られたADCのデジタルデータは、320ワードのメモリーへ記録させます。 サンプリング周期が100KHzくらいですから、C言語で書かれたソフトでも十分間に合います。 メモリー一杯データを記録したら、一旦データの取り込みを中止します。

③ メモリーに記録されたデータをLCD上にグラフとして表示させます。 表示は各メモリーごとのデータを線で結ぶ直線補間方式としました。

④ メモリーのデータを表示し終えたら、また、①に戻りこれを繰り返します。

⑤ ただし、このままでは、先に描画したグラフデータが残っていますので、2回目のグラフデータを書く前に1回目のグラフデータを消す必要があります。 消す方法は、③の書き込み処理をバックグラウンド色で再描画する事により消します。 前のデータを消す方法として、グラフ描画エリア全体を、バックグラウンド色で塗りつぶす方法もありますが、これは結構時間がかかり、グラフィックのチラつきの元になりますので、採用しません。

⑥ オシロスコープですから、LCD画面上に格子のメモリが必要になりますが、今回使用するローコストのLCDグラフィックボードのメモリーは1面分しか有りませんので、この格子パターンも③や⑤の描画で消えてしまいます。従い、⑤のグラフ消し完了後、毎回格子模様を再描画する事にします。

⑦ このオシロスコープは、トリガーなしで、繰り返し描画をおこないますが、そのままでは、前回のグラフデータと同期がとれなく、見た目では、波形が左右に流れる現象が発生します。 この為、繰り返し描画を停止させて、その瞬間の波形のみを表示し続けられるスィッチを追加してあります。

⑧ 通常のオシロはいわゆる「シンクロスコープ」であり、例え繰り返し描画でも、そのトリガーレベルを調整する事により、波形が流れずに、静止して見える機能がありますが、このトリガポイントを検出するには、メモリーが不足し、完全に静止した画面が得られません。 記憶させるメモリーの量を増やし、全く同じ位相のデータを、メモリーの中から拾い出し、それを、続けて描画していけば、波形は静止するはずですが、2Kのメモリーでは実現できませんでした。 これは、PIC24FJ64GA002のRAM 8Kバイト品を入手してから、再検討する事にします。

これらの試行錯誤の結果から得られたLCDの画面は以下です。 ①②⑤⑥③⑦①②・・・の順序で繰り返し動作し、⑧は処理していません。

Iosctest1khz

Iosctest10khz_2

左上が1KHzの正弦波、右上が10KHzの正弦波です。 直線補間していますので、16KHzくらいまでは、それらしく描画できますが、実用的には10KHzくらいまでです。 この時の水平方向のsweep時間をグラフの格子メモリの端から端まで2msecとすると、ADCサンプリング周波数は約133KHzで、PICのスペックをオーバーしていますが、なんとか表示出来ています。

実験に使ったソースは以下です。

oscillo_0.cをダウンロード

Font5_6.hをダウンロード

下の写真は蛇の目基板に組んだテストバージョンのオシロで矩形波を表示させているところです。

Iosctestallview

RAMが2Kしかなかったので、8KのPICに変更します。 この中で、直線や斜め線を描画する、アルゴリズムも改善し、LCDのイニシャライズも修正したプログラムを「PICでオシロスコープ2」 で使っています。

PICでオシロスコープ 2  へ続く。

 

INDEXに戻る

2021年8月 1日 (日)

LCD SPC-S95417-AAAをPICでドライブ

SDRのトランシーバーが実用レベルになりましたので、現在は付いていない、バンドスコープの自作にトライしようと考えておりますが、それを実現する為には、デジタルオシロスコープを製作し、記録されたデータをFFT処理して、その結果をLCD上に表示する必要があります。

そこで、まず、この表示用LCDを入手し、そのLCD上に自由に描画できる必要がありますが、以前、アンテナアナライザに採用した、320x240のLCDはそのノウハウを得とくしているものの、値段が1900円くらいまで上昇し、かつ40pinのフラットケーブル用コネクタとこれを半田付けする基板を必要とします。コネクタは通販で入手できますが、これを実装する基板はカスタムとなり、新作するしか有りません。 1回、かつ1台だけの基板を作る訳にもいかず、このLCDはあきらめて、aitendoで扱っている基板付きの中華LCDを使う事にしますが、このLCDに対しては今までのノウハウは通じませんので、まずは、使いこなす事から始めます。

選択したLCDは★2.4インチ★TFT LCD with 基板 [LCD9325D8A]と言う品番で、1050円(税抜き)で売られていました。 動作チェックはされていましたが、PICでは無いので、ソフトは一から作る必要があります。 そこで、このLCD部分の仕様を確認しようと、リンク先をクリックすると、エラー。

インターネットで色々調べると、このLCDはSPC-S95417-AAAという品番の中華製で、携帯ゲーム機に使われていたもので有る事がわかりました。 pdf版の仕様書を入手し、ドライブIC名を探すと、ILI9325というICらしい。 そこで、このILI9325の仕様書を探し出し、ソフト製作を開始する事にしました。

Lcdtestschema0_3

上がLCD実験用のテスト回路図です。 バンドスコープに使用するPICはdsPIC33CHかPIC32MZレベルの32bit品になりますが、とりあえず、16bitのPIC24FV32KA302で、制御の仕方を勉強する事にします。

aitendoの製品は、LCDと基板は半田付けされておらず37pinのFFCを基板に自分で半田付けする必要があります。 フラックスを少々塗ったFFCを電極に張り付け、セロテープでずれないように固定してから、60Wの半田こてで半田を流しこんで、さっと半田切りを行って、目視でOKの判断をした後、通電しても、バック照明用のLEDは点灯しますが、LCD面にはなにも表示されません。 10倍の拡大鏡を使い、37pin全部の半田付け状況を確認したところ、極細の半田くずでショートしている端子が2か所。これを解消して、やっとLCD上になにか表示されるようになりましたが、これから先が悪戦苦闘の連続でした。

 

このLCDのイニシャライズプログラムをインターネット上で探し出し、とりあえず、それをそのままコピペしたのですが、縦横のスキャンやカラーが思ったように表示されません。 やむなく、ILI9325の英文仕様書の関係しそうな項目をGoogle翻訳で訳し、何度も読み直して、やっとわかった事は、このICの標準姿勢は縦長であるという事でした。 私はこれをオシロやスペアナにして使うつもりなので、横長が標準です。 それが判ると、横長に置いて、左から右へ、上から下へスキャンできるようになりましたが、カラー設定が仕様書に記載されたBGRの設定と逆になってしまいました。 結局、この設定が反転した理由が判らないままですが、動作的に異常はないので、このまま行く事にしました。

グーグル翻訳の場合、pdfの文字列の改行の部分で、文章終了と判断する為、日本語の並びに不自然さがありますが、せっかく作った翻訳仕様書ですので、公開して置きます。

ILI9325の和文翻訳仕様書(抜粋版) ili9325.docxをダウンロード

Lcdtest0

左の写真が完成したテストプログラムによるLCD表示のサンプルです。

表示している、文字は、過去PIC用に作成した自作のフォントです。 黄色のフォントは今回、このLCDに合わせて新作しましたが、コードジェネレーターのバグなのかわかりませんが、スペースのみゴミが表示されます。 その内、改善しようと思います。 写真では、LEDシリーズ抵抗として22Ωが見えていますが、この裏側に10Ωの抵抗が付いており、トータル6.8Ωの抵抗となっています。

LCD表示の速さは、使っているPICのクロックが32MHzの為、ILI9325のspecぎりぎりになっていません。 もっと早いクロックでもディレーを挿入する事なく動作するかも知れませんが、それは、実際にバンドスコープを作る時に確認する事にします。

 

黄色の文字のスペースにゴミがある原因を調べていましたら、X方向のbit数が8を超えるフォントの構造に誤りが有る事が判りました。 この構造の誤りがある状態で、LCD上に正常に文字を表示できる、表示プログラムも誤っている訳で、過去作成したすべてのプログラムが間違っている事になります。

今回、フォントコードジェネレーターを作り替え、X方向のbit数に関係なく、正常に構成出来るようにしましたので、8bit以上のフォントファイルも作り替えました。 表示プログラムもフォントのサイズごとに作っていたものを、ひとつの関数で全部処理出来るように変更しました。

テストプログラム lcds95417aaa_0.cをダウンロード

関連フォント Font5_6.hをダウンロード   Font9.hをダウンロード   Font12.hをダウンロード

RAMが2Kしかなかったので、8KのPICに変更し、直線や斜め線を描画する、アルゴリズムも改善し、LCDのイニシャライズも修正したプログラムを「PICでオシロスコープ2」 で使っています。

PICでオシロスコープへ続く

 

INDEXに戻る

2020年5月24日 (日)

mplab x pickit3 connection failed

<カテゴリー:PICマイコン

Pickit3_error

Windows10のPCにMPLAB X V4.20をインストールして、快適にソフト開発を行っていましたが、先日、すでに完成したソフトの中に、バグがみつかり、これを修復し、再コンパイルしようとしたら、左のショットのように、PICkit3に接続しようとした時、

connection failed

になってしまいます。 

MPLBA X そのものは、左側の Debug Toolの部分にPICkit3とそのシリアルナンバーを認識しており、頭 を抱えていました。Usb_hub_2

  インターネットで調べたら、MPLBA IPE というツールでファームウェアを更新するとか、レジストリを書き換えるとかありますが、レジストリには手を出せませんので、それ以外の方法をああでもない、こうでもないと丸一日つぶした結果、原因はUSBハブでした。 過去もUSBハブを使用していて、問題はなかったのですが、今回使ったELECOMのハブは初めてでした。

PCのUSBポートに直接PICkit3を接続すると、異常は起こりません。 

このハブはCANONのプリンターでは問題ないものの、その後、CANONのデジカメによる画像読みこみでも異常が発見され、使用を中止しました。 USBハブが無いと不便ですので、買い替える事になりました。

NGのハブ ELECOM U3H-A416B

OKのハブ BUFFALO BSH4UR0U3

  

2023年9月

その後、FTDX101Dを導入した時、FT8の受信の為にUSB接続をする必要があり、このELECOMのUSBハブを使ってみました。 単純なRS232Cベースの通信では問題なさそうです。

 

INDEXに戻る

2019年5月 6日 (月)

PIC24FJ64GA004 フラッシュメモリーへの書き込み(EEPROM代用)

<カテゴリー:PICマイコン

16bitのPICマイコンの中で、24FシリーズにはEEPROMを個別に持っているものと、プログラムを格納するフラッシュROMエリアにデータも書きこんで、これを読み出す事により、EEPROMを代用できるものとに分かれます。 今回、PIC24FJ64GA004 において、EEPROM機能を必要としましたので、そのソフトをXC16のプログラムで紹介します。

Microchipやインターネットに情報公開している大先輩方による解説は沢山あるのですが、あまり考えずにコピペして使えるプログラム例がありませんでしたので、コピペだけで、済まそうという方に参考になればと思い公開します。

条件: フラッシュメモリーのアドレス0x9600から600バイトをEEPROM代用に宣言し、その中で64ワード分を読み書きできるようにします。 

このデータメモリーは起動時にフラッシュROMエリアのデータを必要分のみ読み取り、プログラム実行中に変更されるあるいは変更されないデータいずれも、全てまた同じアドレスに書きこむことを基本動作としています。 例では lastmemory[] という変数の中にメモリー必要なデータが保持されるようにしています。 また、書き込み動作は結構時間がかかりますので、64ワード全てが必要でない場合、必要なワードのみを書き込み、影響を最小限にしています。 例では0から6までの引数(7種類)のデータだけを読み書きし、時間短縮を行っています。

コピペする範囲を青色、各自でアレンジする必要あるところを緑で示します。

最初にインクルードファイルです。

#include <libpic30.h>

次にグローバル変数を定義します。

section(".Data_Memory")の記述は、MPLAB Xにてコンパイルした時、メモリーマップが表示されるようにしたもので、リストの中に.Data_memory という情報を見つける事ができます。

//////////////グローバル変数として以下定義

unsigned int lastmemory[64];//EEPROM

const __attribute__((section(".Data_Memory"), space (prog), address (0x9600) )) unsigned int _flash_datas[96*8];

以下、読み書きENDまでが読み込み、書き込み関数です。 ここは何も考えずにコピペすればOKです。

/////////////////////////////////////////////フラッシュメモリー読み書き
void Flash_Read(unsigned char LN) {
 unsigned int i=0;

    unsigned int page = __builtin_tblpage(&_flash_datas);
    unsigned int offset = __builtin_tbloffset(&_flash_datas);
      // フラッシュメモリー読み込み
    TBLPAG = page;
    for (i=0; i<=LN; i++) {
        lastmemory[i] = __builtin_tblrdl(offset + i*2);
    }
}

void Flash_Write(unsigned char LN) {
    unsigned int i=0;
    unsigned int page = __builtin_tblpage(&_flash_datas);
    unsigned int offset = __builtin_tbloffset(&_flash_datas);

    
    // ページ消去
    TBLPAG = page;
    __builtin_tblwtl(offset, 0x0000); // 
    NVMCON = 0x4042;
    asm volatile ("disi #5");
    __builtin_write_NVM();          //erase 8line = 64*8
    while(NVMCONbits.WR);
 
    // ラストメモリー書き込み
    NVMCON = 0x4003;
    TBLPAG = page;
    for (i=0; i<=LN; i++) {
        __builtin_tblwtl(offset + i*2, lastmemory[i]);  // *2 偶数
        __builtin_tblwth(offset + i*2, 0xFF);
   
    asm volatile ("disi #5");
    __builtin_write_NVM();
    while(NVMCONbits.WR);
    }
}
/////////////////////////////////////////////フラッシュメモリー読み書きEND

以下、読み出したデータ lastmemory[] の中を、プログラムで使用している変数に分解します。 フラッシュメモリーはワード単位で読み出されますので、32bitのデータや8bitのデータはそれなりに加工が必要になります。 この例では、lastmemory[0],[1] は合成して32bitのデータに変換しています。 また、例えcharの変数でも16bit全体を使い余計な処理は省いています。

void readlastmemory(){
 unsigned long int bf;
 Flash_Read(6);//引数6は最後の[6]を指定する事
    bf = lastmemory[1];
 bf = bf << 16;
 BASEFREQ = lastmemory[0] | bf;
 V_level = lastmemory[2];
 MODE = lastmemory[3];
 IWB = lastmemory[4];
 RIT = lastmemory[5];
 Ritfreq = lastmemory[6];
}

以下は、プログラムで使用中の変数を lastmemory[] に格納した上フラッシュROMへ書きこみます。

void writelastmemory() {
 lastmemory[0] = BASEFREQ & 0x0000FFFF;//BASEFREQは32bitデータなので、[0],[1]に分割する。
 lastmemory[1] = BASEFREQ >> 16;
 lastmemory[2] = V_level;
 lastmemory[3] = MODE;
 lastmemory[4] = IWB;
 lastmemory[5] = RIT;
 lastmemory[6] = Ritfreq;
 Flash_Write(6);//引数6は最後の[6]を指定する事

}

MPLAB XにてコンパイルするときMPLAB Xの設定を少し変更が必要です。

Mplabx190506

Project Propertiesの中のXC16_gccを選び、上のoption categories の中のMemory Modelを開き、添付のようにチェックマークを入れます。(通常はマークなし) ただし、この状態は私の環境によるもので、使用状態では異なる可能性があります。 エラーが出る場合、この辺のチェックを付けたり外したりしてみて下さい。

このプログラムの実施例はこちらに有ります。

PIC24FV32KAシリーズのEEPROMアクセスコード例はこちらにあります。

dsPIC33fj32GP202(ROMが32Kの16bitマイコン)のフラッシュ領域に256ワードのデータを記憶させた例はこちらに有ります。

 

INDEXに戻る

2018年8月13日 (月)

PICkit3 の修理

<カテゴリー:PICマイコン

DDS VFOの検討中に5Vの三端子レギュレーターが壊れてしまい、+5Vラインに+12Vが現れ、接続してあったPICkit3が煙を出して壊れてしまいました。

壊れたのは、バストランシーバーと呼ばれるPICkit3と外部回路のインターフェースに使われるICでした。

これを修理すべく、まずPICkit3の回路図を探すと、結構多くの情報がありました。 インターネットで調べていくと、MicrochipはPICkit3のクローンを容認しているというか、推奨しているようで、Microchip自身が回路図を公開していました。

pickit3sch.pdfをダウンロード  

この配線図そのものはMicrochip 製なのかクローンを作った会社のものか判りませんが、現物照合すると抵抗値が一部異なる所はありますが、IC名や結線は合っていました。

壊れたICはSN74LVC1T45DBVRという品番のバストランシーバーである事が判りました。 このバストランシーバーのパッケージは何種類もありますが、PICkit3に使われているのは、最後の文字がDBVRという一番大きいサイズのものです。

東京出張の帰りに、このICを秋葉原で探しましたが、結局見つからず。 帰ってからRSで見つけましたので注文し、現物も入手していましたが、その間にクローンのPICkit3を入手していましたので、修理は手づかずの状態でした。

最近、このバストランシーバーを実験する機会があり、PICkit3の修理の事を思い出しましたので、修理にトライする事にしました。

壊れたICは完全に黒焦げで、下の基板も炭化し、一部銅箔も無くなっていました。 本来6個の半田ランドが必要なICですが、6番ピンのランドとストリップラインは消失し、4番ピンに接続するストリップラインも消失していました。 拡大鏡を駆使してなんとかハンダ付けし、出来上がった基板は以下です。

Picki3up

Pickitopen

左上が黒焦げの基板上に新しいICをマウントし、消失したストリップラインの代わりに0.18mmの銅線で配線した状態です。 この作業の後、テスターを使い導通テストを繰り返し、接続漏れや逆に端子間ショートが無い事を確認した後、通電し、PICのターゲットを接続すると、ターゲットのIDが返ってきて、プログラムも無事書き込む事が出来ました。

これから、電源電圧には細心の注意を払う事にします。

INDEXに戻る

2016年1月 1日 (金)

LCD-TS174をPICによりドライブ

<カテゴリー:PICマイコン

「aitendo」という通販ショップで99円のLCDが売られていました。 その他の部品を含めてこのLCDを2個購入したのですが、仕様書はなし、有るのは、使用されているICの品名と、ATMELのチップ用デモソフトのみという物でした。 

今、PICマイコンで正弦波発生器を作っていますが、この周波数表示にちょうど良さそうですので、このデモソフトをPIC用に書き換え、WEB上からダウンロードしたICの仕様書を基に周波数を表示させてみる事にしました。

使用するマイコンはPIC16F1827という8bitのマイコンです。 周波数表示ですので、マイコンのクロックは7.2MHzの水晶発振で、これをPLLで4倍とした28.8MHzのメインクロックとしてあります。

回路図 LCD_demo_schema.pdfをダウンロード

オリジナルのデモソフトをこの配線図に合わせてi/o変更をした上で、XC8でコンパイルできるように書き換えました。 オリジナルの仕様では、一旦LCD全画面をクリアーした後、左側から順番に各セグメントが点灯していきます。 これをヒントに7セグの数値を表示させるコードを調査し、下記のように解析しました。

Ts147_segmap

このコード表をベースに7ケタの整数を表示するプログラムを作りました。数値以外に文字やドットがありますが、今回は使っていません。

Lcd1250disp

このLCD用のICのクロックは3.3uS以上を要求していますので、余裕を見て約6uSくらいのクロックになるようディレーを入れてあります。 また、メイン関数の170行目にwhileで無限ループを作り、以下のプログラムは実行されないようにしてあります。 この170行目のwhile文をコメントアウトすると、オリジナルデモソフトが動作します。  

また、プログラム上にはLEDが出てきますが、デバッグ用です。 さらに、RB0からの外部割込みの記述もありますが、このLCD表示については不要です。

PICkit3からHEXファイルを書き込もうとするとき、このICもVDDを5Vを指定するとエラーになります。4.875Vに設定すると問題無しです。

99円のLCDでも十分実用になります。 周波数のLCD表示が可能になりましたので、正弦波発生器のコントローラーを作る事にします。

ソースコード LCD_TS174BNLdemo.cをダウンロード

このオリジナルソースをベースにXC16でコンパイルしたところ、LCDのデータラインに信号が出ません。 色々調べた結果、下のLCD_Wr_Data()の関数の中で、

 B=B>>7; の処理を追加しないと、現状のままでは、データをi/oポートへ送る事が出来ない事が判りました。 判ってしまえば当たり前の事で、いままで動いていたのが不思議なくらいです。

void LCD_Wr_Data(unsigned char Data,unsigned char cnt) {
   unsigned char i,d,B;
    d = Data;             //Dataを一度ローカル変数に置き換える
    for (i=0;i<cnt;i++) { 
         LCD_WR=0;
         delayNop();
         B=d & 0x80;         //Dataと0x80とアンドを取った値を一度ローカル変数に置く
        B=B>>7;
         LCD_DA =B;          //LCD_DA=Data & 0x80 ではうまくいかない
         delayNop();

         LCD_WR=1;
         delayNop();
         d = d<<1;
       }
  }

INDEXに戻る

2015年12月 9日 (水)

正弦波発生器(PIC18F14K50)

<カテゴリー:PICマイコン

CQ誌のPWM変調AM送信機の記事に魅せられて、微力ながら、このアナログの塊のオールソリッドステートの送信機を作りたくなりました。  WEB上の情報から、この送信機の構成は理解できましたので、部品集めを進める傍らで、AM変調用の低周波発振器の必要性を認識しました。 実は、45年前に購入した20Hzから200KHzまでカバーするKENWOOD製の低周波発振器を6年前に完動品のまま粗大ごみに出してしまった事を悔やんでいます。 

CWのサイドトーン用にウィーンブリッジ式の正弦波発振器の製作例はこのブログでも紹介していますが、せっかくPICマイコンを曲がりなりにもいじれるようになりましたので、マイコンからDA変換を利用した正弦波発生器ができないか検討する事にしました。 WEBで検索すると、PICマイコンで正弦波を発生させる方法が沢山見つかりました。 その中で、マイコンのシステムクロックをフリーランの外部クロックで駆動し、任意の低周波周波数を得る方法と、固定クロックでADの出力周期を変えながら複数のスポット周波数として発生させるアイデアがあるようですが、その中で、比較的ひずみ率が良好で、簡単なCRフィルターで構成出来る8bitのラダー抵抗式DAコンバーターが良さそうです。

AM送信機で必要な周波数は1KHz、及び300Hzから3KHzの変調周波数特性と、これより広い範囲でどれだけ減衰しているかをチェックできる周波数帯となる100Hzから6KHzくらいをスポットでカバーできる周波数があれば良く、周波数も大体でOKですが、ひずみ率は1%以下とし、全周波数帯域に渡り出力レベルは+/-0.5dBくらいに抑えたいという条件があります。

マイコンは、使い道が無く、ジャンク箱に転がっていたPIC18F14K50というチップを拾い上げ、これにアセンブラでソフトを仕込む事にしました。 アセンブラによるソフトの開発は30年以上前にMC68000で少しかじっただけでしたが、データシートやWEBでの情報を頼りに再挑戦する事にしました。

まずは、ちゃんと正弦波が発生できるかどうかですが、約1週間かかり、なんとかそれらしき信号が得られました。 

40hz_nolpf_2

9khz_nolpf_3

左は最低周波数、1サイクルを256分割した40Hzの波形。右は最高周波数、1サイクルを64分割した12.5KHzの波形です。いずれもまだLPFは入っていないDAC出力直後の波形です。

波形の様子から、簡単なCRによるLPFでクロックによる高調波は取り除く事ができそうです。OP-AMPによりカットオフ周波数約30KHzのLPFを作り、DACとこのLPFが持っている周波数特性をもう1段のOP-AMPで補正し、40Hzから12.5KHzまでほぼフラットな正弦波発生器ができました。

40hz_lpf

1khz_lpf

9khz_lpf

左から40Hz,1KHz,12.5KHzのLPF後の波形で、周波数特性の補正を行い、振幅を一定にしたものです。ひずみ率計がありませんので、はっきりした数値は判りませんが、経験的にいずれもひずみ率は1%以下になっているようです。

配線図をダウンロード

A_osc2

A_osc1_2

上がPICによるDAコンバーターとLPFのOP-AMPを実装した基板です。 基板裏側の左側の空き地は後日、この正弦波発生器をコントロールするマイコンを実装するスペースです。

PICのプログラムは周波数を初期設定した後、無限ループに入って、正弦波を出力し続けますので、周波数を変更したい場合、周波数設定用のSW1からSW5をセットした後、RESETスイッチSW9を押すことで実現します。 これをロータリーSWかロータリーエンコーダーの操作のみで実現する為に、周波数表示が可能な簡単なマイコンを実装する予定にしていますが、今回の目的が、AM送信機を作る事なので、コントロールマイコンやケース入れは後回しにします。

 ソースコード sin_wave_osc.ASMをダウンロード

SW1-SW4に対応した周期カウント値は適当な値ですので、周波数カウンターを使い、トリミング必要です。

INDEXに戻る

2015年10月18日 (日)

PICマイコンでSDカードのファイルを読み込む

<カテゴリー:PICマイコン

マイクロチップのMLAの中にあるデモソフトは簡易データロガーともいえるもので、何らかの手段で定期的に入手したデータをデモファイルにAPPENDしながら書き込んでいくものです。 従い、MS-DOSのDIRコマンドに相当したファイル検索や、特定のファイル名をオープンして、中身を読みだすという動作は行いません。 ただし、これらの機能の、コマンドの使い方は例で示してあります。 

今回、SDカードにセーブしたCSVファイルを検索して、LCD上にファイル名を表示させる機能、及び、表示したファイル名を指定して、そのCSVファイルを読み込み、LCD上にSWRカーブを再表示させる事にトライしました。 FILEIOのHELPドキュメントを読んだだけでは理解できず、構造体の勉強を3週間くらいやって、やっと、思ったようにソフトが動くようになりました。

Aa50_find

Aa_50_40m

ソースコードを下記しますが、そのままコピペしても動作しません。 これをデモ用として提供されているソースコードの中に埋め込んでやると期待したような動作が得られます。

MS-DOSのDIRに相当する関数は「FILEIO_Find」という関数を使います。

searchnameは16bitの文字で "*.CSV" と初期設定し、FILEIO_Findの関数を実行させるとsearchRecordの中にファイル名がひとつだけストアされます。 これをset_dir_fname()の関数に送り、そこで2次元の文字列にストアします。この動作を20回繰り返します。 ファイルの数が20以下の場合、i=20で強制的にループを抜けます。

unsigned int  find_SD_card(void) {

     DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;

   FILEIO_OBJECT file;

    FILEIO_SEARCH_RECORD searchRecord;

    init_SDcard();

    unsigned char i;

   uint16_t SD_ER = 0;

      while(SD_ER == 0) {

        switch (demoState) {

            case DEMO_STATE_NO_MEDIA:

                 if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == true) {

                    demoState = DEMO_STATE_MEDIA_DETECTED;  

                    }

                 break;

            case DEMO_STATE_MEDIA_DETECTED:

                  SD_ER=(FILEIO_DriveMount(drive_A, &gSdDrive, &sdCardMediaParameters));

                if (SD_ER ==0){

                    demoState = DEMO_STATE_DRIVE_MOUNTED;

                     } else {

                    demoState = DEMO_STATE_NO_MEDIA;

                    }

                     break;

            case DEMO_STATE_DRIVE_MOUNTED:

                if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, true) == FILEIO_RESULT_SUCCESS) {

                    i=0;

                    set_dir_fname(&searchRecord,i);

                    i++;

                    } //サーチの最初はこのようにtrueを指定して検索

                    while (i < 20) {

                        if (FILEIO_Find (searchname, FILEIO_ATTRIBUTE_MASK, &searchRecord, false) == FILEIO_RESULT_SUCCESS) {

                           set_dir_fname(&searchRecord,i);

                            i++;

                            } else {i=20;} //whileループから抜ける為

                        }  //2回目以降はfalseを指定して検索

・・・・・・

・・・・・・

このfind_SD_cardの関数は、ファイル名を検索して最大で20個表示したら一旦ドライブをアンマウントさせます。

.

.

ファイルの読み出しは「FILEIO_GetChar」という関数を使います。

void get_SDdata(unsigned int *sptr) { //テキストデータを1行(LFまで)読み込む
     uint8_t C=0;
     uint8_t i=0;
     while (C != 0x0A) {
        C=FILEIO_GetChar(sptr);
        if (C == 0x1A) {break;} //EOFでもループを抜ける
        SWR_SDdata[i]=C;
        i++;

     if (i>40) {break;} //1行の文字数が40を超えたら抜ける
        }
     SWR_SDdata[i-2]=0;
  }

セーブされたテキストデータは必ず「CR+LF」で1行完了としていますので、上の関数で、CR+LFが削除された文字列として、SWR_SDdata[]の中にストアされます。

正規のSWRカーブファイル以外の場合、暴走しないように、EOFを見つけたり、1行の文字数が40を超えたら、ループから抜けます。 

.

以下はASCIIからUTF-16への変換関数です。

void Uint8toUint16(uint8_t *fname8) { //ASCIIをUTF-16に変換します。
        unsigned char i ;
        for (i=0;i<13;i++) {
            fname16[i]=fname8[i];
        }
    }   

以下が特定の16bitファイル名「fname16[]」をオープンして読みだす処理になります。

unsigned int  open_SD_card(unsigned char *fptr) {
   DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
   FILEIO_OBJECT file;
   unsigned char i;
    uint16_t SD_ER = 0;
    Uint8toUint16(fptr);

・・・・・

・・・・・

 if (FILEIO_Open (&file, (uint16_t *)fname16, FILEIO_OPEN_READ) == FILEIO_RESULT_FAILURE) {
 
                    demoState = DEMO_STATE_FAILED;
 
                    SD_ER=2;
                    break;
                    }
                    SD_ER=50;
 
        get_SDdata(&file);
        set_FREQ_data(&SWR_SDdata,1);

読み込みは全部で225行に渡りくりかえされますが、それが終わるとファイルクローズします。 

 if (FILEIO_Close (&file) != FILEIO_RESULT_SUCCESS) { //ファイルクローズ                     demoState = DEMO_STATE_FAILED;

                  SD_ER=3;

                    return SD_ER;

                  }          

クローズが失敗したらメインルーチン側で強制的にドライブアンマウントを実行させます。

クローズが成功してもドライブをアンマウントします。

FILEIO_DriveUnmount ('A'); //ドライブアンマウント

SD_ER=20;

return SD_ER;

・・・・・・・

・・・・・・・

ファイルを削除する時は以下のコマンドとなります。

 if (FILEIO_Remove ((uint16_t *)fname16) != FILEIO_RESULT_SUCCESS) {
                        SD_ER=10;
                        }
                    break;

エディター上ではTABを使い、行の整列がきれいに出来ているのですが、このブログに貼り付けるとメチャクチャになって、大変読みにくくなってしまいました。

このデモプログラムのなかでは、かなり詳しいエラーメッセージが定義され、それが番号で返されますが、そのままでは、かえって混乱しますので、新たにSD_ERという変数で、勝手にエラー番号を定義し、ループからの抜けや、メインルーチン側でのエラー処理に使っています。

出来てしまえば、簡単な記述で完成するのですが、ここまでやるのに優に1か月かかりました。

SDカードからファイルを読み込むプログラム FILEIO_read_Faile.cをダウンロード

実際にアンテナアナライザーに組み込んだ状態はここで紹介しています。

INDEXに戻る

2015年9月17日 (木)

PICマイコンからSDカードへのファイル書き込み

<カテゴリー:PICマイコン

LCD表示のアンテナアナライザーの自作の中で、周波数対SWRのグラフを描かせるところまで成功しました。 そこで、このグラフをPCに取り込めないか、試行錯誤しておりました。 そして、やっと、PICマイコンでSDカードにファイルを書き込む事が出来るようになりました。 まだ、数行のテキストデータしかないファイルを書き込んだだけで、グラフデータは未完成ですが、ここまで、出来ると、後は時間の問題となります。

今回は、PICマイコンからFAT32のファイルシステムでフォーマットされたSDカードにテキストファイルを書き込む方法を紹介します。

ハードの構成です。 アンテナアナライザーのハードに秋月で売っているSDカードソケットを接続した、単純な回路となっております。

Pic_sd_schema

 検討するソフトもこのSDカードの部分のみで、LCD表示は実装していません。

秋月から「SDカードスロットDIP化モジュール」という名前のソケットを買ってきて、これを配線図のごとく、マイコンの空きピンに接続します。PIC24FJ128GB106はi/o設定が自由にできますので、このような場合、非常に便利です。

Sd_card0そして、左の画像のごとく実装しました。

この状態でSDカードをドライブするソフトはMicrochipが無償で提供しているfileioというアプリケーションを使います。

このアプリの説明を読んでいると、私のようにC言語のポインターもまともに扱えない者でもなんとかPCで読めるファイルを書き込めるかも知れないと思うようになりました。

しかし、これが間違いの始まりで、検討を開始してからすでに1か月。 やっとのことで、FAT32のファイルシステム上に自作のファイルを書き込む事に成功しました。

Pic_fat32file0 上はエクスプロラーでSDカード内のファイルを表示させたものです。

Sample long file name.txtはデモプログラムが見本として作成したファイルです。

SWR12345.txtは私が作ったファイルです。 いずれも2行、20文字くらいのファイルですが、ファイルの中身は、これから好きに変更できます。

ここまで出来るまでの工程を以下説明します。

MicrochipのサイトからMLAと言われるアプリケーションファイルをダウンロードし、デフォルトの設定のままインストールします。 私がインストールしたファイル名は以下の名前でした。

mla_v2015_08_10_windows_installer.exe

デフォルトでインストールした後、MPLAB Xから以下のプロジェクトを探し

C:\microchip\mla\v2015_08_10\apps\fileio\sd_card_demo_lfn\firmware\MPLABX

fileio_sd_card_demo_lfn を読み込むと、同名のプロジェクトがオープンします。

このプロジェクトができましたら、マイコンの品種設定とi/oの設定を書き換える事により簡単にデモプログラムが動作します。・・・・とはなりませんでした。

Mplabx_sd

上のダイアログはMPLABXにてプロジュクトをオープンした時の画面ですが、上の方にICの品種を指定するランがありますので、実際に使用しているICファミリーを選択します。 

私の場合、実際に使用しているICはPIC24FJ128GB106ですので、ファミリー名はpic24fj256gb110となります。 使用可能なICのファミリー名が左側の「exp16」フォルダーの下に表示されていますので、確認できます。ここにリストされた以外のICで、このデモソフトが動作するかは不明です。

リンクされたファイルには同じ名前で中身の違うものがいくつかあります。main.c やsystem.c が該当しますので、他のホルダーでプロジェクトを構築する場合は、一度デモプロジェクトをオープンし、そのとき表示されるファイルをコピーして他のホルダー移すことで間違いを防ぐ事ができます。 事実、最初、リンクを頼りにファイルをコピーしてきて、独自のホルダーに集めてbuildをかけたところ、エラー続出で困り果てた事がありました。 この為、main.c とsystem.c はそれぞれ、SD_main.c とSD_system.c いう名前にし、のちのち間違わないようにした上で、独自のフォルダーへ移動させ、オリジナルのファイルは元の場所にそのまま残しました。 

まず、lfn(ロングファイル名)を選んだのに、リンクされたヘッダーファイルはlfnなしの普通のfileio.h。 これをハンドでfileio_lfn.hに入れ換えました。 ソースファイルもlfnではなかったような記憶ですが確かでありません。もし、違ってましたらソースファイルもfileio_lfn.c に入れ換えて下さい。

また、system.c の中の一部を以下のように書き換えました。

#pragma config FNOSC = FRCPLL//OSCを32MHzのCR発振に変更

#pragma config FWDTEN=OFF

ただし、このままでは16MHzにしかなりませんでしたので、main()の中で、以下を

追加し32MHzにしました。

OSCCON = 0b0001000110100001; //Fosc FRCPLL 32MHz
 CLKDIV = 0x0000;

また、青色の設定は後日、追加したものです。 このPICマイコンはデフォルトでウォッチドッグタイマーがONになっており、約2分20秒でリセットがかかる原因になっていました。 これが時々暴走する原因と解るまで3週間くらいかかりました。

また、i/oの設定も変更しました。

void USER_SdSpiConfigurePins_1 (void) {     //Initialize the SPI    

RPINR20bits.SDI1R = 25;    //修正

RPOR10bits.RP20R = 7;    //修正

RPOR11bits.RP22R = 8;    //修正

    //enable a pull-up for the card detect, just in case the SD-Card isn't attached    

//  then lets have a pull-up to make sure we don't think it is there.    

//CNPU5bits.CN68PUE = 1;//プルアップはハードで行っていますので、この行は不要です。   

// Deassert the chip select pin    

LATDbits.LATD2 = 1;    //CS端子1に設定

// Configure CS pin as an output    

TRISDbits.TRISD2 = 0;    //CS端子出力に設定

// Configure CD pin as an input    

TRISDbits.TRISD1 = 1;    //CD端子入力に設定

// Configure WP pin as an input   

// TRISDbits.TRISD1 = 1; //この行はコメントアウト

}

・・・・・

・・・・

inline void USER_SdSpiSetCs_1(uint8_t a) {

    LATDbits.LATD2 = a;   //CS端子修正

}

inline bool USER_SdSpiGetCd_1(void) {

    return (!PORTDbits.RD1) ? true : false;//CD端子修正

}

inline bool USER_SdSpiGetWp_1(void) {

    //return (PORTFbits.RF1) ? true : false;//コメントアウトして0を返す

    return 0;

}

ここまで修正してBuildをかけてエラーが出なかったら、成功です。

しかし、PCでFAT32にフォーマットしたSDカードを用意し、マイコンにプログラムを書き込んでもファイルは出来ません。

今度はmain.c の定義の部分を変更します。

typedef enum
{
    DEMO_STATE_MEDIA_DETECTED = 0,
    DEMO_STATE_NO_MEDIA,
    DEMO_STATE_DRIVE_MOUNTED,
    DEMO_STATE_DONE,
    DEMO_STATE_FAILED
} DEMO_STATE;

DEMO_STATE_NO_MEDIA=0という記述が最初の行にありますので、これを上記のごとく2行目に移し、"=0"の文字を削除します。 DEMO_STATE_MEDIA_DETECTEDを一番上にして、"=0"を追記しておきます。これは、Maicrochipのデモ機はCDが0の時ノーメディアなのに対して、秋月のソケットはCDが1のときノーメディアになっている為です。

以上の手直しでデモ用のファイルがSDカード内に出来るようになりました。

次に自作のファイル名でファイル作成にトライです。 ところが、出来たファイル名は文字化けして読めない上、ファイルの中身も空です。 ファイル名は「SWR00001.csv」で始まる連番とする予定ですので、この数値の部分はunsigned int で1から始まる整数です。これをファイルに書き込めるようにASCII変換してファイル名としたのですが、うまく行きません。

色々調べて、判った事は、FAT32のファイル名はASCIIコードではないということでした。ファイル名はutf-16という16bitの文字でエンコードされていました。 XC16の中にあるストリング系の関数は使えませんので、自分でASCII to utf-16の変換ルーチンを作る必要がありました。 

幸い、ASCIIコードの文字だけに限れば、8bitのASCIIコードの上部に0x00のコードを加えて、16bitにするだけなので、変換ルーチンは私でも作れましたが、日本語のファイル名は使えません。

このようにして、「SWR12345」のようなファイル名を付けたテキストファイルを作る事が出来るようになりました。このファイル名の数字の部分を連番のファイル名にし、拡張子をcsvにするとOKとなります。

SDカードは、128Mと8Gの物をテストしましたが、いずれもFAT32でフォーマットしてあれば問題なく使う事ができました。 exFATでフォーマットしたSDカードの場合、エラーがでます。

この小さなデモファイルを作る為に必要なROM容量は約44.9Kバイトです。これから実験しようと考えているなら、ROM容量64Kでは心細く、最低でも128K品が必要でしょう。

ところで、出来たファイルにちゃんとタイムスタンプが付いています。どうやって時間を計っているのでしょうかね。マイコンボードは使わないとき電源OFFなのですが。

このSDカードドライブ機能をアンテナアナライザーに実装する事にします。

SWRグラフをSDカードへセーブ へ続く。

INDEXに戻る

2015年8月14日 (金)

PIC24FJ128GB106 データメモリー不足

<カテゴリー:PICマイコン

TFT LCDにグラフィックや文字を表示させていますが、メモリー容量を64Kから128Kに替えた為、新たにフォントを追加する事にしました。 フォント作成アプリで大文字、小文字、数字、記号などを作り終え、これをincludeファイルにして、コンパイルすると、エラーになります。  出てくるコメントはリンカーエラーとの事で、メモリーが不足しているような内容です。

これらのエラーコメントを頼りにインターネット内で検索すると、Microchip(USA)のFAQページにメモリーを拡張しなければデータサイズは32Kまでと言う説明が見つかりました。 ただし、どうすれば、32K以上のデータメモリーを使えるのかは、やりとりが英文である事もあって、良くわかりません。

そこで、日本語の情報を探すと、データメモリーが32Kまでで制限されている事。 これを32K以上に拡張する為には、レジスターの設定やアドレッシングなど、変更する必要は判りましたが、肝心なXC16による記述方法が良く判りません。

結局、インターネットから探しだした、以下の記述でコンパイラーがエラーを出さなくなり、ちゃんと文字の表示が可能になりました。

コンパイルエラーになった記述例

const unsigned char Font7_space[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };//ASCII 32
const unsigned char Font7_sharp[] = { 0xb, 0xa, 0xa, 0x3f, 0xa, 0x1a, 0x1a, 0x3f, 0x16, 0x16 };// ASCII 35

・・・・・・

・・・・・・

const unsigned char *Font7_table[] = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //ASCII 0-15

・・・・・

・・・・・

コンパイルエラーが無くなった記述例

__eds__ unsigned char Font7_space[] __attribute__((eds)) = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };//ASCII 32
__eds__ unsigned char Font7_sharp[] __attribute__((eds)) = { 0xb, 0xa, 0xa, 0x3f, 0xa, 0x1a, 0x1a, 0x3f, 0x16, 0x16 };// ASCII 35

・・・・・・

・・・・・・

__eds__ unsigned char *Font7_table[] __attribute__((eds)) = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //ASCII 0-15

・・・・・

・・・・・

Aafont7

左の[SWR ANALYZER]の文字が今回作成した10x6のフォントです。

文字を書き込むとき、フォントアドレスをポインターで指定しますが、このポインターの型宣言も下記のようにする必要がありました。

__eds__ unsigned char *fontptr;

INDEXに戻る

2015年8月 3日 (月)

PIC24FJシリーズ SPI 誤動作

<カテゴリー:PICマイコン

アンテナアナライザーのLCDドライブ用に使用していたPIC24FJ64GA004のROMエリアがほぼフルになりましたので、128Kに換える事にしました。 選んだマイコンは、将来USB機能やSDカードを組み込むかも知れないとの考えから、PIC24FJ128GB106という品番のICにしました。 

Aa59pic24fj128gb106

左の画像が、128Kの64pin TQPF品に入れ替えた実装基板です。 変換基板の大きさが、44pinのときより小さくなっている関係で、以外とすっきり配線できました。

回路図的には、44pinの時と同じ構成で、一部i/oの割り当てを変更しただけで、さっそく動作確認です。 ところが、LCDの表示は問題なく表示されますが、コントロールマイコンとの通信がうまくいきません。 周波数表示はでたらめで時々暴走します。 UART通信のプログラムが異常なのかと、色々試しましたがうまくいきません。 じたばたしている内に、通信もうまくいかないのに、さらに、26バイトの伝送に15m秒くらいかかっている事が判り、LCDの表示速度も遅くなっている事に気付きました。 ボーレート38.4Kでは不足みたいです。 56K以上にアップする案もありましたが、 キー入力をADに変更して、ラッチアップの対策もできましたので、残りのUP,DOWNのキーもADに変更する事によりi/oポートが2本余ります。 この際、通信方式もi/o 1本のUARTからi/o 3本のSPIへ変更する事にしました。

しかし、これが、またまた、訳の判らない誤動作に悩まされる事になってしまいました。

時々、伝送に成功しますが、一度リセットをかけると、伝送データがでたらめになります。 約2週間悩んだ末、判った結論は、またまた、伝送路のリンギングによるマイコンのラッチアップでした。 ただし、ラッチアップの影響が小さい為、時々まともに動作するのは、プログラムの性ではないかと、ああでもない、こうでもないとやっていたのがいけなかったようです。 ふと、ハードが原因ではないかと、SPIのクロックやデータの波形をチェックしてみました。

Aa59spi0

Aa59spi1

上の画像は左が対策前の、クロック(下)とデータ(上)です。 右の画像は対策後の波形です。 対策前は、クロックにも、データにもリンギングのオーバーシュートやアンダーシュートが発生し、いずれも時々0.5Vを超えています。 これが伝送データがでたらめになる原因でした。 対策内容は、各ラインに1KΩの直列抵抗を挿入し、リンギングの発生をおさえますが、抵抗だけでは不十分でしたので、GNDとの間に68Pのコンデンサも追加しました。 波形がきれいになって暴走の確率はかなり減少しました。 

しかし、時々、電源ON直後に暴走します。 ただ、基板のGNDラインを指でつかむとか、オシロのGND端子へ接続すると完璧に直ります。 このような症状の原因はノイズです。 ふたつのマイコンのうち、どちらで暴走しているか確認したところ、コントロール側の24FV32KA302が暴走しています。 さらに、このマイコンの入力関係をひとつづつ殺して確かめても暴走するときは暴走します。 最後にたどりついたところはMCLR端子でした。 この部分についてデータシートを再確認したところ、推奨回路はMCLR端子にシリーズに100から470Ωを入れろと書かれていますが、8bit時の延長で抵抗は入れてありませんでした。 そこで、470Ωを追加し、10回くらいのPOWER ON/OFFでは暴走が起こらない事を確認できました。 しかし、頻度は少ないですが、たまに誤動作します。 このマイコンのデータシートには、さらに0.1μFでGNDへ落とせと書いてあります。  さっそく0.1μFのコンデンサを追加したところ暴走が起こらなくなりました。 しかし、PICKIT3の説明書では、MCLRラインにコンデンサを接続するなと書いてあります。 試にこのラインに0.1μFを接続したままで、フラッシュメモリーの書き換えを行ってみましたが、問題なく書き換えが出来ました。 もし、書き換えがうまくいかない時は、コンデンサを外し、アナライザーが完成したら、コンデンサを追加する事にして、コンデンサは追加したままにしています。

LCDドライブ用の24FJ128GB106のMCLRラインにはまだシリーズ抵抗は入っていませんので、抵抗だけは追加する事にしました。

対策済回路図をダウンロード

Aa59_spi2

このSPI通信は、PIC24FV32KA302をマスターとして、PIC24FJ128GB106をスレーブとした一方通行のシリアル通信です。 クロックは約156KHzとし、マスター側はワード(16bit)伝送で割込みなし、全17ワードを連続送信し、その間、CEとしてLの信号を送ります。 スレーブ側は、CE信号がLになったらこれを割込みで捉え、受信バッファのインデックスを0にした後、1ワード受信する度に割込みを発生させ、17ワードのデータをバッファにストアさせます。 CE信号を送ったり、CEを受けてインデックスを0にする動作以外、すべて、データシートにかかれた説明通りの設定です。 

上の画像は、下のパルスがSPIのクロック(SCK)で、上のパルスが受信割込みが発生したときのダミー信号です。 1ワード受信する度に割込みが発生し、先頭ワードのインデックスを0番として順次17ワードを受信バッファに格納していきます。

送信側のPIC24FV32KA302のmain内の初期設定と送信ファンクションは以下です。

main () {

・・・・・・・・・

SPI1CON1 = 0b0000011000111100;//マスターモード クロック1/64
SPI1CON2 = 0b0000000000000000;
SPI1STATbits.SPIROV = 0;
SPI1STATbits.SPIEN = 1;//SPI1有効化

・・・・・・・・・・・・・

送信処理

void sendDATA() {
    unsigned char i;
    SPIFlg = 0;//CE信号をL
     __delay_us(20);
    for (i=0;i <17;i++) {
        while(SPI1STATbits.SPITBF);
        SPI1BUF = TXData[i];
        }
     SPIFlg = 1;//CEをH
}

受信側PIC24FJ128GB106の初期設定と受信割込みルーチン

main() {

・・・・・・・・・・・・・・・

RPINR0bits.INT1R = 21;//INT1をRP21に割り当て(RG6)
 RPINR20bits.SCK1R = 26;//SCK1INをRP26に割り当て(RG7)
 RPINR20bits.SDI1R = 19;//SS1INをRP19に割り当て(RG8)
 SPI1BUF = 0x0;//SPIバッファークリアー
 IFS0bits.SPI1IF = 0;//SPI割込みフラグクリアー
 IEC0bits.SPI1IE = 1;//SPI割込み有効
 IPC2bits.SPI1IP = 3;//SPI割込み優先レベル3
 SPI1CON1 = 0b000011000000000;//SDO使用せず。スレーブモード
 SPI1CON2 = 0b000000000000000;//フレーム未使用
 SPI1STATbits.SISEL = 1;
 SPI1STATbits.SPIEN = 1;//SPI1有効化
 INTCON1 = 0b000000000000000;
 INTCON2 = 0b000000000000010;//INT1 ネガティブエッジ
 IFS1bits.INT1IF = 0;// INT1 割込みフラグクリアー
 IEC1bits.INT1IE =1;//INT1割込み許可
 IPC5bits.INT1IP = 3;//INT1割込み優先レベル3

 ・・・・・・・・・・・・・

CE割込み処理

void __attribute__((interrupt, no_auto_psv)) _INT1Interrupt(void) {
    IFS1bits.INT1IF = 0; //割り込みフラグ解除
    RXindex = 0;
}

SPI受信割込み処理

void __attribute__((interrupt, no_auto_psv)) _SPI1Interrupt(void) {
    unsigned int i;
 //    LED=1;
    IEC0bits.SPI1IE = 0;//受信割込み禁止
    IFS0bits.SPI1IF = 0; //受信割り込みフラグ解除
    i = SPI1BUF;
    RXdata[RXindex] = i;
    RXindex++;
    if (RXindex > 16) {
       RXreadyflag = 1;//全データ受信完了フラグ
       RXindex = 0;
       }
   IEC0bits.SPI1IE = 1;//受信割込み許可
//      LED=0;
}

INDEXに戻る

2015年6月25日 (木)

PIC24FV32KシリーズのEEPROM読み書き

<カテゴリー:PICマイコン

アンテナアナライザーのコントローラーとして、PIC24FV32KA302というマイコンを使っていますが、このマイコンに内臓されたEEPROMは、8bit系のマイコンとは異なり、プログラムメモリーのアドレス上に配置されています。 従い、EEPROMの書き込み読み出し方法は、従来の8bit系とは異なっています。

このEEPROMに書き込んだり、読み込む為の、サンプルプログラムはデータシートの中に出てくるのですが、イマイチ良く判りません。WEB上でサンプルを探しておりましたら、Microchipのホームページ内のFAQのところにひな形のプログラムがありました。 これをコピペしたら、エラーなくコンパイルされ、ちゃんと読み書きできました。

日本語ページでは、なかなか見つける事が出来ませんでしたので、以下そのソースを紹介します。

//データEEPROMへの読み書き

unsigned int eeRead(unsigned int address) {

  while(NVMCONbits.WR); // wait for any last write to complete

  TBLPAG = 0x7f; // eprom is a t 0x7ffe00

  return __builtin_tblrdl(0xFE00+address);

  }

 void eeWrite(unsigned int address, unsigned int data) {

   while(NVMCONbits.WR); // wait for last write to complete

   NVMCON = 0x4058; // Set up NVMCON to erase one word of data EEPROM

   TBLPAG = 0x7f; // eprom is a t 0x7ffe00

   __builtin_tblwtl(0xFE00+address, 0xffff);

   asm volatile ("disi #5");

    __builtin_write_NVM(); // Issue Unlock Sequence & Start Write Cycle

   while(NVMCONbits.WR); // wait for errase to complete

   NVMCON = 0x4004; // Set up NVMCON to write one word of data EEPROM

   __builtin_tblwtl(0xFE00+address, data); // Write EEPROM data to write latch

   asm volatile ("disi #5");

    __builtin_write_NVM();

   }

書き込みは下の1行です。

eeWrite(address,data);

addressがEEPROM内の相対アドレスで0から254までの偶数を指定します。

dataは書き込もうとするワードデータ(16bit)です。 書き込みは16bit単位で行われますので、8bit単位で行いたい時は、書き込む前に、ふたつの8bitデータを連結するか、空の8bit(例えば0x00)と書き込みたいデータを連結したワードデータを用意します。

読み出しは下の1行です。

DATA=eeRead(address);

DATAに16bitデータが格納されます。

PIC24FJ64GAシリーズのフラッシュメモリーに書きこむ例はこちらにあります。

INDEXに戻る

2015年5月30日 (土)

TFT LCDによるアナログメーター 3

<カテゴリー:PICマイコン

Aameter2_2

PC上で動作するコードジェネレーターのバグと、C言語のポインターの使い方でかなり苦労しましたが、左のような、アンテナアナライザーの表示画面ができました。 

なぜLCD上の疑似アナログメーターの表示にこだわるかと言えば、それは、マルチファンクション画面が得られるからです。 画面はこれで完成ではなく、アナログメーター部分を消して、周波数対SWRのグラフを描かせる事により、LCD表示のアナログメーターも生きてくる訳です。 しかし、ここまでの表示で、const用に使えるROMエリアを含めて85%くらい使っており、これ以上のグラフィックを仕込むとエラーになります。 SWRのグラフ表示は、実際にハードと結合した時の様子を見ながら考える事にします。

通常、プログラムの効率化の為、共通の関数を条件判断しながら、使い回ししますが、これをやると、条件判定の為、動作が少しだけ遅くなります。今回のプログラムでも、メーター指示や、数値の表示の中で、IF文が多くなると、目に見えてメーターの動きはおそくなりました。

対策としては、条件判定を必要最小限に抑える代わりに、関数をいくつも設けることにしました。ROMの容量アップになりますが、プログラム用の容量より、グラフィック用のROM容量がはるかに大きく、全体的にはあまり影響はありません。

残り15%のROM容量でどこまで出来るかは、これからの作業になりますが、ROM容量128Kバイトのマイコンは64pinのQFPですので、出来ることなら、この44pinの64Kに収めたいところです。 また、クロックも現在20MHzですが、これを32MHzまで上げる事にします。

このLCDの表示状態で、SWRやZ,R,Xをリアルタイムにデジタル表示すると、アナログメーターの指針の動作速度は、どんどん遅くなっていきますが、 その上で、周波数カウンターを動かすと、周波数カウンターの基本ゲート時間が10ミリ秒必要であり、メーターの指針の動きはもっと遅いものになりそうです。 改善策としては、周波数カウンターは、外付けPICマイコンで処理し、カウントした結果だけをもらうという案になりそうです。

また、RやXを表示させるためには、10000倍した整数計算では、その精度が不十分で、32bit浮動小数点による計算はマストですから、これもLCD表示マイコンから切り離した方がよさそうです。

これら、周波数カウンターやR、Xのベクトル計算も、LCD上でのグラフィック表示がなければ、8bitマイコンでも十分処理可能なものです。

これからハードの設計を始めますが、基本設計はほとんど出来ていますので、蛇の目基板を使い、いかにして手作りするかが、本当の課題です。 完成はいつの事やら。

アンテナアナライザーの製作(センサー回路) に続く。

2015年6月30日追記

ハードウエーアーが基板状態ですがほぼ完成し、LCDアナログメーターの改善を行う事が出来る時期になりました。 当初、メーターの振れ分解能は1度きざみでしたが、動きが粗く、とてもアナログメーターの動きをまねる事ができませんでしたので、LCDの1ピクセル単位の変化となる、0.25度きざみでドライブする事にしました。 しかし、0.25度きざみでそのまま駆動すると、ゼロから無限大までの移動時間は10秒を超えてしまいます。 動きはスムースですが、実用的では有りません。

Aa50meter3_2

そこで、目標の角度と、現在位置の差を計算し、T/Gに対して数度しか離れていない場合、0.25度きざみで送り、その倍の差が有る場合、0.5度きざみで送り、同様に差が倍になるごとに送る角度も2倍にし、最大で2度きざみで送るようにしました。 この細工により、T/G角度近くになると、指針の動きにブレーキがかかりますので、本物のメーターの動きに、より近くなりました。

結果は非常に良好で、7MHzのアンテナをつないで、実際にSWR最少周波数を探す操作をすると、かなりスムースに指針が追従し、なんなく共振点に周波数を合わせる事が出来るようになりました。 本物のアナログメーターには及びませんが、さほど違和感なしに操作できます。 これから完成度を上げていきますが、ROM容量が、目いっぱいの状態ですので、マイコンを変更するまでは、とりあえず、お預けとなりそうです。

左のLCD画像は最新の表示画像で、50Ωのダミー抵抗を装着した時の表示です。

アンテナアナライザーの製作(センサー回路) に続く。

INDEXに戻る

2015年5月12日 (火)

TFT LCDによるアナログメーター 2

<カテゴリー:PICマイコン

 8bitのPICマイコンでは容量不足で、まともにLCDの表示が出来なかった為、マイコンを16bitに替え、かつLCDも一回り大きな2.4インチサイズにして、実用サイズのLCDアナログメーターを実験中です。

16bitpic_pwb_4

16bitpic_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としております。

LCDMeter0.pdfをダウンロード

Lcd320meter1

開発開始してから約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命令で読み込み使う事ができるようになります。  バグだらけのアプリでしたが、なんとか動作するようになりました。

Ccg0

 このアプリは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に収まる範囲で可能な方式として、指針データは常に計算で出し、指針より少しだけ広い四角い範囲のグラフデータに、指針データを重ねると、ちょうどドット数の多いフォントと同じようなデータが作れますので、これをグラフ画面上に上書きすることにしました。

Lcdswrmeter2

左の画像は、そのようにしてメーター目盛の上に、指針とその周囲の目盛画像を上書きしたものです。最初の案より指針データを計算する分だけ動作が遅くなっています。

この目盛の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秒まで改善出来ました。

Lcdswrmeter3

次に、一部、浮動小数点(double)を使用していた計算式を10000倍の整数計算した後、四捨五入した整数に直す方法で、全ての計算を整数で行った結果、ゼロからフルスケールまでの時間は約0.65秒となりました。

左の画像はその速さで指針が動いている時のショットです。動きが速いので、指針もボケて写っていますが、見た目のチラツキは少ないです。

アナログメーターの指針移動時間で違和感が無いのはゼロからフルスケールまで0.3秒くらいの移動時間ですから、あと半分くらいは短縮必要です。

しかし、 現在はメータードライブだけしかやっていませんので、例えば、SWRメーター以外にインピーダンスメーターも同時に表示したり、周波数カウンターの周波数表示など、負担が増えるばかりで、指針の移動スピードもどんどん遅くなってしまいます。

また、この方式の場合、チラツキは最少に抑えられますが、指針の移動スパンは1度以内に限られます。VUメーターではないので、かなり遅い追従時間でも問題は無いと思われますが、実際に作ってみないと、何とも言えません。

次回は、LCDの全画面表示にトライします。

TFT LCDによるアナログメーター 3 に続く。

INDEXに戻る

2015年5月 4日 (月)

TFT LCDによるアナログメーター1

<カテゴリー:PICマイコン

AadigitaltestPICのマイコンを使用して、アンテナチューナーのコントローラーやATUの製作を行ってきましたが、この過程で、SWR計も作ってきました。 PICマイコンに少し、慣れたころ、このマイコンのAD入力にCAA-500のインピーダンス検出DC信号や、SWR検出DC信号を加え、アンテナアナライザーによるインピーダンスやSWRのデジタル表示にトライし、RやXの表示も行えるところまで実験ができましたので、次の目標は、オール自作のアンテナアナライザーと決めました。 左の画像は、CAA500のセンサー基板に、PIC16F1939を使用した自作のマイコンボードとLCDディスプレーを接続し、マイコンで周波数や、SWR、インピーダンス、R、Xを表示させている実験風景です。

アンテナアナライザーのセンサー部分や、広帯域発振回路など、なんとかなりそうですが、これをメカニカルアナログメーターや、キャラクタ表示の液晶で実現してもMFJやコメットと同じなので、面白く有りません。  そこで、マイコンでは、無理と言われる、液晶表示の疑似アナログメーターの実験を始める事にしました。 最近の車のインパネは高精細度の液晶によるスピードメーターやタコメーターがすばらしいデザインの元で実装されております。またKENWOODの最新モデルにも、液晶表示のアナログメーターが実装され、デジタル駆動にもかかわらず、非常にわかりやすいアナログメーターとなっています。 これらの最新技術のLCDアナログメーターに及ばないにしても、安いマイコンと、安い液晶でどこまで、液晶表示のアナログメーターが実現できるかの実験記です。

使うマイコンは、少し役不足ですが、ATUに使ったPIC16F1939。 これで160x128ドットのTFT液晶をドライブします。 液晶は262K色対応で、普通の写真を表示させても、遜色のないカラー画像が表示できるという中国製です。

とりあえずは、TFT LCDを初期設定し、画像や、文字を表示できるところまでトライします。

この実験ボードの配線図です。TFT-LCD.pdfをダウンロード

実験に使うマイコンはROMもRAMもグラフィックLCDをドライブするには小さすぎますので、今回は、基本動作を得とくする事が目的となり、実践版は次の試作までお預けとします。

試用するLCDはDisplaytechのDT018ATFTという品番で、液晶ドライブIC ILI9163Cが内臓されています。 このILI9163Cという台湾製のICはインターネット上でも良くみかけるST7735とコンパチで、ST7735用のイニシャルルーチンでちゃんと初期設定されてしまいます。初期設定が成功したら、後は、ILI9163Cのデータシートを読みながら、ああでもない、こうでも無いと試行錯誤する事になりますが、いつのまにか、文字表示や自作したイメージデータの表示が出来るようになりました。

Pic_lcd_demo

左の画像は、なんとか表示できるようになったので、SWR計の目盛をLCD上に表示させたものです。SWR検出信号をADにつなげば、赤色の指針がSWRを指します。

メーターの目盛は3角関数とピタゴラスの定理を駆使して、描かれており、ブリッジの不平衡電圧を角度に変えて、目盛と同じ式で指針を表示していますので、指示誤差は有りません。

150x50ピクセルくらいの範囲で描画していますので、あまりきれいではありませんが、実験機としては十分です。

ただし、大きな問題があります。

動作がおそろしく遅いのです。

指針が移動するのに、0.5秒くらいかかります。1度移動しようが、60度移動しようが0.5秒です。 これでは、全く使いものにはなりません。  これは、指針も3角関数と、ピタゴラスの定理でXYドットをいちいち計算して表示していたのが最大の原因です。  

これを、指針のドットのみ1度ごとのXYデータの配列として記憶させて置き、測定された指針角度から、このイメージデータを呼び出し、表示させる事にしました。 角度データは80度分必要ですが、とりあえず10度分だけ作って振らせてみました。 指針は赤色で描画した後、一度白色で再描画し、指針を一度消し、次に新しい位置に、赤で描画するという事を繰り返します。 このドット単位での書き換え動作は、目盛と指針が重なった場所の目盛表示を復帰させるのも、ドット単位で行えますので、復帰させるドット情報も簡単に計算できます。 しかし結果は、かなり早くなりましたが、指針のチラツキが目立つようになりました。 まだまだ、改善が必要です。

次に、文字フォントと同じように8x16の書き換え可能なドットパターンを用意し、この範囲に含まれる目盛のドットに加えて、指針のドットも書き込み、これを指針角度に応じて、画面上に再描画させる動作を実験しました。この場合、指針の移動に伴い、旧指針を消すという動作と消えた目盛の復帰動作が不要になりますので、面を書き換える時間増より、コマンド切り替えの回数減少から、LCD側の動作速度がかなり早くなります。 また、ちらつきもほとんど無くなる事も判りました。 ただし、LCDにカラードットを書き込む前のドットパターン作成作業は複雑になりますので、マイコンのクロックを上げたり、16bit RISCタイプに変えるなど、対応が必要になると思われます。

次は、マイコンを16bit品に変え、かつLCDも320x240ドット品に変えて、動作速度の改善に取り組みます。

同じようなLCDをお使いになりたい時の為に、このLCD用の初期設定ルーチンだけですが、以下に示します。

void lcd_CMD(unsigned char CM) {//1-byteコマンド
      RS = 0;
      WR = 0;
      LATD =CM;
      WR = 1;
      RS = 1;
     }
void lcd_DATA(unsigned char DA) {
      WR = 0;
      LATD = DA;
      WR = 1;
     }

void init_LCD() {
      lcd_CMD(0x01);//ソフトリセット
       __delay_ms(120) ;
      lcd_CMD(0x11);//Sleep Out
      __delay_ms(120) ;
      lcd_CMD(0x36);
      lcd_DATA(0xC8);
      lcd_CMD(0x2A);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x9F);
      lcd_CMD(0x2B);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x00);
      lcd_DATA(0x7F);
      lcd_CMD(0x36);
      lcd_DATA(0xAC);
// lcd_CMD(0x29);//Display ON このコマンドは画面クリアーの後が良い。
      lcd_CMD(0x2C);
      __delay_ms(200) ;
 }

TFT LCDによるアナログメーター 2 に続く。

INDEXに戻る

2014年6月20日 (金)

エレキー回路の自作(PIC12F675)

 

<カテゴリ: PICマイコン >

再開局したころから、オートアンテナチューナー(ATU)を模索し、これを自作しようともくろみましたが、挫折が多くて今だに手づかずの状態です。 ここにきて、再度ATUの自作に挑戦しようと思いますが、ATUはそのコントローラーをマイクロコンピューター(マイコン)で作る必要が有り、マイコン開発は避けて通れない状況です。 現役時代はマイコン屋に仕様書を出して、バグを見つけては、ソフト屋をいじめるのが仕事でしたので、自らマイコンソフトを開発した事はありませんでした。 そこで、インターネットでも情報の多いPICマイコンの勉強を始める事にしました。

ハムがマイコンのソフト開発を勉強しようと思えば、最初の教材は、「エレキー」と相場が決まっています。 以下見よう見まねで作ったエレキー回路を紹介します。 なお、ソースファイルは、あまりにも恥ずかしくて公開する自信はありませんでしたが、かなりの方がこの記事にアクセスいただいておりますので、未熟ながら記事の最後の行でダウンロードできるようにしました。

Pickit3_2

使用するマイコンは、開発事例の多い「PIC12F675」とします。秋月で80円で売っていました。 開発環境はMPLAB IDEとHI-TECH Cそれに書き込みアダプターPICkit3です。 書き込みアダプター以外は無償アプリです。

まず、この開発環境構築でトラブリました。メインで使用しているPCはWindows7 64bitバージョンですが、アプリをインストールしてPICkit3を接続してもPICkit3がコネクト状態になりません。USBドライバーがうまくインストールされないようです。Helpをたよりにインターネットで調べていくと、Windows7の64bit版はトラブルらしく、わざわざ解決方法が絵入りで説明されていましたが、私のPCの表示とは一致しません。1日、ああでもないこうでも無いといじったあげく、64bit版を諦めて、Windows XP 32bit版に開発環境を構築する事にしました。インストールが完了し、PICkit3をつなぐと、簡単に認識され、かつファームウェーアーのアップデートを行うということで「OK」をクリックすると、アップデートされ、かつこのPICkit3が正常につながったとコメントがでました。 試に、このファームウェーアーをアップデートしたPICkit3を64bit版のPCにつないでみましたら、こちらも正常に動作するようになりました。  結局、マイクロチップが公式に言っている64bit PCによる不具合ではなく、自社のファームウェーアーにバグが有ったようですね。

やっとPICの開発の勉強ができる環境が整いましたので、PIC12F675の英文データシートとグーグル翻訳を駆使して、ハードの設計を行いました。グーグル翻訳の日本語はほとんど意味が判りません。翻訳された日本語文の中から、判らない単語のみピックアップして、後は英語の原文で理解するのが早いですね。

Elekey675

 上が、このエレキーの全回路図です。 ドットとダッシュの入力端子はマイコンの中の約20KΩの抵抗でプルアップしてあります。送信機に接続されるキー出力はN-MOS FETのオープンドレインとして可能な限り消費電流を減らしました。 また、キーイングのスピード調整は10KΩの可変抵抗で分圧された電圧をマイコンのA/Dコンバーターで読み込み連続可変できるようにし、かつこの可変抵抗器に加える電圧もマーク信号の時だけ加える事により電流を押さえます。 A/Dコンバーターへの信号源出力インピーダンスは10KΩ以下が推奨されていますので、可変抵抗器は20KΩでもOKですが、手持ちが無かったので10KΩとなっています。また、方形波ですが760Hzのサイドトーン信号も出力しています。このサイドトーン信号を実際に使う時は、この端子の後に2段くらいのCRフィルターを設けて高調波を少なくすると聞きやすい音になります。 電源は乾電池3本の4.5Vを想定しています。 CNP1のコネクターはPICkit3を接続する端子で、開発が終われば不要になります。

省電力の配慮をしたのに、SLEEPモード時の消費電流は360μAもあります。乾電池につなぎっぱなしで液漏れせずに使用できる消費電流は、過去の経験から140μAまではOKでしたが、メーカーの判らない100円ショップの電池でも安心していられるのは50μAくらいまでです。SLEEPモードにはいる手順が悪いのか、初期設定が悪いのかと、変更、コンパイル、確認を10数回も繰り返しましたが、一向に改善しません。 もしかしたら、ICが不良品?と予備のマイコンと交換したら、あっさりと直ってしまいました。 動作はすべて正常なのに、SLEEP状態の電流が多いという現象に遭遇しましたら、まず最初にマイコンチップを疑った方が早く解決できそうです。 ICは最初からの不良品ではなく、私が壊したと思われます。なぜなら、一度ラッチアップさせ、マイコンがアッチッチになった事がありましたので。

Elekey675b

最終的な消費電流は以下のようになりました。

マーク出力状態  1.4mA

スタンバイ状態   0.78mA

スリープ状態       1μA以下

マーク信号の出力が終わってから、約3秒後にスリープ状態へ移行します。

左の画像はスタンバイ状態での消費電流を測定したものですが、スリープ状態では、テスターの針はほとんどゼロを指します。 開発ボードにはLEDも見えますが、実際は使っていません。

一応完成したので、キーイングすると、今までのCK-100Aに比べて非常に打ちにくく、さらに時々スリープモードから復帰しません。 CWの短点はコンテストの時など40m秒くらいの長さしかなく、時には35m秒くらいの速さになる事もありますので、通常のチャタリング吸収手法は使えず、とりあえずチャタリング対策なしで設計していました。 キーを自作のキーに変えると、さほど気にならないのですが、GHDのキーにすると、打ちにくさが目立ちます。 そこでGHDキーのチャタリング波形をチェックしてみました。

Elekey675c

左の画像はGHDキーでキーダウンしたときのマイコンのGP4端子の波形です。一応1KΩと0.01μFのフィルターは入っていますがノイズを押さえる効果があっても、チャタリングの吸収は出来ておりません。  チャタリング吸収の為に、通常20~30m秒かけて、入力変化があったと判定させますが、この期間は次の入力を受け付けない訳で、短点、長点メモリーというエレキーには欠かせない機能が制限を受けます。 従い、このキーを受け付けない期間は出来るだけ短くする必要があります。 この為、タイマー0を使ったKey入力の状態チェックは約4m秒くらいで行っていました。 GHDキーのチャタリングを、デジタルストレージオシロで十数回測定した結果、上の画像が一番ひどいチャタリングで幅は5m秒くらいあります。 その為、チャタリング発生中に次のキー状態をチェックする事になり、多重割り込みが発生したり、キー入力を誤判定していたものでした。

キーのチャタリングで5m秒はかなり優秀な方で、手入れが悪いと、10m秒くらいになる事もあります。 よって余裕をみて、タイマー0で割込みが発生してから、約15m秒は次の割込みを禁止し、短点、長点メモリーも機能している事を確かめて、とりあえず逃げました。

ソフト屋からみると、かなり低レベルの部分でトラブりましたが、とりあえず勉強になりました。

しばらく使っていましたが、どうもしっくりいかないので、キー入力のチェック間隔を約16m秒にした上で、割り込み処理中にあった15m秒の割り込み禁止期間は廃止し、かつ長点の長さを従来の3短点から3.3短点に変更しました。 これで、28ワード/分のコンテストスピードでも違和感なく打電できるようになりました。

エレキー用HEXファイルをダウンロード

HEXファイルは説明なしで更新しております。気になる方は最新のファイルをご利用ください。

Eleky675d_2

Elekey675case_2

出来上がったエレーキーは、小さな透明ケースに収納し、FT-450を使った移動運用時に持っていくことにしました。 50MHz 50W運用で時々誤動作がおこりますので、キー出力ラインにLCのフィルターを追加してあります。 LもCもジャンク箱から最初に掴んだものを取り付けましたので、定数は吟味しておりません。

ワンチップマイコンでは無く、プログラムの不要なICによるエレキーの製作はエレキー回路の追加 で紹介しております。

とりあえず、PICマイコンの開発ができるようになりましたので、本来の目的である、ATUの開発に着手しました。 バリコン式ATUの自作 1 を参照下さい。

スリープモードへの入り方、復帰の仕方のみ、ソースファイルを抜粋しました。

void interrupt TimerSleep( void ) {
     if (T0IF == 1) {             // タイマー0の割込み?
          TMR0 = 0x00 ;         // タイマー0の初期化
           if ((GP5 == 0) && (dashfg == 1)) {  
                dotmemofg = 1;
                dashmemofg = 0;
                }
      if ((GP4 == 0) && (dotfg == 1)) {  
             dashmemofg = 1;
             dotmemofg = 0;
             }
       slpcount++;//スリープカウンター
       T0IF = 0;
       }
 if (GPIF == 1) {//sleep modeからの割り込みチェック
       cnt0 = 0;
       GPIF = 0;
       GPIE = 0;
       } 
}

以下main()の中のループの一部です。

if (slpcount > 200) {//スリープカウントが200を超えたら
  GPIF = 0;
  GPIE = 1;
  asm ("sleep");//スリープモードへ
  asm ("nop");//スリープモードから復帰した時のダミー命令
  GPIE = 0;
  }

...

全ソースファイル elekey12f675.cをダウンロード (バグ修正済み)

2017年2月追記

このエレキーの電池は100円ショップの単4アルカリ乾電池3本でしたが、2年8か月でとうとう力尽き、2017年2月に新品と交換しました。

 

2020年11月

プログラムにバグが発見されましたので、XC8用に書き換えて修正しました。

elekey_XC8_version.cをダウンロード

2024年4月

エレキーのWPM速度を表示出来る新エレキーを作り始めました。

 

INDEXに戻る