AD9833 sinyal jeneratör entegresi yardım

Başlatan magnetron, 07 Mayıs 2021, 12:44:02

magnetron

merhaba forum

AD9833 sinyal jeneratörünü düzgün çalıştıramadım

https://github.com/Bardia-Afshar/AD9833-STM32

burdaki kütüphaneyi kullandım delayleri fazla fazla verdim

ama sadece sinüs dalga oluşturuyor ve de frekansı sweep yaptıramadım

ayrıca frekans da tam doğru çalışmıyor 20 KHz veriyorum 19830 Hz oluşuyor

acaba bu IC yi düzgün çalıştırabilen var mı ?

kodlarımı ekliyorum

teşekkür



uint8_t disptimer=0;

 while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
//showtime();
   HAL_Delay(100);
   HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
   disptimer++;
   frqfl=20000.5F+(float)(disptimer*5);phsfl=100.0F;
   AD9833_Init();
   //  AD9833_SetWaveData(/*frqfl,phsfl*/);
  }
  /* USER CODE END 3 */
}

/*
 * ad9833.c
 *
 */


#include "AD9833.h"
#include "main.h"
// ------------------- Variables ----------------
uint16_t FRQLW = 0;    // MSB of Frequency Tuning Word
uint16_t FRQHW = 0;    // LSB of Frequency Tuning Word
uint32_t  phaseVal=0;  // Phase Tuning Value
uint8_t WKNOWN=0;      // Flag Variable
extern float frqfl,phsfl;
// -------------------------------- Functions --------------------------------
void Delay(volatile uint32_t delay){
 while(delay--){};
}
// ------------------------------------------------ Software SPI Function
void writeSPI(uint16_t word) {
 for (uint8_t i = 0; i < 16 ; i++) {
          if(word & 0x8000) HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET);  //bit=1, Set High
 else HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_RESET);        //bit=0, Set Low
 Delay(5);
 HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_RESET);            //Data is valid on falling edge
 Delay(5);
 HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);
 word = word<<1; //Shift left by 1 bit
        }
 HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_RESET);                    //Idle low
 Delay(5);
}

// ------------------------------------------------ Sets Output Wave Type
void AD9833_SetWave(uint16_t Wave){
  switch(Wave){
  case 0:
  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2000); // Value for Sinusoidal Wave
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=0;
    break;
  case 1:
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2028); // Value for Square Wave
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=1;
    break;
  case 2:
        HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2002); // Value for Triangle Wave
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=2;
    break;
  default:
    break;
  }
}

// ------------------------------------------------ Sets Wave Frequency & Phase (In Degree) In PHASE0 & FREQ0 Registers
void AD9833_SetWaveData(void/*float Frequency,float Phase*/){
 float Frequency,Phase;
Delay(5);
 Frequency=frqfl;Phase=phsfl;
 // ---------- Tuning Word for Phase ( 0 - 360 Degree )
 if(Phase<0)Phase=0; // Changing Phase Value to Positive
 if(Phase>360)Phase=360; // Maximum value For Phase (In Degree)
 phaseVal  = ((int)(Phase*(4096/360)))|0XC000;  // 4096/360 = 11.37 change per Degree for Register And using 0xC000 which is Phase 0 Register Address

 // ---------- Tuning word for Frequency
long freq=0;
freq=(int)(((Frequency*pow(2,28))/FMCLK)+1); // Tuning Word
FRQHW=(int)((freq & 0xFFFC000) >> 14); // FREQ MSB
FRQLW=(int)(freq & 0x3FFF);  // FREQ LSB
FRQLW |= 0x4000;
FRQHW |= 0x4000;
 // ------------------------------------------------ Writing DATA
 HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET);
HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);
HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
 HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET); //low = selected
 Delay(5);
 writeSPI(0x2100); // enable 16bit words and set reset bit
 writeSPI(FRQLW);
 writeSPI(FRQHW);
    writeSPI(phaseVal);
 writeSPI(0x2000); // clear reset bit
 Delay(5);
 HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET); //high = deselected
//AD9833_SetWave(WKNOWN);
Delay(5);
return;
}

// ------------------------------------------------ Initializing AD9833
void AD9833_Init(/*uint16_t WaveType,float FRQ,float Phase*/void){
// float FRQ,Phase;
HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET); // Set All SPI pings to High
HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);  // Set All SPI pings to High
HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);  // Set All SPI pings to High
AD9833_SetWave(2);//WaveType);                              // Type Of Wave
//FRQ= frqfl;Phase=phsfl;
AD9833_SetWaveData();//FRQ,Phase);                        // Frequency & Phase Set
return;
}


yas

Alıntı yapılan: magnetron - 07 Mayıs 2021, 12:44:02ayrıca frekans da tam doğru çalışmıyor 20 KHz veriyorum 19830 Hz oluşuyor

Bu fark %1 in altında bir hataya tekabül ediyor. Muhtemelen 25MHz lik kristalin tam olarak 25.000.000 Hz olarak çalışmamasından kaynaklanıyordur. Kristalin uçlarında kullanılan kapasitelerden birini trimer kondansatörle değiştirip 25MHz akort edersen hata düzelecektir. Yada yazılımla ofset vererek kalibre etme yöntemini seçebilirsin. Diğer kısımlar için fikrim yok.

eeburakdemir

Merhaba,
Ben arduino da denemiştim. Bahsettiğiniz gibi ufak tefek frekans sapmaları oluyor. Bütün dalga formları düzgün bir şekilde çıkıyordu.
Asla pes etme...

magnetron

Alıntı yapılan: eeburakdemir - 07 Mayıs 2021, 21:51:58Merhaba,
Ben arduino da denemiştim. Bahsettiğiniz gibi ufak tefek frekans sapmaları oluyor. Bütün dalga formları düzgün bir şekilde çıkıyordu.

hocam yararlandığınız kütüphanenin internet linkini paylaşır mısınız

teşekkür

ferdem

Alıntı yapılan: yas - 07 Mayıs 2021, 14:20:31Bu fark %1 in altında bir hataya tekabül ediyor. Muhtemelen 25MHz lik kristalin tam olarak 25.000.000 Hz olarak çalışmamasından kaynaklanıyordur. Kristalin uçlarında kullanılan kapasitelerden birini trimer kondansatörle değiştirip 25MHz akort edersen hata düzelecektir. Yada yazılımla ofset vererek kalibre etme yöntemini seçebilirsin. Diğer kısımlar için fikrim yok.

Buradaki frekans hatası kristal kararlılığından çok fazla, hadi diyelim kristalimiz +-100ppm olsun, bu 1 MHz de 100 Hz demektir. 20 KHz de ise 2 Hz civarında olur. DDS in çıkışı master osilatörün 2^N de biri olacak, kontrolü böyle yapmak lazım. Örneğin master frekans 10.220 MHz ise çıkışta 5.110 MHz, 2.555 MHz gibi frekanslar kontrol edilerek DDS e doğru yazıldığı anlaşılabilir.

Bu modeli hiç kullanmadım ama bu kadar frekans sapması normal gelmedi. Başka bir hata olmalı, frekans formülü datasheet te var :
Output frequency= fMCLK/2^28 × FREQREG.

fMCLK DDS e verdiğimiz clock frekans, FREQREG de 28 bit bir register. Bu register a yazılan değerin doğru olduğuna emin olmak lazım, floating işlemlerde bir hata olmuş olabilir. Örneğin bu registere 2^27, 2^26, 2^25, 2^20 gibi basit değerler yazıp çıkış frekansının fMCLK frekansının yarısı, 1/4... olup olmadığını görmek lazım.

ipek

olmaz ama bir ihtimal ,program Clok şartını incelemek gerekebilir,zira bu çin modüllerin iki varyantı var 25 ve 27 MHz..

eeburakdemir

#7
@magnetron aşağıdaki linkdeki gibi bağlantı yapmıştim. Buradaki adımları dene birde. Ayrıca istenilen frekansın yüzde yüz bulunamaması bir tek sende olan bir durum değil. Bende kullanırken forumlardan okuduğum kadarıyla ve osiloskoptaki gödüğüm değerler , okadar kadı kızında da olur dercesineydi.

https://www.instructables.com/Signal-Generator-AD9833/
Asla pes etme...

berkay_91

çalışan arduino kodları

/*
AD9833 Pin      Arduino Pin     Description
CLK              SCK            SPI Clock pin
DAT              MOSI           SPI Master Out Slave In data pin
FNC              User defined   SPI transfer enable (active LOW)
VCC              5V             Recommend a 10 uF capacitor in parallel with a 0.1 uF capacitor
GND              GND         
*/

#include <AD9833.h>     

#define FNC_PIN 4       
AD9833 gen(FNC_PIN); 

//   Signal type - SINE_WAVE, TRIANGLE_WAVE, SQUARE_WAVE, and HALF_SQUARE_WAVE

void setup() {
    gen.Begin();              
    gen.ApplySignal(SINE_WAVE,REG0,100);
    gen.EnableOutput(true);   
}

void loop() {

}



yas

Alıntı yapılan: ferdem - 07 Mayıs 2021, 22:33:15Buradaki frekans hatası kristal kararlılığından çok fazla, hadi diyelim kristalimiz +-100ppm olsun, bu 1 MHz de 100 Hz demektir. 20 KHz de ise 2 Hz civarında olur. DDS in çıkışı master osilatörün 2^N de biri olacak, kontrolü böyle yapmak lazım. Örneğin master frekans 10.220 MHz ise çıkışta 5.110 MHz, 2.555 MHz gibi frekanslar kontrol edilerek DDS e doğru yazıldığı anlaşılabilir.

Alıntı YapVariation(HZ)=(f*ppm)/10^6

olarak hesaplanmalı bu durumda 100ppm de 25MHz için 2500Hz lik sapma olabilir. Kristallerde merkez frekans toleransı haricinde birde sıcaklığın büyük etken olduğu frekans stabilitesi var onu ve kristal uçlarındaki kapasitelerin etkisini hiç hesaba katmadım bile. Bu tarz çalışmalarda kalibrasyon çok önemli ise akort için mutlaka trimer olmalı diye düşünüyorum. Çünkü dds osc nin 25Mhz olduğunu varsayarak işlemleri gerçekleştiriyor osc değişirse (yani referans değişirse) sonucun hesaplanandan farklı çıkması normal. Bunlara + ilave olarak referans alınarak mukayese yapılan ölçüm aletinin de doğruluğu ayrı bir konu. Gerçeğe göre -50 Hz bizde hata olsa, +80 Hz referans alınan cihazda hata olsa hata 130Hz sapma ölçeriz. Ölçümün referansa göre hatasız olması için sapmamızın referans alınan ölçüm aletindeki ile aynı olması gerekli.

berkay_91

Alıntı yapılan: magnetron - 08 Mayıs 2021, 11:13:04hocam kodlar eksik olabilir mi

kodlar eksik olamaz hocam, uygun kütüphaneyi eklememiş olabilirsiniz kütüphane linki
https://dosya.co/vsz5844i4j4x/AD9833-Library-Arduino-master.rar.html

bu kodları kullanarak aşağıdaki projeyi yaptım