Jump to content
ELFORUM - Forumul electronistilor

DDS


Rx-Tx
 Share

Recommended Posts

  • 7 months later...

Schema plus codul original le gaseti  aici 

http://ja2gqp.blogspot.ro/2014/02/arduino-ad9850-dds-vfo.html

http://i62.tinypic.com/2ii7jma.jpg

http://i59.tinypic.com/5cev4n.jpg

 

mai jos este codul modificat de mine pentru lcd 20x4 cu S-metru

 

------------------------------------------------------------------------------------
 
//    Copyright©2014.JA2GQP.All rights reserved.
//
//    
//      (Target frequency = IF frquency + frequency)
//                                                  2014/2/28
//                                                  JA2GQP
//--------------------------------------------------------------------
//  Function
//    1.Upper Heterodyne(Target Frequency = IF Frequency + Frequency)
//    2.RIT Operation(-50kHZ to 50kHZ)
//    3.STEP(100k,10k,1k,100,10)
//    4.Memory Operation is Push RIT
//      (Frequency and Step)
//    5.Protection Operation At The Time Of Transmission
//    6.Channel Memory.Main Channel(Ch0) + 3 Channel(Ch1,Ch2,Ch3)
//    7.Split Operation(7.00MHz to 7.20MHz Limited!)
//--------------------------------------------------------------------
//  Library
//
//////////////////////////////////////////////////////////////////////
 
#include <LiquidCrystal.h>
#include <rotary.h>
#include <EEPROM.h>
 
//----------  LCD Pin Assign  ------------------
 
LiquidCrystal lcd(13, 12, 11, 10, 9, 8);   // RS,R/W,DB4,DB5,DB6,DB7
 
//----------  Define Constant Value   ----------
                                           
const byte  ENC_A = 2;                     // Encorder A
const byte  ENC_B = 3;                     // Encoeder B
const byte  SW_STEP = 4;                   // STEP Sw
const byte  SW_RIT = 5;                    // RIT Sw
const byte  SW_SPLIT = 6;                  // SPLIT Sw
const byte  SW_TX = 7;                     // TX Sw
const byte  W_CLK = 14;                    // DIO14(A0)
const byte  FQ_UD = 15;                    // DIO15(A1)
const byte  DATA = 16;                     // DIO16(A2)
const byte  SW_CH1 = 17;                   // DIO17(A3)
const byte  SW_CH2 = 18;                   // DIO18(A4)
const byte  SW_CH3 = 19;                   // DIO18(A5)
 
const long  IF_FRQ = 9996500L;             // IF Frequency
const long  LW_FRQ = 1000000L;             // Lower Limit
const long  HI_FRQ = 30000000L;             // Upper Limit
const long  DEF_FRQ = 7130000L;            // Init Frequency
const long  DEF_STP = 1000L;               // Init STEP
const long  LW_RIT = -50000L;              // RIT Lower Limit
const long  HI_RIT = 50000L;               // RIT Upper Limit
const long  LW_VFO = IF_FRQ + LW_FRQ;      // Vfo Lower Limit
const long  HI_VFO = IF_FRQ + HI_FRQ;      // Vfo Upper Limit
const long  DEF_VFO = IF_FRQ + DEF_FRQ;    // Vfo Default Frequency
 
const unsigned long  DDS_CLK = 125000000L; // AD9850 Clock
const unsigned long  TWO_E32 = 4294967295L;// 2^32
const byte  DDS_CMD = B00000000;           // AD9850 Command
 
//----------  EEPROM Memory Address   ----------
 
const byte  Frq_Eep0 = 0x00;               // Frequency Ch0
const byte  Frq_Eep1 = 0x04;               //           Ch1                                            
const byte  Frq_Eep2 = 0x08;               //           Ch2
const byte  Frq_Eep3 = 0x0c;               //           Ch3
 
const byte  Stp_Eep0 = 0x10;               // STEP Ch0
const byte  Stp_Eep1 = 0x14;               //      Ch1                                            
const byte  Stp_Eep2 = 0x18;               //      Ch2
const byte  Stp_Eep3 = 0x1c;               //      Ch3
 
//----------  Encorder Pin Assign(INT)  --------
 
Rotary r = Rotary(ENC_A,ENC_B);            // 2 = ENC_A,3 = ENC_B
 
//----------  Memory Assign  -------------------
 
long Vfo_Dat = 0;                         // VFO Data
long Dds_Dat = 0;                         // DDS Data
long Rit_Dat = 0;                         // RIT Data
long Rit_Datb = 0;                        // RIT Data Old
long Enc_Stp = 0;                         // STEP
long Lng_Wk1 = 0;                         // Long Work1
long Lng_Wk2 = 0;                         // Long Work2
 
char *Lcd_Dat = "           ";            // Lcd Display Buffer
 
byte Byt_Chn = 0;                         // Channel SW
byte Byt_Chnb = 0;                        // Channel SW Old
byte Flg_Rit = 0;                         // RIT Flag
byte Flg_Ritb = 0;                        // RIT Flag Old
byte Flg_Tx = 0;                          // TX Flag
byte Flg_Spl = 0;                         // SPLIT Flag
 
 
/* Modify the pin number below to meet your board
 */
#define IN_LEFT    7  // analog input for left channel
/* Other minor configurable value
 */
#define T_REFRESH    100            // msec bar refresh rate
#define T_PEAKHOLD   3*T_REFRESH    // msec peak hold time before return
 
/* local variable
 */
byte  fill[6]={ 0x20,0x00,0x01,0x02,0x03,0xFF };      // character used to fill (0=empty  5=full)
byte  peak[7]={ 0x20,0x00,0x04,0x05,0x06,0x07,0x20 }; // character used to peak indicator
int   lmax[2];                                        // level max memory
int   dly[2];                                         // delay & speed for peak return
 
void  bar  ( int row,int lev )
{
  lcd.setCursor( 0,row );
  lcd.write( row ? 'R' : 'L' );
  for( int i=1 ; i<20 ; i++ )
  {
    int f=constrain( lev      -i*5,0,5 );
    int p=constrain( lmax[row]-i*5,0,6 );
    if( f )
      lcd.write( fill[ f ] );
    else
      lcd.write( peak[ p ] );
  }
  if( lev>lmax[row] )
  {
    lmax[row] = lev;
    dly[row]  = -(T_PEAKHOLD)/T_REFRESH;                // Starting delay value. Negative=peak don't move
  }
  else
  {
    if( dly[row]>0 )
      lmax[row] -= dly[row]; 
 
    if( lmax[row]<0 )
      lmax[row]=0;
    else
      dly[row]++;
  }
}
 
byte block[8][8]=
{
  { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 },  // define character for fill the bar
  { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 },
  { 0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C },
  { 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E },
 
  { 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 },  // define character for peak level
  { 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 },
  { 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02 },
  { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },
};
 
//----------  Initialization  Program  ---------------
 
void setup(){
   {
  lcd.begin( 20,4 );
  for( int i=0 ; i<8 ; i++ )
    lcd.createChar( i,block );
}
  pinMode(SW_STEP,INPUT_PULLUP);
  pinMode(SW_RIT,INPUT_PULLUP);
  pinMode(SW_SPLIT,INPUT_PULLUP);
  pinMode(SW_TX,INPUT_PULLUP);
  pinMode(SW_CH1,INPUT_PULLUP);
  pinMode(SW_CH2,INPUT_PULLUP);
  pinMode(SW_CH3,INPUT_PULLUP);
 
  lcd.begin(20, 4);                        // LCD 20*4
 
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();                                    // INT Enable
 
  pinMode(FQ_UD,OUTPUT);
  pinMode(W_CLK,OUTPUT);
  pinMode(DATA,OUTPUT);
 
  Flg_Tx = 0;
  Flg_Rit = 0;
  Flg_Spl = 0;
 
  lcd.clear();
  Fnc_Chsw();                                // Channel Sw Read
  Byt_Chnb = Byt_Chn;
  Fnc_Eep_Rd();                              // EEPROM Read
}
 
//----------  Main program  ---------------
 
void loop() {
       {
 
  int anL = map( sqrt( analogRead( IN_LEFT  )*20 ),0,128,0,80 );  // sqrt to have non linear scale (better was log)
 
  bar( 2,anL );
          // set the cursor to column 1, line 1
  lcd.setCursor(0, 4);
  delay(80);
  // Print a message to the LCD.
  lcd.print("S1_3_5_7_9_+10_+40db");
    }
  if(Flg_Tx == 0){                          // Tx off?
    if(digitalRead(SW_STEP) == LOW){        // STEP Sw On?
      Fnc_Stp();                            //     Yes,STEP proc.
    }
    if(digitalRead(SW_RIT) == LOW){         // RIT Sw On?
      Fnc_Rit();                            //     Yes,RIT proc.
    }
    if(digitalRead(SW_SPLIT) == LOW){       // SPLIT Sw On?
      Fnc_Spl();                            //     Yes,SPLIT proc.
    }
    Fnc_Chsw();                             // Channel Sw read
    if(Byt_Chnb != Byt_Chn){                // Channnel SW Chenge?
      if(Byt_Chnb == 0){                    // Channnel 0?  
        Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep0);     //   Yes,Vfo_Dat Save
        Fnc_Eep_Sav4(Enc_Stp,Stp_Eep0);     //       Enc_Step Save
        Flg_Ritb = Flg_Rit;
        Rit_Datb = Rit_Dat;
        Flg_Rit = 0;
        Flg_Spl = 0;
        Rit_Dat = 0;
      }
 
      if(Byt_Chnb != 0){                    // Other(Ch1-Ch3) Channnel?
        Flg_Rit = 0;
        Flg_Spl = 0;
        if((Byt_Chn == 0) && (Flg_Ritb == 1)){ 
          Flg_Rit = 1;
          Rit_Dat = Rit_Datb;
        }
      }
   
      Byt_Chnb = Byt_Chn;
      Fnc_Eep_Rd();
    }
  }
  if(digitalRead(SW_TX) == LOW){            // Tx On?
    Flg_Tx = 1;                             //    Yes,Flg_Tx Set
  }
  else{                                
    Flg_Tx = 0;                            //     No,Flg_Tx Reset            
  }
 
  if(Flg_Rit == 1){                        // RIT?
    Dds_Dat = Vfo_Dat + Rit_Dat;           //    Yes,Dds_Dat Set
  }
  else{
    Dds_Dat = Vfo_Dat;                     //    No,Dds_Dat Set
  }
 
  if(Flg_Tx == 1){                         // Tx?
    if(Flg_Spl == 1){                      // SPLIT?
      Dds_Dat = Vfo_Dat + Rit_Dat;         //    Yes,Dds_Dat Set
    }
      else{
        Dds_Dat = Vfo_Dat;                 //    No,Dds_Dat Set
      }
  }
  Fnc_Dds(Dds_Dat);                        // AD9850 DDS Out
  Fnc_Lcd();                               // LCD Display
  delay(100);
 
//----------  Encorder procedure(INT)  ---------------
 
ISR(PCINT2_vect) {
  unsigned char result = r.process();
 
  if(Flg_Tx == 0){
    if(result) {
      if(result == DIR_CW){
        Lng_Wk1 = Vfo_Dat + Enc_Stp;
        Lng_Wk2 = Rit_Dat + Enc_Stp;
      }
      else{
          Lng_Wk1 = Vfo_Dat - Enc_Stp;
          Lng_Wk2 = Rit_Dat - Enc_Stp;
      }  
      if((Flg_Rit == 1) || (Flg_Spl == 1)){
        Rit_Dat = Lng_Wk2;
      }
      else{
        Vfo_Dat = Lng_Wk1;
        Rit_Dat = 0;
      }
      Vfo_Dat = constrain(Vfo_Dat,LW_VFO,HI_VFO);
 
      if(Flg_Spl == 1){
        Rit_Dat = constrain(Rit_Dat,(LW_VFO - Vfo_Dat),(HI_VFO - Vfo_Dat));
      }
      else{
        Rit_Dat = constrain(Rit_Dat,LW_RIT,HI_RIT);
      }
    }
  }
}
 
//----------  Function DDS set  ---------------
 
void Fnc_Dds(double frquency){
  unsigned long wrk = frquency * TWO_E32 / DDS_CLK;
 
  digitalWrite(FQ_UD,LOW);
 
  shiftOut(DATA,W_CLK,LSBFIRST,wrk);
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 8));
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 16));
  shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 24));
  shiftOut(DATA,W_CLK,LSBFIRST,DDS_CMD);   // AD9850 command
 
  digitalWrite(FQ_UD,HIGH);
}
 
//----------  Function Encorder STEP  ---------
 
void Fnc_Stp(){
  if(Enc_Stp == 10){                      // Step = 10Hz ?
    Enc_Stp = 100000;                     //   Yes,100khz set
    }
    else{
      Enc_Stp = Enc_Stp / 10;             // Step down 1 digit
      }
//  delay(250);
  Fnc_Step_Disp();
//  Fnc_Lcd();
  while(digitalRead(SW_STEP) == LOW)
    ;
  delay(250);
}
 
//----------  Function STEP Display  ----------
 
void Fnc_Step_Disp(){
  lcd.setCursor(0,1);
  lcd.print("    ");                    // Clear step display
  lcd.setCursor(0,1);
  if(1 <= (Enc_Stp / 1000)){            // kiro?      
    lcd.print(Enc_Stp / 1000);          //   Yes,Convert kiro
    lcd.print("k");
    }
    else{
      lcd.print(Enc_Stp);
      }
}
 
//----------  Function String Dot Edit  --------
char *Fnc_Dot_Edit(char *str,long n){
  int  i = 0;                           // Write the number
  char *p = str;
  unsigned long  u = abs(n);
 
  do{
    *p++ = "0123456789"[u % 10];
    u = u / 10;
    i++;
    if((0 != u) && (0 == (i % 3)))
      *p++ = '.';
    }
  while( 0 != u );
 
  if ( n < 0 )
     *p++ = '-';
   *p = '0';
   Fnc_Revr( str );
   return str;
}
 
//----------  Function String Reverse  ---------
 
void Fnc_Revr(char *str){
  int i,n;
  char c;
 
  n=strlen(str);
  for(i = 0;i < n / 2;i++){
    c=str;
    str=str[n - i - 1];
    str[n - i - 1]=c;
  }
}
 
//----------  Function Save EEPROM 2byte  ---------
 
void Fnc_Eep_Sav2(unsigned int value,int address){
  address += 1;
  for(int i = 0;i < 2;i++){
    byte toSave = value & 0xFF;
    if(EEPROM.read(address) != toSave){
      EEPROM.write(address,toSave);
      }
    value = value >> 8;
    address--;
  }
}
 
//----------  Function Save EEPROM 4byte  ---------
 
void Fnc_Eep_Sav4(long value,int address){
  address += 3;
  for(int i = 0;i < 4;i++){
    byte toSave = value & 0xFF;
    if(EEPROM.read(address) != toSave){
      EEPROM.write(address,toSave);
      }
    value = value >> 8;
    address--;
  }
}
 
//----------  Function Load EEPROM 2byte  ---------
 
unsigned int  Fnc_Eep_Lod2(int address){
  unsigned int value = EEPROM.read(address);
  value = value << 8;
  return value | EEPROM.read(address + 1);
}
 
//----------  Function Load EEPROM 4byte  ---------
 
long Fnc_Eep_Lod4(int address){
  long value = 0;
  for(int i = 0;i < 4;i++){
    value = value | EEPROM.read(address);
    if( i < 3){
      value = value << 8;
      address++;
      }
  }
  return value;
}
 
//----------  Function LCD Display  ---------
 
void Fnc_Lcd(){
  if(Flg_Tx == 1){
    lcd.setCursor(0,0);
    lcd.print("TX");
  }
  else{
    lcd.setCursor(0,0);
    lcd.print(Byt_Chn);
  }
 
  Fnc_Step_Disp();
 
  if(Flg_Rit == 1){
    lcd.setCursor(5,1);
    lcd.print("R:          ");
    Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
    lcd.setCursor(7,1);
    lcd.print(Lcd_Dat);
    if((Rit_Dat >= 1000) || (Rit_Dat <= -1000)){
      lcd.print("k");
    }
  }
 
  if(Flg_Spl == 1){
    lcd.setCursor(5,1);
    lcd.print("S:          ");
    Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
    lcd.setCursor(7,1);
    lcd.print(Lcd_Dat);
    if((Rit_Dat >= 1000) || (Rit_Dat <= -1000)){
      lcd.print("k");
    } 
  }
 
  if((Flg_Rit == 0) && (Flg_Spl == 0)){
    Fnc_Dot_Edit(Lcd_Dat,Vfo_Dat - IF_FRQ);
    lcd.setCursor(1,0);
    lcd.print(":              ");
    lcd.setCursor(3,0);
    lcd.print(Lcd_Dat);
    lcd.print("MHz");
 
    lcd.setCursor(6,1);
    lcd.print("      VFO-A");
  }
}
 
 
//----------  Function Rit  ---------
 
void Fnc_Rit(){
  if(Flg_Rit == 0){
    Rit_Dat = 0;
    Flg_Rit = 1;
    Flg_Spl = 0;
    switch(Byt_Chn){
      case 1:
        Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep1);
        Fnc_Eep_Sav4(Enc_Stp,Stp_Eep1);
        break;
      case 2:
        Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep2);
        Fnc_Eep_Sav4(Enc_Stp,Stp_Eep2);
        break;
      case 3:
        Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep3);
        Fnc_Eep_Sav4(Enc_Stp,Stp_Eep3);
        break;
      default:
        Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep0);
        Fnc_Eep_Sav4(Enc_Stp,Stp_Eep0);
        break;
    }
  }
  else{
    Flg_Rit = 0;
  }
  while(digitalRead(SW_RIT) == LOW)
    ;
  delay(250);
 
//----------  Function Channel SW Check  ---------
 
void Fnc_Chsw(){
  if(digitalRead(SW_CH1) == LOW){
    Byt_Chn = 1;
  }
  else if(digitalRead(SW_CH2) == LOW){
    Byt_Chn = 2;
  }
  else if(digitalRead(SW_CH3) == LOW){
    Byt_Chn = 3;
  }
  else{
    Byt_Chn = 0;
  }
}
 
//----------  Function EEPROM Read  ---------
 
void Fnc_Eep_Rd(){
  if(Fnc_Eep_Lod4(Frq_Eep0) <= LW_VFO){
    Vfo_Dat = DEF_VFO;
    Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep0);
    Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep1);
    Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep2);
    Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep3);
  }
  else{
    switch(Byt_Chn){
      case 1:
        Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep1);
        break;
      case 2: 
        Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep2);
        break;
      case 3: 
        Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep3);
        break;
      default:
        Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep0);
        break;
    }
  }
  if(Vfo_Dat <= 0){
    Vfo_Dat = DEF_VFO;
  }
  if(Fnc_Eep_Lod4(Stp_Eep0) <= 0){
    Enc_Stp = DEF_STP;
    Fnc_Eep_Sav4(Enc_Stp,Stp_Eep0); 
    Fnc_Eep_Sav4(Enc_Stp,Stp_Eep1);
    Fnc_Eep_Sav4(Enc_Stp,Stp_Eep2);
    Fnc_Eep_Sav4(Enc_Stp,Stp_Eep3);
  }
  else{
    switch(Byt_Chn){
      case 1:
        Enc_Stp = Fnc_Eep_Lod4(Stp_Eep1);
        break;
      case 2: 
        Enc_Stp = Fnc_Eep_Lod4(Stp_Eep2);
        break;
      case 3: 
        Enc_Stp = Fnc_Eep_Lod4(Stp_Eep3);
        break;
      default:
        Enc_Stp = Fnc_Eep_Lod4(Stp_Eep0);
        break;
    }
  }
  if(Enc_Stp <= 0){
    Enc_Stp = DEF_STP;
  }
}
 
//----------  Function Split  ---------
 
void Fnc_Spl(){
  if(Flg_Spl == 0){
    Flg_Spl = 1;
    Flg_Rit = 0;
    Rit_Dat = 0;
  }
  else{
    Flg_Spl = 0;
  }
  while(digitalRead(SW_SPLIT) == LOW)
    ;
  delay(250);
}
Edited by MARLANU
Link to comment
Share on other sites

  • 1 month later...

Buna dimineata, 

 

Felicitari pentru device, arata foarte bine. As dori sa-mi construiesc si eu unul, dar n-am abordat niciodata Arduino.

V-as ramane indatorat pentru niste explicatii in plus, poate ar fi utile si altora:

 

- nu am experienta in programare, dar am vazut ca la inceputul codului sursa, scrie ca este limitat doar la banda de 7MHz; 

in pozele dvs. se vede o frecventa din 14MHz. Pana la urma, care este realitatea? Ati modificat sursele si acum poate functiona in oricare alta banda?

- daca da, exista posibilitatea de a genera semnale pentru comutarea filtrelor de banda si trece-jos? (eventual bufferate)

- ar fi extrem de utila modificarea softului astfel incat sa suporte introducerea unei frecvente de la o tastatura; e posibil?

- actuala versiune de soft, ofera posibilitatea generarii unor frecvente diferite in functie de modul de lucru ? (CW, USB, LSB si direct, fara shift)

- proiectul original, am vazut ca e dezvoltat pe Arduino Uno, dar in pozele postate de dvs. am vazut o placuta Arduino Nano. N-am idee cum se face trecerea de la unul la celalalt; pur si simplu, se poate scrie softul respectiv direct in Nano? E nevoie de un programator separat, sau se foloseste un soft specializat si conectare prin mufa microUSB ? (repet, n-am folosit niciodata Arduino si n-am nici un fel de experienta cu el, scuze daca intrebarea ar putea parea ridicola! ).

 

Cu multumiri,

Ancient

Edited by ancient
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines