2020年12月29日火曜日

遅ればせながらPIC手習い(その3)

  さて、話をプログラミングに戻そう。

 PICを使う上で最も重要なのはpinの使い方だ。全体を眺めると、20pin以下のPICの場合、刻印のある1番pinはVdd、上から見て反時計周りに最後のpinがVssになっているようだ。 他のpinには色々な信号を割り付ける事が出来るようになっている。

 16F18346の場合教本(英文マニュアル)のTable3に信号の一覧表がある。例えば一番上の(20pin-PDIPパッケージで)19番pinの場合デジタル入出力の名前はRA0、つまりAレジスタのビット0である。このpinには他にデフォルトでADコンバータのANA0(A0入力)、或いはDAコンバータの出力(DAC1OUT)等が割り付けられている。

また次のようにpinにデフォルトで割り付けられていない信号も存在する。

  このような信号とpinの割り付けをコントロールするのが内蔵されてるPPS(peripheral pin select)モジュールだ。16F18346の場合使えるポートはA,B,Cの3つである。ただし各ポート毎に全8ビットが使える訳ではなく、実際に16F18346で使えるのはA0~A5、B4~B7、C0~C7のみである。これらはそのままデジタル入出力の信号名RAn、RBn、RCn(nはビットを表す数字)に対応し、電源を除く18本のpinに割り振られている。これが次図である。


 各々のpinをデジタルで使うのかアナログで使うのかを決めるのがPPSのANSELxレジスタである(xはA,B,Cの何れか)。自分が使いたいモジュールの信号がデジタルなのかアナログなのかはマニュアルのTable1-3にある。ANSELxレジスタの対応するビットが1の端子はアナログ、0の端子はデジタル入出力となる。
 デジタル入出力の場合、TRISxレジスタでその端子が入力か出力かを指定する。もしアナログで使う場合はTRISxの対応するビットも1とする。つまりビット単位で次の設定を行うことになる。

 これらのレジスタをC言語でビット単位に扱うにはレジスタ名に「bits」を付けドットを付けた後にビット位置を表す定数名を書く。この定数名はレジスタ名+数字と同じではない場合もあるのでMPLABのプログラム編集画面では示される候補の中から選択すればよい。例えば3番pin(RA4)をデジタル入力に使うためには ANSELAbits.ANSA4=0、TRISAbits.TRISA4=1 とする。また ANSELA=0b10101010、TRISA=0b01010101 のようにレジスタの全ビットを同時に書き込む書き方もできる。

 機能をpinに割り振るためには、ANSELxレジスタとTRISxレジスタの対応するビットを指定する他、どの機能(モジュール)をどのpinに割り振るか指定する必要がある。これは実際には次のように sssPPS或いはRxnPPSのレジスタで指定する。

  • sssPPS  = pin番号  (入力の場合)
  • RxnPPS = 信号番号  (出力の場合)

 入力の場合、左辺のsssは前述のTable3に書いてある信号名、出力の場合のRxnはRC4の様なデジタルのpin名である。 右辺のpin数(実際のpinの番号ではない)や信号番号は英文マニュアルの13.8節のREGISTER 13-1, 13-2 に説明されているが英文なので慣れないと取り付きが悪い(割り付けの変更が出来ない信号もあるようである)。例えばRC7をUARTの出力、RC6をUARTの入力と定義したい場合は、
    RXPPS   = 0b10110;       //RX input is RC6
    RC7PPS = 0b10100;       //RC7 source is TX
 と記述する。

 以上のようにあるpinにある機能を割り付けるのに通常3つのレジスタに値を設定する必要がある。 例外としてデジタルの入出力を直接ソフトで扱う場合(例えばLEDを点滅する場合やスイッチのON/OFFの検知など)はANSELx、TRISxの2つを設定するだけで済む。

 pinの割り付けが済んで、初めてPICに内蔵される機能を使う事ができる。 

(つづく)


2020年12月20日日曜日

遅ればせながらPIC手習い(その2)

  目標としている回路はLEDで光を出し、その光をフォト検出器(トランジスタ)(PD)で受光し、その比を求める機械である。光の通し方によって透過型や反射型、散乱型など考えられるが回路的には同じで良いと考える(もし受光量が微弱であればロックインアンプを使う事も考える必要がある)。

 LEDの光量は電流値にほぼ比例する。またPDも受光量に比例した電流が得られる。そこでD/Aコンバータの出力電圧でLEDを電流駆動するとともに、PDに流れる電流を電圧に変換してA/Dコンバータに取り込む回路が必要である。PICのD/Aコンバータの外部回路の駆動能力は低いので高インピーダンスで受ける必要がある。またA/Dコンバータの入力インピーダンスも高くないので低インピーダンスで電圧を与える必要がある。いくつか試した後、次の回路に落ち着いた。 

 IC2は単電源のフルスイング汎用OPアンプであり、秋月で売ってるJRCのNJU7043Dを使った。Tr1はジャンク箱に転がっていた普通のNPNトランジスタ(2SC641)で、エミッタフォロワーで電流増幅に使っている。PIC 16F18346のD/Aコンバータの出力はデフォルトの19番pinに出力する。R1とLEDは直列に接続しているのでLEDにはR1と同じ電流が流れる。R1は電流を電圧に変換するための抵抗で、この電圧がD/Aコンバータの出力と同じになるようOPアンプに負帰還をかけている。

 R1の電圧はPICの16番pinからA/Dコンバータに取り込んでLEDの電流をモニターできるようにしている。

 R2はPDの出力電流を電圧に変換する。この電圧はOPアンプによる高インピーダンスのボルテージフォロワーで受けてPICの15番pinからA/Dコンバータに渡している。R2の値は取り扱う光量とフォトトランジスタの性能で決める。感度が足りなければPDをダーリントン接続にするとよい。

 D/Aコンバータの出力電圧をVdaとするとR1及びLEDに流れる電流Iledは Iled=Vda/R1である。このときTr1のエミッタ電圧VeはLEDの順方向電圧降下をVfとすると Ve=Vda+Vf となる。またベース電圧VbはTr1のベースエミッタ間の電圧をVbeとして、Vb= Vda+Vf+Vbe である。OPアンプとTr1のベースは直結しているからOPアンプの出力電圧Vop=Vbである。すなわちVop= Vda+Vf+Vbe という関係が成立する。
 OPアンプの最大出力電圧Vophを4.9V、Vbeを0.7Vとすると、4.9 = Vda+Vf+0.7、すなわち Vdah=4.2-Vf がこの回路が機能するD/Aコンバータの最大出力電圧である。このときLEDにIldehの電流を流すためにはR1の値は、R1=Vdah/Iledh とする必要がある。一般的にIldehは20mA(0.02A)である。
 もし赤色や赤外LED(Vf=1.2V)を使うとすると、Vdahは3.0Vとなり、R1は150Ωとなる。また白色LED(Vf=3.2V)を使うとVdahは1.0VでR1は50Ωとなる。

 このようにPDのLEDに順方向電圧降下Vfの大きい青や白色LEDを使う場合この回路ではダイナミックレンジが狭まるのでTr1をPNP型に替えたほうが良いかもしれない。この場合Tr1のEとCを逆に接続、さらにOPアンプの入力の+/-を逆にする(次図参照)。仮に順方向電圧降下が3.2V/20mAのLEDを使う場合R1は50Ω程度となる。またR9は20KΩ程度である。

 

 ちなみにI2Cを使った液晶表示器(LCD)との接続は次のように簡単である。液晶は秋月で売ってる AE-AQM1602A(16文字×2行)を使った。I2Cの信号線は複数のデバイスが接続できるバス形式のワイヤードOR接続である。従ってプルアップ抵抗が必要であり、LCD補助基板内のプルアップ抵抗を半田付けでONにしている。

 一応ソフトが上手く動くようになったので、ユニバーサル基板に組み上げた(写真は追加回路を含む)。


このとき電池駆動する事が前提なので3端子レギュレータを使った簡単な電源回路を組み込んだ。

 この回路の消費電流はせいぜい十数mAなので電源に20V程度を供給してもTO-92パッケージの小型3端子レギュレータの定格を超えない。さらに電池駆動を前提として電源電圧の監視回路を組み込んだ。具体的には電源電圧をR7とR8で分圧してA/Dコンバータに与えている。抵抗で分圧するのは 電源電圧が高くなってもA/Dコンバータの入力電圧がA/Dコンバータの上側の参照電圧(Vref+、約4Vに設定)以下に収まるようにするためである。

 最後に、ユーザインターフェイスとして次のような回路を組んだ。

 これらは動作確認用LEDとスイッチ及びジャンパーである。これらはソフトで機能を設定することで自由に使える。

(つづく)
 





2020年12月18日金曜日

遅ればせながらPIC手習い(その1)

 知人に頼まれた機械をどう作るか考えていたら、PICが良いんじゃないかというアイデアに辿り着いた。PICという名前やCPUやメモリ、様々な周辺回路が1つのICチップに内蔵されていて百円程度という夢のような値段で入手できる事は以前から知っており、PICの見本として八潮の秋月で適当に見繕って8pinと14pinの安いPICを買った以外は未だ手を出したことが無い。もちろんライター(プログラムの書き込み器)も持ち合わせていなかった。

 情報を得ようとネットで検索するとPICにはものすごく多くの種類があることが分かり、CPUのビット巾だけでも8ビットから32ビットまである。内蔵する周辺回路もてんこ盛りでかなり複雑に出来ている。私が半世紀近く前に卒論に使ったインテルの8080で同じものをディスクリートで組んだらラック1つを占有するだろう。こんなものが百円程度で買えるとはすごい世の中になったものである。一方こんなアナログとデジタルが混在した複雑なものを僅か8ピンや14ピン程度のICにどうやって押し込んでいるのか謎である。

 PICには通常OSや外部記憶の様なものはなく、プログラムをPICに直書きして動かす。プログラムの開発環境としてはPICの製造元の Microchip Technology 社がMPLAB X IDEというソフトを無償で提供しており、アセンブラやCで書けるようになっている。

 どのPICを使うにしてもライターは必須であるが、これも Microchip Technology 社がPickitという名前で販売しているほか中華製のコピーもあり、秋月電子でも独自に開発したPicKit2の互換品を売っている。ただPicKit2はデザインが古くMPLABではもはやサポートせずWindows10にも対応していないようなので(何故かいまだに秋月で売っている)今後の事を考え最新型のPicKit4を買った。PicKit4にPICを付けるアダプタは簡単なので、とりあえず必要な20pinのものを自作した。要はPicKitの5本の線を決まった足に直接接続するだけで20pin以下のPICには対応できるようだ。

 これでネットで出回っているLEDを点滅させる簡単なプログラム(バージョンが古いのかコンパイルエラーとなり少し修正する必要があった)を、昔見本として買っていた14pinのPIC 16F1823に書き込んで、ブレッドボードで組んだ回路で動かしてみると簡単に動いた。 プログラム本体は次のようなものだ。

     while(1){
        RA2 = 1;
        __delay_ms(100);
        RA2 = 0;
        __delay_ms(100);
    }

しかし、その前段階としての念仏が多い。例えば、

#pragma config FOSC = INTOSC
#pragma config WDTE = OFF

     OSCCON = 0x00;
     TRISA  = 0x00;

といった書き方で、これはPICの初期設定だったり、ハードウェアの操作であったりする訳であるが、ここに登場する大文字の名前がプログラム中には定義されておらず、ある意味仲間内での秘密の呪文であり私みたいな異教徒には理解できない言葉である(実際には#include文を辿っていけば発見できるかもしれないが、そこには値は定義されていても意味は含まれていない)。しかし、これらを知らないとPICのプログラミングは不可能。
 これを身に着けPIC教徒の洗礼を受けるには経典を読むしかない、ということでAmazonを彷徨って経典を探した。PICに関する経典は古いものが多く最新の情報が全般的に得られそうなものは少ない。とりあえず「C言語によるPICプログラミング大全」という経典を得た。これも元は改訂版が2009年という古いもののようであるが、2018年にリニューアルされ、さらにネットで2020年の最新情報が提供されている。

 これを手元に大航海に出た。 次の目標は16F18346を使ったとある回路である。この16F18346は20pinのICであり電源を除く18pinをプログラミングにより色々な目的に使うことが出来る。

 

 16F18346を使う理由はI2Cインターフェイスを持ちLCDと簡単に接続できてお勧めとのネット記事を見かけたからである。それにA/DやD/Aコンバータを内蔵しており、メモリーもそこそこあり目的には十分である。おまけに秋月で1個160円と安い。内部の構成は次のようになっている。


 とりあえず、ブレッドボードで組んでネット情報の再現を試みた。

  そこで分かったのは、私が買った経典は数多くあるPICの一般的な使い方について書いてあるが個々のPICの方言には対応していないという事である。LEDチカチカやLCD表示程度はネットで得た情報で何とかなったがそれでは応用が効かない。こうなったら原典に当たるしかない。

 そこでMicrochipから16F18346のマニュアル(PDF)をダウンロードした。英文でなんと500ページある。1ページ10円のコンビニ印刷でも全部印刷したら5千円!!!、160円のPICを使うのにこんなに経費がかかるとは。
 とりあえず必要そうな部分300ページ程を印刷した。

 (つづく)