2018年5月7日月曜日

ADF4351 PLL Local oscillator

35MHz-4400MHzまで出力できるADF4351エバボードが、Aliexpressで約$21で購入できる。購入した時より安価になった。VCOチューニングpinが出ているので、FM変調が出来るのでは? と期待しているが、取敢えずローカル発振器として纏めた。受信機で確認した限りでは、分解能10kHZであればC/N低下が認められなかった。50MHzから4480MHz(5.6GHzLO)使えるであろう。



回路図である。レベルコンバータ無しとしたので、Arduino pro mini(mega168 8MHz)を使った。周波数はBCD SWで行う様にした為、10chである。また、今後の事を考慮したI/O割付にした。










ADF4351PLLのレジスタチェックToolである。プログラムは、ADF435x software である。レジスタR5からR0まで、順次書き込めば、ADF4351が動作する。このプログラムでチェックした値を初期値としてスケッチに書いている。 









スケッチ

ダウンロードサイトのADF4351フォルダに保管ある。

//////////////////////////////////////////////////////////////////////////////
//       Copyright©2018.JA2GQP.All rights reserved.
//            ADF4351 Pll Local oscillator         
//                                                    2018/5/5
//                                                    JA2GQP     
//
//----------------------------------------------------------------------------     
//  The original is here. 
//      https://github.com/Giorgiofox/ADF4351-Arduino-LCDSHIELD
//
//////////////////////////////////////////////////////////////////////////////

#include <SPI.h>

//------------------------ Define value --------------------------------------- 

#define LOCK          4                       // pin4
#define LE             5                       //    5
#define Xtal_Freq     12.8                  // 12.8MHz(default 25(25MHz))
#define Scal_10kHz    0.01                // Scaling 10kHz

//------------------------ Register definition -------------------------------- 

/////////////////////////////////////////
// Frequency is 35.00MHz to 4400.00MHz
//     (set data is 3500 to 440000)
/////////////////////////////////////////

const long int FREQ[10] = {
        43000,                                // switch 0 430.00MHz
        43100,                                //            1 431.00MHz
        43200,                                //            2 432.00MHz
        43300,                                //            3 433.00MHz
        43400,                                //            4 434.00MHz
        43500,                                //            5 435.00MHz
        43600,                                //            6 436.00MHz
        43700,                                //            7 437.00MHz
        43800,                                //            8 438.00MHz
        43900};                               //            9 439.00MHz

/////////////////////////////////////////
// ADF4351 Register initialize value
/////////////////////////////////////////

uint32_t registers[6] = {               // 437.00MHz @12.8MHz
        0x888008,                          // Register 0( 0x4580A8   @25MHz)
        0x8008041,                         //               1(0x80080C9               )
        0x4E42,                              //               2(   0x4E42                  )           
        0x4B3,                                //               3(    0x4B3                  )
        0xB6703C,                          //               4( 0xBC803C                )
        0x580005} ;                        //              5( 0x580005                 )    

/////////////////////////////////////////
// Register declaration
/////////////////////////////////////////

double  RFout,
        REFin,
        PFDRFout = Xtal_Freq,                 // X'tal frequency set
        OutputChannelSpacing = Scal_10kHz,    // Scaling(10kHz)
        FRACF;
unsigned long int RFint,
        RFintold = 0,
        INTA,
        MOD,
        FRAC;
byte OutputDivider;

//------------------------ Setup ----------------------------------------------

void setup(){
  pinMode(LOCK, INPUT_PULLUP);               // PIN 2 en entree pour lock
  pinMode(14, INPUT_PULLUP);                  // PIN A0(Digital 14)
  pinMode(15, INPUT_PULLUP);                  //     A1(        15)
  pinMode(16, INPUT_PULLUP);                  //     A2(        16)
  pinMode(17, INPUT_PULLUP);                  //     A3(        17)
  pinMode(LE, OUTPUT);                            // Setup pins

  digitalWrite(LE, HIGH);
  SPI.begin();                                             // Init SPI bus
  SPI.setDataMode(SPI_MODE0);                 // CPHA = 0 et Clock positive
  SPI.setBitOrder(MSBFIRST);                      // highs in the lead
}

//------------------------ Main -----------------------------------------------

void loop(){
  RFint = FREQ[Bcd_switch()];
  Pll_ADF4351();  
}

//------------------------ SPI 32BIT Register Write proc. --------------------- 

void WriteRegister32(const uint32_t value){
  digitalWrite(LE, LOW);
  for (int i = 3; i >= 0; i-- )               
    SPI.transfer((value >> 8 * i) & 0xFF);
  digitalWrite(LE, HIGH);
  digitalWrite(LE, LOW);
}

//------------------------ ADF4351 Register set -------------------------------

void Set_Reg()                                
  for (int i = 5; i >= 0; i-- )               // Reg5 --> Reg0 Write
  WriteRegister32(registers[i]);
}

//------------------------ BCD switch read ------------------------------------

int Bcd_switch(){
  unsigned int sw = 0;

  if(digitalRead(14) == LOW)                  // Bit0 code set
    sw |= B00000001;
    else
      sw &= B11111110;
  if(digitalRead(15) == LOW)                  // Bit1 code set
    sw |= B00000010;
    else
      sw &= B11111101;
  if(digitalRead(16) == LOW)                  // Bit2 code set
    sw |= B00000100;
    else
      sw &= B11111011;
  if(digitalRead(17) == LOW)                  // Bit3 code set
    sw |= B00001000;
    else
      sw &= B11110111;

  return sw;                                  // return(Binary switch data)  
}

//------------------------ Pll ADF4351 proc. ----------------------------------

void Pll_ADF4351(){
  RFout=RFint;
  RFout=RFout/100;

  if (RFint != RFintold){
    if (RFout >= 2200){
      OutputDivider = 1;
      bitWrite (registers[4], 22, 0);
      bitWrite (registers[4], 21, 0);
      bitWrite (registers[4], 20, 0);
    }
    if (RFout < 2200){
      OutputDivider = 2;
      bitWrite (registers[4], 22, 0);
      bitWrite (registers[4], 21, 0);
      bitWrite (registers[4], 20, 1);
    }
    if (RFout < 1100){
      OutputDivider = 4;
      bitWrite (registers[4], 22, 0);
      bitWrite (registers[4], 21, 1);
      bitWrite (registers[4], 20, 0);
    }
    if (RFout < 550){
      OutputDivider = 8;
      bitWrite (registers[4], 22, 0);
      bitWrite (registers[4], 21, 1);
      bitWrite (registers[4], 20, 1);
    }
    if (RFout < 275){
      OutputDivider = 16;
      bitWrite (registers[4], 22, 1);
      bitWrite (registers[4], 21, 0);
      bitWrite (registers[4], 20, 0);
    }
    if (RFout < 137.5){
      OutputDivider = 32;
      bitWrite (registers[4], 22, 1);
      bitWrite (registers[4], 21, 0);
      bitWrite (registers[4], 20, 1);
    }
    if (RFout < 68.75){
      OutputDivider = 64;
      bitWrite (registers[4], 22, 1);
      bitWrite (registers[4], 21, 1);
      bitWrite (registers[4], 20, 0);
    }

    INTA = (RFout * OutputDivider) / PFDRFout;
    MOD = (PFDRFout / OutputChannelSpacing);
    FRACF = (((RFout * OutputDivider) / PFDRFout) - INTA) * MOD;
    FRAC =round(FRACF); // On arrondit le résultat

    registers[0] = 0;                         // Register 0
    registers[0] = INTA << 15;// OK
    FRAC = FRAC << 3;
    registers[0] = registers[0] + FRAC;

    registers[1] = 0;                         // Register 1
    registers[1] = MOD << 3;
    registers[1] = registers[1] + 1 ;   // adding the address "001"
    bitSet (registers[1], 27);              // Prescaler on 8/9

    bitSet (registers[2], 28);              // Register 2(Pll lock setup)
    bitSet (registers[2], 27);
    bitClear (registers[2], 26);

    Set_Reg();                                 // ADF4351 Register write
    RFintold = RFint;
  }
}

結果

ADF4351エバボード上の25MHzオシレータは個体差によるが、精度が悪く、12.8MHz TCXO(秋月電子)に交換した。スケッチでは、ADF435x softwareで求めた437.00MHzのデータを初期値にしているが、50MHzから1.2GHz帯までは動作確認した。