「PIC AVR 工作室」サイトの日記的なブログです。
サイトに挙げなかった他愛ないことを日記的に書き残してます。
PIC AVR 工作室 ブログ



DDSファンクションジェネレータのコントロールを
行うためのスケッチ、とりあえず書けた。

http://picavr.uunyan.com/avr_m2_dds_fg.html
これに繋いで使うコントローラ部分。シリアルで
制御コマンドをI/Fするためのもの。LCD画面で
見ながら、操作内容にしたがってDDSファンクション
ジェネレータにコマンド送信するので、PCが要らない。

オイラの場合、使っているオシロがUSB接続タイプで
PC画面で操作/表示するヤツだから、PCで操作しなくて
いいファンクションジェネレータは、何かと便利。


スケッチはこんな感じ。

/*   AVR DDS function generator controller   */
/*        with aitendo LCD keypad shield     */
/*   http://www.dfrobot.com/wiki/index.php/Arduino_LCD_KeyPad_Shield_%28SKU:_DFR0009%29   */
/*                                          */
/*    *input : keypad on LCD shield         */
/*    *output : LCD and USART               */
/*                                          */
/*    created by nekosan                    */
/*             created : 2013.10.21  V0.1   */
/*                                          */


#include <LiquidCrystal.h>

/* I/O pins for aitendo lcd shield */
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


/**********************************?
/***   declare global variables   */
/**********************************?

/* key names table */
char key_name[][10] = {
  "none   ",
  "select ",
  "left   ",
  "down   ",
  "up     ",
  "right  " };

/* wave form name table */
char wave_name[][4] = {
  "sin",
  "sq ",
  "tr ",
  "sw1",
  "sw2"};
  

/* freq and wave memory */
char num_data[6] = {0,0,0,0,0 ,0};  // initial = 0Hz , sine wave

/* limit table */
char limit[6] = {2,9,9,9,9 ,4};
    // limit freq = 29999hz
    // limit wave = 4 (sw2)

/* cursor position X */
int cur_x[7] = {0,1,2,3,4,7 ,15};
int pos_x = 0;



/*****************************/
/***   declare functions   ***/
/*****************************/

/* cognition witch button is pushed */
int key_sense() {

  /* last key */
  static char last_key = 0;  // initial = none
  /* key record ( for sensing key-change ) */  
  static char key_record[3] = { 0,0,0 };  // initial = none, none, none
  /* define threshold for keypads */
  const int keypad_th[] = {
    (1023 + 720) / 2,  /* none - select */
    (720 + 479) / 2,  /* select - left */
    (479 + 307) / 2,  /* left - down */
    (307 + 132) / 2,  /* down - up */
    (132 + 0) / 2 };  /* up - right */

  int key_in;
  int i;

  key_in = analogRead(0);

  key_record[2] = key_record[1];
  key_record[1] = key_record[0];
  int now_key = 0;
  for (i=0; iif (key_in if ((key_record[0] == key_record[1]) &&
      (key_record[1] == key_record[2])) {
    last_key = now_key;
  }
  delay(1);
  return last_key;
}


/* pick up key changing */
int key_check(int new_key) {
  static int old_key = 0; //initial = none
  int ret = 0;
  
  if (new_key != old_key) {
    old_key = new_key;
    ret = new_key;
  }
  return ret;
}


/* change a value */
void change_value(int key_change) {
  int i;
  
  switch (key_change) {
    case 1:  // select
      if (pos_x == 6) {
        reset_dds();  // send reset command
        for (i=0;i// all clear
        }
      }
      break;
    case 2:  // left
      pos_x--;
      if (pos_x < 0) {
        pos_x = 0;
      }
      break;
    case 3:  // down
      if (pos_x // declement
        if (num_data[pos_x] < 0) {
          num_data[pos_x] = 0;
        }
      }
      break;
    case 4:  // up
      if (pos_x // inclement
        if (num_data[pos_x] > limit[pos_x]) {
          num_data[pos_x] = limit[pos_x];
        }
        if (num_data[0] >= 2) {  // if over 20000hz
          num_data[0] = 2;
          for (i=1;ibreak;
    case 5:  // right
      pos_x++;
      if (pos_x > 6) {
        pos_x = 6;
      }
      break;
    default:
      break;
  }
  print_lcd();  // print freq and wave data on lcd
  
}


/* print out on lcd */
void print_lcd() {
  int i;
  
  /* print freq data */
  lcd.setCursor(0, 0);
  for (i=0;iwrite(num_data[i] + '0');
  }
  lcd.print("F ");
  
  /* print wave data */
  lcd.write(num_data[5] + '0');
  lcd.print("W(");
  lcd.print(wave_name[num_data[5]]);
  lcd.print(") R");  // 'R' means 'reset'

  /* set cursor */
  lcd.setCursor(cur_x[pos_x],0);
}


/* output to dds via uart */
void uart_out() {
  int i;
  
  /* output freq data */
  for (i=0;iSerial.write(num_data[i] + '0');
  }
  Serial.print("F");
  
  /* output wave data */
  Serial.write(num_data[5] + '0');
  Serial.print("W");
}


/* reset dds */
void reset_dds(){
  Serial.print("R");
}



/************************/
/***   main process   ***/
/************************/

void setup()
{
  /* setup LCD */
  analogWrite(10,127);  // back light brightness
  lcd.begin(16, 2);
  lcd.clear();
  lcd.cursor();  // display cursor on
//  lcd.blink();  // blink cursor on

  print_lcd();  // print freq and wave on lcd
  
  Serial.begin(19200);  // to DDS synthesizer
  Serial.println( (int)pow(10.0,4.0-(float)0.0 ) );
}


void loop() {
  int i=0;
  int key_in;
  int key_change;
  
  key_in = key_sense();
  key_change = key_check(key_in);
  
  if (key_change != 0) {
    change_value(key_change);
    uart_out();
    //Serial.println();
  }

}


まだ実機には繋いでないので、ちゃんと動作するか
は責任持てないんだけど、単純な代物なので、
まぁ動かないことはないんじゃないかと。

http://www.aitendo.com/product/7410
LCDキーパッドシールドに繋いで、電源入れたの
がこれ。PCに繋いでデバッグ中の様子。



ストロボ使って撮ると、こんな風に見づらいけど、
上1行の16文字分に
  00000F 0W(sin) R
  ^
こんな風に書いてある。カーソルは一番左に。

左から、周波数が00000Hz、波形0(sin波)で、
Rはリセットスイッチという意味。

「左右」キーでカーソルを動かして、各数値
(周波数部分、波形番号)か「R」の部分を選択、
「上下」で数値を上下、「R」のときに「セレクト」
を押すと、DDSファンクションジェネレータを
システムリセット。

何か変更が行われた場合に、周波数と波形の
制御信号を出力。(目下、シリアルモニタで動作
確認をした状態)

キー入力は、面倒なので、リピートが掛からない
処理方法。PCのキーボードみたいにリピート効くと
便利なんだけど。


上1行しか使っていないのは、以前作った
http://brown.ap.teacup.com/nekosan0/1733.html
http://brown.ap.teacup.com/nekosan0/1739.html
この2ch出力のDDSファンクションジェネレータを
動かすときに、残りのもう1行を使う予定だから。


なんにしても、DDSファンクションジェネレータと
実機を繋いで動かしてみるには、LCDシールドに
ピンヘッダをハンダづけする必要があるので、
またこんど。


コイツが動くようになったら、ウクレレ用の
クロマチックチューナと繋いでテストに使う
目論見なのだ。

あっちはあっちで、ちゃんと進めないとな。


それにしても、LCDとキーパッドが一つの
シールドに纏まってるだけで、なにかと
便利だな。



コメント ( 0 )
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする