tiistai 6. syyskuuta 2016


 VHF 145MHz / 2m VCO using Adafruit si5351 and Arduino Nano.

Please look more refined code here:
https://oh2btg.blogspot.com/2018/10/si5351-phase-shift-measurements.html


Oscillator is covering frequency band 130...150MHz.
Frequency step is selectable from 1kHz...1MHz. Output frequency is not absolutely accurate. There can be few kHz error. Anyway it is suitable for radio amateur experiments
Here is Arduino code. It is heavily modified from other si5351 code made by
nt7s
sq9nje
ak2b

Eero
oh2btg(at)sral.fi

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

Adafruit_SI5351 clockgen = Adafruit_SI5351();

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

/* OH2BTG VHF version v 0,0,4

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

#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 = 145500000 ;//start freq
uint32_t radix = 12500; //start step size 12.5kHz
uint32_t si5351ctl;
uint32_t si5351apu;
uint32_t si5351apu2;
boolean changed_f = 1;
String tbfo = "";
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //  LCD: RS,E,D4,D5,D6,D7
/**************************************/
/* Displays the frequency             */
/**************************************/
void display_frequency()
{
  uint16_t f, g;
 lcd.clear();
  lcd.setCursor(3,0);
  f = vfo / 1000000;   //variable is now vfo instead of 'frequency' vfo esim 145787500
  si5351ctl = vfo * 24 / 100000;  // simple calculation for ctl word
  si5351apu = si5351ctl /1000;  // feedback divider integer
  si5351apu2 = si5351ctl % 1000; // feedback divider fraktion
  Serial.println(" si5351apu");
  Serial.println(si5351apu);
  Serial.println(" si5351apu2");
  Serial.println(si5351apu2);
  Serial.println(" si5351ctl");
  Serial.println(si5351ctl);
  Serial.println(" vfo");
  Serial.println( vfo);
 // 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;
  }
  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 > F_MAX)
  //      vfo = F_MAX;
  //    if(vfo < F_MIN)
  //      vfo = F_MIN;

  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(" Erska Testaa");
 // lcd.begin(16, 2);                        // Initialize and clear the LCD
 lcd.clear();
 lcd.setCursor(0,0);
    lcd.print("  OH2BTG ");
     lcd.setCursor(0,1);
    lcd.print("VHF v.0.0.4");
  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();
  display_frequency();  // Update the display
}

void loop(void)
{
 // Update the display if the frequency has been changed
  if (changed_f)
  {
    display_frequency();
  clockgen.setupPLL(SI5351_PLL_A, (si5351apu),(si5351apu2), 1000); // write si5351ctl divider word
  clockgen.setupMultisynthInt(0, SI5351_PLL_A, SI5351_MULTISYNTH_DIV_6);

      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 = 1000;
        break;
    }
    display_radix();
  }
}

sunnuntai 1. maaliskuuta 2015

6M / 50MHz Duplexer for Repeater. Do it Yourself

Ready Duplexer. Installed to Nokia Aluminium ladder.
This duplexer resonators are made from 1"5/8 helical coaxial cable.
It have 4 resonators per RX and TX direction.

It is essential to have some sweep analyzer of network analyzer.
capable to sweep 20...70MHz band.
Without analyzer tuning of resonators is quite challange.
With analyzer you can see difference of high and lo quality capacitors and coils
Circuit diagram of 6 resonator system. principle is same with 8 resonators
In theory 8 resonator system you can get deeper notch attenuation

List of materials:

Needed Frequencys: Our case 51.370MHz and 51.970MHz
8 pcs 120cm long 1"5/8 coaxial cable. Thicker cable is also OK 

10m of Aircell 7 or RG-214 double shield coaxial cable for resonator interconnections

3m of 7/8" or 1/2" foam isolated coaxial cable. This is used for make high quality capasitors 10...15pF connecting signal to top of resonator

4 pcs high quality N-male connectors for both end of resonator line

1 pcs  N-female T adapter for interconnect antenna and RX / TX line of duplexer

4 pcs high quality trimmer capasitors 4...30pF. Used for minimize pass attenuation

4 pcs high quality coils 20...100nH. Used for minimize pass attenuation. Can be find inside 450MHz NMT radio duplexer, for example

Some pieces high quality fixed capasitors to put parallel to trimmer capasitor if needed.
values 30pF 45pF 60pF 80pF for example
Example of high quality coils and capasitors
Homemade capacitor made from 7/8" inner conductor with foam isolation
Capacitor above is adjustable very accurately few picofarads from 10...15pF

Top of duplexer coils and capacitors are visible
Picture above you can see that high and lo frequency resonators are divided horizontally left and right group




 51.970MHz pass -1.52dB
 and notch -90.23dB





51.370MHz pass -1.79dB
and notch -90.43dB




Pictures above show final attenuation measurements from duplexer