Monday, January 26, 2015

Installing Libraries and running code for Si5351 Arduino VFO

**as of 4/11/15 Jason's library has changed and this program will not work if you just downloaded the library. Use the new library and sketch from this posting. With newer versions of the Arduino IDE, downloading and installing libraries is a little easier - see this posting. The main thing is, remove the old library before installing a new one. 
***Also, it is much easier now to add a new library. See this page.

We are going to use the NT7S Si5351 library from Github along with a sketch from SQ9NJE.

To quote the Adafruit Arduino Libraries tutorial, "User installed libraries should be installed in your sketchbook libraries folder so they can be used with all versions of the IDE. This way, if a new version of the IDE is released, you don't have to re-install all your favorite libraries! It would be a good idea to go through the tutorial if you are confused on this point.

Download and install the NT7S Si5351 library by clicking "Download Zip" on the right side of the page.
You will get a file called "Si5351Arduino-master.zip" Click on the file name and from the menu above and click on extract. Now you will have a file folder called "Si5351Arduino-master". This is not an acceptable file name as far as the Arduino IDE is concerned. Arduino doesn't like hypens. So right click on the folder name and change it to "Si5351".
Where you put this library folder is very important. Open the Arduino program and under "File" on the top left menu, click on "Preferences". This will show you where the IDE expects to see user sketches and user libraries ( Sketchbook location: ). The folder "Arduino" will list all your sketches and contains another folder called "libraries" This is where you will put the folder called Si5351 and Rotary.


The Si5351 folder contains two files which are most important, the one ending in ".cpp" and the one ending in ".h". The .h or header file describes the functions and variables for the cpp file that does all the work. If you are using another board like the one from Hans Summers  QRP Labs, it uses a crystal of 27MHz instead of the 25Mhz crystal used in the Adafruit or NT7S board. In which case you will need to edit the line in the si5351.h file that says:

#define SI5351_XTAL_FREQ        25000000
to
#define SI5351_XTAL_FREQ        27000000

*In the new version of Jason's library, it is no longer necessary to do this. You can put the crystal frequency in as the second initialization parameter i.e.
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27000000);

You could edit this with Notepad but it might be difficult. A much easier approach for editing files that contain code is to use a program called Notepad++. It's free and very easy to use. In our case just go to the Si5351 folder, open it and right click on si5351.h and click "edit with Notepad++", make the change as above and click on File, Save. 

**DO NOT edit with a word processor program like Word.

Download the *Rotary library from SQ9NJE's website by clicking on "Rotary Libraryor  "Biblioteka Rotary(if you haven't right clicked on the page and clicked "Translate to English").
Follow the instructions as above.

Download sketch from   LCD_VFO_Si5351.ino
(if you're using the latest NT7S library, use the sketch mentioned at the top of the post)

  /*
  This entire program is taken from Jason Mildrum, NT7S and Przemek Sadowski, SQ9NJE and Ben Buxton.
  There is not enough original code written by me to make it worth mentioning.
  http://nt7s.com/
  http://sq9nje.pl/
  Rotary library by Ben Buxton
   */

  #include <Rotary.h>
  #include <si5351.h>
  #include <Wire.h>
  #include <LiquidCrystal.h>


  #define F_MIN        1000000L              // Lower frequency limit
  #define F_MAX       30000000L           // change to suit your needs for upper limit
  #define ENCODER_A        3                 // Encoder pin A
  #define ENCODER_B        2                 // Encoder pin B
  #define ENCODER_BTN  11                //increments tuning step size
  #define LCD_RS 5
  #define LCD_E   6
  #define LCD_D4 7
  #define LCD_D5 8
  #define LCD_D6 9
  #define LCD_D7 10

  LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);     // LCD - pins
  Si5351 si5351;
  Rotary r = Rotary(ENCODER_A, ENCODER_B);

  volatile uint32_t frequency0 = 14000000L;       //You change these to your own frequencies
  volatile uint32_t frequency1 = 9000000L;
  volatile uint32_t frequency2 = 10000000L;
  volatile uint32_t radix = 100;                            //100Hz steps to start with  
  boolean changed_f = 0;                                     // frequency has changed flag

  /**************************************/
  /* Interrupt service routine for      */
  /* encoder frequency change           */
  /**************************************/
  ISR(PCINT2_vect) {
    unsigned char result = r.process();
    if (result == DIR_CW)
      set_frequency(1);                        
    else if (result == DIR_CCW)
      set_frequency(-1);                        
  }
  /**************************************/
  /* Change the frequency               */
  /* dir = 1    Increment               */
  /* dir = -1   Decrement               */
  /**************************************/
  void set_frequency(short dir)
  {
    if(dir == 1)
      frequency0 += radix;
    if(dir == -1)
      frequency0 -= radix;
 
    if(frequency0 > F_MAX) //if you comment out these four lines
      frequency0 = F_MAX;  //then you can avoid checking
    if(frequency0 < F_MIN) //upper and lower limits
      frequency0 = F_MIN;  //do the math, though, and set the limits for F_MAX
                                           //and F_MIN for the vfo you are using
 
    changed_f = 1;
  }
  /**************************************/
  /* Read the button with debouncing    */
  /**************************************/
  boolean get_button()
  {
    if(!digitalRead(ENCODER_BTN))
    {
      delay(20);
      if(!digitalRead(ENCODER_BTN))
      {
        while(!digitalRead(ENCODER_BTN));
        return 1;
      }
    }
    return 0;
  }

  /**************************************/
  /* Displays the frequency             */
  /**************************************/
    void display_frequency()
  {
    uint16_t f, g;
    lcd.setCursor(4, 0);
    f = frequency0 / 1000000;
    if(f<10)
      lcd.print(' ');
    lcd.print(f);
    lcd.print('.');
    f = (frequency0 % 1000000)/1000;
    if(f<100)
      lcd.print('0');
    if(f<10)
      lcd.print('0');
    lcd.print(f);
    lcd.print('.');
    f = frequency0 % 1000;
    if(f<100)
      lcd.print('0');
    if(f<10)
      lcd.print('0');
    lcd.print(f);
    lcd.print("Hz");
  }

  /**************************************/
  /* Displays the frequency change step */
  /**************************************/
  void display_radix()
  {
    lcd.setCursor(10, 1);
    switch(radix)
    {
      case 10:
        lcd.print("  10");
        break;
      case 100:
        lcd.print(" 100");
        break;
      case 1000:
        lcd.print("  1k");
        break;
      case 10000:
        lcd.print(" 10k");
        break;
      case 100000:
        lcd.print("100k");
        break;
     case 1000000: //change these lines to tune in 1MHz increments
        lcd.print("1M");
        break;
    }
    lcd.print("Hz");
  }


  void setup()
  {
    lcd.begin(16, 2);                                                    // Initialize and clear the LCD
    lcd.clear();
    Wire.begin();
    // Start serial and initialize the Si5351
    si5351.init(SI5351_CRYSTAL_LOAD_8PF);

   //Comment out the si5351.set_freq lines of the outputs you don't want to use
   // same for  si5351.drive_strength

   // Set CLK0 to output to 14 MHz ( frequency0) with a fixed PLL frequency
    si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
    si5351.set_freq(frequency0, SI5351_PLL_FIXED, SI5351_CLK0);

    // Set CLK1 to output 9 MHz (frequency1)
    si5351.set_freq(frequency1, 0, SI5351_CLK1);

    // Set CLK2 to output 10 MHz (frequency2)
    si5351.set_freq(frequency2, 0, SI5351_CLK2);

    si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_2MA); //change the 2 to a 4, 6, or 8
    si5351.drive_strength(SI5351_CLK1,SI5351_DRIVE_2MA); //for more power output
    si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_2MA);
 
     pinMode(ENCODER_BTN, INPUT_PULLUP);
     PCICR |= (1 << PCIE2);           // Enable pin change interrupt for the encoder
     PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
     sei();
     display_frequency();  // Update the display
     display_radix();
  }

  void loop()
  {
    // Update the display if the frequency has been changed
    if(changed_f)                   //changed_f  = 1 because encoder was moved
    {
      display_frequency();
     
      si5351.set_freq(frequency0, SI5351_PLL_FIXED, SI5351_CLK0);
      changed_f = 0;                // set back to 0 after updating si5351 with new freq.
    }
 
    // Button press changes the frequency change step
    if(get_button())                             //default radix was 100
    {                                                   //so the next time the button is pressed ...        
      switch(radix)
      {
        case 10:
          radix = 100;
          break;
        case 100:                               //case will be 100
          radix = 1000;                      //so step is increased to 10000
          break;
        case 1000:
          radix = 10000;
          break;
          case 10000:
          radix = 100000;
          break;
        case 100000: //change these lines to tune in 1MHz increments
          radix = 1000000;
          break;
        case 1000000:
          radix = 10;
          break;
      }
      display_radix();
    }
  }

13 comments:

  1. Hi Tom,

    Great work! I just wanted to clarify that the Rotary library is actually not mine. Sadly I don't know who wrote it or where I got it from so I can't give the author the due credit. If anyone recognizes it please let me know!

    73,
    Przemek SQ9NJE

    ReplyDelete
  2. Hi Przemek,

    i looked in the Rotary.cpp file and found that it is by Ben Buxton.

    Tom, ak2b

    ReplyDelete
    Replies
    1. Hi guys!
      Over a few days around google try to find full executive library for Si5351+ Arduino,but all the time in the sketch something missing...must doing something wrong!
      Can you send me link with full executive library include SI5351, Encoder and lcd!
      Think about SDR project,and this is fantastic signal generator for that!
      Thanks in advance!
      Željko-9a3ru

      Delete
    2. Hi Zeljko,
      All the code an libraries have links on this page. click on:
      "NT7S Si5351"
      "*Rotary library"
      "LCD_VFO_Si5351.ino"

      Tom, ak2b

      Delete
  3. Hi Tom! Mny tnx for answer!
    And yes...i know that..but my main problem is...HOW 3 DIFFERENT LIBRARY(SKETCH) PUT IN THE ONLY ONE ,AND COMPILE.If you explain to me HOW....my all problem gone:))
    Yes...i m not young, and have zero experiance with C++ and similar stuff unfortunatelly!!
    Best regards ,and waiting for your answer!
    Željko-9A3RU

    ReplyDelete
  4. Hi Zeljko,
    The sketch that ends in .ino i.e LCD_VFO_Si5351.ino should be put in a folder called "LCD_VFO_Si5351" in the direcectory "C:\Users\{your name}\Documents\Arduino"
    The two libraries, Rotary and Si5351 should be downloaded and extracted. After extracting these files, rename the folders to Rotary and Si5351 and put them the directory as above except it will be in the "libraries" folder i.e.
    "C:\Users\{your name}\Documents\Arduino\libraries"
    Your directory structure should look like this when you are done (you may have other sketch folders)

    C:\Users\{your name}\Documents\Arduino\
    ............................................................LCD_VFO_Si5351
    .......................................................................LCD_VFO_Si5351.ino
    ............................................................libraries\
    .........................................................................Rotary\
    .............................................................................. Rotary.h
    ...............................................................................Rotary.cpp
    ........................................................................ Si5351\
    ................................................................................Si5351.h
    ................................................................................Si5351.cpp

    The libraries may contain examples. It is ok if they remain in the folder.

    From here, you should be able to open the sketch by it's name "LCD_VFO_Si5351.ino" in the Arduino program and download it.
    Tom, ak2b



    ReplyDelete
  5. Hello, yes i doing like you told me!
    File Rotary ,and Si5351 upload without any problem!
    But, LCD_VFO_Si5351.ino, can not upload, report me bunch of error...think something is wrong inside code...or...dont know!
    Please, give me your e-mail ,and i send you the picture from that thing!
    Regards!
    Zeljko-9a3ru

    ReplyDelete
  6. Hi Tom!
    One favore!
    Please. compile ALL needed files for me ,and send me on seleniczeljko@gmail.com!
    Think ,that is most reasonable answer for me!
    Thanks in advance!
    9A3RU

    ReplyDelete
  7. Hi

    The problem may be multiple libraries.
    http://forum.arduino.cc/index.php?topic=128635.0
    There may be two libraries named "LiquidCrystal."
    Where Arduino keeps native libraries depends upon the
    operating system. But the original library probably needs to
    be renamed.

    regards
    tom
    k1trb
    .

    ReplyDelete
    Replies
    1. Hi guys!
      After few days--- finaly all wkd i expected!!!!
      Just ...someone can tell me ....to change frequency for 1mhz with encoder...what can i do?
      Best regards to all!
      Željko-9a3ru

      Delete
    2. Hi Željko,
      Glad you got it to work. Change the lines in your code to the ones outlined in blue to tune in 1Mhz increments.
      Tom, ak2b

      Delete
  8. Sorry Tom!
    I send you short video.....please watch..and fix the error!
    link:https://www.youtube.com/watch?v=-ALsik6cLX4
    Sorry for poor quality!
    Željko

    ReplyDelete
    Replies
    1. Sorry, that is not an error I can fix. It is a library error that should be fixed soon.

      Delete