« 2009年4月 | トップページ | 2009年7月 »

2009年6月21日 (日)

PIC12F509を用いたなんちゃって正弦波発振器の構想

まず結論から.

Photo こんな回路を作れば,できそうな感じになってきた.PIC12F509の動作は,正弦波に程近い(とはいっても高々8倍の周波数だが)VVVFの指令パルスを出す.これを受けて実際のVVの部分の実現をどうするか,だ.当初より変更してトランジスタはPNPタイプのものにしたが比較的簡単な回路でできそう.抵抗値は現物あわせで決めた.計算すりゃいいんだけれどね.計算してもどうせ確認するし,実際には手持ちの抵抗で実現できる値を選ぶんだろうから,ということであとはPICが正確なパルス指令を出してやれば良い.

本当はPICから出た指令パルスの波形をオシロでとりたいのだが,家にそんなものは無い.LEDを点灯して貧乏なデバッグを実施する.なんとなく,できてそう.試しに,PICの指令パスル出力をそのまま圧電スピーカにつないでみた.圧電スピーカは直流分が入っていてもいいし,電力もいらないので簡単に確認ができる.

完全ではないが,それらしき周期でパルスを発生している.GP3はプの音,440Hzの低音側っぽい音だ.また,GP5はピの音,880Hzを意図した発振をするはず.この2つのI/Oを順番にOnさせると,オクターブになるはず.....うーん.微妙に音痴.ちょっと高い音が低めだ

これは,例の発振周波数×8倍の周波数で時間待ちをしているところの,定数違いだろう.やっぱり計算はビール抜きのときにやらなきゃね.

ただし,おおまかにはあっているので,つまらないところで命令数を数え間違えているなどの原因だろうから,今のところは気にしない.いざとなったら高々2音のオクターブ関係なんだから,ホビーの王道現合という手だってある.

ところで,PIC12F509でもやってしまった.もう片付いた話だが,新しいPICの種類を使う度に,再三こうした目に遭うので今後の戒めの意味で書き記そう.

GP2のコントロールが効かないのだ.今回,TRISの設定値は0x28,GP0,GP1,GP2,GP4が出力だ.GP0,1,4は正確にソフトウエア通りにON/OFFしているようだが,GP2だけうんともすんともいわない.LEDをつけても,ロジックプローブを当てても,まったく無反応.まるで入力に設定されているようなのだ.

ここでマニュアルを読む.GP2がアサインされているのは,T0CKI,TMR0の外部クロック入力と兼用のピンだ.うーん,こいつとあたっているのか.

確かにマニュアルには,OPTIONビットの中にTMR0のクロックソースを指定するビットがある.TMR0の外部クロックを有効にすると,このピンは入力に設定される.(TRISをオーバーライトする,とある)しかも,パワーリセット時のデフォルト値は,外部入力なのだ.

ヤラレタ.

だけどPICの気持ちがわかれば,直すのも簡単.OPTION命令でTMR0のクロックソースをIntに切り替えて,無事GP3は出力として使えるようになりました.

「PIC12F509FakeOfSinWave.asm」をダウンロード

2009年6月20日 (土)

PIC12F509ちっさいけれど,ピリリ

PIC16F88+SC1602S*Bを使った陸上タイム計測器の時報(スタート音)に使う正弦波発信器モドキをPIC12F509で作ってみよか,と思いつき,考えてみた.Excelで試算した内容を冷静にも一度見てみた.
プリスケーラを2とか1に設定すれば,TMR0を使って何とか1KHz前後までは何とか発生できる見込み.でもPIC12F509って,割り込みが無いんだよな.すると,ソフトウエアでTMR0の計数値を見張り,例えばFF→00になった瞬間をSTATUS-Zフラグで検出すれば出来るのだけれど,これにはbtfs?命令とGOTOディレクティブでループを構成しなければならない.でも待てよ?プリスケーラが1ということは,TMR0のカウントクロックとCPUの動作するインストラクションクロックが全く同一ってコトだな.そうすると,TMR0のオーバフローを検出するループが仮に3マシンサイクル(btfs?(=1サイクル)+goto(2サイクル))になってしまうので,タイミングが0~3サイクルは狂ってしまうことになる.うーん,残念だけれどTMR0は使わないほうが良いね.このクラスのPICで組まれる一般的な方法として,nopやLoopで時間待ちをしたほうが良さそうだ. nopやloopで時間待ちをする場合,ソフトウエアの正確なコードが決まらないとどんな時間待ちをどのような定数でやれば良いかも決まらない.卵鶏状態でなにも決まらない.
そこで,コードを書き始めることにする.

Vvvf何ちゃって正弦波発信器は,PIC12F509のGPIOをVVVF(Variable Voltage & Variable Frequency))っぽく制御すれば制限波っぽい波形を生成できるんじゃないか,という幼稚な発想で始めた遊びだ.発生させたい正弦波の8倍の周波数で,VVVF的パルスを生成する為の指令(1ビット)を出力する.これをトランジスタで受け,オープンコレクタ出力にして指令に対応した電圧が生成されるように負荷抵抗をセットしてやれば良い.オープンコレクタにするのは,複数の指令パルスを受けた電圧をワイヤードORで結線することでして連続波形にする為だ.(ほんとうはOPアンプの加算回路で合成するべきなのかもしれないが,遊びだから面倒くさいことはなるべくやりたくないのだ.後は交流カップリングとアッテネータを介してで386(1WオーディオアンプIC)へ送れば良いんじゃないか.

さてと,ソフトを作るには...MPLAB のIDEの環境を整えて,っと.MicroChipのサンプルソースを変更してソフトを書けば良いね.サンプルソフトを見てみた.すると,

ORG     0x3FF             ; processor reset vector

; Internal RC calibration value is placed at location 0x3FF by Microchip
; as a movlw k, where the k is a literal value.

ORG     0x000             ; coding begins here
movwf   OSCCAL            ; update register with factory cal value

とある.え?リセット割り込みベクタが03ffH??? しかも何のソースコードも書いていないし.その後すぐにorg000Hがあるし.

データシートを斜め読みしてみると,12F509はPricisionな内蔵RC発振器を有しており,かつそのキャリブレーション値が工場出荷時に書かれているというのだ.上記のサンプルソースと併せて解釈すると,キャリブレーション値はプログラムメモリの03ffHにmovlw kの形式で保持されているという.(kがキャリブレーション値)なおかつ,03ffHはリセットベクタだというから,電源リセット時にはここからCPUは動作を始める.PIC12F509の場合,03ffHのこの命令の次にPC(プログラムカウンタ)が向かうところはオ-バーフローして000Hだ.ここにはmovwf OSCCAL命令があり,Wレジスタに保持された,工場で書き込まれた内蔵RCオシレータのキャリブレーション値がキャリブレーションレジスタに目出たく書かれ,とてもリーズナブルな仕組みで4MHz(誤差1%)のPricisionなCPU動作クロックが供給されるということになる.こんな仕組みが60円のCPUに入っているなんて,にくいねぇ.4MHzの発振器から供給されたクロックは,4分周されてTMR0のカウントアップ用クロックソースとして供給される.だからこの場合,カウントクロックは1MHzだ.また,CPUのマシンサイクルは4クロックで供給されるので,1マシンサイクルは1MHzとなる.かくして,ユーザはTMR0で1μSecで刻むなり,1命令で1μSecを消費するなりということで,単純だが精度の良く計算のしやすいクロックを用いてアプリケーションを作成することができる.

さて,PIC12F509は8pinのIC.内蔵クロックで駆動するとなると,電源+,Gndに2pinを消費するが,残りの6品は全てI/Oとして使える.但し,GPIO3だけは入力としてしか使えないそうだ.ちょっと不満.何でbit3なんだ.MCLR*との関係なんだろうけれど...ま,こういう割り切りがPICの魅力でもあるんだけれどね.
かくして,趣味で.
Bit0(出力)角度 -1π/16~3π/16, 5π/16~7π/16の時の出力指令
Bit1(出力)角度 3π/16~5π/16, 15π/16~17π/16の時の出力指令
Bit2(出力)角度 7π/16~9π/16,13π/16~15π/16の時の出力指令
Bit3(入力)低音:ブッ(440Hz)の発振指令
Bit4(出力)角度 11π/16~13π/16の時の出力指令
Bit5(入力)高音:ピー(880Hz)の発振指令
というピンアサインとした.
入力のビットパターンが変わらない限りは,所定のサイクルで上記Bit0,1,2,4をサイクリックにON/OFFさせれば良い.
一つのパルスを発生させるソフトはおおよそ次のようになるだろう
ModeL_1_8_PI  ; 1/8PI Out PitPatern=0x04
     movf GPIO,W      ←1Clock
     andlw CommandMaskBitPattern  ←1Clock
     xorwf mode,W      ←1Clock
     btfsc STATUS,Z     ←1Clock
     goto setMode

  ;;; Wait xxx Instruction Clock
     movlw LowToneWaitFactor    <<<- ここまで
     call wait_8_Plus_4_by_n_Clocks     LowToneWaitFactor×4+8 ->>>
     nop         ←(補正)1Clock
     nop         ←(補正)1Clock

  ;;; Out Signal to GPIO
      movlw 0x04      ←1Clock
     movwf GPIO      ←1Clock
     goto ModeL_3_8_PI    ←2Clock

ここで,共通の時間待ちサブルーチンを以下とした
wait_8_Plus_4_by_n_Clocks
wait_8P4n000  movwf wait_8P4nCounter0
wait_8P4n001  decf wait_8P4nCounter0,F
     btfsc STATUS,Z
     return
     goto wait_8P4n001

この条件で消費クロックを数え,excelから時間待ちFactorと調整用のNOPを入れて正しく440Hz,または880Hzの正弦波っぽくなるように調整した.

「pic509.xls」をダウンロード

コンパイルは通ったぞ.とりあえず.

「PIC12F509FakeOfSinWave.asm」をダウンロード
「P12C509.INC」をダウンロード
「ms509.inc」をダウンロード

大きな勘違いは無いと思うけれど.ビールの見ながらExcelシートと作ったし.計算間違ってなければいいなあ.取り合えず,今度の休みにでも動作確認してみよう.

それにしても,60円のPIC12F509もやるもんだ.がんばっているなぁ.

2009年6月12日 (金)

恐るべし,陸上競技場

完成した!,と思った自作光電管式陸上競技タイム計測器をとある陸上競技場へ持ち込んで最終確認...のつもりが,5月の晴天下の陸上競技場は只者ではなかった.

 体育館内でのテスト,自宅前の市道上でのトライアルにはほぼ満足できる性能,使い勝手だった.本当に実際の計測環境での最終確認のつもりで,まずはPM1:30.陸上競技場のトラック内部の中央部に陣取って練習の邪魔にならぬよう意気揚々とくみ上げた....が,レーザ光の光軸がずれているにも関わらず,光電管スイッチがONしてしまう.ははぁ,5月の晴天下,周囲にさえぎるモノの無い陸上競技場だから,照り返しが外乱光になっているのだな,と思い,レーザ発光側,センサ側ともその場にあるもので覆ってみたが,変わらず.近距離でなら,ON,OFFを認識してくれるが,発光側と受光側を30cmも離すともうONしっぱなし.
 壊れたのかな,と思い,ベンチ内の日陰で再びトライアルしてみると,今まで通りほぼ完全に振舞ってくれる.再び日なたへ出すと,もうダメ.そうすると,温度そのものの影響じゃないな.
 それを確かめるべく,夕方5:30に再びトライアル.昼間に比べると立っている時の上半身近辺の気温はかなり涼しくなっている.しかしこれでも現象はそう変わらない.ここで思い当たるのは熱を蓄えた陸上競技場の地面から上がってくる温度.赤外線カメラで見てみたら,かなり真っ赤になっていることなんだろうな.例によって測定器なんて全く持っていないから,想像の域を超えないけれど.
後日,フォトトランジスタPTS610,PTS615の特性を見てみると,なんと感度のピークは800nmではないか.赤色レーザ光の波長は650nm.細かい数値は覚えていないが,赤外線って確か800nmくらいの波長だったように思う.むしろ,赤外線の方を強く拾うんだね.きっと.
 というわけで,ここは電子回路上で対策するしかないことになる.今はフォトトランジスタの入光・遮光時の電圧変化に対して,単純に74HC14のスレッショルドにあわせてバイアスをかけているだけ.従って外乱信号が74HC14のスレッショルドよりも高い位置に来てしまえば,常時ONになってしまい,光電管センサとしては使い物にならないのだと考えるとつじつまが合う.
 やっぱ,フツウにコンパレータで取ろう.その前段でOff時の外乱光をキャンセルできるレベルシフトを行えるようにすれば良いかな.LM324あたりの単電源OPアンプでなんとかできたら良いな.だめならこの方式での自作はあきらめかな.

実はもう一つ我慢なら無いことがあった.
非常に気に入っていた,スタートの時報音だったが,完全なアナログ発信回路を用いた為,どうも温度変化に弱い.高温になればなるほど,高い音にシフトするばかりか,ブッブッブッピーのプの音(440Hz=Aを想定)とピーの音(880Hz=オクターブ上のAを想定)のオクターブ関係がずれて,スタートダッシュのモチベーションを根こそぎ取り去るようなマヌケな音になる.
Drums担当だとは言え,若かりし頃はアマチュアミュージシャンの端くれだったプライドが我慢の限界を超えた.
Vvvf ようし.ここもデジタル化するぞ!どうせいつかはやろうと思っていたんだ.とはいえ,PICだけで可聴音域の完全な正弦波を発生させることは難しい.考えたのは,VVVF方式.正弦波っぽく電圧可変,周波数可変のパルスを生成するのだ.
本当は正弦波を発生したいが,デジタル制御で赤の信号を作り,なんとなく正弦波っぽく聞こえる発振器を作る.何ちゃって正弦波だ.デジタル制御によるパルス列だから,周波数は温度に拠らず,また,オクターブの関係に至っては正確無比にKeepできるというものだ.
これをPIC12F509あたりでできたらオモシロイ.D/Aの機能が無いので周辺ICの力は借りることにはなるが,8ピン・割り込み無し・\60円のPICであえてチャレンジしてみる.PIC12F509にもTMR0は実装されている.こいつを使って.やるとすると,どうなるか...

「pic509.xls」をダウンロード

今回は440Hz.12F509内臓の4MHzクロックでPICをドライブすると,TMR0の計数クロックは1MHzとなる.前出のグラフのように,発生させたい正弦波周波数の8倍でスイッチON/OFFをするための動作タイミングを1MHzの計数クロックでTMR0を使った場合の設定を算出してみると...
 440Hz  プリスケーラ=2,TMR0のカウント値=142
 880Hz  プリスケーラ=1,TMR0のカウント値=142
と,この場合でゆけばプリスケーラ値を1,2と切り替えれば良いことになる.4MHzでPIC12F509を動作させた時のインストラクションクロックは1MHzなので,TMR0のカウントクロックと同じだ.だから,厳しいほうの880Hzで見ても,142インストラクションに1回の割合でパルス発生をしてやれば良いことになる.パルス発生とはいっても,PIC12F509から見ればGPIOを切り替えるだけだ.うーんこれなら,割り込み無くても何とかなるんじゃないかな~.あるとおもいます.
と,言うわけで,Mesure88プロジェクトは最後の(最後にしたい)山場を迎える.

« 2009年4月 | トップページ | 2009年7月 »