Olá pessoal, e todos que acompanha o blog e nosso canal no YouTube. Trago para o final de ano um presente de Natal. Ainda sobre o esboço que copiei do vídeo e publicado aqui no blog e no YouTube, com pequenas atualizações para serem adaptados no Cobra 148 GTL ou outros transceptores. O esboço ou sketch é simples mas temos em CLK0 VFO com adição ou subtração da FI configurando no esboço, temos em CLK1 BFO frequência de FI digitada no começo do esboço, esta frequência tem variação em LSB, USB, com 1500Hz abaixo e acima da frequência do AM, que são refletidas no VFO CLK0. Assim para quem quiser poderá usar CLK1 como Carrier oscilador, poderá precisar de um Buffer, ou simplesmente ligar no local do cristal de 7.800Mhz, se alguém perdeu o cristal ou está danificado de Carrier oscilador 7.800 Mhz Cobra 148 GTL, ou outros transceptores podem usar este recurso com sucesso para reviver seu transceptor.
Bem como já relatei no começo deste, o sketch é atualizado no STEP agora fixo, começo da frequência imediato mesmo depois da tela de inicialização Cobra 148 GTL. O sketch ficou mais leve, estável, e muito melhor que o primeiro foi até 110 Mhz com ótima estabilidade, não mais de 110 Mhz, o que dá para ser usado em transceptores comerciais ou montagens em casa homebrew, nas faixas de HF, VHF até 50 ou 70 Mhz, tudo isso com os modos AM, LSB, USB. Fiz algumas alterações para ver se ele subiria até os 160 Mhz mas não deu, tentei modificar a biblioteca, também não tive sucesso. Outras tentativas de colocar um S/Meter na parte de baixo do display, chave TX, RX em CLK0 com frequência do display e frequência do VFO +/- do BFO, não deram certo além da memoria EEPROM que não deu certo também. Pessoal não é fácil só copiar e colar linhas de comandos de outros esboços e vai dá certo, não, não vai dá certo, eu ainda estou aprendendo mas digo para mudar um esboço tem que saber como fazer está modificação, é para quem tem muito conhecimento no código C++ Arduino, em alguns casos simples como imprimir um nome ou outras simples modificações, são fáceis, mas outras como ás que citei, teremos que modificar muito o esboço para ter o que queremos. Vocês podem ver vários exemplos de muitas modificações feitas por Radioamadores e amantes da eletrônica digital do projeto do DDS VFO 10K 220Mhz até os chineses copiou e estão comercializando este magnífico DDS VFO que é muito bom para nossos transceptores. Ele é amplamente divulgado em vídeos, sites, blogs, eu acho pelas minhas pesquisas que é o projeto do Júlio Cesar DDS VFO e mais modificados no mundo. Parabéns Júlio Cesar. Enquanto muitos acham que só podem modificarem os esboços quem é programador, eu li e ouvir, vários relatos de colegas do mundo inteiro que diz não saber muito sobre Arduino e Código C++, mas mesmo assim fazem modificações e dão certo. Não dá para eu listar aqui os sites e vídeos que tem este projeto do Júlio Cesar como argumento de modificações, pois são inúmeros. Vamos retornar ao nosso simples e eficiente DDS VFO AM, LSB, USB. Eu gostaria se tiver alguém aqui no Brasil ou no mundo que quiser mandar como colocar um S/Meter e memória EEPROM nestes esboços, eu ficaria realmente feliz e divulgo seu nome ou como queira ser divulgado.
Pessoal eu recebi muitos e-mail e comentários perguntando como colocar este DDS VFO em um transceptor AM SSB. Minha resposta: Seja qual a marca e modelo, se o rádio tiver AM, FM, CW, LSB, USB, vocês terão de acrescentar no esboço estes modos e digitar seus pinos e suas frequências de FI. vejam com atenção ás linhas de comando do esboço, e façam o mesmo. Para transceptores que tem a chave de AM, LSB, USB, Cobra 148 GTL a chave é S403-3 com +8 volts. Os pinos D6 USB, D7 LSB, D8 AM, do Arduino no esboço elas tem que ir para LOW, negativo, GND terra, para isso teremos que montar uma chave eletrônica a transistor NPN de uso geral, onde o coletor vai ao pino do Arduino, emissor ao GND negativo, e base entra o sinal S403-3 segue a dois resistores um em série de 22k a 47K outra idêntica e um capacitor de cerâmica ou poliéster de 103, 10nF base para negativo GND. Abaixo está o esquema da chave eletrônica que servirá para demais transceptores que tem chave com alimentação +B outros que tem alimentação a GND negativo não precisa de tais chaves. Não podemos esquecer que para vocês colocarem o DDS VFO em seu transceptor, terão de montar um simples Buffer amplificador de RF com um ou dois transistores, o transistor melhor é BF 199 ou outros de alta frequência para quem vai até 220 Mhz, Vejam na página do Sr. PU2REO manual em PDF DVFO como instalar o DDS VFO em um Cobra 148 GTL. Parabéns muito obrigado ao PU2REO pela contribuição. Abaixo tradução do PU2REO na página do Buffer manual v1.5.
"Vamos voltar ao assunto: depois de remover os componentes de rádio marcados com um quadrado vermelho
nos esquemas de rádio, é hora de colocar o DVFO para funcionar. Se você observar os esquemas de rádio, é fácil identificar que o pino nº 1 do CI2 (UHIC 070) é a saída do VFO analógico. Portanto, é exatamente aí que vamos inserir nosso novo gerador. Após alguns testes, descobri que o Si5351 não é adequado para acoplamento direto com L20, devido à sua baixa corrente e tensão de saída, entre outros 2 ou 3 motivos que estão além do escopo deste manual. É aí que entra um amplificador de sinal pequeno: Esquema do Amplificador de Sinal Pequeno (ou simplesmente "Buffer"). Para construir este buffer, usei o TR20 do meu próprio rádio. Você pode usar um BC547, que também funcionará bem. A versão final deste buffer foi montada na placa de circuito impresso e soldada no mesmo local onde antes estava o UHIC-070."
Esquema Buffer amplificador simples RF PU2REO.
PCB Buffer PU2REO.
Esquema ligações dos periféricos no Arduino DDS VFO CB AM, LSB, USB.
Fotos abaixo é esboço, tem Modo AM, LSB, USB, STEP fixo, TRX. frequência na parte de baixo do display. É o recomendado e foi o primeiro a ser atualizado. Mais estável, mais leve. inicialização rápido da frequência ao ligar, mesmo com tela de inicialização.
Tela de inicialização Cobra 148 GTL. Poderá modificar para outros transceptores.
Tela do DDS VFO atualizado com STEP fixo, TRX, Modo AM, LSB, USB, frequência VFO parte inferior display.
Vai até 110 Mhz com ótima estabilidade. Depois desta frequência fica instável.
Vejam no Frequencímetro a FI é 7.800Khz.
Selecione o programa, copie, depois abra na área de trabalho o Arduino IDE, limpe delete e cole dentro.
/**********************************************************************************
Updated sketch copied from YouTube by CT7API Manuel Ferreira.
Updated by Waldir Cardoso. 12/2025. https://projetosetransceptores.blogspot.com/
Blog: Projetos e Transceptores. Brazil.
This sketch will work with the Cobra 148 GTL, and equipment with 3 or 5 switches
for AM, LSB, USB. Modification to the sketch for FM, CW. Cobra 148 GTL-DX, SuperStar 3900.
***********************************************************************************/
//---------------------------------------------------------------------------------
// Function
// 1.VFO CLK0 34 Mhz AM LSB USB MODE
// 2.BFO CLK1 BFO FI 7.800 Khz AM LSB USB MODE
// 3.STEP(1MHz,100,10,1kHz,100,10,1Hz)
////////////////////////////////////////////////////////////////////////
//Libraries
#include <si5351.h> //https://github.com/etherkit/Si5351Arduino/releases/tag/v1.1.2
#include <Wire.h> //IDE Standard
#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
#include <Rotary.h> //Ben Buxton https://github.com/brianlow/Rotary
#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library
//----------------------------------------------------------------------------------------------------
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define F_MIN 100000000UL
#define F_MAX 16000000000UL
#define ENCODER_A 2
#define ENCODER_B 3
#define ENCODER_BTN 5
#define USB_PIN 6
#define LSB_PIN 7
#define AM_PIN 8
//#define rx_tx 9
int lsbstate = 0;
int amstate = 0;
int usbstate = 0;
Si5351 si5351; //Si5351 I2C Address 0x60
Rotary r = Rotary(3, 2);
volatile int32_t AM = 780000000ULL;
volatile int32_t LSB = 779850000ULL; //LSB = IF - 1500Hz
volatile int32_t USB = 780150000ULL; //USB = IF + 1500Hz
volatile int32_t bfo = 780000000ULL; //Intermediary frequency IF
volatile int32_t vfo = 2696500000ULL / SI5351_FREQ_MULT; // frequency display initialization
volatile uint32_t radix = 10000; //start step size - change to suit
boolean changed_f = 0;
String tbfo = "";
//bool sts = 0;
#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 Decrement */
/**************************************/
void set_frequency(short dir)
{
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;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(100, 1);
//display.print(sts ? "TX" : "RX");
display.print("TRX");
display.setCursor(3,1);
display.print("MODE:");
display.println(tbfo);
/**************************************/
/* Displays the frequency change step */
/**************************************/
//display.setCursor(60,1);
//display.print(F("ST:"));
display.setCursor(45,9);
display.print(F("STEP:"));
switch (radix)
{
case 1:
display.println(F(" 1 Hz"));
break;
case 10:
display.println(F(" 10 Hz"));
break;
case 100:
display.println(F(" 100 Hz"));
break;
case 1000:
display.println(F(" 1 kHz"));
break;
case 10000:
display.println(F(" 10 kHz"));
break;
case 100000:
display.println(F("100 kHz"));
break;
case 1000000:
display.println(F(" 1 MHz"));
break;
}
/**************************************/
/* Displays the frequency */
/**************************************/
display.setTextSize(2);
f = vfo / 1000000; //variable is now vfo instead of 'frequency'
if (f < 10)
display.print(' ');
display.print(f);
display.print('.');
f = (vfo % 1000000) / 1000;
if (f < 100)
display.print('0');
if (f < 10)
display.print('0');
display.print(f);
display.print('.');
f = vfo % 1000;
if (f < 100)
display.print('0');
if (f < 10)
display.print('0');
display.print(f);
display.display();
display.clearDisplay();
}
/**************************************/
/* S E T U P */
/**************************************/
void setup()
{
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.display();
//pinMode(rx_tx, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(USB_PIN, INPUT_PULLUP);
pinMode(LSB_PIN, INPUT_PULLUP);
pinMode(AM_PIN, INPUT_PULLUP);
si5351.set_correction(18000); //**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, 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
//Serial.println((long)((vfo * SI5351_FREQ_MULT) - bfo) * -1);
si5351.set_freq(((vfo * SI5351_FREQ_MULT) + bfo), SI5351_PLL_FIXED, SI5351_CLK0);
volatile uint32_t vfoT =((vfo * SI5351_FREQ_MULT) - bfo);
tbfo = " AM";
// Set CLK1 to output bfo frequency
si5351.set_freq( bfo,0,SI5351_CLK1);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA);
#endif
Splash();
pinMode(ENCODER_BTN, INPUT_PULLUP);
PCICR |= (1 << PCIE2); // Enabled pin change interrupt for the encoder
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
display_frequency(); // Update the display
}
/**************************************/
/* L O O P */
/**************************************/
void loop()
{
// Update the display if the frequency has been changed
{ display_frequency();
#ifdef IF_Offset
//you can also subtract the bfo to suit your needs
//si5351.set_freq(((vfo * SI5351_FREQ_MULT) - bfo), SI5351_PLL_FIXED, SI5351_CLK0); // VFO subtrai á IF
si5351.set_freq(( vfo * SI5351_FREQ_MULT) + bfo, SI5351_PLL_FIXED, SI5351_CLK0); // VFO soma á IF
si5351.set_freq( bfo,0,SI5351_CLK1); // IF
si5351.output_enable(SI5351_CLK0, 1); // Enable CLK0 //1 - Enable / 0 - Disable CLK
si5351.output_enable(SI5351_CLK1, 1); // Enable CLK1
#endif
//{
//sts = digitalRead(rx_tx) == LOW;
//}
usbstate = digitalRead(USB_PIN);
if (usbstate == LOW) {
//USB
bfo = USB;
tbfo = " USB";
}
amstate = digitalRead(AM_PIN);
if (amstate == LOW) {
//AM
bfo = AM;
tbfo = " AM";
}
lsbstate = digitalRead(LSB_PIN);
if (lsbstate == LOW) {
// LSB
bfo = LSB;
tbfo = " LSB";
}
}
// Button press changes the frequency change step for 1 Hz steps
if (get_button())
{
switch (radix)
{
case 1:
radix = 10;
break;
case 10:
radix = 100;
break;
case 100:
radix = 1000;
break;
case 1000:
radix = 10000;
break;
case 10000:
radix = 100000;
break;
case 100000:
radix = 1000000;
break;
case 1000000:
radix = 1;
break;
}
display_frequency();
}
}
void Splash() {
display.setTextSize(2);
display.setCursor(5, 1);
display.print("Cobra 148");
display.setCursor(45, 17);
display.print("GTL");
display.display();
delay(3000);
display.clearDisplay();
}
O esboço e fotos abaixo tem o modo RX e TX falso, não atua nem CLK0 e CLK1, só serve para ter uma referência no display de recepção e transmissão, ao ser acionado pino D9 alto sem ligação RX, em LOW, negativo TX no transceptor Cobra 148 GTL ou outros transceptores.
Tela de inicialização para Cobra 148 GTL, poderá ser modificado para transceptor diferente.
Foto modo RX falso.
Modo TX falso.
Selecione todo programa, copie, depois abra na área de trabalho o Arduino IDE, limpe delete e cole dentro.
/**********************************************************************************
Updated sketch copied from YouTube by CT7API Manuel Ferreira.
Updated by Waldir Cardoso. 12/2025. https://projetosetransceptores.blogspot.com/
Blog: Projetos e Transceptores. Brazil.
This sketch will work with the Cobra 148 GTL, and equipment with 3 or 5 switches
for AM, LSB, USB. Modification to the sketch for FM, CW. Cobra 148 GTL-DX, SuperStar 3900.
***********************************************************************************/
//---------------------------------------------------------------------------------
// Function
// 1.VFO CLK0 34 Mhz AM LSB USB MODE
// 2.BFO CLK1 BFO FI 7.800 Khz AM LSB USB MODE
// 3.STEP(1MHz,100,10,1kHz,100,10,1Hz)
////////////////////////////////////////////////////////////////////////
//Libraries
#include <si5351.h> //https://github.com/etherkit/Si5351Arduino/releases/tag/v1.1.2
#include <Wire.h> //IDE Standard
#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
#include <Rotary.h> //Ben Buxton https://github.com/brianlow/Rotary
#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library
//----------------------------------------------------------------------------------------------------
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define F_MIN 100000000UL
#define F_MAX 16000000000UL
#define ENCODER_A 2
#define ENCODER_B 3
#define ENCODER_BTN 5
#define USB_PIN 6
#define LSB_PIN 7
#define AM_PIN 8
#define rx_tx 9
int lsbstate = 0;
int amstate = 0;
int usbstate = 0;
Si5351 si5351; //Si5351 I2C Address 0x60
Rotary r = Rotary(3, 2);
volatile int32_t AM = 780000000ULL;
volatile int32_t LSB = 779850000ULL; //LSB = IF - 1500Hz
volatile int32_t USB = 780150000ULL; //USB = IF + 1500Hz
volatile int32_t bfo = 780000000ULL; //Intermediary frequency IF
volatile int32_t vfo = 2696500000ULL / SI5351_FREQ_MULT; // frequency display initialization
volatile uint32_t radix = 10000; //start step size - change to suit
boolean changed_f = 0;
String tbfo = "";
bool sts = 0;
#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 Decrement */
/**************************************/
void set_frequency(short dir)
{
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;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(100, 1);
display.print(sts ? "TX" : "RX");
//display.print("TRX");
display.setCursor(3,1);
display.print("MODE:");
display.println(tbfo);
/**************************************/
/* Displays the frequency change step */
/**************************************/
//display.setCursor(60,1);
//display.print(F("ST:"));
display.setCursor(45,9);
display.print(F("STEP:"));
switch (radix)
{
case 1:
display.println(F(" 1 Hz"));
break;
case 10:
display.println(F(" 10 Hz"));
break;
case 100:
display.println(F(" 100 Hz"));
break;
case 1000:
display.println(F(" 1 kHz"));
break;
case 10000:
display.println(F(" 10 kHz"));
break;
case 100000:
display.println(F("100 kHz"));
break;
case 1000000:
display.println(F(" 1 MHz"));
break;
}
/**************************************/
/* Displays the frequency */
/**************************************/
display.setTextSize(2);
f = vfo / 1000000; //variable is now vfo instead of 'frequency'
if (f < 10)
display.print(' ');
display.print(f);
display.print('.');
f = (vfo % 1000000) / 1000;
if (f < 100)
display.print('0');
if (f < 10)
display.print('0');
display.print(f);
display.print('.');
f = vfo % 1000;
if (f < 100)
display.print('0');
if (f < 10)
display.print('0');
display.print(f);
display.display();
display.clearDisplay();
}
/**************************************/
/* S E T U P */
/**************************************/
void setup()
{
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.display();
pinMode(rx_tx, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(USB_PIN, INPUT_PULLUP);
pinMode(LSB_PIN, INPUT_PULLUP);
pinMode(AM_PIN, INPUT_PULLUP);
si5351.set_correction(18000); //**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, 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
//Serial.println((long)((vfo * SI5351_FREQ_MULT) - bfo) * -1);
si5351.set_freq(((vfo * SI5351_FREQ_MULT) + bfo), SI5351_PLL_FIXED, SI5351_CLK0);
volatile uint32_t vfoT =((vfo * SI5351_FREQ_MULT) - bfo);
tbfo = "AM";
// Set CLK1 to output bfo frequency
si5351.set_freq( bfo,0,SI5351_CLK1);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA);
#endif
Splash();
pinMode(ENCODER_BTN, INPUT_PULLUP);
PCICR |= (1 << PCIE2); // Enabled pin change interrupt for the encoder
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
display_frequency(); // Update the display
}
/**************************************/
/* L O O P */
/**************************************/
void loop()
{
// Update the display if the frequency has been changed
{ display_frequency();
#ifdef IF_Offset
//you can also subtract the bfo to suit your needs
//si5351.set_freq(((vfo * SI5351_FREQ_MULT) - bfo), SI5351_PLL_FIXED, SI5351_CLK0); // VFO subtrai á IF
si5351.set_freq(( vfo * SI5351_FREQ_MULT) + bfo, SI5351_PLL_FIXED, SI5351_CLK0); // VFO soma á IF
si5351.set_freq( bfo,0,SI5351_CLK1); // IF
si5351.output_enable(SI5351_CLK0, 1); // Enable CLK0 //1 - Enable / 0 - Disable CLK
si5351.output_enable(SI5351_CLK1, 1); // Enable CLK1
#endif
{
sts = digitalRead(rx_tx) == LOW;
}
usbstate = digitalRead(USB_PIN);
if (usbstate == LOW) {
//USB
bfo = USB;
tbfo = "USB";
}
amstate = digitalRead(AM_PIN);
if (amstate == LOW) {
//AM
bfo = AM;
tbfo = "AM";
}
lsbstate = digitalRead(LSB_PIN);
if (lsbstate == LOW) {
// LSB
bfo = LSB;
tbfo = "LSB";
}
}
// Button press changes the frequency change step for 1 Hz steps
if (get_button())
{
switch (radix)
{
case 1:
radix = 10;
break;
case 10:
radix = 100;
break;
case 100:
radix = 1000;
break;
case 1000:
radix = 10000;
break;
case 10000:
radix = 100000;
break;
case 100000:
radix = 1000000;
break;
case 1000000:
radix = 1;
break;
}
display_frequency();
}
}
void Splash() {
display.setTextSize(2);
display.setCursor(5, 1);
display.print("Cobra 148");
display.setCursor(45, 17);
display.print("GTL");
display.display();
delay(3000);
display.clearDisplay();
}
Copie e cole no Arduino IDE, o esboço que mais interessar, todos tem a mesma função em CLK0 e CLK1
Vamos ás fotos e esboço:
Este abaixo é como está nas fotos tem. Modo: AM, LSB, USB, ST: para STEP, frequência no meio e uma área livre em baixo do display, eu estava tentando adicionar um S/Meter embaixo, não conseguir, ficou para futuras modificações.
Esta é a foto do DDS com esboço abaixo para futuro S/Meter.
Vejam quando fui passar de 99Mhz, o último (0) zero ficou na parte de baixo, não dá para ele ir até 100Mhz, ou vai atrapalhar o S/Meter.
/**********************************************************************************
Updated sketch copied from YouTube by CT7API Manuel Ferreira.
Updated by Waldir Cardoso. 12/2025. https://projetosetransceptores.blogspot.com/
Blog: Projetos e Transceptores. Brazil.
This sketch will work with the Cobra 148 GTL, and equipment with 3 or 5 switches
for AM, LSB, USB. Modification to the sketch for FM, CW. Cobra 148 GTL-DX, SuperStar 3900.
***********************************************************************************/
//---------------------------------------------------------------------------------
// Function
// 1.VFO CLK0 34 Mhz AM LSB USB MODE
// 2.BFO CLK1 BFO FI 7.800 Khz AM LSB USB MODE
// 3.STEP(1MHz,100,10,1kHz,100,10,1Hz)
////////////////////////////////////////////////////////////////////////
//Libraries
#include <si5351.h> //https://github.com/etherkit/Si5351Arduino/releases/tag/v1.1.2
#include <Wire.h> //IDE Standard
#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
#include <Rotary.h> //Ben Buxton https://github.com/brianlow/Rotary
#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library
//----------------------------------------------------------------------------------------------------
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define F_MIN 100000000UL
#define F_MAX 16000000000UL
#define ENCODER_A 2
#define ENCODER_B 3
#define ENCODER_BTN 5
#define USB_PIN 6
#define LSB_PIN 7
#define AM_PIN 8
//#define rx_tx 9
#define PIN_S_METER_IN A3
int lsbstate = 0;
int amstate = 0;
int usbstate = 0;
Si5351 si5351; //Si5351 I2C Address 0x60
Rotary r = Rotary(3, 2);
volatile int32_t AM = 780000000ULL;
volatile int32_t LSB = 779850000ULL; //LSB = IF - 1500Hz
volatile int32_t USB = 780150000ULL; //USB = IF + 1500Hz
volatile int32_t bfo = 780000000ULL; //Intermediary frequency IF
volatile int32_t vfo = 2696500000ULL / SI5351_FREQ_MULT; // frequency display initialization
volatile uint32_t radix = 10000; //start step size - change to suit
boolean changed_f = 0;
String tbfo = "";
//bool sts = 0;
#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 Decrement */
/**************************************/
void set_frequency(short dir)
{
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;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
//display.setCursor(100, 1);
//display.print(sts ? "TX" : "RX");
//display.print("TRX");
display.setCursor(3,1);
display.print("MODE:");
display.println(tbfo);
/**************************************/
/* Displays the frequency change step */
/**************************************/
display.setCursor(60,1);
display.print(F("ST:"));
//display.setCursor(45,9);
//display.print(F("STEP:"));
switch (radix)
{
case 1:
display.println(F(" 1 Hz"));
break;
case 10:
display.println(F(" 10 Hz"));
break;
case 100:
display.println(F(" 100 Hz"));
break;
case 1000:
display.println(F(" 1 kHz"));
break;
case 10000:
display.println(F(" 10 kHz"));
break;
case 100000:
display.println(F("100 kHz"));
break;
case 1000000:
display.println(F(" 1 MHz"));
break;
}
/**************************************/
/* Displays the frequency */
/**************************************/
display.setTextSize(2);
f = vfo / 1000000; //variable is now vfo instead of 'frequency'
if (f < 10)
display.print(' ');
display.print(f);
display.print('.');
f = (vfo % 1000000) / 1000;
if (f < 100)
display.print('0');
if (f < 10)
display.print('0');
display.print(f);
display.print('.');
f = vfo % 1000;
if (f < 100)
display.print('0');
if (f < 10)
display.print('0');
display.print(f);
display.display();
display.clearDisplay();
}
/**************************************/
/* S E T U P */
/**************************************/
void setup()
{
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.display();
//pinMode(rx_tx, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(USB_PIN, INPUT_PULLUP);
pinMode(LSB_PIN, INPUT_PULLUP);
pinMode(AM_PIN, INPUT_PULLUP);
si5351.set_correction(18000); //**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, 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
//Serial.println((long)((vfo * SI5351_FREQ_MULT) - bfo) * -1);
si5351.set_freq(((vfo * SI5351_FREQ_MULT) + bfo), SI5351_PLL_FIXED, SI5351_CLK0);
volatile uint32_t vfoT =((vfo * SI5351_FREQ_MULT) - bfo);
tbfo = "AM";
// Set CLK1 to output bfo frequency
si5351.set_freq( bfo,0,SI5351_CLK1);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA);
#endif
Splash();
pinMode(ENCODER_BTN, INPUT_PULLUP);
PCICR |= (1 << PCIE2); // Enabled pin change interrupt for the encoder
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
display_frequency(); // Update the display
}
/**************************************/
/* L O O P */
/**************************************/
void loop()
{
// Update the display if the frequency has been changed
{ display_frequency();
#ifdef IF_Offset
//you can also subtract the bfo to suit your needs
//si5351.set_freq(((vfo * SI5351_FREQ_MULT) - bfo), SI5351_PLL_FIXED, SI5351_CLK0); // VFO subtrai á IF
si5351.set_freq(( vfo * SI5351_FREQ_MULT) + bfo, SI5351_PLL_FIXED, SI5351_CLK0); // VFO soma á IF
si5351.set_freq( bfo,0,SI5351_CLK1); // IF
si5351.output_enable(SI5351_CLK0, 1); // Enable CLK0 //1 - Enable / 0 - Disable CLK
si5351.output_enable(SI5351_CLK1, 1); // Enable CLK1
#endif
//{
//sts = digitalRead(rx_tx) == LOW;
//}
usbstate = digitalRead(USB_PIN);
if (usbstate == LOW) {
//USB
bfo = USB;
tbfo = "USB";
}
amstate = digitalRead(AM_PIN);
if (amstate == LOW) {
//AM
bfo = AM;
tbfo = "AM";
}
lsbstate = digitalRead(LSB_PIN);
if (lsbstate == LOW) {
// LSB
bfo = LSB;
tbfo = "LSB";
}
}
// Button press changes the frequency change step for 1 Hz steps
if (get_button())
{
switch (radix)
{
case 1:
radix = 10;
break;
case 10:
radix = 100;
break;
case 100:
radix = 1000;
break;
case 1000:
radix = 10000;
break;
case 10000:
radix = 100000;
break;
case 100000:
radix = 1000000;
break;
case 1000000:
radix = 1;
break;
}
display_frequency();
}
}
void Splash() {
display.setTextSize(2);
display.setCursor(5, 1);
display.print("Cobra 148");
display.setCursor(45, 17);
display.print("GTL");
display.display();
delay(3000);
display.clearDisplay();
}




Nenhum comentário:
Postar um comentário
Façam seus comentários com experiências no projeto. Ou de sua opinião.