Vocês, que curte e gosta dos projetos do blog, por gentileza olhem às propagandas e click para maiores detalhes no que interessar, desta forma vocês estarão ajudando o blog. Muito obrigado por acessar e ajudar o blog, conto com vocês muito agradecido.
Olá, publico mais dois esboços ou programas modificados e em vídeo, desta vez é do site Circuit Secrets em vídeos no YouTube sobre este simples DDS VFO para transceptores PX CB, AM, FM. Para quem tem um velho Walkie Talkie com cristais, o TX sempre é na frequência do canal, o RX a maioria sempre está - 455 Khz abaixo, para os transceptores com PLL ou montado por você, corrija ás linhas de comando do programa para - e + ou + e - FI em CLK0 e CLK1. Vocês vão definir no programa como será o DDS VFO para o transceptor, tem também a chave de RX e TX, que vocês poderão montar uma chave eletrônica com transistor e colocar no próprio PTT do transceptor. Este simples DDS VFO vai de 24.205 Mhz a 29.705 Mhz, com os dígitos e canais RC controle remoto ou telecomandos, no display T1, T2, T3, T4, T5, segue em sequência sempre de 10 em 10 Khz para cada canal de PX CB, porem os dígitos canal 23 mostra frequência de 27.235 Mhz quando o correto pelo código internacional FCC e adotado aqui no Brasil é canal 23 frequência 27.255 Mhz. Ou seja a frequência do canal 25, 27.255 Mhz seria no canal 23 = 27.255 Mhz, essa divergência chegou ao Brasil nos anos 80, com o CCE 500/60 tenho um até hoje, este transceptor não tem esta modificação entre os canais 23 e 25, ou seja ele vai do canal 1 ao 60, só saltando os canais RC, telecomandos, sempre de 10 em 10 Khz até o canal 60. Por isso eu coloquei o DDS VFO até o canal 85 = 27.855 Mhz, sem entrar nas discursões dos canais, vocês vão ter ás referências que estão nas frequências liberadas pela ANATEL. Este simples DDS VFO não tem os modos LSB, USB, só podemos usar modos AM ou FM, isso porque não tem os steps de 1Hz, 10Hz, 100Hz, 10Khz, 100Khz, não podemos clarificar a voz ou variar a frequência em Hz, não tem o deslocamento LSB - 1.500Hz, e USB +1.500Hz em VFO CLK0 Por estes motivos não podemos instalar em transceptores SSB.
Vejam nos comentários deste vídeo que eu solicitei os modos AM, SSB, também o display só mostrava até o canal 39. Vejam a resposta do autor no mesmo vídeo. Então partir para mais uma simples modificação no esboço que ficasse como eu queria.
Bem realmente não está como queria, pois eu tentei colocar os modos LSB, USB, mas não tive êxito, perdi muito tempo e só dava erros, como sempre digo, não sou um programador, e sim um aprendiz em modificações. Faltou-me sabedoria do código C++ que é muito complicado, não é o inglês, mas sim ás linhas de comandos das variáveis, void setup e void loop.
Vejam ás fotos com os programas abaixo, para nossos projetos de Walkie Talkie, transceptores AM, FM etc.
Em círculos vermelhos são ás bibliotecas usadas nos programas, a biblioteca Wire.h já está no Arduino IDE. Não instale muitas bibliotecas pois poderá acontecer conflitos entre elas e isso dará erros no esboço. Não deixe o Arduino IDE atualizar bibliotecas, ou remova para outra pasta ás que forem instaladas pelo próprio Arduino IDE. Para reinstalar coloque elas em .ZIP e instale em arquivo .ZIP.
Inicialização sem o Circuit Secret digitei este, ocupa menos espaço no programa.
Coloquei até canal 85 frequencia 27.855 Mhz.
Este é o primeiro canal telecomando RC.
Frequência que mostra no display canal 23 também está no Frequencímetro.
Deveria ser 27.255 Mhz.
Frequência CLK0 RX. Canal 1 = 26.965 Mhz.
Frequência CLK0 TX. Canal 1 26.965 Mhz - 455Khz = 26.510 Mhz.
Coloquei a chave TX no Encoder mas está errado.
Vejam que em CLK1 RX temos a mesma frequência de CLK0 porem TX temos + 455Khz.
Frequência RX CLK1.
CLK1 TX 26.965 + 455 Khz = 27.420 Mhz.
Frequência TX CLK1.
Pessoal façam alterações nas linhas se desejar Offset outras FIs, + ou - TX, + ou - RX, em CLK0 ou CLK1.
Estas linhas 51 a 55, vocês poderão alterar para ter Offset IF em RX ou TX e calibrar frequência do si5351.
//Some radios use a local 10.240mhz oscilator and the offset if it is simply mixed with the other local oscilator
//would be -10240000
unsigned long long txOffset=45500; //Enter your IF frequency, ex: 45500 = 455kHz, 1070000 = 10.7MHz, 0 = to direct convert receiver or RF generator, + will add and - will subtract IF offfset.
unsigned long long rxOffset=0; //Enter your IF frequency
long int calibration=18000; //This is used to callibrate the si5351.
Estas linhas 265 a 269, vocês poderão alterar para frequência inicialização BFO FI CLK1.
//VFO and BFO frequency initialization
unsigned long long tempchannelho=i;
vfofrequency=26955000+(tempchannelho*10000ULL); // VFO CLK0 initialization frequency
//bfofrequency=34755000+(tempchannelho*10000ULL); // BFO CLK1 initialization frequency
//bfofrequency=34300000+(tempchannelho*10000ULL);
Estas linhas de 291 a 294 vocês poderão definir TX Offset + ou - para VFO ou BFO.
si5351.set_freq((vfofrequency-txOffset*10ull)*100ull, SI5351_CLK0); // VFO RX frequency initialization, TX frequency - FI
si5351.set_freq((vfofrequency+txOffset*10ull)*100ull, SI5351_CLK1); // VFO RX frequency initialization, TX frequency + FI
//si5351.set_freq((bfofrequency-txOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((bfofrequency+txOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency + FI
}
Estas linhas de 303 a 306 vocês poderão definir RX Offset + ou - para VFO ou BFO.
si5351.set_freq((vfofrequency+rxOffset*10ull)*100ull, SI5351_CLK0); // VFO RX frequency initialization, TX frequency - FI
si5351.set_freq((vfofrequency-rxOffset*10ull)*100ull, SI5351_CLK1); // VFO RX frequency initialization, TX frequency + FI
//si5351.set_freq((bfofrequency+rxOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((bfofrequency-rxOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency + FI
}
Abaixo o programa algoritmo que fiz ás simples modificações para nossos projetos RTX em AM ou FM.
Selecione e copie todo programa esboço, abra o seu Arduino IDE na área de trabalho, limpe tudo e cole, vá em Arquivo depois Salvar como, renomeei o esboço e escolha a pasta a ser salvo.
Copie abaixo.
/* //Arduino pro mini based export VFO designed for repairing and upgrading old AM/FM C.B. radios.
//It is also a great visual upgrade with the modern styling of a multi colored Oled display.
//This sketch brought to you free of charge by circuit secrets
// ##### ### ###### ##### # # ### #######
// # # # # # # # # # # #
// # # # # # # # # #
// # # ###### # # # # #
// # # # # # # # # #
// # # # # # # # # # # #
// ##### ### # # ##### ##### ### #
// ##### ####### ##### ###### ####### ####### #####
// # # # # # # # # # # #
// # # # # # # # #
// ##### ##### # ###### ##### # #####
// # # # # # # # #
// # # # # # # # # # # #
// ##### ####### ##### # # ####### # #####
//If you find this useful please visit our youtube and subscribe for more youtube/circuitsecrets
//You may use this sketch at your own risk, we are not responsible for damages from use of this sketch.
//We make no claims to the quality of this sketch and it is intended to be for educational use only.
//You may distribute and modify this in any way you wish for free or comercially.
//We only ask that you reference the original producer and distributor circuit secrets.
//visit our website for more sketches, designs, schematics and diagrams..circuitsecrets.com//
*/
//----------------------------------------------------------------------------------------------------------------
// Modified sketch for home-made or commercial transceivers,
// Walkie Talkies, direct conversion superheterodyne or double conversion
// by Waldir Cardoso. Blog: https://projetosetransceptores.blogspot.com/ 2025/09/25.
//--------------------------------------------------------------------
// Function.
// 1.RX TX Key
// 2.VFO (CLK0) 85 Channel CB. + 5 channels RC display
// 3.VFO (CLK0) Frequency 24.205 Mhz to 29.705 Mhz
// 4.STEP(10khz) Channel CB
// 5.BFO (CLK1) RX = 26.965 Mhz initialization, TX 26.965 Mhz + (IF)
// 6 VFO (CLK0) RX = 26.965 Mhz initialization, TX 26.965 Mhz - (IF)
// 7.IF with Intermediate Frequency (IF) offset
//wire library for i2c
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include "si5351.h"
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display1(128, 64, &Wire, -1);
//variable to hold the desired frequency information for the si5351
unsigned long long vfofrequency=2696500000; // frequency display initialization
//unsigned long long bfofrequency=0;
//Some radios use a local 10.240mhz oscilator and the offset if it is simply mixed with the other local oscilator
//would be -10240000
unsigned long long txOffset=45500; //Enter your IF frequency, ex: 45500 = 455kHz, 1070000 = 10.7MHz, 0 = to direct convert receiver or RF generator, + will add and - will subtract IF offfset.
unsigned long long rxOffset=0; //Enter your IF frequency
long int calibration=18000; //This is used to callibrate the si5351.
//this holds the transmit and recieve state for switching the offset for the VFO
bool transmit=false;
//This is simple latching so when a channel button is pressed it only changes one channel before being released.
// bool channelLatch1=false;
// bool channelLatch2=false;
//bool menuLatch=false;
//variables used for menu control
//int menuItem=1;
//int modeSelector=0;
bool selectItem=false;
int grey=0;
int greyold=0;
int temp1=0;
int temp2=0;
//create instance of si5351
Si5351 si5351;
//variable to keep track of what channel we are on
int channel=1;
/*
//the dimensions of the splash screen bmp
#define LOGO_HEIGHT 64
#define LOGO_WIDTH 88
the splash screen bmp
static const unsigned char PROGMEM logo_bmp[] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xe0, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xea, 0xff, 0x0f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x1d, 0xac, 0x7f, 0xc3, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x79, 0xae, 0x7f, 0xf8, 0xc4,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x88, 0xb7, 0xff, 0xfc, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe7, 0xae, 0xff, 0xff, 0xfe, 0x3e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x8f, 0x00, 0x07, 0xf8,
0xe3, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x38, 0x78, 0x3f, 0x20, 0xf3, 0xed, 0xbf, 0xff, 0xff, 0xff,
0xfe, 0x6c, 0x63, 0xfe, 0xfc, 0x07, 0x07, 0x9f, 0xff, 0xff, 0xff, 0xfc, 0xc4, 0x8f, 0xfb, 0xff,
0x1c, 0x01, 0xcf, 0xff, 0xff, 0xff, 0xf9, 0x37, 0x3f, 0xf7, 0xfe, 0x38, 0x30, 0x6f, 0xff, 0xff,
0xff, 0xfb, 0xf4, 0x7f, 0xdf, 0xfc, 0xe0, 0x18, 0x27, 0xff, 0xff, 0xff, 0xf3, 0x79, 0xff, 0xbf,
0xf1, 0xc4, 0x9e, 0x33, 0xff, 0xff, 0xff, 0xe5, 0x13, 0xd6, 0xff, 0xe7, 0xe7, 0xcf, 0x9b, 0xff,
0xff, 0xff, 0xc8, 0xe7, 0xfd, 0xff, 0x8e, 0x32, 0xc6, 0xd9, 0xff, 0xff, 0xff, 0xdc, 0x4f, 0xbf,
0xfe, 0x38, 0x10, 0xe6, 0x19, 0xff, 0xff, 0xff, 0x9e, 0x9f, 0xfd, 0xfc, 0x74, 0x18, 0x73, 0x71,
0xff, 0xff, 0xff, 0xa7, 0xbf, 0xbf, 0xf1, 0xe2, 0x4c, 0xf1, 0xc7, 0xff, 0xff, 0xff, 0x31, 0x3f,
0x6b, 0xe7, 0xcd, 0x0c, 0x5b, 0x8f, 0xff, 0xff, 0xff, 0x5e, 0x7d, 0xff, 0x8e, 0x2f, 0x06, 0x0e,
0x1f, 0xff, 0xff, 0xfe, 0x4a, 0x7b, 0xfe, 0x3c, 0xa7, 0x93, 0x1c, 0xdf, 0xff, 0xff, 0xfe, 0x44,
0xef, 0xfc, 0x74, 0x63, 0xc8, 0x31, 0xcf, 0xff, 0xff, 0xfe, 0xf4, 0xdf, 0xf9, 0xe2, 0x73, 0xc1,
0xe7, 0xcf, 0xff, 0xff, 0xfe, 0xfc, 0x7f, 0xe3, 0xcb, 0x19, 0xe3, 0x87, 0xcf, 0xff, 0xff, 0xfc,
0xf8, 0xff, 0xcf, 0xef, 0x08, 0xa7, 0x27, 0xcf, 0xff, 0xff, 0xfc, 0xf9, 0xff, 0x1c, 0xe1, 0x9c,
0x3c, 0x67, 0xef, 0xff, 0xff, 0xfd, 0xfb, 0xfc, 0x70, 0x70, 0xcb, 0x39, 0xe7, 0xef, 0xff, 0xff,
0xfd, 0xfb, 0xf9, 0xe0, 0xf8, 0x49, 0xe3, 0xf7, 0xef, 0xff, 0xff, 0xfd, 0xfb, 0xe3, 0xc8, 0x7c,
0x21, 0xcf, 0xe7, 0xef, 0xff, 0xff, 0xfd, 0xfb, 0xc7, 0x4a, 0x7f, 0xa7, 0x1f, 0xe7, 0xcf, 0xff,
0xff, 0xf9, 0xfb, 0x1f, 0x67, 0x3d, 0xbc, 0x7f, 0xe7, 0xcf, 0xff, 0xff, 0xf9, 0xfa, 0x39, 0xa3,
0x3e, 0x38, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xfd, 0xf8, 0xe0, 0xf3, 0x9f, 0xe3, 0xff, 0xef, 0xcf,
0xff, 0xff, 0xfd, 0xf3, 0xc4, 0xf9, 0xcf, 0xcf, 0xff, 0xef, 0xdf, 0xff, 0xff, 0xfd, 0xc7, 0xda,
0x68, 0xc7, 0x1f, 0xff, 0xcf, 0xdf, 0xff, 0xff, 0xfd, 0x1c, 0xce, 0x3c, 0xce, 0x7f, 0xff, 0xcf,
0x9f, 0xff, 0xff, 0xfc, 0x38, 0x4f, 0x36, 0x78, 0xff, 0x9f, 0x97, 0x9f, 0xff, 0xff, 0xfc, 0xf0,
0x27, 0x9e, 0x73, 0xff, 0xbf, 0x9d, 0xbf, 0xff, 0xff, 0xf1, 0xc9, 0x23, 0x8b, 0xc7, 0xfc, 0xff,
0x31, 0x3f, 0xff, 0xff, 0xe7, 0x8c, 0x33, 0xc3, 0x9f, 0xdd, 0xff, 0x3b, 0x7f, 0xff, 0xff, 0x8e,
0x24, 0x19, 0xfe, 0x3f, 0xcf, 0xfe, 0x46, 0x7f, 0xff, 0xff, 0xdc, 0xa6, 0x09, 0xbc, 0xfe, 0x8b,
0xfe, 0xc2, 0xff, 0xff, 0xff, 0xcc, 0xd3, 0x26, 0x71, 0xfd, 0xbf, 0xfc, 0xbc, 0xff, 0xff, 0xff,
0xe6, 0x79, 0x03, 0xc7, 0xfd, 0x9f, 0xf9, 0x99, 0xff, 0xff, 0xff, 0xf6, 0x79, 0x83, 0x9f, 0xfc,
0xbf, 0xf2, 0x49, 0xff, 0xff, 0xff, 0xf3, 0x3c, 0xce, 0x3f, 0xfe, 0xff, 0xe6, 0x73, 0xff, 0xff,
0xff, 0xf9, 0x1c, 0x5c, 0xff, 0xff, 0xff, 0x8c, 0x27, 0xff, 0xff, 0xff, 0xf9, 0x9a, 0x71, 0xff,
0xff, 0xff, 0x3e, 0x4f, 0xff, 0xff, 0xff, 0xfc, 0xcb, 0xe0, 0x7d, 0xf7, 0xfc, 0x73, 0x9f, 0xff,
0xff, 0xff, 0xfe, 0xe3, 0x8e, 0x1f, 0xff, 0xf1, 0xb1, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x3f,
0x83, 0xff, 0x86, 0x16, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x3c, 0x7f, 0xf0, 0x00, 0x3f, 0x0c, 0xff,
0xff, 0xff, 0xff, 0xff, 0x90, 0x3f, 0xff, 0xc7, 0xd3, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83,
0x1f, 0xff, 0xd8, 0x80, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xc7, 0xff, 0xc0, 0xa0, 0x8f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xc8, 0x0e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8, 0x7f, 0x98, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0x03,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
*/
//--------------void setup --------------------------------------------------------------------------------
void setup() {
//encoder pin function
pinMode(13,INPUT_PULLUP);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
// Enable interupts on port C
PCICR |= B00000010;
// Select PCINT pins 0 and 1 of port C a0 and a1
PCMSK1 |= B00000011;
delay(200);
// put your setup code here, to run once:
if(!display1.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
//if it cannot start stop the program
for(;;);
}
//clear the display buffer
//display1.clearDisplay();
//call the drawlogo function
//drawlogo();
//delay to show off the logo before starting the main program
//delay(3000);
display1.clearDisplay();
//set the text size
display1.setTextSize(2);
// Set the text color, the 1306 only supports white
display1.setTextColor(WHITE);
// Set the curser at the top left position
display1.println("");
display1.print(" Walkie ");
display1.print("Talkie");
display1.display();
delay(3000);
//PrintTextToDisplay();
//initialize the si5351, setting the oscilator load to the default, no refference frequency, no frequency correction
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, calibration);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); //Output current 2MA, 4MA, 6MA or 8MA
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA); //Output current 2MA, 4MA, 6MA or 8MA
}
//------------- void loop-------------------------------------------------------------------------------------------------
void loop(){
//call the display and frequency calculation function
displayChannelAndFrequency(channel);
//read pin 13 to check for tx pin to be grounded
if(digitalRead(13)==LOW){
//set the transmit state to true
tx();
//set the transmit state to false when the pin is high
}else rx();
//buttonState=encoderlogic();
//Limit the channel range to typical export range
if(channel>275){
channel=-275;
}
//Limit the channel range to typical export range
if(channel<-275){
channel=275;
}
}
/*
//function to draw the logo to the screen
void drawlogo(void) {
clear the display buffer
display1.clearDisplay();
drawBitmap method is called with the desired center position of the image
the name of the image and the image size
this draws the bitmap to the buffer
display1.drawBitmap(
(display1.width() - LOGO_WIDTH ) / 2,
(display1.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
the contents of the buffer are displayed.
display1.display();
}
*/
//function to display the vfo text takes the channel number as an argument
void displayChannelAndFrequency(int i){
//we create a string and initialize it to the frequency for channel 1
String frequency="26.965";
int tempchannel=0;
//we create a switch to set the string to the corrosponding frequency of the selected channel
//organize frequency to channel display
tempchannel=i;
if(i>3){
tempchannel--;
}
if(i>8){
tempchannel--;
}
if(i>13){
tempchannel--;
}
if(i>18){
tempchannel--;
}
if(i>23){
tempchannel--;
}
//This code does all of the formating of the text
//clear the buffer
display1.clearDisplay();
//set the text size
display1.setTextSize(2);
// Set the text color, the 1306 only supports white
display1.setTextColor(WHITE);
// Set the curser at the top left position
display1.println(" ");
if (i>0&i<91){
display1.setCursor(0,0);
// Print CH to the display
display1.println("CANAL");
//set the cursor next to the CH text at the top
display1.setCursor(70,0);
// print the channel number
display1.println(tempchannel);
display1.setCursor(95,0);
// print the channel number
if(i==4){
display1.println("T1");}
if(i==9){
display1.println("T2");}
if(i==14){
display1.println("T3");}
if(i==19){
display1.println("T4");}
if(i==24){
display1.println("T5");}
}
//VFO and BFO frequency initialization
unsigned long long tempchannelho=i;
vfofrequency=26955000+(tempchannelho*10000ULL); // VFO CLK0 initialization frequency
//bfofrequency=34755000+(tempchannelho*10000ULL); // BFO CLK1 initialization frequency
//bfofrequency=34300000+(tempchannelho*10000ULL);
//display1.clearDisplay();
display1.setTextColor(WHITE);
//set the text size
display1.setTextSize(2);
display1.setCursor(0,25);
// Set the text color, the 1306 only supports white
float tempvfoval=vfofrequency;
float displayvalue=tempvfoval/1000000;
// print the frequency to the display
//display1.println("test");
display1.print(displayvalue, 3);
display1.println(".Mhz");
display1.display();
}
//function to handle the TX state
void tx(void){
// Set CLK0 to output frequency. We multiply our frequenzy by 100 unsigned unsigned long because the frequency is set in
//100ths of hertz not hertz. We set the clock 0
//we subtract the tx local oscilator value for the mixer
si5351.set_freq((vfofrequency-txOffset*10ull)*100ull, SI5351_CLK0); // VFO RX frequency initialization, TX frequency - FI
si5351.set_freq((vfofrequency+txOffset*10ull)*100ull, SI5351_CLK1); // VFO RX frequency initialization, TX frequency + FI
//si5351.set_freq((bfofrequency-txOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((bfofrequency+txOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency + FI
}
//function to handle the RX state
void rx(void){
//Set CLK0 to output frequency. We multiply our frequenzy by 100 unsigned unsigned long because the frequency is set in
//100ths of hertz not hertz. We set the clock 0
//we subtract the tx local oscilator value for the mixer
si5351.set_freq((vfofrequency+rxOffset*10ull)*100ull, SI5351_CLK0); // VFO RX frequency initialization, TX frequency - FI
si5351.set_freq((vfofrequency-rxOffset*10ull)*100ull, SI5351_CLK1); // VFO RX frequency initialization, TX frequency + FI
//si5351.set_freq((bfofrequency+rxOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((bfofrequency-rxOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency + FI
}
//Interupt service routine this is used to read the encoder state when the interupt is triggered
ISR (PCINT1_vect){
//int clickdetect=0;
if(digitalRead(A0)==LOW){
temp1=0;}else temp1=1;
if(digitalRead(A1)==LOW){
temp2=0;}else temp2=2;
grey=temp1+temp2;
if(grey==0){
if(greyold==1){
channel--;
}
if(greyold==2){
channel++;
}
}
if(grey!=greyold){
}
greyold=grey;
//return clickdetect;
}
Abaixo fotos e esboço ou programa coloquei em CLK1 em RX frequência de 34.765 Mhz, e TX - 455 = 34.310 Mhz, só para vocês terem uma noção o FI Offset será a mesma de 455 Khz ou que vocês digitarem no programa para CLK0 e CLK1, este esboço não serve para o Cobra 148 GTL ou transceptores SSB.
Vejam que permanece em CLK0 RX 26.965 Mhz, e TX FI - 455Khz.
Vejam em TX CLK0 - 455 Khz = 26.510 Mhz.
Vejam que em CLK1 digitei a frequência de 34.765 canal 1.
Vejam em TX CLK1 é - 455 Khz 34.310 Mhz.
Abaixo é o esboço algoritmo que fiz ás simples modificações para nossos projetos RTX em AM ou FM.
Selecione e copie todo programa esboço, abra o seu Arduino IDE na área de trabalho, limpe tudo e cole, vá em Arquivo depois Salvar como, renomeei o esboço e escolha a pasta a ser salvo.
Copie abaixo.
/* //Arduino pro mini based export VFO designed for repairing and upgrading old AM/FM C.B. radios.
//It is also a great visual upgrade with the modern styling of a multi colored Oled display.
//This sketch brought to you free of charge by circuit secrets
// ##### ### ###### ##### # # ### #######
// # # # # # # # # # # #
// # # # # # # # # #
// # # ###### # # # # #
// # # # # # # # # #
// # # # # # # # # # # #
// ##### ### # # ##### ##### ### #
// ##### ####### ##### ###### ####### ####### #####
// # # # # # # # # # # #
// # # # # # # # #
// ##### ##### # ###### ##### # #####
// # # # # # # # #
// # # # # # # # # # # #
// ##### ####### ##### # # ####### # #####
//If you find this useful please visit our youtube and subscribe for more youtube/circuitsecrets
//You may use this sketch at your own risk, we are not responsible for damages from use of this sketch.
//We make no claims to the quality of this sketch and it is intended to be for educational use only.
//You may distribute and modify this in any way you wish for free or comercially.
//We only ask that you reference the original producer and distributor circuit secrets.
//visit our website for more sketches, designs, schematics and diagrams..circuitsecrets.com//
*/
//--------------------------------------------------------------------------------------------
// Modified sketch for home-made or commercial transceivers,
// Walkie Talkies, direct conversion superheterodyne or double conversion
// by Waldir Cardoso. 2025/09/25.
// Blog: https://projetosetransceptores.blogspot.com/
//--------------------------------------------------------------------------------------------
// Function.
// 1.RX TX Key
// 2.VFO (CLK0) 85 Channel CB + 5 channels RC display
// 3.VFO (CLK0) Frequency 24.205 Mhz to 29.705 Mhz
// 4.STEP(10khz) Channel CB
// 5.BFO (CLK1) RX = 34.765 Mhz initialization, TX 34.765 Mhz - (IF)
// 6.VFO (CLK0) RX = 26.965 Mhz initialization, TX 26.965 Mhz - (IF)
// 6.IF with Intermediate Frequency (IF) offset
//wire library for i2c
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include "si5351.h"
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display1(128, 64, &Wire, -1);
//variable to hold the desired frequency information for the si5351
unsigned long long vfofrequency=2696500000; // frequency display initialization
unsigned long long bfofrequency=0;
//Some radios use a local 10.240mhz oscilator and the offset if it is simply mixed with the other local oscilator
//would be -10240000
unsigned long long txOffset=45500; //Enter your IF frequency, ex: 45500 = 455kHz, 1070000 = 10.7MHz, 0 = to direct convert receiver or RF generator, + will add and - will subtract IF offfset.
unsigned long long rxOffset=0; //Enter your IF frequency
long int calibration=18000; //This is used to callibrate the si5351.
//this holds the transmit and recieve state for switching the offset for the VFO
bool transmit=false;
//This is simple latching so when a channel button is pressed it only changes one channel before being released.
//bool channelLatch1=false;
//bool channelLatch2=false;
//bool menuLatch=false;
///variables used for menu control
//int menuItem=1;
//int modeSelector=0;
bool selectItem=false;
int grey=0;
int greyold=0;
int temp1=0;
int temp2=0;
//create instance of si5351
Si5351 si5351;
//variable to keep track of what channel we are on
int channel=1;
/*
//the dimensions of the splash screen bmp
#define LOGO_HEIGHT 64
#define LOGO_WIDTH 88
the splash screen bmp
static const unsigned char PROGMEM logo_bmp[] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xe0, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xea, 0xff, 0x0f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x1d, 0xac, 0x7f, 0xc3, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x79, 0xae, 0x7f, 0xf8, 0xc4,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x88, 0xb7, 0xff, 0xfc, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe7, 0xae, 0xff, 0xff, 0xfe, 0x3e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x8f, 0x00, 0x07, 0xf8,
0xe3, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x38, 0x78, 0x3f, 0x20, 0xf3, 0xed, 0xbf, 0xff, 0xff, 0xff,
0xfe, 0x6c, 0x63, 0xfe, 0xfc, 0x07, 0x07, 0x9f, 0xff, 0xff, 0xff, 0xfc, 0xc4, 0x8f, 0xfb, 0xff,
0x1c, 0x01, 0xcf, 0xff, 0xff, 0xff, 0xf9, 0x37, 0x3f, 0xf7, 0xfe, 0x38, 0x30, 0x6f, 0xff, 0xff,
0xff, 0xfb, 0xf4, 0x7f, 0xdf, 0xfc, 0xe0, 0x18, 0x27, 0xff, 0xff, 0xff, 0xf3, 0x79, 0xff, 0xbf,
0xf1, 0xc4, 0x9e, 0x33, 0xff, 0xff, 0xff, 0xe5, 0x13, 0xd6, 0xff, 0xe7, 0xe7, 0xcf, 0x9b, 0xff,
0xff, 0xff, 0xc8, 0xe7, 0xfd, 0xff, 0x8e, 0x32, 0xc6, 0xd9, 0xff, 0xff, 0xff, 0xdc, 0x4f, 0xbf,
0xfe, 0x38, 0x10, 0xe6, 0x19, 0xff, 0xff, 0xff, 0x9e, 0x9f, 0xfd, 0xfc, 0x74, 0x18, 0x73, 0x71,
0xff, 0xff, 0xff, 0xa7, 0xbf, 0xbf, 0xf1, 0xe2, 0x4c, 0xf1, 0xc7, 0xff, 0xff, 0xff, 0x31, 0x3f,
0x6b, 0xe7, 0xcd, 0x0c, 0x5b, 0x8f, 0xff, 0xff, 0xff, 0x5e, 0x7d, 0xff, 0x8e, 0x2f, 0x06, 0x0e,
0x1f, 0xff, 0xff, 0xfe, 0x4a, 0x7b, 0xfe, 0x3c, 0xa7, 0x93, 0x1c, 0xdf, 0xff, 0xff, 0xfe, 0x44,
0xef, 0xfc, 0x74, 0x63, 0xc8, 0x31, 0xcf, 0xff, 0xff, 0xfe, 0xf4, 0xdf, 0xf9, 0xe2, 0x73, 0xc1,
0xe7, 0xcf, 0xff, 0xff, 0xfe, 0xfc, 0x7f, 0xe3, 0xcb, 0x19, 0xe3, 0x87, 0xcf, 0xff, 0xff, 0xfc,
0xf8, 0xff, 0xcf, 0xef, 0x08, 0xa7, 0x27, 0xcf, 0xff, 0xff, 0xfc, 0xf9, 0xff, 0x1c, 0xe1, 0x9c,
0x3c, 0x67, 0xef, 0xff, 0xff, 0xfd, 0xfb, 0xfc, 0x70, 0x70, 0xcb, 0x39, 0xe7, 0xef, 0xff, 0xff,
0xfd, 0xfb, 0xf9, 0xe0, 0xf8, 0x49, 0xe3, 0xf7, 0xef, 0xff, 0xff, 0xfd, 0xfb, 0xe3, 0xc8, 0x7c,
0x21, 0xcf, 0xe7, 0xef, 0xff, 0xff, 0xfd, 0xfb, 0xc7, 0x4a, 0x7f, 0xa7, 0x1f, 0xe7, 0xcf, 0xff,
0xff, 0xf9, 0xfb, 0x1f, 0x67, 0x3d, 0xbc, 0x7f, 0xe7, 0xcf, 0xff, 0xff, 0xf9, 0xfa, 0x39, 0xa3,
0x3e, 0x38, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xfd, 0xf8, 0xe0, 0xf3, 0x9f, 0xe3, 0xff, 0xef, 0xcf,
0xff, 0xff, 0xfd, 0xf3, 0xc4, 0xf9, 0xcf, 0xcf, 0xff, 0xef, 0xdf, 0xff, 0xff, 0xfd, 0xc7, 0xda,
0x68, 0xc7, 0x1f, 0xff, 0xcf, 0xdf, 0xff, 0xff, 0xfd, 0x1c, 0xce, 0x3c, 0xce, 0x7f, 0xff, 0xcf,
0x9f, 0xff, 0xff, 0xfc, 0x38, 0x4f, 0x36, 0x78, 0xff, 0x9f, 0x97, 0x9f, 0xff, 0xff, 0xfc, 0xf0,
0x27, 0x9e, 0x73, 0xff, 0xbf, 0x9d, 0xbf, 0xff, 0xff, 0xf1, 0xc9, 0x23, 0x8b, 0xc7, 0xfc, 0xff,
0x31, 0x3f, 0xff, 0xff, 0xe7, 0x8c, 0x33, 0xc3, 0x9f, 0xdd, 0xff, 0x3b, 0x7f, 0xff, 0xff, 0x8e,
0x24, 0x19, 0xfe, 0x3f, 0xcf, 0xfe, 0x46, 0x7f, 0xff, 0xff, 0xdc, 0xa6, 0x09, 0xbc, 0xfe, 0x8b,
0xfe, 0xc2, 0xff, 0xff, 0xff, 0xcc, 0xd3, 0x26, 0x71, 0xfd, 0xbf, 0xfc, 0xbc, 0xff, 0xff, 0xff,
0xe6, 0x79, 0x03, 0xc7, 0xfd, 0x9f, 0xf9, 0x99, 0xff, 0xff, 0xff, 0xf6, 0x79, 0x83, 0x9f, 0xfc,
0xbf, 0xf2, 0x49, 0xff, 0xff, 0xff, 0xf3, 0x3c, 0xce, 0x3f, 0xfe, 0xff, 0xe6, 0x73, 0xff, 0xff,
0xff, 0xf9, 0x1c, 0x5c, 0xff, 0xff, 0xff, 0x8c, 0x27, 0xff, 0xff, 0xff, 0xf9, 0x9a, 0x71, 0xff,
0xff, 0xff, 0x3e, 0x4f, 0xff, 0xff, 0xff, 0xfc, 0xcb, 0xe0, 0x7d, 0xf7, 0xfc, 0x73, 0x9f, 0xff,
0xff, 0xff, 0xfe, 0xe3, 0x8e, 0x1f, 0xff, 0xf1, 0xb1, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x3f,
0x83, 0xff, 0x86, 0x16, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x3c, 0x7f, 0xf0, 0x00, 0x3f, 0x0c, 0xff,
0xff, 0xff, 0xff, 0xff, 0x90, 0x3f, 0xff, 0xc7, 0xd3, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83,
0x1f, 0xff, 0xd8, 0x80, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xc7, 0xff, 0xc0, 0xa0, 0x8f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xc8, 0x0e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8, 0x7f, 0x98, 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0x03,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
*/
//--------------void setup --------------------------------------------------------------------------------
void setup() {
//encoder pin function
pinMode(13,INPUT_PULLUP);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
// Enable interupts on port C
PCICR |= B00000010;
// Select PCINT pins 0 and 1 of port C a0 and a1
PCMSK1 |= B00000011;
delay(200);
// put your setup code here, to run once:
if(!display1.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
//if it cannot start stop the program
for(;;);
}
//clear the display buffer
//display1.clearDisplay();
//call the drawlogo function
//drawlogo();
//delay to show off the logo before starting the main program
//delay(3000);
display1.clearDisplay();
//set the text size
display1.setTextSize(2);
// Set the text color, the 1306 only supports white
display1.setTextColor(WHITE);
// Set the curser at the top left position
display1.println("");
display1.print(" Walkie ");
display1.print("Talkie");
display1.display();
delay(3000);
//PrintTextToDisplay();
//initialize the si5351, setting the oscilator load to the default, no refference frequency, no frequency correction
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, calibration);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); //Output current 2MA, 4MA, 6MA or 8MA
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA); //Output current 2MA, 4MA, 6MA or 8MA
}
//------------- void loop--------------------------------------------------------------------------------------------
void loop(){
//call the display and frequency calculation function
displayChannelAndFrequency(channel);
//read pin 13 to check for tx pin to be grounded
if(digitalRead(13)==LOW){
//set the transmit state to true
tx();
//set the transmit state to false when the pin is high
}else rx();
//buttonState=encoderlogic();
//Limit the channel range to typical export range
if(channel>275){
channel=-275;
}
//Limit the channel range to typical export range
if(channel<-275){
channel=275;
}
}
/*
//function to draw the logo to the screen
void drawlogo(void) {
clear the display buffer
display1.clearDisplay();
drawBitmap method is called with the desired center position of the image
the name of the image and the image size
this draws the bitmap to the buffer
display1.drawBitmap(
(display1.width() - LOGO_WIDTH ) / 2,
(display1.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
the contents of the buffer are displayed.
display1.display();
}
*/
//function to display the vfo text takes the channel number as an argument
void displayChannelAndFrequency(int i){
//we create a string and initialize it to the frequency for channel 1
String frequency="26.965";
int tempchannel=0;
//we create a switch to set the string to the corrosponding frequency of the selected channel
//organize frequency to channel display
tempchannel=i;
if(i>3){
tempchannel--;
}
if(i>8){
tempchannel--;
}
if(i>13){
tempchannel--;
}
if(i>18){
tempchannel--;
}
if(i>23){
tempchannel--;
}
//This code does all of the formating of the text
//clear the buffer
display1.clearDisplay();
//set the text size
display1.setTextSize(2);
// Set the text color, the 1306 only supports white
display1.setTextColor(WHITE);
// Set the curser at the top left position
display1.println(" ");
if (i>0&i<91){
display1.setCursor(0,0);
// Print CH to the display
display1.println("CANAL");
//set the cursor next to the CH text at the top
display1.setCursor(70,0);
// print the channel number
display1.println(tempchannel);
display1.setCursor(95,0);
// print the channel number
if(i==4){
display1.println("T1");}
if(i==9){
display1.println("T2");}
if(i==14){
display1.println("T3");}
if(i==19){
display1.println("T4");}
if(i==24){
display1.println("T5");}
}
//VFO and BFO frequency initialization
unsigned long long tempchannelho=i;
vfofrequency=26955000+(tempchannelho*10000ULL); // VFO CLK0 initialization frequency
bfofrequency=34755000+(tempchannelho*10000ULL); // BFO CLK1 initialization frequency
//bfofrequency=34300000+(tempchannelho*10000ULL);
//display1.clearDisplay();
display1.setTextColor(WHITE);
//set the text size
display1.setTextSize(2);
display1.setCursor(0,25);
// Set the text color, the 1306 only supports white
float tempvfoval=vfofrequency;
float displayvalue=tempvfoval/1000000;
// print the frequency to the display
//display1.println("test");
display1.print(displayvalue, 3);
display1.println(".Mhz");
display1.display();
}
//function to handle the TX state
void tx(void){
// Set CLK0 to output frequency. We multiply our frequenzy by 100 unsigned unsigned long because the frequency is set in
//100ths of hertz not hertz. We set the clock 0
//we subtract the tx local oscilator value for the mixer
si5351.set_freq((vfofrequency-txOffset*10ull)*100ull, SI5351_CLK0); // VFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((vfofrequency+txOffset*10ull)*100ull, SI5351_CLK1); // VFO RX frequency initialization, TX frequency + FI
si5351.set_freq((bfofrequency-txOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((bfofrequency+txOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency + FI
}
//function to handle the RX state
void rx(void){
//Set CLK0 to output frequency. We multiply our frequenzy by 100 unsigned unsigned long because the frequency is set in
//100ths of hertz not hertz. We set the clock 0
//we subtract the tx local oscilator value for the mixer
si5351.set_freq((vfofrequency+rxOffset*10ull)*100ull, SI5351_CLK0); // VFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((vfofrequency-rxOffset*10ull)*100ull, SI5351_CLK1); // VFO RX frequency initialization, TX frequency + FI
si5351.set_freq((bfofrequency+rxOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency - FI
//si5351.set_freq((bfofrequency-rxOffset*10ull)*100ull, SI5351_CLK1); // BFO RX frequency initialization, TX frequency + FI
}
//Interupt service routine this is used to read the encoder state when the interupt is triggered
ISR (PCINT1_vect){
//int clickdetect=0;
if(digitalRead(A0)==LOW){
temp1=0;}else temp1=1;
if(digitalRead(A1)==LOW){
temp2=0;}else temp2=2;
grey=temp1+temp2;
if(grey==0){
if(greyold==1){
channel--;
}
if(greyold==2){
channel++;
}
}
if(grey!=greyold){
}
greyold=grey;
//return clickdetect;
}
Nenhum comentário:
Postar um comentário
Façam seus comentários com experiências no projeto. Ou de sua opinião.