VFO COM SI5351
até 225MHz* - Variante do Multi-featured VFO
* valor testado na minha montagem
Este artigo
refere-se a este link :
Multi-Featured VFO April, 6
, 2015
Veja tambem detalhes de layout em :
Si5351
simple VFO hardware setup
Fizemos algumas simples modificações no VFO anterior uma
foi o aumento da frequencia de operação, outro foi no
step : pois para alterar o step ou passo era necessario comprimir o
botão do encoder e o passo era aumentado, mas o passo somente
caminhava em uma direção: subindo até o maximo e
ai retornava ao inicio.
Modifiquei para que ao pressionar o botão do encode aparece um
sublinhado (underline) que mantendo pressionado e girando o sublinhado
muda de casa decimal (para cima ou para baixo) e ao soltar o
botão a casa decimal selecionanda podera ser alterada.
Outra modificação que fizemos foi gerar 3 sketches (o
artigo original tambem tinha estas opções) sendo um para
conversão direta, outro para SSB ou superjheterodino e um
terceiro para operação com fase ou SDR com o VFO a quatro
vezes a frequencia do display.
Esquema :

A cópia
da biblioteca esta aqui library
NT7S por motivos de
update.
Outros sketches após este
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Sketch "conversão direta" DC - frequencia do display igual a
frequencia de saida (em CLK0).
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/*
This entire program is taken from Jason Mildrum, NT7S and Przemek
Sadowski, SQ9NJE.
There is not enough original code written by AK2b to make it worth
mentioning.
http://nt7s.com/
http://sq9nje.pl/
http://ak2b.blogspot.com/
I made some mods ...first updating the sketch to new library from NT7S
..in frequency coverage and the mode for frequency change..
pressing the encoder and turn it at same time ...it will move a
underline showing
the place where it is OK to change
THIS SKETCH IS A VFO FOR Direct Conversion equipments or
frequency generator
http://py2ohh.w2c.com.br/
*/
#include <Rotary.h>
#include <si5351.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define F_MAX 23000000000UL
#define ENCODER_A
3
// Encoder pin A nano/uno pin D3
#define ENCODER_B
2
// Encoder pin B nano/uno pin D2
#define ENCODER_BTN 11
#define LCD_RS
5
// LCD pin 4
#define LCD_E
6
// LCD pin 6 nano/uno pin D6
#define LCD_D4
7
// LCD pin11 nano/uno pin D7
#define LCD_D5
8
// LCD pin12 nano/uno pin D8
#define LCD_D6
9
// LCD pin13 nano/uno pin D9
#define LCD_D7
10
// LCD pin14 nano/uno pin D10
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6,
LCD_D7); // LCD - pin assignement in
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);
volatile uint32_t vfo = 700000000ULL / SI5351_FREQ_MULT; //start freq
now 7MHz- change to suit
volatile uint32_t radix = 100; //start step size -
change to suit
boolean changed_f = 0;
String tbfo = "";
short und = 3; //controle do underline
short pot = 3; // controle de multiplicador
#define Direct_conversion //What you see on display is what you get
/**************************************/
/* 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 and underline */
/* dir = 1
Increment
*/
/* dir = -1 Decrement
/**************************************/
void set_frequency(short dir)
{
if (!digitalRead(ENCODER_BTN)){
lcd.setCursor( 12-und,0);
if (dir == 1){
und += 1;
switch (und) {
case 4 :
und=5;
break;
case 8 :
und=9;
break;
case 12 :
und=11;
break;
}
}
if (dir == -1){
und += -1;
switch (und) {
case 4 :
und=3;
break;
case 8 :
und=7;
break;
case 0 :
und=1;
break;
}
}
pot = und;
if (und > 3) (pot += -1);
if (und > 7) (pot += -1);
lcd.setCursor( 12-und,0);
lcd.cursor();
}
else
{lcd.noCursor();
if (dir == 1)
vfo += radix;
if (dir == -1){
if (vfo > radix ) {
vfo -= radix;
}}
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(1, 0);
f = (vfo )/ 1000000; //variable is now vfo
instead of 'frequency'
if (f < 100) {
lcd.print(' '); }
if (f < 10){
lcd.print(' ');}
lcd.print(f);
lcd.print('.');
f = (vfo % 1000000) / 1000;
if (f < 100)
lcd.print('0');
if (f < 10)
lcd.print('0');
lcd.print(f);
lcd.print('.');
f = vfo % 1000;
if (f < 100)
lcd.print('0');
if (f < 10)
lcd.print('0');
lcd.print(f);
lcd.print("Hz");
}
void setup()
{
Serial.begin(19200);
lcd.begin(16,
2);
// Initialize and clear the LCD
lcd.clear();
Wire.begin();
si5351.set_correction(140); //**mine. There is a calibration
sketch in File/Examples/si5351Arduino-Jason
//where you can determine the correction by using the serial
monitor.
//initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27000000,0); //If you're
using a 27Mhz crystal, put in 27000000 instead of 0
// 0 is the default crystal frequency of 25Mhz.
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
// Set CLK0 to output the starting "vfo" frequency as set above
by vfo = ?
//si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_2MA); //you can
set this to 2MA, 4MA, 6MA or 8MA
//be careful though - measure into 50ohms
#ifdef Direct_conversion
si5351.set_freq((vfo * SI5351_FREQ_MULT), SI5351_CLK0);
#endif
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()
{
// Update the display if the frequency has been changed
if (changed_f)
{
display_frequency();
#ifdef Direct_conversion
si5351.set_freq((vfo * SI5351_FREQ_MULT),
SI5351_CLK0);
tbfo = "";
#endif
changed_f = 0;
}
if (get_button())
{
switch (pot)
{
case 1:
radix = 1;
break;
case 2:
radix = 10;
break;
case 3:
radix = 100;
break;
case 4:
radix = 1000;
break;
case 5:
radix = 10000;
break;
case 6:
radix = 100000;
break;
case 7:
radix = 1000000;
break;
case 8:
radix = 10000000;
break;
case 9:
radix = 100000000;
break;
}
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Sketch para equipamentos por fase ou SDR com o VFO em uma frequencia 4x
a mostrada no display (em CLK0).
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
/*
This entire program is taken from Jason Mildrum, NT7S and Przemek
Sadowski, SQ9NJE.
There is not enough original code written by me to make it worth
mentioning.
http://nt7s.com/
http://sq9nje.pl/
http://ak2b.blogspot.com/
I made some mods ...first updating the sketch to new library from NT7S
..in frequency coverage and the mode for frequency change..
pressing the encoder and turn it at same time ...it will move a
underline showing
the place where it is OK to change
THIS SKETCH IS A VFO FOR SDR equipments that uses VFO freq. at 4x
http://py2ohh.w2c.com.br/
*/
#include <Rotary.h>
#include <si5351.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define F_MIN
100000000UL
// Lower frequency limit
#define F_MAX 23000000000UL
#define ENCODER_A
3
// Encoder pin A
#define ENCODER_B
2
// Encoder pin B
#define ENCODER_BTN 11
#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 - pin assignement in
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);
volatile uint32_t vfo = 700000000ULL / SI5351_FREQ_MULT; //start freq -
change to suit
volatile uint32_t radix = 100; //start step size -
change to suit
boolean changed_f = 0;
String tbfo = "";
short und = 3;
short pot = 3;
#define FreqX4 //output is four times the display frequency
//--------------------------------------------------------------------------------------------------
/**************************************/
/* 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 Decrement56
/**************************************/
void set_frequency(short dir)
{
if (!digitalRead(ENCODER_BTN)){
lcd.setCursor( 12-und,0);
if (dir == 1){
und += 1;
switch (und) {
case 4 :
und=5;
break;
case 8 :
und=9;
break;
case 12 :
und=11;
break;
}
}
if (dir == -1){
und += -1;
switch (und) {
case 4 :
und=3;
break;
case 8 :
und=7;
break;
case 0 :
und=1;
break;
}
}
pot = und;
if (und > 3) (pot += -1);
if (und > 7) (pot += -1);
lcd.setCursor( 12-und,0);
lcd.cursor();
}
else
{lcd.noCursor();
if (dir == 1)
vfo += radix;
if (dir == -1){
if (vfo > radix ) {
vfo -= radix;
}}
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(1, 0);
f = (vfo )/ 1000000; //variable is now vfo
instead of 'frequency'
if (f < 100) {
lcd.print(' '); }
if (f < 10){
lcd.print(' ');}
lcd.print(f);
lcd.print('.');
f = (vfo % 1000000) / 1000;
if (f < 100)
lcd.print('0');
if (f < 10)
lcd.print('0');
lcd.print(f);
lcd.print('.');
f = vfo % 1000;
if (f < 100)
lcd.print('0');
if (f < 10)
lcd.print('0');
lcd.print(f);
lcd.print("Hz");
lcd.setCursor(1, 1);
lcd.print(tbfo);
//Serial.println(vfo + bfo);
//Serial.println(tbfo);
}
void setup()
{
Serial.begin(19200);
lcd.begin(16,
2);
// Initialize and clear the LCD
lcd.clear();
Wire.begin();
si5351.set_correction(140); //**mine. There is a calibration
sketch in File/Examples/si5351Arduino-Jason
//where you can determine the correction by using the serial
monitor.
//initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27000000,0); //If you're
using a 27Mhz crystal, put in 27000000 instead of 0
// 0 is the default crystal frequency of 25Mhz.
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
// Set CLK0 to output the starting "vfo" frequency as set above
by vfo = ?
#ifdef FreqX4
si5351.set_freq((vfo * SI5351_FREQ_MULT) * 4, SI5351_CLK0);
#endif
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()
{
// Update the display if the frequency has been changed
if (changed_f)
{
display_frequency();
#ifdef FreqX4
si5351.set_freq((vfo * SI5351_FREQ_MULT) * 4,
SI5351_CLK0);
tbfo = "";
#endif
changed_f = 0;
}
// Button press changes the frequency change step for 1 Hz steps
if (get_button())
{
switch (pot)
{
case 1:
radix = 1;
break;
case 2:
radix = 10;
break;
case 3:
radix = 100;
break;
case 4:
radix = 1000;
break;
case 5:
radix = 10000;
break;
case 6:
radix = 100000;
break;
case 7:
radix = 1000000;
break;
case 8:
radix = 10000000;
break;
case 9:
radix = 100000000;
break;
}
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Sketch para equipos SSB como ARARINHA, BINGO (antigo) e BITX ou
equipamentos superheterodinos que usam uma frequencia intermediaria FI
(no caso os valores são para FI de 10MHz - podendo ser
alterada). A frequencia de saida pode ser (FI- frequencia) desejada ou
(FI+frequencia) desejada. Saida do VFO em CLK0 e do BFO em CLK2.
Para alterações nestas funções favor entrar
em contato comigo via email ...
[email protected] remover os xxx...
XXXXXXXXXXXXXXXXXXXXXXXXXXXX
/*
This entire program is taken from Jason Mildrum, NT7S and Przemek
Sadowski, SQ9NJE.
There is not enough original code written by me to make it worth
mentioning.
http://nt7s.com/
http://sq9nje.pl/
http://ak2b.blogspot.com/
I made some mods ...first updating the sketch to new library from NT7S
..in frequency coverage and the mode for frequency change..
pressing the encoder and turn it at same time ...it will move a
underline showing
the place where it is OK to change
THIS SKETCH IS A VFO FOR superheterodine or SSB equipments that
uses IF
http://py2ohh.w2c.com.br/
*/
#include <Rotary.h>
#include <si5351.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define F_MIN
100000000UL
// Lower frequency limit
#define F_MAX 23000000000UL
#define ENCODER_A
3
// Encoder pin A
#define ENCODER_B
2
// Encoder pin B
#define ENCODER_BTN 11
#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 - pin assignement in
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);
//Valores para um FI de 10MHz altere se necessario
//Values for IF=10MHz change if necessary
volatile uint32_t LSB = 999950000ULL; //LSB = IF - 1500Hz
volatile uint32_t USB = 1000150000ULL; // USB = IF +1500Hz
volatile uint32_t bfo = 1000000000ULL; //Intermediary frequency IF
//These USB/LSB frequencies are added to or subtracted from the vfo
frequency in the "Loop()"
//In this example my start frequency will be 14.000000 plus 10.001500
or clk0 = 24.0015Mhz
volatile uint32_t vfo = 1400000000ULL / SI5351_FREQ_MULT; //start freq
7MHz - change to suit
volatile uint32_t radix = 100; //
boolean changed_f = 0;
String tbfo = "";
short und = 3;
short pot = 3;
//-------------------------------
--------------------------------------
#define IF_Offset //Output is the display plus or minus the bfo
frequency
/**************************************/
/* 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 Decrement56
/**************************************/
void set_frequency(short dir)
{
if (!digitalRead(ENCODER_BTN)){
lcd.setCursor( 12-und,0);
if (dir == 1){
und += 1;
switch (und) {
case 4 :
und=5;
break;
case 8 :
und=9;
break;
case 12 :
und=11;
break;
}
}
if (dir == -1){
und += -1;
switch (und) {
case 4 :
und=3;
break;
case 8 :
und=7;
break;
case 0 :
und=1;
break;
}
}
pot = und;
if (und > 3) (pot += -1);
if (und > 7) (pot += -1);
lcd.setCursor( 12-und,0);
lcd.cursor();
}
else
{lcd.noCursor();
if (dir == 1)
vfo += radix;
if (dir == -1){
if (vfo > radix ) {
vfo -= radix;
}}
changed_f = 1;
}
// 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;
}
/**************************************/
/* Displays the
frequency
*/
/**************************************/
void display_frequency()
{
uint16_t f, g;
lcd.setCursor(1, 0);
f = (vfo )/ 1000000; //variable is now vfo
instead of 'frequency'
if (f < 100) {
lcd.print(' '); }
if (f < 10){
lcd.print(' ');}
lcd.print(f);
lcd.print('.');
f = (vfo % 1000000) / 1000;
if (f < 100)
lcd.print('0');
if (f < 10)
lcd.print('0');
lcd.print(f);
lcd.print('.');
f = vfo % 1000;
if (f < 100)
lcd.print('0');
if (f < 10)
lcd.print('0');
lcd.print(f);
lcd.print("Hz");
lcd.setCursor(1, 1);
lcd.print(tbfo);
}
void setup()
{
Serial.begin(19200);
lcd.begin(16,
2);
// Initialize and clear the LCD
lcd.clear();
Wire.begin();
si5351.set_correction(140); //**mine. There is a calibration
sketch in File/Examples/si5351Arduino-Jason
//where you can determine the correction by using the serial
monitor.
//initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27000000,0); //If you're
using a 27Mhz crystal, put in 27000000 instead of 0
// 0 is the default crystal frequency of 25Mhz.
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
// Set CLK0 to output the starting "vfo" frequency as set above
by vfo = ?
#ifdef IF_Offset
si5351.set_freq((vfo * SI5351_FREQ_MULT) + bfo, SI5351_CLK0);
//desligada
volatile uint32_t vfoT = (vfo * SI5351_FREQ_MULT) + bfo;
tbfo = "USB";
// Set CLK2 to output bfo frequency
si5351.set_freq( bfo, SI5351_CLK2);
//si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_2MA); //you can
set this to 2MA, 4MA, 6MA or 8MA
//si5351.drive_strength(SI5351_CLK1,SI5351_DRIVE_2MA); //be
careful though - measure into 50ohms
//si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_2MA); //
#endif
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()
{
// Update the display if the frequency has been changed
if (changed_f)
{
display_frequency();
#ifdef IF_Offset
if (vfo >= 10000000 )
{
bfo = USB;
tbfo = "USB";
si5351.set_freq((vfo * SI5351_FREQ_MULT) + bfo, SI5351_CLK0);
si5351.set_freq( bfo, SI5351_CLK2);
}
else if (vfo < 10000000 )
{
bfo = LSB;
tbfo = "LSB";
si5351.set_freq((bfo -(vfo *
SI5351_FREQ_MULT)) , SI5351_CLK0);
si5351.set_freq( bfo, SI5351_CLK2);
}
#endif
changed_f = 0;
}
if (get_button())
{
switch (pot)
{
case 1:
radix = 1;
break;
case 2:
radix = 10;
break;
case 3:
radix = 100;
break;
case 4:
radix = 1000;
break;
case 5:
radix = 10000;
break;
case 6:
radix = 100000;
break;
case 7:
radix = 1000000;
break;
case 8:
radix = 10000000;
break;
case 9:
radix = 100000000;
break;
}
//display_radix();
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
73 de py2ohh may -2017