VFO DDS ARDUINO - AD9850 - IR REMOTE

Ola amigos


FOTO: MONTAGEM COM O ARDUINO NANO

Resolvemos publicar este DDS usando o Arduino com controle remoto, como estou descrevendo como iniciar no Arduino via radio, ou seja montando coisas par uso em radio, no blogspot arduino4radio. Como as coisas demoram para acontecer por lá e tem muitos colegas apressados aqui vai um pitaco do que fizemos.
De antemão aviso que não estudei programação e aprendi sozinho a programar, como tambem eletronica, pois nunca fui a escola destas materias ... de informatica tive algumas aulas de Fortran faz uns 40 anos, na Faculdade de matematica eram computadores IBM/360 de grande porte , usavam cartões perfurados para carregar os programas, visto isso praticamente nunca estudei informatica.
Este programa como outros que faço pode ser em muito aperfeiçoado e isto deixo a cargo de quem entende do assunto, sei que a ideia de como fazer tambem tem seu valor e  este trabalho é exatamente para isso, para divulgar a ideia, o programa funciona e certamente deve ter Bugs, mas ao menos servirá para uso em nosso Hobby.
Trabalha de  1Hz a 42MHz de 1 em 1 Hz e a operação é via controle remoto.
A montagem é simples pois utilisa modulos comprados prontos, montagem mesmo somente do driver que possui dois transistores.

Video no YOUTUBE deste VFO

Vamos ao esquema


Driver

Os transistores do driver podem ser substituidos
2N3904 = 2N2222 = BC547 = BC548
BD135 = DB137 = BD139 = 2N2218 = 2N2219 estes transistores devem ser da Phlips ou Motorola.
Os toroides podem ser substituidos por toroides retirados de lampadas economicas. Eu sempre enrolo em fios tipo 30AWG encapados por plastico colorido, que ajuda na identificação (retirados de cabos telefonicos)
Eu montei em um modulo e fixei em um placa de circuito impresso comercial com ilhas para cada furo,  assim soldei pinos macho, para Vcc, terra entra de RF e saida de RF, assim se tornou um shield do arduino. E facilita a montagem em uma placa comercial  com soquetes ou conectores femea.

Montagem completa


O esquema chapeado do VFO sem o amplificador de RF
Note que o circuito que opera o I2C ligado ao display de LCD é soldado diretamente no LCD, mas pode ser soqueteado tambem.






FOTO : MODULOI2C SOLDADO AO DISPLAY LCD 1602



Lista de material e onde comprar

01 Arduino nano  Atmega 328 + USB cable for Arduino -  (
CH340 driver)  - V3.0
 
Compre com um cabo se vc não possuir um, este cabo é de conector USB normal para conector mini USBb, o USBb é um conector usado por maquinas fotograficas e alguns videogames,  é facil de confundir com USBa usado por celulares Sansung ... na duvida compre o primeiro com cabo e se comprar outros compre sem o cabo.
Com cabo no Ebay sai por volta de R$12,80 com frete gratis, sem o cabo R$8,80
Na Dealextreme com cabo  sai por R$26
Na Aliexpress com cabo sai por R$10 e sem o cabo por R$7,30 ... neste voce pode comprar com pagamento por boleto bancario.
No mercado livre vc paga R$19 mais correio
Na Flip Flop (Brasil) vc paga R$60 mais o frete.

01 LCD 2 linhas de 16 caracteres 2x16 ou 1602 com back light

Ebay R$6,50 frete gratis
Dealextreme R$15 frete gratis
Aliexpress R$5,60 frete gratis
ML R$10 incluir frete
Flip Flop R$19 mais frete.

01 controlador I2C para LCD1602 16x2

Ebay R$3,50 frete gratis
Dealextreme R$7,56
Aliexpress R$3,29 e R$7,70 o jogo LCD + controlador I2C  com frete gratis
MLR$ 12 mais frete
Flip Flop R$16 mais frete

01 Modulo DDS AD9850

Ebay R$32 frete gratis
Dealextreme R$32,50 frete gratis
Aliexpress R$33,50 frete gratis
ML R$75 mais frete
Flip Flop não tem

01 Sensor de IR HX1838

Pode ser retirado de TV ou videocassete ou outro aparelho que fosse controlado por conproleremoro IR (infra vermelho).
Ebay 10 peças R$3,90 ou 1 pç mais controle remoto (sem bateria incluida) 4,78 frete gratis
Dealextreme 01pç com controle remoto 
(sem bateria incluida) R$12 frete gratis
Aliexpress
01pç com controle remoto (sem bateria incluida) R$4,60 - 100pçs HX1838  R$32 frete gratis
ML
01pç com controle remoto (sem bateria incluida) R$13 mais frete
Flip Flop  não tem

Material adicional

Connectors 40 pins female - regua de 40 pinos de conector femea soldavel

Ebay R$3,67 10 peças frete gratis
Aliexpress R$4,80 10 peças frete gratis
ML R$1,14 cada incluir frete

Conector BNC painel para RF

Ebay R$4,50 10 peças frete gratis
Aliexpress R$ 15,30 10 peças frete gratis

Placa PCB padrão com ilhas isoladas

Ebay 70mmx90mm 10 peças R$10 com frete gratis
Aliexpress 70mmx90mm  R$ 12,00 10 peças frete gratis



FOTO :  MONTAGEM EXPERIMENTAL COM ARDUINO UNO (embaixo, a direita, placa com modulos de amplificador de RF (BD135) , sensor de SWR (2 toroides) , amplificador de sinais (LM324), amplificador com J310, fonte com 78l05, diodos zener de 4v7(segurança do arduino) e terminal de saida)
Estes modulos são para o testador de filtros  (BD135 78l05 e J310) e para o analizador de antenas (SWR  LM324 e zener) - no arduino altera somente o software

Montagem livre  -  o VFO pode ficar em caixa plastica mas é preferivel montar em caixa metalica, quem preferir : montar um controlador com 7805 e alimentar diretamente o Arduino.
Para funciona obviamente é necessario que os codigos das teclas do controle remoto sejam reconhecidas pelo Arduino, e como cada controle remoto tem um codigo especial é necessario descobrir este codigo.
para isto apos a montagem este programa deve ser carregado
 
Nota a biblioteca
IRremote.h deve ser baixada deste link e adicionada ao programador do Arduino
https://github.com/z3t0/Arduino-IRremote

Sketch (programa do arduino)

/* Sensor de Infravermelho IR Lê e imprime na porta
serial do PC, o valor em HEX hexadecimal, da tecla  pressionanda, do controle remoto.

 ___
|( )|  PINO 1 = Sinal para o arduino pino 11
|___|  PIN) 2 = Terra ou GND
| | |  PINO 3 = 3V3
| | |
1 2 3
Arduino  IRremote livraria
https://github.com/z3t0/Arduino-IRremote
*/

#include <IRremote.h>

int PINO_RX = 11; //define o pino 11 como de recepção
IRrecv irrecv(PINO_RX);// define o pino 11 como receptor de Infravermelho
decode_results resultado; // passa os valores lidos para a variavel resultado

void setup()
{
  Serial.begin(9600); // Inicia a comunicação serial
  irrecv.enableIRIn(); // Inicia a recepção de Infravermelho IR
}

void loop() {
  if (irrecv.decode(&resultado)) { //  if = se tiver algum valor em resultado faça as linhs seguintes até
// a chave se não pule
    Serial.println(resultado.value, HEX);// coloca na seria (tela do PC) o valor hexadecimadl da tecla apertada
    irrecv.resume(); // pronta para receber o proximo valor
  }// fecha o comando if 
}

Anote o valor hexa, de cada tecla, exibido no monitor do PC.

Depois altere no sketch do VFO abaixo, um codigo para cada tecla
lembre-se que vc precisa teclar uma tecla para mudar a frequencia por numeros e outra tecal no final para confirmar.
A mudança para cima ou para baixo de numeros de casa decimais é feita por uma tecla + para subir e por uma tecla - para descer  .... já uma tecla define se o cursor para mudança de caixa vai a esquerda <=   outra tela define se ele vai a direita =>   ... e a frequencia nesta caso se altera automaticamente ...

Nota: para este programa ser compilado é necessario adiciona a biblioteca LiquidCrystal_I2C diponivel neste link :
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/LiquidCrystal_V1.2.1.zip

Sktech principal (baseado em varios sketchs retirados da WEB)

#include <Wire.h> // biblioteca comunicação
#include <LiquidCrystal_I2C.h> // biblioteca LCD
#include <IRremote.h> // biblioteca controle remoto
#define W_CLK 7       // Pino D7  - ligue ao pino (CLK) "word load clock" do modulo AD9850
#define FQ_UD 6      // Pino D6 - ligue ao pino (FQ) "freq update" do modulo AD9850
#define DATA 5      //Pino D5 - ligue ao pino (DATA) "serial data load" do modulo AD9850
#define RESET 4      //Pino D4 - ligue ao pino (RST) "reset" do modulo AD9850
#define FREQCORR 0 // correção de frequencia por software
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
volatile unsigned long frequencia = 1000000;    // Inicia em 10MHz
String letra; // uma letra ou numero considerado como letra
String palavra = ""; //uma palavra ou sequencia de letras
long numero = 0; // um numero a palavra transformada em numero
int freq; // valor da frequencia
int IRRX_pino = 11; // define o pino de recepção do IR como D11
IRrecv irrecv(IRRX_pino);
decode_results resultado; // apresenta o valor lido no IR em resultado
float armazenavalor; // armazena o valor lido do IR
int num = 0; // num é um flag ou bandeira se altera a bandeira ocorre algo
int digi = 5; // posição do cursor da frequencia começa no meio 5
double degrau = 0.1; // é o valor em que o cursor da frequencia esta
int i = 1; //
long frmax = 45000000;
long frmin = 10;
int espa = 1;
String branco = " ";
// Inicializa o display, geralmente. no endereco 0x27 o meu eh 0x3F
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// teclas do controle remoto substitua por exemplo o valor FF6897 da tecla 0 pelo valor lido no PC ao
// teclar zero no controle remoto
float n0 = 0xFF6897  ; //tecla 0
float n1 = 0xFF30CF  ; // tecla 1
float n2 = 0xFF18E7  ; //tecla 2
float n3 = 0xFF7A85  ; //tecla 3
float n4 = 0xFF10EF  ; //tecla 4
float n5 = 0xFF38C7  ; //tecla 5
float n6 = 0xFF5AA5  ; //tecla 6
float n7 = 0xFF42BD  ; //tecla 7
float n8 = 0xFF4AB5  ; //tecla 8
float n9 = 0xFF52AD  ; //tecla9
float nn = 0xFF629D  ; //tecla CH entrar valor numerico da freq. em kHz
float nncfm = 0xFF906F  ; //tecla EQ confirma valor numerico da frequencia
float nce = 0xFF22DD  ; //tecla <<= seta cursor a esquerda
float ncd = 0xFF02FD  ; //tecla =>> seta cursor a direita
float nsobe = 0xFFA857  ; //tecla + sobe um valor na posição do cursor
float ndesce = 0xFFE01F  ; //tecla - abaixa um valor na posição do cursor

void setup() {
  Serial.begin(9600);
  lcd.begin (16, 2);
  pinMode(FQ_UD, OUTPUT);
  pinMode(W_CLK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(RESET, OUTPUT);
  pulseHigh(FQ_UD);
  irrecv.enableIRIn(); // Inicializa o receptor IR
}
void loop () {
  if (frequencia > frmax) {
    (frequencia = frmax) ;
  }
  if (frequencia < frmin) {
    (frequencia = frmin);
  }
  if (frequencia >= 10000000)
  {
    espa = 1;
    branco = " ";
  }
  if ((frequencia < 10000000) && (frequencia > 999999))
  {
    (espa = 2);
    branco = " 0";
  }
  if ((frequencia < 1000000) && (frequencia > 99999))
  {
    (espa = 3);
    branco = " 00";
  }
  if ((frequencia < 100000) && (frequencia > 9999))
  {
    (espa = 4);
    branco = " 000";
  }
  if ((frequencia < 10000) && (frequencia > 999))
  {
    (espa = 5);
    branco = " 0000";
  }
  if ((frequencia < 1000) && (frequencia > 99))
  {
    (espa = 6);
    branco = " 00000";
  }
  if ((frequencia < 100) && (frequencia > 9))
  {
    (espa = 7);
    branco = " 00000";
  }
  lcd.setCursor(2, 0);
  lcd.print("Frequencia");
  lcd.setCursor(0, 1);
  lcd.print(branco);
  lcd.setCursor(espa, 1);
  sendFrequency(frequencia);
  lcd.print(frequencia);
  lcd.print(" Hz");
  if (irrecv.decode(&resultado))
  {
    armazenavalor = (resultado.value);
    if (armazenavalor == nn)
    {
      lcd.clear();
      lcd.setCursor(10, 0);
      lcd.print("in kHz");
      delay (1000);
      numerico();
      lcd.clear();
    }
    if (armazenavalor == ncd)
    {
      digi = (digi + 1);
      if (digi > 8 )
      {
        digi = 1 ;
      }
      lcd.setCursor(digi, 1);
      lcd.cursor();
      delay(1000);
    }
    if (armazenavalor == nce)
    {
      digi = (digi - 1);
      if (digi < 1 )
      {
        digi = 8 ;
      }
      lcd.setCursor(digi, 1);
      lcd.cursor();
      delay(1000);
    }
    if (armazenavalor == nsobe) //soma
    {
      do
      {
        degrau = degrau * 10;
        i = i + 1;
      } while (i < (10 - digi));
      frequencia = frequencia + degrau;
      delay(500);
      i = 1;
      degrau = 0.1;
    }
    if (armazenavalor == ndesce) //abaixa
    {
      do
      {
        degrau = degrau * 10;
        i = i + 1;
      } while (i < (10 - digi));
      frequencia = frequencia - degrau;
      delay(500);
      i = 1;
      degrau = 0.1;
    }
    lcd.noCursor();
    irrecv.resume();
  }
  num = 0;
}

void tfr_byte(byte data)
{
  for (int i = 0; i < 8; i++, data >>= 1) {
    digitalWrite(DATA, data & 0x01);
    pulseHigh(W_CLK);   //after each bit sent, CLK is pulsed high
  }
}

// Send frequency and command word to AD9850
void sendFrequency(double frequencia) {
  int32_t freq = frequencia * 4294967295 / (125000000 + FREQCORR); // note 125 MHz clock on 9850
  for (int b = 0; b < 4; b++, freq >>= 8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0);
  pulseHigh(FQ_UD);
}

void numerico() {
  // put your main code here, to run repeatedly:
  while (num == 0) {
    if (irrecv.decode(&resultado))
    {
      armazenavalor = (resultado.value);
      if (armazenavalor == n1)
      {
        letra = "1";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n2)
      {
        letra = "2";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n3)
      {
        letra = "3";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n4)
      {
        letra = "4";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n5)
      {
        letra = "5";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n6)
      {
        letra = "6";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n7)
      {
        letra = "7";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n8)
      {
        letra = "8";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n9)
      {
        letra = "9";
        palavra = palavra + letra;
        delay (500);
      }
      if (armazenavalor == n0)
      {
        letra = "0";
        palavra = palavra + letra;
        delay (500);
      }
      // xero = xero + ero;
      //lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(palavra);
      lcd.print("kHz");
      // delay(2000);
      if (armazenavalor == nncfm)
      {
        palavra = (palavra + "000");
        numero = palavra.toInt();
        lcd.setCursor(0, 1);
        if (numero > 45000000) {
          (numero = 45000000);
        }
        if (numero < 1000) {
          (numero = 1000);
        }
        frequencia = numero;
        lcd.print(numero);
        freq = numero;
        palavra = "";
        letra = "";
        numero = 0;
        num = 1;
        delay(1000);
      }
      irrecv.resume();
    }
  }
}



Arquivos .INO de programação

Identificador de teclas do controle remoto

Programa pricipal -Arduino VFO DDS

Qualquer duvida escrevam

73 de py2ohh miguel