2026年8月1日土曜日

Arduino Nano - DDS AD9850 VFO

dsPIC33FJ64GP802 - PSN SSB ジェネレータ に使用する目的でDDS AD9850 VFOを自作50MHz SSB CWトランシーバー以外にも使用できるように改造しましたが使えませんでしたVFO出力コネクタをSMAコネクタに変更しAD9850出力をBPFフイルタを通さずSMAコネクタに直接接続できるようにしました(ケーブルとBPF基板の差替えで目的のBPFフイルタを入れることができる)プログラムを変更することにより50MHz (規格40MHz)まで周波数設定変更ができます。    




回路図

























50MHz SSB CW トランシーバー 










50MHz SSB CW トランシーバー(ミズホ通信 SG-9 :  9MHz SSBジェネレータを使用)
に2代目 DDS AD9850  VFO (2021.3製作)接続。

初代 DDS VFO
シャーシは2代目にも流用
秋月電子
・SUPER AKI-80  
・AE-DDS






オシロスコープ VFO 14MHz 出力波形














プログラム  Arduino Nano VFO出力 14MHz
#include <Rotary.h>            //  Rotary encoder: https://github.com/brianlow/Rotary
#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <EF_AD9850.h>
// EF_AD9850(CLK,FQ_UP,RESET,DATA)
EF_AD9850 AD9850(9, 10, 11, 8);
//アドレス0x27 16文字2行の液晶
LiquidCrystal_I2C lcd(0x27, 16, 2);
Rotary r = Rotary(2, 3);              // Rotary encoder for frequency connects to interrupt pins

//#define  A0
//#define  A1
//#define  A2  
#define HoldSW A3
#define StepSW 4
#define RitSW  5
#define OFF 0
#define ON  1

long push = 0;
int Rit = OFF;
int Step = OFF;
int Hold = OFF;
//long unsigned int freq = 1000;         // Set initial frequency.
long start_freq = 14000000; //VFO
long end_freq =   14040000;
long freq = 14000000;  
long disp_offset = 0;
int  offset = 0 ;   //dds_frequency offset
//long unsigned int freqOld = freq;
long freqOld = freq;
char disp_buf[16];
char disp_buf2[16];
long stepf = 100;   //1Hz 10Hz 100Hz
long  ritf = 0;
long  ritfOld = 0;
int  wr = 0 ;       //ad9850 write
void updateDisplay() {      
  if (freq+disp_offset < 1000) {
    sprintf(disp_buf, "%10ld", freq+disp_offset);
  }
  else if (freq+disp_offset < 1000000) {
    int freqL = (freq+disp_offset) % 1000;
    int freqM = (freq+disp_offset) / 1000;
    sprintf(disp_buf, "%6d,%03d", freqM, freqL);
  }
  else {
    int freqL = (freq+disp_offset)  % 1000;
    int freqM = ((freq+disp_offset) / 1000) % 1000;
    int freqH = (freq+disp_offset) / 1000000;
    sprintf(disp_buf, "%2d,%03d,%03d", freqH, freqM, freqL);
  }  
  lcd.setCursor(3, 1);
  lcd.print(disp_buf);
  lcd.print("Hz");  
}
                                       
ISR(PCINT2_vect) {                      //encoder interrupt  
  if (Rit == OFF && Hold == OFF ){      //rit off ,rx holdsw_off
  unsigned char result = r.process();
  if (result) {
    if (result == DIR_CW) {
      if ((freq + stepf) <= end_freq) freq += stepf;
    } else {
      if ((freq - stepf) >= start_freq) freq -= stepf;
    }
    if (freq <= 1)  freq = 1;
    if (freq >= end_freq) freq = end_freq;  
 }
 }
  if (digitalRead(RitSW) == HIGH && Rit == ON ){        //rit on
   unsigned char result = r.process();
  if (result) {
    if (result == DIR_CW) {
      if ((ritf + stepf) <= 1000) ritf += stepf;
    } else {
      if ((ritf - stepf) >= -1000) ritf -= stepf;
    }    
    if (ritf >= 10000) ritf = 10000;
    if (ritf <= -10000) ritf = -10000;
  }
  }
}


void setup() {
  pinMode(2, INPUT);     // Pins for interrupt-driven rotary encoder and push buttons
  pinMode(3, INPUT);    
  pinMode(RitSW, INPUT);
  pinMode(StepSW, INPUT);
  pinMode(HoldSW, INPUT);
 
  // Configure interrupt and enable for rotary encoder.
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();  
  lcd.init();
  lcd.backlight();
  lcd.clear();  
  lcd.setCursor(0, 0);
  lcd.print("AD9850");  
  lcd.setCursor(0, 1);  
  lcd.print("DDS VFO");  
  delay(2000);
  lcd.clear();  
  // Initialise the AD9850 module.
  AD9850.init();
  AD9850.reset();
  AD9850.wr_serial(0x00, freq+offset);
  updateDisplay();
  lcd.setCursor (10, 0);
  lcd.print(" _"); //10hz
}
void loop() {  
   if (digitalRead(StepSW) == LOW ) {    
      push++;
   if (push > 50 ){
      Step = !Step;
      push = 0;                
  }  
   if (Step == ON ){
      stepf = 100;
      lcd.setCursor (10, 0);
      lcd.print("_ ");  
   }
   else{
      stepf = 10;
      lcd.setCursor (10, 0);
      lcd.print(" _");
   }
 }          
   if (digitalRead(HoldSW) == LOW ) {        
      push++;
   if (push > 400 ){
      Hold = !Hold;
      push = 0;  
    if (Hold == ON ){
    lcd.setCursor (15, 1);
    lcd.print("H");          
    }
    else{
    lcd.setCursor (15, 1);
    lcd.print(" ");  
    }
  }
  }      
   if (digitalRead(RitSW) == LOW ) {    
      push++;
   if (push > 500 ){
      Rit = !Rit;
      push = 0;
    if (Rit == ON ){
    lcd.setCursor (13, 0);
    lcd.print("RIT");              
    }
    else{
    lcd.setCursor (13, 0);
    lcd.print("   ");      
    }
  }          
  }      
  if (digitalRead(RitSW) == HIGH && Rit == ON  ){ //rx rit_on        
      stepf = 1;       //1HZ
      while(digitalRead(RitSW) == HIGH ){      
      if (ritfOld != ritf) {
      AD9850.wr_serial(0x00, freq+offset+ritf);    
      ritfOld=ritf;    
      lcd.setCursor (3, 0);
      sprintf(disp_buf2, "%10ld", ritf);
      lcd.print(disp_buf2);
      lcd.print("RIT");  
    }
      if(wr=10000) {                              //ad9850 write  1/10000
      AD9850.wr_serial(0x00, freq+offset+ritf);  
      wr=0;
      }
      wr=wr+1;
      lcd.setCursor (3, 0);
      sprintf(disp_buf2, "%10ld", ritf);
      lcd.print(disp_buf2);
      lcd.print("RIT");    
   }  
      ritf = ritfOld;
      ritfOld = ritfOld;
      freq = freqOld;
      freqOld = freqOld;
      lcd.setCursor (9, 0);
      lcd.print("  _     "); //step
      stepf = 10;    
      Rit = OFF;        
  }
 
     
  if (freqOld != freq) {
      AD9850.wr_serial(0x00, freq+offset);
      updateDisplay();
      freqOld = freq;
     
    }
    if(wr=10000) {                              //ad9850 write  1/10000
      AD9850.wr_serial(0x00, freq+offset);      
      wr=0;
      }
      wr=wr+1;  
  }



0 件のコメント:

コメントを投稿

dsPIC33 - PSN SSB ジェネレータ テスト

PSN SSB ジェネレータをブレッドボードに製作しました。WaveGene信号発生器と搬送波Si5351A(2倍:14MHz)→PSN SSB ジェネレータ(7MHz) →SDRSharpSSB受信。LSB・USBの 周波数特性 確認が出来ました。 ●同ブログ【 dsPIC33...