PICのプログラムは、主にCCS PIC Cコンパイラーを使用し、たまにアセンブラを使用しています。
PICライターは、秋月電子のAKI-PICプログラマーVer4を使用しました。
PICを使ったクラシックギターの音程をビジュアル的に表示できるチューナーを作成してみようと思い、 いろいろと調べ、また実験を重ねてやっと作成できました。
トランジスタ技術に掲載された幾島康夫さんのH8マイコンを使った
ギター・ピッチ・チューナーをPICで作成できないかと試みてみましたが、
うまくいきませんでした。残念ながら力不足でした。
そこで、ストロボ方式に切り替えて、PICのCCPモジュールのコンペアモードを
使ってビジュアル的に表示できるチューナーを作成しました。何とか使えるものが作成できました。
この回路には、PIC16F873A を使用しました。外観の写真のように左右8個のLED、 計16個の LED を
円形に並べ、その中央にMode表示用の7SEG-LEDを一つ配置し、その下の黒い丸はコンデンサマイクです。
そして右下に、弦選択と基準周波数選択の「Mode切替スイッチ」を、左下に弦選択と基準周波数選択用の
「選択スイッチ」を配置してあります。側面に電源スイッチを付けていますが電源は、9Vの乾電池を
使用しています。
1.「Mode切替スイッチ」が弦選択の時、7SEG表示は次のようになります。
「1」は1弦、「2」は2弦、「3」は3弦、
「4」は4弦、「5」は5弦、「6」は6弦
2.選択スイッチを一度押すごとに1~6までが7SEGに表示されます。
3.「Mode切替スイッチ」が基準周波数選択の時は、以下のように設定してあります。
「1」は439Hz、「2」は440Hz、
「3」は441Hz、「4」は442Hz、
「5」は443Hz、「6」は444Hz、
「7」は445Hz、です。
上記と同様に、選択スイッチを一度押すごとに1~7までが7SEGに表示されます。
4.実際に使用するとき、
(1)左右のLEDの点灯が下方に流れるときは、ギターのピッチが基準周波数より低いときです。
したがって、ギターのピッチを上げます。
(2)左右のLEDの点灯が上方に流れるときは、ギターのピッチが基準周波数より高いときですので、
ギターのピッチを下げます。
(3)ギターのピッチが合っているときは、LEDが点灯したまま流れが止まります。
下記に回路図を表示しておきます。
1.PIC16F873Aを次のように使用しています。
(1)RA0~RA3:1つの7SEG-LEDを表示するためのデコーダ/ドライバ「74HC4511」へ
(2)RA4:モード切替用スイッチへ
(3)RA4:モード切替用スイッチへ
(4)RA5:7SEG-LEDのカウントアップ用プッシュスイッチへ
(5)RB0~RB7:片側LED8個へ
(6)RC0~RC7:もう一方の片側LED8個へ
(7)セラミック発振子は20MHzです。
2.コンデンサマイクからアンプ「LM358」を通し2段のバッファからの出力を上記16個のLEDと
接続しています。
3.電源は9Vの電池を使用しています。
CCPモジュールをコンペアモードで使用し、コンペアレジスタでタイマ1がT/8μSec毎に
割り込みが入るようにして、下図のような信号で8個のLEDを点滅させます。
1.RC0~RC7に接続した8個のLEDも同様に点滅させます。
2.例えば、f=110.0Hzのとき、T=1/f より T=9091μSec となるので、コンペアレジスタで
タイマ1がT/8=1136μSec毎に割り込みが入るようにします。
3.CCP1のCCPRレジスタにタイマ1でT/8μSecの時間カウントになる値をセットしておき、
タイマ1がカウント動作を開始してカウント値が一致したときタイマ1をリセットする
モードにしておけば、タイマ1は、0~CCPRレジスタの値までのカウント動作をずっと
繰り返すことになります。
したがってコンペア一致の割り込みは9091μSec周期で発生することになります。
4.このCCP割込み処理の中でLEDを点滅させ、これとコンデンサマイクの信号を増幅させた
出力とを結合させます。
5.PIC(クロック20MHz)の命令サイクルタイムが0.2μSecですから、タイマ1は、命令サイクル
である0.2μSec毎に+1するので、プリスケーラで1倍とすれば、
(1)0.2μSec×1×count値=9091μSec/8から、count値=5682となります。
(2)基準周波数ごとのcount値を計算した結果を下図に示します。正確には、count値は
計算結果より1を引いています。
黄色の部分をプログラムに使用しています。
ギター・ピッチ・チューナーのPICプログラムを掲載しておきます。
///// Guitar_Modulation ///// #include <16f873A.h> #fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP #use delay (clock=20000000) #use fast_io(B) int icount=0; int pb_value; int pc_value; int Pre_str = 4; int Pre_fre = 1; long Cp_count [6][7] = { {1899,1895,1891,1887,1882,1878,1874}, {2536,2530,2524,2520,2513,2507,2502}, {3195,3188,3180,3174,3166,3159,3152}, {4265,4256,4246,4237,4227,4217,4208}, {5694,5681,5668,5656,5642,5630,5617}, {7601,7583,7566,7550,7532,7515,7498}, }; //// CCP1割り込み処理関数 #int_ccp1 //CCP1の割り込み void ccp1_isr() { icount++; if (icount>7) { pb_value=1; pc_value=1; icount=0; } else { pc_value = input_c(); pb_value = input_b(); pc_value = pc_value<<1; pb_value = pb_value<<1; } output_B(pb_value); output_C(pc_value); } void main() { setup_adc_ports(NO_ANALOGS); set_tris_a(0xF0); set_tris_b(0); set_tris_c(0); output_b(0x01); output_c(0x01); setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //タイマ1 プリスケーラ1倍で内部クロック動作 setup_ccp1(CCP_COMPARE_RESET_TIMER); //CCP1 コンペアー一致でタイマ1リセット CCP_1 = Cp_count[Pre_str][Pre_fre]; set_timer1(0); //タイマ1初期セット enable_interrupts(INT_CCP1); //割り込み許可 enable_interrupts(GLOBAL); while(1) //アイドルループ { if (input(PIN_A4)) { output_a(Pre_str+1); if (!input(PIN_A5)) { Pre_str = Pre_str+1; if (Pre_str>5) { Pre_str=0; } output_a(Pre_str+1); } delay_ms(400); } else { output_a(Pre_fre+1); if (!input(PIN_A5)) { Pre_fre = Pre_fre+1; if (Pre_fre>6) { Pre_fre=0; } output_a(Pre_fre+1); } delay_ms(400); } CCP_1 = Cp_count[Pre_str][Pre_fre]; } }
参考としてプリント基板「IC基板」・「LED基板(ケース表面用)」の図2枚とケース内の写真を 掲載しておきます。