
写真1 AD9833 DDS MSOP 0.5ピッチ 変換基板に乗せる
それはさておき、
このチップは10ピンのMSOPで、写真にようにピンセットの先ほどの大きさです。
変換基板に取り付けましたが、ピンのピッチは0.5なので、半田付けにはちょっと技術が必要です。
まずチップをゲルタイプの瞬間接着剤で正確な位置に仮止めしておきます。
フラックスをほんのわずか塗って、すべてのピンにわざとまたがるくらい半田を盛ります。
半田吸い取り線で、余分な半田を吸い取って、出来上がり。
慣れれば簡単ですが、最初は数個パーにする覚悟がいります(笑)。
このDDSは、マスタクロック(MCLK)周波数は最高25MHzで、その場合最高発振周波数(ナイキスト周波数)は12.5MHzとなり、分解能は0.1Hzです。
今回は手持ち部品の関係で、20MHzのクリスタルを使用したので、10MHzまでのプログラマブルオシレータとして、実験してみました。この場合の分解能は約0.075Hzです。

写真1 ロータリエンコーダ EC16Bをつないで、カウンタ値をアップ/ダウン
マイコン内部の数値変更を指示したりする場合に使います。ボリュームをADコンバータにつないで、電圧値を読んで指示に使うこともできますが、他の処理をしながらADコンバータに変換指示するのは、煩雑です。
ロータリーエンコーダの場合、割り込みを掛けるようにすれば、常に監視する必要はありません。また、信号がパルスのため正確な処理が可能ですし、無限の回転系で、左回り、右回りが識別できるので加減指示が可能です。
ロータリエンコーダはピンからキリまでいろいろあり、高級なものは高くて手が出ませんが、実験などにそこそこ使えるものは秋月電子などで購入できます。
ロータリエンコーダ(インクリメンタル方式)はAとB 二つのチャネルがあり、軸を回転させると、それぞれにパルスが出ますが、それは互い違いになっており、一方のパルスが変化したときの、もう一方のレベルを見れば、回転方向がわかります。
ただ、単純にレベルの変化だけを見ると、チャタリングによる誤動作が目立つので、より確実な方法として、秋月電子のキットの説明書に掲載されている「ロータリエンコーダの読み取りについて」]を参考にさせていただきました。
使用するコンポーネントは、Clock, Interrupt, Digital Out pin, I2Cです。(今回は直交エンコーダは使用していません)
ロータリエンコーダは、A端子、B端子をそれぞれ10KΩでプルアップしておきます。
【schematic】

プログラムは、まず、1msインターバルの割り込みを作ります。Clockコンポーネントを組み込み、周波数を1KHzに設定します。
Clockコンポーネントの出力をInterruptコンポーネントにつなぎ、1ms毎の割り込みを発生させます。
ロータリエンコーダのA,Bチャネル用に、Degital Inputピンを組み込みます。
今回はAをP[0]5, BをP[0]6につなぎました。
割り込み処理ルーチンでは、割り込みを3カウント(3ms)したら、ロータリエンコーダのA_ChとB_ChのDegital Inpitピンの状態を読込み、説明書にあるアルゴリズムで右回りか左回りかを判定して、ロックポジション(クリック)でカウンタをアップ/ダウンします。
これで、1クリックでカウンタが増減します。
割り込み処理ルーチンでは、回転方向がわかるようにフラグをセットし、メインルーチンで、フラグを見ながらRight/Leftとカウンタの値をLCDに表示します。
【Program】I2C LCDの部分は省略
//mian.c
#include <device.h>
#include <stdio.h>
void I2C_LCD_Init(void);
void I2C_LCD_ClearLine2(void);
void I2C_LCD_WriteString(uint8, uint8, uint8*);
CY_ISR_PROTO(Clock_1ms_Interrupt);
int16 counter = 0;
uint8 int_cnt = 0;
uint8 now = 0;
uint8 prev = 0;
int8 change = 0;
char string[10];
CY_ISR(Clock_1ms_Interrupt){
if(int_cnt == 3) { //make 3ms
int_cnt = 0;
now = (A_Ch_Read() << 1) + B_Ch_Read();
if(prev != now) {
if (((prev << 1) + now) & 0x02) {
if(now == 0x03){ //right, lock position
counter++;
if(counter > 255) counter = 255;
change = 1;
}
} else {
if(now == 0x03){ //left, lock position
counter--;
if(counter <= 0) counter = 0;
change = -1;
}
}
prev = now;
}
} else
int_cnt++;
}
void main(){
CyGlobalIntEnable;
isr_Clock_1ms_StartEx(Clock_1ms_Interrupt);
I2C_Start();
I2C_LCD_Init();
I2C_LCD_WriteString(0, 0, "R.Encorder Test" );
for( ;; ){
if(change == 1){
I2C_LCD_WriteString(0, 1, "Right" );
} else if(change == -1){
I2C_LCD_WriteString(0, 1, "Left " );
}
sprintf(string, "%3d", counter);
I2C_LCD_WriteString(8, 1, string);
change = 0;
CyDelay(100);
}
}
(JF1VRR)