Sari la conținut
ELFORUM - Forumul electronistilor

DDS


Rx-Tx

Postări Recomandate

  • Răspunsuri 13
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • MARLANU

    4

  • nico_2010

    3

  • yo5qax

    2

  • Rx-Tx

    1

Top autori în acest subiect

  • 7 luni mai târziu...

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);
}
Editat de MARLANU
Link spre comentariu
  • 1 lună mai târziu...

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

Editat de ancient
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări