迷走の果て・Tiny Objects

迷走する日々の覚え書きです。自分で分かってることは省略してますので、念のため。

AD9833 DDSモジュールを試す(1)

アマゾンでAD9833DDSモジュールを買ってしまいました。
10月14日に発送通知があり、26日に到着しました。

商品の説明には
「オンボードの高速は300Mアンプと、低域通過フィルタリングされています。 」
とありますが、そんな部品は見当たりません。
ちゃんとしたした説明をつけてほしいものですが、これがチャイナクオリティでしょうか。
AD9833module表

先のAD9850DDSモジュールを使った記事で参考にしたサイトを書いた人が、AD9833 Waveform Generatorという記事を書かれていたので、これまた参考にしました。

回路図です、先のAD9850 Sinewave Generatorと同じく、表示にはI2C接続LCDを使いました。
AD9833DDS_ schematic

1MHz正弦波出力です。DDSモジュールのクロックである25MHzがのっかってます。LPFをつけるつもりです。
AD9833DDS1MHz.jpg
スケッチです、ちょっと問題があります。動作を優先させたためです。
次の休みにゆっくり見直します。


//AD9833 Signal  generator
// edy
//2016/10/25 First version(ver 0.1)
//
//参考にしたweb page
//AD9833 Waveform Generator
//http://www.vwlowen.co.uk/arduino/AD9833-waveform-generator/AD9833-waveform-generator.htm


// PCF8574を使ったI2C接続モジュールを使う
// https://www.amazon.co.jp/dp/B010Q000V2/
// arduino用ライブラリ
// https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
//

#include <Rotary.h>            //  Rotary encoder: https://github.com/brianlow/Rotary
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

const int SINE = 0x2000;                    // Define AD9833's waveform register value.
const int SQUARE = 0x2020;                  // When we update the frequency, we need to
const int TRIANGLE = 0x2002;                // define the waveform when we end writing.

int wave = 0;
int waveType = SINE;
int wavePin = 7;
int freqUpPin = 2;                          // Define rotary encoder pins.
int freqDownPin = 3;
int stepUpPin = 5;
int stepDownPin = 6;

const float refFreq = 25000000.0;           // On-board crystal reference frequency

const int FSYNC = 10;                       // Standard SPI pins for the AD9833 waveform generator.
const int CLK = 13;                         // CLK and DATA pins are shared with the TFT display.
const int DATA = 11;

Rotary r = Rotary(freqUpPin, freqDownPin);    // Rotary encoder for frequency connects to interrupt pins
Rotary i = Rotary(stepUpPin, stepDownPin);    // Rotart encoder for setting increment.

long freq = 10000;               // Set initial frequency.
long freqOld = freq;

long incr = 1000;
long oldIncr = 1000;
char disp_buf[16];

char* stepText[18] = {
 "       1Hz",
 "       2Hz",
 "       5Hz",
 "      10Hz",
 "      20Hz",
 "      50Hz",
 "     100Hz",
 "     200Hz",
 "     500Hz",
 "   1,000Hz",
 "   2,000Hz",
 "   5,000Hz",
 "  10,000Hz",
 "  20,000Hz",
 "  50,000Hz",
 " 100,000Hz",
 " 200,000Hz",
 " 500,000Hz"
};

int stepPointer = 5;
//long  incr = 0;
String units = stepText[stepPointer];

void setup() {

 pinMode(freqUpPin, INPUT_PULLUP);      // Set pins for rotary encoders as INPUTS and enable
 pinMode(freqDownPin, INPUT_PULLUP);    // internal pullup resistors.
 pinMode(stepUpPin, INPUT_PULLUP);
 pinMode(stepDownPin, INPUT_PULLUP);
 pinMode(wavePin, INPUT_PULLUP);

 // Configure interrupt and enable for rotary encoder.
 PCICR |= (1 << PCIE2);
 PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
 sei();
 SPI.begin();
 delay(50);

 lcd.begin();
 lcd.clear();  // LCD画面消去
 lcd.setCursor( 0, 0 );
 lcd.print( "AD9833" );
 lcd.setCursor( 0, 1 );
 lcd.print( "Signal Generator" );
 delay(1000);
 lcd.clear();

 AD9833reset();                                   // Reset AD9833 module after power-up.
 delay(50);
 AD9833setFrequency(freq, SINE);                  // Set the frequency and Sine Wave output
 updateDisplay();
}

void getStep() {
 switch (stepPointer) {
   case 0:  incr = 1; break;
   case 1:  incr = 2; break;
   case 2:  incr = 5; break;
   case 3:  incr = 10; break;
   case 4:  incr = 20; break;
   case 5:  incr = 50; break;
   case 6:  incr = 100; break;
   case 7:  incr = 200; break;
   case 8:  incr = 500; break;
   case 9:  incr = 1000; break;
   case 10: incr = 2000; break;
   case 11: incr = 5000; break;
   case 12: incr = 10000; break;
   case 13: incr = 20000; break;
   case 14: incr = 50000; break;
   case 15: incr = 100000; break;
   case 16: incr = 200000; break;
   case 17: incr = 500000; break;
 }
}

void updateDisplay() {
 getStep();
 units = stepText[stepPointer];
 //lcd.clear();
 lcd.setCursor( 0, 0 );
 lcd.print( "STEP: " );
 lcd.print(units );

 lcd.setCursor( 0, 1 );
 lcd.print("FRQ:");
 if (freq < 1000) {
   sprintf(disp_buf, "%10ld", freq);
 }
 else if (freq < 1000000) {
   int freqL = freq % 1000;
   int freqM = freq / 1000;
   sprintf(disp_buf, "%6d,%03d", freqM, freqL);
 }
 else {
   int freqL = freq  % 1000;
   int freqM = (freq / 1000) % 1000;
   int freqH = freq / 1000000;
   sprintf(disp_buf, "%2d,%03d,%03d", freqH, freqM, freqL);
 }
 lcd.print(disp_buf);
 lcd.print("Hz");
}

void loop() {

 if (oldIncr != incr) {
   updateDisplay();
   oldIncr = incr;
 }

 // Check 'increment' rotary encoder. Increase or decrease 'increment' by a factor of x10
 // if encoder has been turned.
 unsigned char result = i.process();
 if (result) {
   if (result == DIR_CW)  {
     stepPointer++;
     if (stepPointer > 17) stepPointer = 0;
   }
   if (result == DIR_CCW) {
     stepPointer--;
     if (stepPointer < 0) stepPointer = 17;
   }
   updateDisplay();
 }

 // Check if push button on 'increment' rotary encoder is pushed and set Wave Type accordingly.
 if (digitalRead(wavePin) == LOW) {
   wave += 1;
   if (wave > 2) wave = 0;
   switch (wave) {
     case 0: waveType = SINE; break;
     case 1: waveType = SQUARE; break;
     case 2: waveType = TRIANGLE; break;
   }
   AD9833setFrequency(freq, waveType);     // Set AD9833 to frequency and selected wave type.
   updateDisplay();
   delay(200);
 }

 if (freq != freqOld) {                    // If frequency has changed, interrupt rotary encoder
   AD9833setFrequency(freq, waveType);     // must have been turned so update AD9833 and display.
   updateDisplay();
   freqOld = freq;                         // Remember new frequency to avoid unwanted display
 }                                         // and AD9833 updates.
}

// AD9833 documentation advises a 'Reset' on first applying power.
void AD9833reset() {
 WriteRegister(0x100);   // Write '1' to AD9833 Control register bit D8.
 delay(10);
}

// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(long frequency, int Waveform) {

 long FreqWord = (frequency * pow(2, 28)) / refFreq;

 int MSB = (int)((FreqWord & 0xFFFC000) >> 14);    //Only lower 14 bits are used for data
 int LSB = (int)(FreqWord & 0x3FFF);

 //Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0
 LSB |= 0x4000;
 MSB |= 0x4000;

 WriteRegister(0x2100);
 WriteRegister(LSB);                  // Write lower 16 bits to AD9833 registers
 WriteRegister(MSB);                  // Write upper 16 bits to AD9833 registers.
 WriteRegister(0xC000);               // Phase register
 WriteRegister(Waveform);             // Exit & Reset to SINE, SQUARE or TRIANGLE

}
void WriteRegister(int dat) {

 // Display and AD9833 use different SPI MODES so it has to be set for the AD9833 here.
 SPI.setDataMode(SPI_MODE2);

 digitalWrite(FSYNC, LOW);           // Set FSYNC low before writing to AD9833 registers
 delayMicroseconds(10);              // Give AD9833 time to get ready to receive data.

 SPI.transfer(highByte(dat));        // Each AD9833 register is 32 bits wide and each 16
 SPI.transfer(lowByte(dat));         // bits has to be transferred as 2 x 8-bit bytes.

 digitalWrite(FSYNC, HIGH);          //Write done. Set FSYNC high
}

// Interrupt service routine for the 'frequency' rotary encoder.

ISR(PCINT2_vect) {
 unsigned char result = r.process();
 if (result) {
   if (result == DIR_CW) {
     if ((freq + incr) <= 10000000) freq += incr;
   } else {
     if ((freq - incr) >= 1) freq -= incr;
   }
   if (freq <= 1)  freq = 1;
   if (freq >= 10000000) freq = 10000000;
 }
}

関連記事
スポンサーサイト

コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

この記事へのトラックバックURL
http://edycube.blog2.fc2.com/tb.php/933-3fe79703

 | HOME | 

文字サイズの変更

プロフィール

edy

最新記事一覧(サムネイル画像付き)

脈拍センサーMAX30100を試す(5) May 20, 2017
MT3608モジュールを使ったDSO Shell用電源 May 16, 2017
脈拍センサー MAX30100を試す(4)MAX30100_Registers.h を調べる。 May 13, 2017
脈拍センサー MAX30100を試す(3)正常動作?? May 12, 2017
脈拍センサー MAX30100を試す(2)スケッチとライブラリー May 10, 2017
脈拍センサー MAX30100を試す(1) May 08, 2017
Studuino用電池ボックスを作る(2) May 06, 2017
Studuino用電池ボックスを作る May 05, 2017
MT3608モジュールのテスト Apr 30, 2017
BME280モジュールを使った温度・湿度・気圧計(2)DSO Shellを使って動作電流を測る Apr 23, 2017

全記事表示リンク

全ての記事を表示する

ブログリンク

リンク

このブログをリンクに追加する

月別アーカイブ

05  04  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  05  04  03  02  12  11  10  09  07  05  04  03  04  03  01  12  11  10  08  07  06  05  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  05  04  02  01  12  10  09  08  07  06  05  04  03  02  01  12  11  10  09  08  07  06  05  03  02  01  12  11  10  09  08  07  06  05  04  03  02  01  12  10  09  08  07  06  05  04  03  02  01 

カテゴリ

プログラミング (0)
freescale (1)
AVR (3)
テルミン (16)
緊急警報放送 (3)
78K (1)
PSoC (295)
地上デジタル放送 (2)
電子工作 (399)
HX711 (2)
ACS712 (6)
数学 (6)
パソコン (12)
PLC (14)
未分類 (39)
ブログ関係 (20)
スカイプ (37)
ロボット (1)
LTSpice (8)
OCXO (0)
arduino (28)
maxima (1)
フランクリン発振回路 (3)
GPS (3)
DTMF (1)
Linux (1)
KOMAINO (7)

タグリスト

最近のコメント

最近のトラックバック

メールフォーム

名前:
メール:
件名:
本文:

検索フォーム

アクセス

RSSリンクの表示

フリーエリア

FC2Ad

まとめ

Template by たけやん