Go Down

Topic: Frequency generator code for Si5351 adafruit (Read 77 times) previous topic - next topic

OH2BTG

Here is RF generator code for adafruit Si5351 and Si5351 chip.
It is capable to make frequency output from 1MHz to 150MHz with various step from 100Hz to 10MHz.
It can be used as local oscillator for amateur radio. Signal output is square wave so there is lot of harmonics. They must be taken a count if this generator is used for transmitter.

It uses rotary coder and small standard LCD display.

Many parts of SW is borrowed from various other sketches, but frequency calculation part is studied from  si5351 AN619 and checked using Clock Builder Pro from Silicon Labs

Im not aware of bugs. Igot code ready last night so it is not extensively tested.

Best Regard:
OH2BTG

Code: [Select]



/**************************************************************************/

//v.0.0.5 09.09.2017 Frequency generator 1...150MHz with 100Hz steps.  OH2BTG


/**************************************************************************/


#include <Wire.h>
#include <Adafruit_SI5351.h>
#include <LiquidCrystal.h>
#include <rotary.h>
#include <si5351.h>

Adafruit_SI5351 clockgen = Adafruit_SI5351();

#define ENCODER_A    3                      // Encoder pin A
#define ENCODER_B    2                      // Encoder pin B
#define ENCODER_BTN  4 // Encoder c button
Rotary r = Rotary(ENCODER_A, ENCODER_B);
volatile uint32_t vfo = 14578750000 ;// initial frequency in Hz Put your favourite frequency here
uint32_t pllFreq; // si5351 internal vco frequency
uint32_t radix = 12500; //start step size 12.5kHz
uint32_t si5351multiCount; // Multicounter
uint32_t si5351multi_int;  // Multicounter integer
uint32_t si5351nomi; // Multicounter nominator
uint32_t si5351denomi = 1000000; //Multicounter denominator one million
uint32_t si5351divider; // VCO output divider integer part
boolean changed_f = 1;
String tbfo = "";
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //  LCD: RS,E,D4,D5,D6,D7 Erska
/**************************************/
/* Displays the frequency             */
/**************************************/
void count_frequency()
{
  uint16_t f, g;
 lcd.clear();
  lcd.setCursor(3,0);
  f = vfo / 1000000;   //variable is now vfo instead of 'frequency' vfo esim 145787500
  si5351divider = 900000000/vfo; // vfo divider integer
  pllFreq = si5351divider * vfo; // counts pllFrequency
  si5351multiCount = pllFreq / 25; // feedback divider
  si5351multi_int = pllFreq / 25000000; // feedback divider integer
  si5351nomi = si5351multiCount % 1000000;  // feedback divider integer
  si5351denomi = 1000000; // feedback divider fraktion
  Serial.print(" vfo ");
  Serial.println( vfo); 
  Serial.print(" pllFreq ");
  Serial.println( pllFreq);
  Serial.print("si5351divider ");
  Serial.println(si5351divider);
  Serial.print(" si5351multiCount ");
  Serial.println(si5351multiCount);
  Serial.print(" si5351multi_int ");
  Serial.println(si5351multi_int);
  Serial.print(" si5351nomi ");
  Serial.println(si5351nomi);
  Serial.print(" si5351denomi ");
  Serial.println(si5351denomi);
 // Serial.println(f = vfo / 1000000); // printtaa f 145.XXX.XXX
  if (f < 10)
   lcd.print("");
  lcd.print(f);
  lcd.print(",");
  f = (vfo % 1000000) / 1000; // printtaa taajuuden 3 viim numeroa XXX.550.XXX
 // Serial.println (f = (vfo % 1000000) / 1000);
  if (f < 100)
    lcd.print("0");
  if (f < 10)
    lcd.print("0");
  lcd.print(f);
  lcd.print(".");
 // f = vfo % 1000;
   f = (vfo % 1000) / 100; // removing 2 last digit from frequency reading
 // Serial.println( f = vfo % 1000); // printtaa XXX.XXX.000
 // if (f < 100)
   // lcd.print("0");
 // if (f < 10)
  //  lcd.print("0");
  lcd.print(f); //
  lcd.print("MHz");
 // lcd.setCursor(0, 0);
 // lcd.print(tbfo);
//  Serial.println(vfo + bfo);
//  Serial.println(tbfo);
}

/**************************************/
/* Displays the frequency change step */
/**************************************/
void display_radix()
{
  lcd.setCursor(0, 1);
  switch (radix)
  {
    case 1:
      lcd.print("    1");
      break;
    case 10:
      lcd.print("   10");
      break;
    case 100:
      lcd.print("  100");
      break;
    case 1000:
      lcd.print("   1k");
      break;
    case 12500:
      lcd.print("12.5k");
      break;
    case 100000:
      lcd.setCursor(0, 1);
      lcd.print(" 100k");
      break;
    case 1000000:
      lcd.setCursor(1, 1);
      lcd.print("  1M"); //1MHz increments
      break;
    case 10000000:
      lcd.setCursor(1, 1);
      lcd.print(" 10M"); //10MHz increments
      break;
  }
  lcd.print("Hz");
        Serial.println("radix");
       Serial.println(radix);
}
/**************************************/
/* 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)
    vfo += radix;
  if (dir == -1)
    vfo -= radix;

      if(vfo > 150000000)
        vfo = 100000;
      if(vfo < 100000)
        vfo = 150000000;
      if (vfo < 0)
        vfo = 100000;
  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;
}

void setup(void)
{
    Serial.begin(115200);
   Serial.println(" Hello Word ");  // Put your favourite text here
 // lcd.begin(16, 2);                        // Initialize and clear the LCD
 lcd.clear();
 lcd.setCursor(0,0);
    lcd.print("  OH2BTG ");
     lcd.setCursor(0,1);
    lcd.print("1-150MHz v.0.0.5");
  delay(2000);  //2seconds
  Wire.begin();
 
  /* Initialise the sensor */
  if (clockgen.begin() != ERROR_NONE)
  {

    while(1);
  }
 
  /* Enable the clocks */
  clockgen.enableOutputs(true);
    pinMode(ENCODER_BTN, INPUT_PULLUP);
  PCICR |= (1 << PCIE2);           // Enable pin change interrupt for the encoder
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
  count_frequency();  // Count f and update the display
}

void loop(void)

 // Update the display if the frequency has been changed
  if (changed_f)
  {
    count_frequency();
  clockgen.setupPLL(SI5351_PLL_A, (si5351multi_int),(si5351nomi),(si5351denomi)); // write si5351ctl divider word 
 // clockgen.setupMultisynthInt(0, SI5351_PLL_A, SI5351_MULTISYNTH_DIV_6);
  clockgen.setupMultisynth(0, SI5351_PLL_A,(si5351divider),0,1 );
      changed_f = 0;
}
  // Button press changes the frequency step
  if (get_button())
  {
    switch (radix)
    {

   //   case 1:
   //     radix = 10;
   //     break;
   //   case 10:
    //    radix = 100;
    //    break;
     case 100:
        radix = 1000;
        break;
      case 1000:
        radix = 12500;
        break;
      case 12500:
        radix = 100000;
        break;
      case 100000:
        radix = 1000000;
        break;
      case 1000000:
      radix = 10000000;
        break;
      case 10000000:
        radix = 100;
        break;   
    }
    display_radix();
  }
}


OH2BTG

I find one error right away here:

volatile uint32_t vfo = 14578750000;// initial frequency in Hz Put your favourite frequency here

two zeros too much, must be:

volatile uint32_t vfo = 145787500;// initial frequency in Hz Put your favourite frequency here

OH2BTG


Go Up