アンテナアナライザPCBを秋月電子ABS樹脂ケース(112-TS)に収納した。タクトスイッチは、同じく秋月のP-03648に、タクトスイッチキャップを2段重ね、操作部がケース全面より1mm位出る様にした。ケース蓋は、背面側にして、BNCコネクタが蓋に干渉することなく、付ける事が出来た。
左側。
中央にUSBコネクタ。
下側。
タクトスイッチキャップは2個貼り合わせて高さを調整した。基板とケース固定に使っているスペーサは、17mmに調整。
右側。
ケース蓋が背面側に開く。
無線機の製作記録の全てを公開してます。 https://sites.google.com/view/ja2gqpから必要なファイルをダウンロードできます。 このBlogは、詳細な説明は一切行っておらず、ある程度のスキルが要求されます。 質問に応じますが、カスタマイズは対応しません。尚、コメントは誰でも出来る様に変更しました。
2015年11月27日金曜日
2015年11月26日木曜日
Antenna Analyzer 2.2"TFT
Arduino nanoとAD9850 DDS Moduleを使ったアンテナアナライザで、 K6BEZ開発をDG7EAOがTFTを使ってスタンドアーロンでも使える様に改造した物である。このTFT付きアナライザは、PCリンク、スタンドアーロンでも使える優れもので、電源はUSB経由。
DG7EAOサイトの説明は断片的で,単純に真似してもIO割り付けに整合性がなく、動作しない。そのため、回路図、PCB、スケッチに矛盾が無く動作する様、纏めた。
実装基板は、秋月電子のアクリルケースに収納できるサイズとした。
部品実装基板。
TFTは、高さ8.5のピンソケット。DDSとnanoは、高さ3.5のピンソケットを使った。
抵抗0Ω(4本)は、ジャンパー。
回路図。
ダイオードは、1N60を使用。入手困難な部品がないので、簡単に作れる筈。
基板サイズ 80x112
/***************************************************************************\
* Name : DDS_Sweeper.BAS *
* Author : Beric Dunn (K6BEZ) *
* Notice : Copyright (c) 2013 CC-BY-SA *
* : Creative Commons Attribution-ShareAlike 3.0 Unported License *
* Date : 9/26/2013 *
* Version : 1.0 *
* Notes : Written using for the Arduino Micro *
* : Pins: *
* : A0 - Reverse Detector Analog in *
* : A1 - Forward Detector Analog in *
* : Modified by Norbert Redeker (DG7EAO) 07/2014 *
* : TFT Display mit ILI9341 Chip, SPI, 240 x 320 *
* : usglib Grafik Bibliothek https://code.google.com/p/ucglib/ *
*---------------------------------------------------------------------------*
* Modification: 2015/11/26 JA2GQP *
* A1)DDS Pin Assign *
* A2)Ucglib_ILI9341_18x240x320_SWSPI Parameters *
* A3)DDS Reset Sequence *
\***************************************************************************/
#include <SPI.h>
#include "Ucglib.h"
// Define Pins used to control AD9850 DDS
//const int FQ_UD=10; // N6BEZ
//const int SDAT=11;
//const int SCLK=9;
//const int RESET=12;
//const int FQ_UD=9; // DG7EAO
//const int SDAT=11;
//const int SCLK=10;
//const int RESET=12;
const int FQ_UD=11; //A1)DDS Pin Assign JA2GQP
const int SDAT=10; //
const int SCLK=12; //
const int RESET=9; //
// Variablen für Display
double vswrArray[110]; //Array für SWR
int z = 0; // Index für Array
double SwrFreq = 14; // Variable für Freq. mit SWR Min.
double SwrMin = 100; // Variable für SWR Min.
double Freq1 = 1; // Freq. Links unterste Zeile Display
double Freq2 = 15; // Freq. Mitte unterste Zeile Display
double Freq3 = 30; // Freq. Mitte unterste Zeile Display
unsigned long milliold = 0; //Millisekunden für Entprellung Interrupt
unsigned long millinew = 0; //Millisekunden für Entprellung Interrupt
int flag = 0; // wir auf 1 gesetzt bei Interrupt, in void Loop perform_sweep
double counter = 0; // Zähler um erste Interrupts zu ignorieren
// Variablen für Messung
double Fstart_MHz = 1; // Start Frequency for sweep
//double Fstop_MHz = 10; // Stop Frequency for sweep
double Fstop_MHz = 30; // Stop Frequency for sweep
double current_freq_MHz; // Temp variable used during sweep
long serial_input_number; // Used to build number from serial stream
int num_steps = 100; // Number of steps to use in the sweep
char incoming_char; // Character read from serial stream
//Konstruktor für Display
//Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 10, /*data=*/ 11, /*cd=*/ 6 , /*cs=*/ 5, /*reset=*/ 4); // DG7EAO
Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 8, /*data=*/ 7, /*cd=*/ 6 , /*cs=*/ 5, /*reset=*/ 4); //A2) JA2GQP
// the setup routine runs once when you press reset:----------------------------------
void setup() {
// Schreibe Info Text auf Display
//ucg.begin(UCG_FONT_MODE_TRANSPARENT);
ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
ucg.setRotate90();
ucg.setFont(ucg_font_ncenR14r);
//ucg.setColor(255, 255, 255); //weiss
//ucg.setColor(255, 0, 0); //rot
ucg.setColor(0, 255, 0); //grün
//ucg.setColor(1, 255, 0,0); // rot, Index1
ucg.setPrintPos(0,75);
ucg.print("Arduino");
ucg.setPrintPos(10,100);
ucg.print("Antennen");
ucg.setPrintPos(20,125);
ucg.print("Analyzer");
ucg.setPrintPos(30,150);
ucg.print("DG7EAO");
// Configiure DDS control pins for digital output
pinMode(FQ_UD,OUTPUT);
pinMode(SCLK,OUTPUT);
pinMode(SDAT,OUTPUT);
pinMode(RESET,OUTPUT);
//Tasten Interrupt an PIN 2
pinMode(2,OUTPUT);
digitalWrite(2, HIGH);
attachInterrupt(0, key2, FALLING);
unsigned long milliold = millis();
//Tasten Interrupt an PIN 3
pinMode(3,OUTPUT);
digitalWrite(3, HIGH);
attachInterrupt(1, key3, FALLING);
//milliold = millis();
// Configure LED pin for digital output
pinMode(13,OUTPUT);
pinMode(A0,INPUT); // Set up analog inputs on A0 and A1
pinMode(A1,INPUT);
analogReference(INTERNAL); //internal reference voltage
Serial.begin(57600); // initialize serial communication at 57600 baud
// Reset the DDS
//digitalWrite(RESET,HIGH); // N6BEZ
//digitalWrite(RESET,LOW);
digitalWrite(RESET,HIGH); //A3)DDS Reset Sequence JA2GQP
delay(1); //
digitalWrite(RESET,LOW); //
//
digitalWrite(SCLK,HIGH); //
digitalWrite(SCLK,LOW); //
digitalWrite(FQ_UD,HIGH); //
digitalWrite(FQ_UD,LOW); //
serial_input_number=0; //Initialise the incoming serial number to zero
}
// the loop routine runs over and over again forever:----------------------------------
void loop() {
//Check for character
if(Serial.available()>0){
incoming_char = Serial.read();
switch(incoming_char){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
serial_input_number=serial_input_number*10+(incoming_char-'0');
break;
case 'A': //Turn frequency into FStart
Fstart_MHz = ((double)serial_input_number)/1000000;
serial_input_number=0;
break;
case 'B': //Turn frequency into FStop
Fstop_MHz = ((double)serial_input_number)/1000000;
serial_input_number=0;
break;
case 'C': //Turn frequency into FStart and set
// DDS output to single frequency
Fstart_MHz = ((double)serial_input_number)/1000000;
SetDDSFreq(Fstart_MHz * 1000000);//SetDDSFreq(Fstart_MHz);
delay(100);
SetDDSFreq(Fstart_MHz * 1000000);
serial_input_number=0;
break;
case 'N': // Set number of steps in the sweep
num_steps = serial_input_number;
serial_input_number=0;
break;
case 'S':
case 's':
Perform_sweep();
break;
case '?': // Report current configuration to PC
Serial.print("Start Freq:");
Serial.println(Fstart_MHz*1000000);
Serial.print("Stop Freq:");
Serial.println(Fstop_MHz*1000000);
Serial.print("Num Steps:");
Serial.println(num_steps);
break;
}
Serial.flush();
}
if (flag == 1 && counter >2) //Perform Sweep nach Interrupt PIN2 oder 3
{ // ingnoriere Startup Interrupts durch counter
flag = 0;
Perform_sweep();
}
}
void Perform_sweep(){
double FWD=0;
double REV=0;
double VSWR;
double Fstep_MHz = (Fstop_MHz-Fstart_MHz)/num_steps;
z = 0;
SwrMin = 100;
ucg.setPrintPos(220,150);
ucg.print("... Starte");
ucg.clearScreen();
for(int i=0;i<=num_steps;i++){ // Start loop
current_freq_MHz = Fstart_MHz + i*Fstep_MHz;// Calculate current frequency
SetDDSFreq(current_freq_MHz*1000000); // Set DDS to current frequency
//delay(10); // Wait a little for settling
delay(100);
REV = analogRead(A0); // Read the reverse voltages
FWD = analogRead(A1); // forward voltages
REV = REV-5; //Offset Correction
if(REV>=FWD){REV = FWD-1;}
if (REV <1) {REV = 1;}
VSWR = (FWD+REV)/(FWD-REV);
VSWR = VSWR * 1000; //Scale Output
Serial.print(current_freq_MHz*1000000); // Send current line back to PC over serial bus
Serial.print(",0,");
Serial.print(VSWR);
Serial.print(",");
Serial.print(FWD);
Serial.print(",");
Serial.println(REV);
vswrArray[z] = VSWR/1000; //Submitter SWR to Array
if (vswrArray[z] > 10) vswrArray[z] = 10; //Max SWR
if (vswrArray[z] < SwrMin && vswrArray[z] > 1){ //Minimum SWR
SwrMin = vswrArray[z]; //Minimum SWR and frequency store
SwrFreq = current_freq_MHz;
}
z = z + 1;
}
// Send "End" to PC to indicate end of sweep
Serial.println("End");
Serial.flush();
//Zeichne Grid
CreateGrid();
//Linienfarbe = rot
ucg.setColor(255, 0, 0); //rot
// Draw Line
// 30 = swr 10 210 = swr 0
// Diff swr 10 = 180
// swr 2 = 18 * 2
double last = 10;
double xx = 6;
int j = 1;
for (int i = 1 ;i < 103; i++){
xx = vswrArray[i];
ucg.drawLine(j,210-last*18, j+1, 210-xx*18);
ucg.drawLine(j+1,210-last*18, j+2, 210-xx*18);
j = j + 3;
last = xx;
}
}
// Setze DDS Frequenz-----------------------------------------------------------------
void SetDDSFreq(double Freq_Hz){
int32_t f = Freq_Hz * 4294967295/125000000; // Calculate the DDS word - from AD9850 Datasheet
for (int b=0;b<4;b++,f>>=8){ // Send one byte at a time
send_byte(f & 0xFF);
}
send_byte(0); // 5th byte needs to be zeros(AD9850 Command Parameters)
digitalWrite(FQ_UD,HIGH); // Strobe the Update pin to tell DDS to use values
digitalWrite(FQ_UD,LOW);
}
// Sende Daten an DDS-----------------------------------------------------------------
void send_byte(byte data_to_send){
for (int i=0; i<8; i++,data_to_send>>=1){ // Bit bang the byte over the SPI bus
digitalWrite(SDAT,data_to_send & 0x01); // Set Data bit on output pin
digitalWrite(SCLK,HIGH); // Strobe the clock pin
digitalWrite(SCLK,LOW);
}
}
//Zeichne Grid auf TFT Display--------------------------------------------------------
void CreateGrid(){
//ucg.clearScreen();
double maxSwr = 10;
ucg.drawHLine(0,120,310);
ucg.drawHLine(0,196,310);
ucg.drawVLine(78,30,180);
ucg.drawVLine(155,30,180);
ucg.drawVLine(233,30,180);
ucg.setPrintPos(0, 235);
ucg.print(Freq1,3);
ucg.setPrintPos(130, 235);
ucg.print(Freq2,3);
ucg.setPrintPos(260, 235);
ucg.print(Freq3,3);
ucg.setPrintPos(10, 15);
ucg.print("SWR");
ucg.setPrintPos(70, 15);
ucg.print(SwrMin,2);
ucg.setPrintPos(115, 15);
ucg.print(">");
ucg.setPrintPos(130, 15);
ucg.print(maxSwr,2);
ucg.setPrintPos(250, 15);
//ucg.print((freqCenter/1000000*1.05),3);
ucg.print(SwrFreq,3);
ucg.drawRFrame(0,30,310,180, 1);
}
// Interrupt Service Routine----------------------------------------------------------
// Abfrage Low an Pin 2
void key2(){
counter = counter + 1; //ignoriere Startup Interrupts > counter
//Entprellen mit millis()
millinew = millis();
if (millinew - milliold < 1000){
milliold = millinew;
return;
}
milliold = millinew;
Fstart_MHz = 1; // Start Frequency for sweep
Fstop_MHz = 30; // Stop Frequency for sweep
num_steps = 102; // Steps
Freq1 = 1; // Unterste Zeile Display Freq. Links
Freq2 = 15; // Unterste Zeile Display Freq. Mitte
Freq3 = 30; // Unterste Zeile Display Freq. Recht
//Perform_sweep();
flag = 1;
}
// Interrupt Service Routine----------------------------------------------------------
// Abfrage Low an Pin 3
void key3()
{
counter = counter + 1; //ignoriere Startup Interrupts > counter
millinew = millis(); //Entprellen mit millis()
if (millinew - milliold < 1000){
milliold = millinew;
return;
}
milliold = millinew;
int x = SwrFreq + 0.5; //Runde auf Mhz
Fstart_MHz = x-1; // Start Frequency for sweep
Fstop_MHz = x+1; // Stop Frequency for sweep
num_steps = 102; // Steps
Freq1 = x-1; // Unterste Zeile Display Freq. Links
Freq2 = x; // Unterste Zeile Display Freq. Mitte
Freq3 = x+1; // Unterste Zeile Display Freq. Rechts
//Perform_sweep();
flag = 1;
}
DG7EAOサイトの説明は断片的で,単純に真似してもIO割り付けに整合性がなく、動作しない。そのため、回路図、PCB、スケッチに矛盾が無く動作する様、纏めた。
実装基板は、秋月電子のアクリルケースに収納できるサイズとした。
部品実装基板。
TFTは、高さ8.5のピンソケット。DDSとnanoは、高さ3.5のピンソケットを使った。
抵抗0Ω(4本)は、ジャンパー。
回路図。
ダイオードは、1N60を使用。入手困難な部品がないので、簡単に作れる筈。
基板サイズ 80x112
Program
コメントに字下げなどの工夫がなくて読みづらく、一部書換を行ったが、プログラム変更は3点である。/***************************************************************************\
* Name : DDS_Sweeper.BAS *
* Author : Beric Dunn (K6BEZ) *
* Notice : Copyright (c) 2013 CC-BY-SA *
* : Creative Commons Attribution-ShareAlike 3.0 Unported License *
* Date : 9/26/2013 *
* Version : 1.0 *
* Notes : Written using for the Arduino Micro *
* : Pins: *
* : A0 - Reverse Detector Analog in *
* : A1 - Forward Detector Analog in *
* : Modified by Norbert Redeker (DG7EAO) 07/2014 *
* : TFT Display mit ILI9341 Chip, SPI, 240 x 320 *
* : usglib Grafik Bibliothek https://code.google.com/p/ucglib/ *
*---------------------------------------------------------------------------*
* Modification: 2015/11/26 JA2GQP *
* A1)DDS Pin Assign *
* A2)Ucglib_ILI9341_18x240x320_SWSPI Parameters *
* A3)DDS Reset Sequence *
\***************************************************************************/
#include <SPI.h>
#include "Ucglib.h"
// Define Pins used to control AD9850 DDS
//const int FQ_UD=10; // N6BEZ
//const int SDAT=11;
//const int SCLK=9;
//const int RESET=12;
//const int FQ_UD=9; // DG7EAO
//const int SDAT=11;
//const int SCLK=10;
//const int RESET=12;
const int FQ_UD=11; //A1)DDS Pin Assign JA2GQP
const int SDAT=10; //
const int SCLK=12; //
const int RESET=9; //
// Variablen für Display
double vswrArray[110]; //Array für SWR
int z = 0; // Index für Array
double SwrFreq = 14; // Variable für Freq. mit SWR Min.
double SwrMin = 100; // Variable für SWR Min.
double Freq1 = 1; // Freq. Links unterste Zeile Display
double Freq2 = 15; // Freq. Mitte unterste Zeile Display
double Freq3 = 30; // Freq. Mitte unterste Zeile Display
unsigned long milliold = 0; //Millisekunden für Entprellung Interrupt
unsigned long millinew = 0; //Millisekunden für Entprellung Interrupt
int flag = 0; // wir auf 1 gesetzt bei Interrupt, in void Loop perform_sweep
double counter = 0; // Zähler um erste Interrupts zu ignorieren
// Variablen für Messung
double Fstart_MHz = 1; // Start Frequency for sweep
//double Fstop_MHz = 10; // Stop Frequency for sweep
double Fstop_MHz = 30; // Stop Frequency for sweep
double current_freq_MHz; // Temp variable used during sweep
long serial_input_number; // Used to build number from serial stream
int num_steps = 100; // Number of steps to use in the sweep
char incoming_char; // Character read from serial stream
//Konstruktor für Display
//Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 10, /*data=*/ 11, /*cd=*/ 6 , /*cs=*/ 5, /*reset=*/ 4); // DG7EAO
Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 8, /*data=*/ 7, /*cd=*/ 6 , /*cs=*/ 5, /*reset=*/ 4); //A2) JA2GQP
// the setup routine runs once when you press reset:----------------------------------
void setup() {
// Schreibe Info Text auf Display
//ucg.begin(UCG_FONT_MODE_TRANSPARENT);
ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
ucg.setRotate90();
ucg.setFont(ucg_font_ncenR14r);
//ucg.setColor(255, 255, 255); //weiss
//ucg.setColor(255, 0, 0); //rot
ucg.setColor(0, 255, 0); //grün
//ucg.setColor(1, 255, 0,0); // rot, Index1
ucg.setPrintPos(0,75);
ucg.print("Arduino");
ucg.setPrintPos(10,100);
ucg.print("Antennen");
ucg.setPrintPos(20,125);
ucg.print("Analyzer");
ucg.setPrintPos(30,150);
ucg.print("DG7EAO");
// Configiure DDS control pins for digital output
pinMode(FQ_UD,OUTPUT);
pinMode(SCLK,OUTPUT);
pinMode(SDAT,OUTPUT);
pinMode(RESET,OUTPUT);
//Tasten Interrupt an PIN 2
pinMode(2,OUTPUT);
digitalWrite(2, HIGH);
attachInterrupt(0, key2, FALLING);
unsigned long milliold = millis();
//Tasten Interrupt an PIN 3
pinMode(3,OUTPUT);
digitalWrite(3, HIGH);
attachInterrupt(1, key3, FALLING);
//milliold = millis();
// Configure LED pin for digital output
pinMode(13,OUTPUT);
pinMode(A0,INPUT); // Set up analog inputs on A0 and A1
pinMode(A1,INPUT);
analogReference(INTERNAL); //internal reference voltage
Serial.begin(57600); // initialize serial communication at 57600 baud
// Reset the DDS
//digitalWrite(RESET,HIGH); // N6BEZ
//digitalWrite(RESET,LOW);
digitalWrite(RESET,HIGH); //A3)DDS Reset Sequence JA2GQP
delay(1); //
digitalWrite(RESET,LOW); //
//
digitalWrite(SCLK,HIGH); //
digitalWrite(SCLK,LOW); //
digitalWrite(FQ_UD,HIGH); //
digitalWrite(FQ_UD,LOW); //
serial_input_number=0; //Initialise the incoming serial number to zero
}
// the loop routine runs over and over again forever:----------------------------------
void loop() {
//Check for character
if(Serial.available()>0){
incoming_char = Serial.read();
switch(incoming_char){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
serial_input_number=serial_input_number*10+(incoming_char-'0');
break;
case 'A': //Turn frequency into FStart
Fstart_MHz = ((double)serial_input_number)/1000000;
serial_input_number=0;
break;
case 'B': //Turn frequency into FStop
Fstop_MHz = ((double)serial_input_number)/1000000;
serial_input_number=0;
break;
case 'C': //Turn frequency into FStart and set
// DDS output to single frequency
Fstart_MHz = ((double)serial_input_number)/1000000;
SetDDSFreq(Fstart_MHz * 1000000);//SetDDSFreq(Fstart_MHz);
delay(100);
SetDDSFreq(Fstart_MHz * 1000000);
serial_input_number=0;
break;
case 'N': // Set number of steps in the sweep
num_steps = serial_input_number;
serial_input_number=0;
break;
case 'S':
case 's':
Perform_sweep();
break;
case '?': // Report current configuration to PC
Serial.print("Start Freq:");
Serial.println(Fstart_MHz*1000000);
Serial.print("Stop Freq:");
Serial.println(Fstop_MHz*1000000);
Serial.print("Num Steps:");
Serial.println(num_steps);
break;
}
Serial.flush();
}
if (flag == 1 && counter >2) //Perform Sweep nach Interrupt PIN2 oder 3
{ // ingnoriere Startup Interrupts durch counter
flag = 0;
Perform_sweep();
}
}
void Perform_sweep(){
double FWD=0;
double REV=0;
double VSWR;
double Fstep_MHz = (Fstop_MHz-Fstart_MHz)/num_steps;
z = 0;
SwrMin = 100;
ucg.setPrintPos(220,150);
ucg.print("... Starte");
ucg.clearScreen();
for(int i=0;i<=num_steps;i++){ // Start loop
current_freq_MHz = Fstart_MHz + i*Fstep_MHz;// Calculate current frequency
SetDDSFreq(current_freq_MHz*1000000); // Set DDS to current frequency
//delay(10); // Wait a little for settling
delay(100);
REV = analogRead(A0); // Read the reverse voltages
FWD = analogRead(A1); // forward voltages
REV = REV-5; //Offset Correction
if(REV>=FWD){REV = FWD-1;}
if (REV <1) {REV = 1;}
VSWR = (FWD+REV)/(FWD-REV);
VSWR = VSWR * 1000; //Scale Output
Serial.print(current_freq_MHz*1000000); // Send current line back to PC over serial bus
Serial.print(",0,");
Serial.print(VSWR);
Serial.print(",");
Serial.print(FWD);
Serial.print(",");
Serial.println(REV);
vswrArray[z] = VSWR/1000; //Submitter SWR to Array
if (vswrArray[z] > 10) vswrArray[z] = 10; //Max SWR
if (vswrArray[z] < SwrMin && vswrArray[z] > 1){ //Minimum SWR
SwrMin = vswrArray[z]; //Minimum SWR and frequency store
SwrFreq = current_freq_MHz;
}
z = z + 1;
}
// Send "End" to PC to indicate end of sweep
Serial.println("End");
Serial.flush();
//Zeichne Grid
CreateGrid();
//Linienfarbe = rot
ucg.setColor(255, 0, 0); //rot
// Draw Line
// 30 = swr 10 210 = swr 0
// Diff swr 10 = 180
// swr 2 = 18 * 2
double last = 10;
double xx = 6;
int j = 1;
for (int i = 1 ;i < 103; i++){
xx = vswrArray[i];
ucg.drawLine(j,210-last*18, j+1, 210-xx*18);
ucg.drawLine(j+1,210-last*18, j+2, 210-xx*18);
j = j + 3;
last = xx;
}
}
// Setze DDS Frequenz-----------------------------------------------------------------
void SetDDSFreq(double Freq_Hz){
int32_t f = Freq_Hz * 4294967295/125000000; // Calculate the DDS word - from AD9850 Datasheet
for (int b=0;b<4;b++,f>>=8){ // Send one byte at a time
send_byte(f & 0xFF);
}
send_byte(0); // 5th byte needs to be zeros(AD9850 Command Parameters)
digitalWrite(FQ_UD,HIGH); // Strobe the Update pin to tell DDS to use values
digitalWrite(FQ_UD,LOW);
}
// Sende Daten an DDS-----------------------------------------------------------------
void send_byte(byte data_to_send){
for (int i=0; i<8; i++,data_to_send>>=1){ // Bit bang the byte over the SPI bus
digitalWrite(SDAT,data_to_send & 0x01); // Set Data bit on output pin
digitalWrite(SCLK,HIGH); // Strobe the clock pin
digitalWrite(SCLK,LOW);
}
}
//Zeichne Grid auf TFT Display--------------------------------------------------------
void CreateGrid(){
//ucg.clearScreen();
double maxSwr = 10;
ucg.drawHLine(0,120,310);
ucg.drawHLine(0,196,310);
ucg.drawVLine(78,30,180);
ucg.drawVLine(155,30,180);
ucg.drawVLine(233,30,180);
ucg.setPrintPos(0, 235);
ucg.print(Freq1,3);
ucg.setPrintPos(130, 235);
ucg.print(Freq2,3);
ucg.setPrintPos(260, 235);
ucg.print(Freq3,3);
ucg.setPrintPos(10, 15);
ucg.print("SWR");
ucg.setPrintPos(70, 15);
ucg.print(SwrMin,2);
ucg.setPrintPos(115, 15);
ucg.print(">");
ucg.setPrintPos(130, 15);
ucg.print(maxSwr,2);
ucg.setPrintPos(250, 15);
//ucg.print((freqCenter/1000000*1.05),3);
ucg.print(SwrFreq,3);
ucg.drawRFrame(0,30,310,180, 1);
}
// Interrupt Service Routine----------------------------------------------------------
// Abfrage Low an Pin 2
void key2(){
counter = counter + 1; //ignoriere Startup Interrupts > counter
//Entprellen mit millis()
millinew = millis();
if (millinew - milliold < 1000){
milliold = millinew;
return;
}
milliold = millinew;
Fstart_MHz = 1; // Start Frequency for sweep
Fstop_MHz = 30; // Stop Frequency for sweep
num_steps = 102; // Steps
Freq1 = 1; // Unterste Zeile Display Freq. Links
Freq2 = 15; // Unterste Zeile Display Freq. Mitte
Freq3 = 30; // Unterste Zeile Display Freq. Recht
//Perform_sweep();
flag = 1;
}
// Interrupt Service Routine----------------------------------------------------------
// Abfrage Low an Pin 3
void key3()
{
counter = counter + 1; //ignoriere Startup Interrupts > counter
millinew = millis(); //Entprellen mit millis()
if (millinew - milliold < 1000){
milliold = millinew;
return;
}
milliold = millinew;
int x = SwrFreq + 0.5; //Runde auf Mhz
Fstart_MHz = x-1; // Start Frequency for sweep
Fstop_MHz = x+1; // Stop Frequency for sweep
num_steps = 102; // Steps
Freq1 = x-1; // Unterste Zeile Display Freq. Links
Freq2 = x; // Unterste Zeile Display Freq. Mitte
Freq3 = x+1; // Unterste Zeile Display Freq. Rechts
//Perform_sweep();
flag = 1;
}
2015年10月9日金曜日
TA7358 X'tal Converter
TA7358を使ったクリコン。50MHz用として作ったが、coilと水晶を選べば、簡単に目的の周波数の物が出来る。coilは、手巻き品の為、FCZ coilデータの通り、巻いた。 ファイルは、JA2GQP's Download siteに全てupしてある。(FCZ coilは、data sheetホルダー)
回路図である。電源は、供給電圧の自由度からレギュレータなどを入れてない。50MHz IF7.3MHzとしたが、この周波数に拘る事は無い。
PCBサイズ 47 × 43
回路図である。電源は、供給電圧の自由度からレギュレータなどを入れてない。50MHz IF7.3MHzとしたが、この周波数に拘る事は無い。
PCBサイズ 47 × 43
2015年10月4日日曜日
DSP6959 50MHz AM RX
DSP6959を使った50MHz AM受信機である。DSP6959を親機に、TA7358のクリコンと組合わせた。親機の受信周波数が連続してない為、希望の受信周波数に見合う水晶発振子を選らばなければならない。手持ちの水晶発振子から10.24MHz(4逓倍の40.96MHz)、43.3MHzの2候補があった。両方共コンバータとして動作させる事が出来たが、感度重視で43.3MHzを選んだ。また、チューニング用ボリュームとシリーズの抵抗は、受信範囲を狭くする為に入れてある。その結果、受信範囲50.485MHz~50.650MHzとなった。
回路図である。スピーカは、ROUTまたはLOUTとGNDに繋ぐのではなく、ROUTとLOUTに繋ぐ。これを間違えるると3V時、0.23A位の電流が流れる。本機の電流は、0.04A~0.06A。
基板サイズ 82 x 47
回路図である。スピーカは、ROUTまたはLOUTとGNDに繋ぐのではなく、ROUTとLOUTに繋ぐ。これを間違えるると3V時、0.23A位の電流が流れる。本機の電流は、0.04A~0.06A。
基板サイズ 82 x 47
2015年9月9日水曜日
Arduino AD9834 DDS VFO PCB版
Arduino AD9850 VFOのプログラムを移植。開発は、Arduino IDE1.6.5r5で行ったが、相変わらずlcd.printにバグがある。プログラムは、このバグ対策済。
回路図である。2次高調波低減の為、バッファアンプのベース抵抗を2.2kから4.7k。(プロトタイプの回路図と同じ)
修正後
IDEのバージョンに関係なく、正常表示する様、モジュールを変更。
//---------- Function STEP Display ----------
void Fnc_Step_Disp(){
lcd.setCursor(0,1);
switch(Enc_Stp){
case 10:
lcd.print("10 ");
break;
case 100:
lcd.print("100 ");
break;
case 1000:
lcd.print("1k ");
break;
case 10000:
lcd.print("10k ");
break;
case 100000:
lcd.print("100k");
break;
}
}
回路図である。2次高調波低減の為、バッファアンプのベース抵抗を2.2kから4.7k。(プロトタイプの回路図と同じ)
Bug改修部分
修正前
Arduino IDE 1.0.Xで、正常表示するが、IDE1.6.Xで誤表示する。
//---------- Function STEP Display ----------
void Fnc_Step_Disp(){
lcd.setCursor(0,1);
lcd.print(" "); // Clear step display
lcd.setCursor(0,1);
if(1 <= (Enc_Stp / 1000)){ // kiro?
lcd.print(Enc_Stp / 1000); // Yes,Convert kiro
lcd.print("k");
}
else{
lcd.print(Enc_Stp);
}
}
修正後
IDEのバージョンに関係なく、正常表示する様、モジュールを変更。
//---------- Function STEP Display ----------
void Fnc_Step_Disp(){
lcd.setCursor(0,1);
switch(Enc_Stp){
case 10:
lcd.print("10 ");
break;
case 100:
lcd.print("100 ");
break;
case 1000:
lcd.print("1k ");
break;
case 10000:
lcd.print("10k ");
break;
case 100000:
lcd.print("100k");
break;
}
}
program
Arduino AD9850 DDS VFOを移植。Fnc_Dds以外殆ど同じ。
//////////////////////////////////////////////////////////////////////
// AD9834 DDS VFO Premixed type program ver.1.0
//
// Copyright(C)2014.JA2GQP.All rights reserved.
//
// 7.000MHz to 7.200MHz Limitted.
// (Target frequency = IF frquency + frequency)
// 2014/12/29
// JA2GQP
//--------------------------------------------------------------------
// Function
// 1.Upper Heterodyne(Target Frequency = IF Frequency + Frequency)
// 2.RIT Operation(-50kHZ to 50kHZ)
// 3.STEP(100k,10k,1k,100,10)
// 4.Memory Operation is Push RIT
// (Frequency and Step)
// 5.Protection Operation At The Time Of Transmission
// 6.Channel Memory.Main Channel(Ch0) + 3 Channel(Ch1,Ch2,Ch3)
// 7.Split Operation(7.00MHz to 7.20MHz Limited!)
//--------------------------------------------------------------------
// Bug fix
// 1.2015/9/9 Arduino IDE 1.6.X lcd.print Fnc_Step_Disp()
//////////////////////////////////////////////////////////////////////
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <rotary.h>
#include <EEPROM.h>
//---------- LCD Pin Assign ------------------
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for
// a 16 chars and 2 line display
//---------- Define Constant Value ----------
const byte ENC_A = 2; // Encorder A
const byte ENC_B = 3; // B
const byte SDATA = 4; // AD9834 SDATA
const byte SCLK = 5; // SCLK
const byte FSYNC = 6; // FSYNC
const byte SW_STEP = 7; // STEP Sw
const byte SW_RIT = 8; // RIT Sw
const byte SW_SPLIT = 9; // SPLIT Sw
const byte SW_CH1 = 10; // Channel 1
const byte SW_CH2 = 11; // 2
const byte SW_CH3 = 12; // 3
const byte SW_TX = 13; // TX Sw
const long IF_FRQ = 9996500L; // IF Frequency
const long LW_FRQ = 7000000L; // Lower Limit
const long HI_FRQ = 7200000L; // Upper Limit
const long DEF_FRQ = 7050000L; // Init Frequency
const long DEF_STP = 1000L; // Init STEP
const long LW_RIT = -50000L; // RIT Lower Limit
const long HI_RIT = 50000L; // Upper Limit
const long LW_VFO = IF_FRQ + LW_FRQ; // Vfo Lower Limit
const long HI_VFO = IF_FRQ + HI_FRQ; // Upper Limit
const long DEF_VFO = IF_FRQ + DEF_FRQ; // Vfo Default Frequency
const unsigned long DDS_CLK = 56000000L; // AD9834 Clock 56Mhz
const unsigned long TWO_E28 = 268435456L; // 2^28
//---------- EEPROM Memory Address ----------
const byte Frq_Eep0 = 0x00; // Frequency Ch0
const byte Frq_Eep1 = 0x04; // Ch1
const byte Frq_Eep2 = 0x08; // Ch2
const byte Frq_Eep3 = 0x0c; // Ch3
const byte Stp_Eep0 = 0x10; // STEP Ch0
const byte Stp_Eep1 = 0x14; // Ch1
const byte Stp_Eep2 = 0x18; // Ch2
const byte Stp_Eep3 = 0x1c; // Ch3
//---------- Encorder Pin Assign(INT) --------
Rotary r = Rotary(ENC_A,ENC_B); // 2 = ENC_A,3 = ENC_B
//---------- Memory Assign -------------------
long Vfo_Dat = 0; // VFO Data
long Dds_Dat = 0; // DDS Data
long Rit_Dat = 0; // RIT Data
long Rit_Datb = 0; // RIT Data Old
long Enc_Stp = 0; // STEP
long Lng_Wk1 = 0; // Long Work1
long Lng_Wk2 = 0; // Long Work2
char *Lcd_Dat = " "; // Lcd Display Buffer
byte Byt_Chn = 0; // Channel SW
byte Byt_Chnb = 0; // Channel SW Old
byte Flg_Rit = 0; // RIT Flag
byte Flg_Ritb = 0; // RIT Flag Old
byte Flg_Tx = 0; // TX Flag
byte Flg_Spl = 0; // SPLIT Flag
//---------- Initialization Program ---------------
void setup(){
lcd.init(); // initialize the lcd
lcd.backlight(); // LCD backlight on
pinMode(SW_STEP,INPUT_PULLUP);
pinMode(SW_RIT,INPUT_PULLUP);
pinMode(SW_SPLIT,INPUT_PULLUP);
pinMode(SW_TX,INPUT_PULLUP);
pinMode(SW_CH1,INPUT_PULLUP);
pinMode(SW_CH2,INPUT_PULLUP);
pinMode(SW_CH3,INPUT_PULLUP);
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei(); // INT Enable
pinMode(FSYNC,OUTPUT);
pinMode(SCLK,OUTPUT);
pinMode(SDATA,OUTPUT);
Flg_Tx = 0;
Flg_Rit = 0;
Flg_Spl = 0;
lcd.clear();
Fnc_Chsw(); // Channel Sw Read
Byt_Chnb = Byt_Chn;
Fnc_Eep_Rd(); // EEPROM Read
}
//---------- Main program ---------------
void loop() {
if(Flg_Tx == 0){ // Tx off?
if(digitalRead(SW_STEP) == LOW){ // STEP Sw On?
Fnc_Stp(); // Yes,STEP proc.
}
if(digitalRead(SW_RIT) == LOW){ // RIT Sw On?
Fnc_Rit(); // Yes,RIT proc.
}
if(digitalRead(SW_SPLIT) == LOW){ // SPLIT Sw On?
Fnc_Spl(); // Yes,SPLIT proc.
}
Fnc_Chsw(); // Channel Sw read
if(Byt_Chnb != Byt_Chn){ // Channnel SW Chenge?
if(Byt_Chnb == 0){ // Channnel 0?
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep0); // Yes,Vfo_Dat Save
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep0); // Enc_Step Save
Flg_Ritb = Flg_Rit;
Rit_Datb = Rit_Dat;
Flg_Rit = 0;
Flg_Spl = 0;
Rit_Dat = 0;
}
if(Byt_Chnb != 0){ // Other(Ch1-Ch3) Channnel?
Flg_Rit = 0;
Flg_Spl = 0;
if((Byt_Chn == 0) && (Flg_Ritb == 1)){
Flg_Rit = 1;
Rit_Dat = Rit_Datb;
}
}
Byt_Chnb = Byt_Chn;
Fnc_Eep_Rd();
}
}
if(digitalRead(SW_TX) == LOW){ // Tx On?
Flg_Tx = 1; // Yes,Flg_Tx Set
}
else{
Flg_Tx = 0; // No,Flg_Tx Reset
}
if(Flg_Rit == 1){ // RIT?
Dds_Dat = Vfo_Dat + Rit_Dat; // Yes,Dds_Dat Set
}
else{
Dds_Dat = Vfo_Dat; // No,Dds_Dat Set
}
if(Flg_Tx == 1){ // Tx?
if(Flg_Spl == 1){ // SPLIT?
Dds_Dat = Vfo_Dat + Rit_Dat; // Yes,Dds_Dat Set
}
else{
Dds_Dat = Vfo_Dat; // No,Dds_Dat Set
}
}
Fnc_Dds(Dds_Dat); // AD9850 DDS Out
Fnc_Lcd(); // LCD Display
delay(100);
}
//---------- Encorder procedure(INT) ---------------
ISR(PCINT2_vect) {
unsigned char result = r.process();
if(Flg_Tx == 0){
if(result) {
if(result == DIR_CW){
Lng_Wk1 = Vfo_Dat + Enc_Stp;
Lng_Wk2 = Rit_Dat + Enc_Stp;
}
else{
Lng_Wk1 = Vfo_Dat - Enc_Stp;
Lng_Wk2 = Rit_Dat - Enc_Stp;
}
if((Flg_Rit == 1) || (Flg_Spl == 1)){
Rit_Dat = Lng_Wk2;
}
else{
Vfo_Dat = Lng_Wk1;
Rit_Dat = 0;
}
Vfo_Dat = constrain(Vfo_Dat,LW_VFO,HI_VFO);
if(Flg_Spl == 1){
Rit_Dat = constrain(Rit_Dat,(LW_VFO - Vfo_Dat),(HI_VFO - Vfo_Dat));
}
else{
Rit_Dat = constrain(Rit_Dat,LW_RIT,HI_RIT);
}
}
}
}
//---------- Function DDS set ---------------
void Fnc_Dds(double frquency){
unsigned long wrk = frquency * TWO_E28 / DDS_CLK;
unsigned int wrk1,wrk2,wrk3;
wrk1 = 0x2000;
wrk2 = wrk & 0x3fff;
wrk2 = wrk2 | 0x4000;
wrk3 = wrk >> 14;
wrk3 = wrk3 & 0x3fff;
wrk3 = wrk3 | 0x4000;
digitalWrite(SCLK,HIGH); // Added 2014/12/29
digitalWrite(FSYNC,LOW);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk1 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk1);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk2 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk2);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk3 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk3);
digitalWrite(FSYNC,HIGH);
}
//---------- Function Encorder STEP ---------
void Fnc_Stp(){
if(Enc_Stp == 10){ // Step = 10Hz ?
Enc_Stp = 100000; // Yes,100khz set
}
else{
Enc_Stp = Enc_Stp / 10; // Step down 1 digit
}
delay(250);
Fnc_Step_Disp();
Fnc_Lcd();
while(digitalRead(SW_STEP) == LOW)
;
delay(250);
}
//---------- Function STEP Display ----------
void Fnc_Step_Disp(){
lcd.setCursor(0,1);
switch(Enc_Stp){
case 10:
lcd.print("10 ");
break;
case 100:
lcd.print("100 ");
break;
case 1000:
lcd.print("1k ");
break;
case 10000:
lcd.print("10k ");
break;
case 100000:
lcd.print("100k");
break;
}
}
//---------- Function String Dot Edit --------
char *Fnc_Dot_Edit(char *str,long n){
int i = 0; // Write the number
char *p = str;
unsigned long u = abs(n);
do{
*p++ = "0123456789"[u % 10];
u = u / 10;
i++;
if((0 != u) && (0 == (i % 3)))
*p++ = '.';
}
while( 0 != u );
if ( n < 0 )
*p++ = '-';
*p = '\0';
Fnc_Revr( str );
return str;
}
//---------- Function String Reverse ---------
void Fnc_Revr(char *str){
int i,n;
char c;
n=strlen(str);
for(i = 0;i < n / 2;i++){
c=str[i];
str[i]=str[n - i - 1];
str[n - i - 1]=c;
}
}
//---------- Function Save EEPROM 2byte ---------
void Fnc_Eep_Sav2(unsigned int value,int address){
address += 1;
for(int i = 0;i < 2;i++){
byte toSave = value & 0xFF;
if(EEPROM.read(address) != toSave){
EEPROM.write(address,toSave);
}
value = value >> 8;
address--;
}
}
//---------- Function Save EEPROM 4byte ---------
void Fnc_Eep_Sav4(long value,int address){
address += 3;
for(int i = 0;i < 4;i++){
byte toSave = value & 0xFF;
if(EEPROM.read(address) != toSave){
EEPROM.write(address,toSave);
}
value = value >> 8;
address--;
}
}
//---------- Function Load EEPROM 2byte ---------
unsigned int Fnc_Eep_Lod2(int address){
unsigned int value = EEPROM.read(address);
value = value << 8;
return value | EEPROM.read(address + 1);
}
//---------- Function Load EEPROM 4byte ---------
long Fnc_Eep_Lod4(int address){
long value = 0;
for(int i = 0;i < 4;i++){
value = value | EEPROM.read(address);
if( i < 3){
value = value << 8;
address++;
}
}
return value;
}
//---------- Function LCD Display ---------
void Fnc_Lcd(){
if(Flg_Tx == 1){
lcd.setCursor(0,0);
lcd.print("T");
}
else{
lcd.setCursor(0,0);
lcd.print(Byt_Chn);
}
Fnc_Step_Disp();
if(Flg_Rit == 1){
lcd.setCursor(5,1);
lcd.print("R: ");
Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
lcd.setCursor(7,1);
lcd.print(Lcd_Dat);
if((Rit_Dat >= 1000) || (Rit_Dat <= -1000)){
lcd.print("k");
}
}
if(Flg_Spl == 1){
lcd.setCursor(5,1);
lcd.print("X: ");
Fnc_Dot_Edit(Lcd_Dat,Rit_Dat);
lcd.setCursor(7,1);
lcd.print(Lcd_Dat);
if((Rit_Dat >= 1000) || (Rit_Dat <= -1000)){
lcd.print("k");
}
}
if((Flg_Rit == 0) && (Flg_Spl == 0)){
Fnc_Dot_Edit(Lcd_Dat,Vfo_Dat - IF_FRQ);
lcd.setCursor(1,0);
lcd.print(": ");
lcd.setCursor(3,0);
lcd.print(Lcd_Dat);
lcd.print("MHz");
lcd.setCursor(5,1);
lcd.print(" JA2GQP");
}
}
//---------- Function Rit ---------
void Fnc_Rit(){
if(Flg_Rit == 0){
Rit_Dat = 0;
Flg_Rit = 1;
Flg_Spl = 0;
switch(Byt_Chn){
case 1:
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep1);
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep1);
break;
case 2:
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep2);
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep2);
break;
case 3:
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep3);
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep3);
break;
default:
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep0);
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep0);
break;
}
}
else{
Flg_Rit = 0;
}
while(digitalRead(SW_RIT) == LOW)
;
delay(250);
}
//---------- Function Channel SW Check ---------
void Fnc_Chsw(){
if(digitalRead(SW_CH1) == LOW){
Byt_Chn = 1;
}
else if(digitalRead(SW_CH2) == LOW){
Byt_Chn = 2;
}
else if(digitalRead(SW_CH3) == LOW){
Byt_Chn = 3;
}
else{
Byt_Chn = 0;
}
}
//---------- Function EEPROM Read ---------
void Fnc_Eep_Rd(){
if(Fnc_Eep_Lod4(Frq_Eep0) <= LW_VFO){
Vfo_Dat = DEF_VFO;
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep0);
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep1);
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep2);
Fnc_Eep_Sav4(Vfo_Dat,Frq_Eep3);
}
else{
switch(Byt_Chn){
case 1:
Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep1);
break;
case 2:
Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep2);
break;
case 3:
Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep3);
break;
default:
Vfo_Dat = Fnc_Eep_Lod4(Frq_Eep0);
break;
}
}
if(Vfo_Dat <= 0){
Vfo_Dat = DEF_VFO;
}
if(Fnc_Eep_Lod4(Stp_Eep0) <= 0){
Enc_Stp = DEF_STP;
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep0);
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep1);
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep2);
Fnc_Eep_Sav4(Enc_Stp,Stp_Eep3);
}
else{
switch(Byt_Chn){
case 1:
Enc_Stp = Fnc_Eep_Lod4(Stp_Eep1);
break;
case 2:
Enc_Stp = Fnc_Eep_Lod4(Stp_Eep2);
break;
case 3:
Enc_Stp = Fnc_Eep_Lod4(Stp_Eep3);
break;
default:
Enc_Stp = Fnc_Eep_Lod4(Stp_Eep0);
break;
}
}
if(Enc_Stp <= 0){
Enc_Stp = DEF_STP;
}
}
//---------- Function Split ---------
void Fnc_Spl(){
if(Flg_Spl == 0){
Flg_Spl = 1;
Flg_Rit = 0;
Rit_Dat = 0;
}
else{
Flg_Spl = 0;
}
while(digitalRead(SW_SPLIT) == LOW)
;
delay(250);
}
Arduino AD9834 DDS PCB
Arduino UNO版AD9834 DDSをPCB化した。このPCBテストの為、水晶発振器代替(チャンネル切替方式)7MHz用にAD9851のプログラムを移植した。試験するには、コンパクトなプログラムなので重宝する。DDS発振周波数は、送信時、7.195MHz、7.181MHz、7.160MHz。また、受信時は、0Hz(DDS発振停止)。
回路図である。バッファアンプのベース抵抗は、2次高調波低減の為、4.7kとした。プログラムで使わないI/Oは、書いてない。
基本波のスペクトラム。
広帯域増幅なので致し方ないが、バッファアンプ付加により、n次のスプリアスがある。4次以降のスプリアスは、見当らなかった。この程度であれば、アプリケーションで対応可能だ。
電源電圧5V時、出力4mW。バッファアンプの電源は、VINからでもジャンパー出来るので、出力アップ可能。
基板サイズ 69 x 54。
オシレターは、正方形、長方形に対応。
//////////////////////////////////////////////////////////////////////
// AD9834 DDS VFO Premixed type program ver.1.0
//
// Copyright(C)2014.JA2GQP.All rights reserved.
// Crystal replacement
// 2015/9/8
// JA2GQP
//--------------------------------------------------------------------
// Function
// 1.ch0=7.195Mhz ch1=7.181Mhz ch2=7.160Mhz ch3=7.195Mhz
// 2.TX=chenel frequency RX=0Hz(off)
//////////////////////////////////////////////////////////////////////
//---------- Define Constant Value ----------
const byte SDATA = 4; // AD9834 SDATA
const byte SCLK = 5; // SCLK
const byte FSYNC = 6; // FSYNC
const byte SW_CH1 = 10; // Channel 1
const byte SW_CH2 = 11; // 2
const byte SW_CH3 = 12; // 3
const byte SW_TX = 13; // TX Sw
const long FRQ_CH0 = 7195000L; // CH0=7.195Mhz
const long FRQ_CH1 = 7181000L; // CH1=7.181Mhz
const long FRQ_CH2 = 7160000L; // CH2=7.160Mhz
const long FRQ_CH3 = 7195000L; // CH3=7.195Mhz
const unsigned long DDS_CLK = 56000000L; // AD9834 Clock 56Mhz
const unsigned long TWO_E28 = 268435456L; // 2^28
//---------- Memory Assign -------------------
long Dds_Dat = 0; // DDS Data
//---------- Initialization Program ---------------
void setup(){
pinMode(SW_TX,INPUT_PULLUP); // Input pin set
pinMode(SW_CH1,INPUT_PULLUP);
pinMode(SW_CH2,INPUT_PULLUP);
pinMode(SW_CH3,INPUT_PULLUP);
pinMode(FSYNC,OUTPUT); // Output pin set
pinMode(SCLK,OUTPUT);
pinMode(SDATA,OUTPUT);
}
//---------- Main program ---------------
void loop() {
if(digitalRead(SW_CH1) == LOW){
Dds_Dat = FRQ_CH1;
}
else if(digitalRead(SW_CH2) == LOW){
Dds_Dat = FRQ_CH2;
}
else if(digitalRead(SW_CH3) == LOW){
Dds_Dat = FRQ_CH3;
}
else{
Dds_Dat = FRQ_CH0;
}
if(digitalRead(SW_TX) == HIGH){ // Rx?
Dds_Dat = 0L;
}
Fnc_Dds(Dds_Dat);
delay(100);
}
//---------- Function DDS set ---------------
void Fnc_Dds(double frquency){
unsigned long wrk = frquency * TWO_E28 / DDS_CLK;
unsigned int wrk1,wrk2,wrk3;
wrk1 = 0x2000;
wrk2 = wrk & 0x3fff;
wrk2 = wrk2 | 0x4000;
wrk3 = wrk >> 14;
wrk3 = wrk3 & 0x3fff;
wrk3 = wrk3 | 0x4000;
digitalWrite(SCLK,HIGH); // Added 2014/12/29
digitalWrite(FSYNC,LOW);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk1 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk1);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk2 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk2);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk3 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk3);
digitalWrite(FSYNC,HIGH);
}
回路図である。バッファアンプのベース抵抗は、2次高調波低減の為、4.7kとした。プログラムで使わないI/Oは、書いてない。
基本波のスペクトラム。
広帯域増幅なので致し方ないが、バッファアンプ付加により、n次のスプリアスがある。4次以降のスプリアスは、見当らなかった。この程度であれば、アプリケーションで対応可能だ。
電源電圧5V時、出力4mW。バッファアンプの電源は、VINからでもジャンパー出来るので、出力アップ可能。
基板サイズ 69 x 54。
オシレターは、正方形、長方形に対応。
program
7MHz AM送信機用に周波数が設定してある。受信時は、発振停止。クロックは、手持ちの部品で周波数を選んで56MHzとしたが、この周波数に拘る事は無い。//////////////////////////////////////////////////////////////////////
// AD9834 DDS VFO Premixed type program ver.1.0
//
// Copyright(C)2014.JA2GQP.All rights reserved.
// Crystal replacement
// 2015/9/8
// JA2GQP
//--------------------------------------------------------------------
// Function
// 1.ch0=7.195Mhz ch1=7.181Mhz ch2=7.160Mhz ch3=7.195Mhz
// 2.TX=chenel frequency RX=0Hz(off)
//////////////////////////////////////////////////////////////////////
//---------- Define Constant Value ----------
const byte SDATA = 4; // AD9834 SDATA
const byte SCLK = 5; // SCLK
const byte FSYNC = 6; // FSYNC
const byte SW_CH1 = 10; // Channel 1
const byte SW_CH2 = 11; // 2
const byte SW_CH3 = 12; // 3
const byte SW_TX = 13; // TX Sw
const long FRQ_CH0 = 7195000L; // CH0=7.195Mhz
const long FRQ_CH1 = 7181000L; // CH1=7.181Mhz
const long FRQ_CH2 = 7160000L; // CH2=7.160Mhz
const long FRQ_CH3 = 7195000L; // CH3=7.195Mhz
const unsigned long DDS_CLK = 56000000L; // AD9834 Clock 56Mhz
const unsigned long TWO_E28 = 268435456L; // 2^28
//---------- Memory Assign -------------------
long Dds_Dat = 0; // DDS Data
//---------- Initialization Program ---------------
void setup(){
pinMode(SW_TX,INPUT_PULLUP); // Input pin set
pinMode(SW_CH1,INPUT_PULLUP);
pinMode(SW_CH2,INPUT_PULLUP);
pinMode(SW_CH3,INPUT_PULLUP);
pinMode(FSYNC,OUTPUT); // Output pin set
pinMode(SCLK,OUTPUT);
pinMode(SDATA,OUTPUT);
}
//---------- Main program ---------------
void loop() {
if(digitalRead(SW_CH1) == LOW){
Dds_Dat = FRQ_CH1;
}
else if(digitalRead(SW_CH2) == LOW){
Dds_Dat = FRQ_CH2;
}
else if(digitalRead(SW_CH3) == LOW){
Dds_Dat = FRQ_CH3;
}
else{
Dds_Dat = FRQ_CH0;
}
if(digitalRead(SW_TX) == HIGH){ // Rx?
Dds_Dat = 0L;
}
Fnc_Dds(Dds_Dat);
delay(100);
}
//---------- Function DDS set ---------------
void Fnc_Dds(double frquency){
unsigned long wrk = frquency * TWO_E28 / DDS_CLK;
unsigned int wrk1,wrk2,wrk3;
wrk1 = 0x2000;
wrk2 = wrk & 0x3fff;
wrk2 = wrk2 | 0x4000;
wrk3 = wrk >> 14;
wrk3 = wrk3 & 0x3fff;
wrk3 = wrk3 | 0x4000;
digitalWrite(SCLK,HIGH); // Added 2014/12/29
digitalWrite(FSYNC,LOW);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk1 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk1);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk2 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk2);
shiftOut(SDATA,SCLK,MSBFIRST,(wrk3 >> 8));
shiftOut(SDATA,SCLK,MSBFIRST,wrk3);
digitalWrite(FSYNC,HIGH);
}
2015年8月27日木曜日
AD9851 DDS 50Mhz水晶発振子代替PCB版
Arduino UNOを使ったAD9851 DDS水晶発振子代替PCB版。公開中のプロトタイプをPCB化した物で、パターン引き回し上、DIOアドレスを変更。 水晶発振子代替と表現しているが、水晶発振クオリティを目指したものでは無い。 DDSクオリテイのチャンネル切替式である。バッファアンプは同調方式を採用し、クリーンな増幅をしている。簡易スペアナで見る限り、スプリアスは見当たらない。ただ、受信機でモニターすると、多少、ざわつき(DDS固有かも知れないが・・・)を感じる。問題になるレベルでないと思う。
回路図である。チャンネル切替方式に必要な所以外、書いてない。チェンネル切替が不要であれば、50.6Mhz(デフォルト)一波となる。送信切替は、接点入力/電圧入力可能。出力は、真空管ドライブ可能なレベルである。
基板サイズ 69 x 54
//////////////////////////////////////////////////////////////////////
// AD9851 DDS VFO Premixed type program ver.1.0
//
// Copyright(C)2014-2015.JA2GQP.All rights reserved.
// Crystal replacement
// 2015/8/26
// JA2GQP
//--------------------------------------------------------------------
// Function
// 1.ch0=50.6Mhz ch1=50.55Mhz ch2=50.62Mhz ch3=50.69Mhz
// 2.TX=chenel frequency RX=0Hz(off)
//////////////////////////////////////////////////////////////////////
//---------- Define Constant Value ----------
const byte DATA = 12; // DIO12
const byte W_CLK = 14; // DIO14
const byte FQ_UD = 15; // DIO15
const byte SW_CH1 = 9; // Channel 1
const byte SW_CH2 = 10; // 2
const byte SW_CH3 = 11; // 3
const byte SW_TX = 13; // TX Sw
const byte DDS_RST = 8; // DDS Reset
const long FRQ_CH0 = 50600000L; // CH0=50.6Mhz
const long FRQ_CH1 = 50550000L; // CH1=50.55Mhz
const long FRQ_CH2 = 50620000L; // CH2=50.62Mhz
const long FRQ_CH3 = 50690000L; // CH3=50.69Mhz
const unsigned long DDS_CLK = 192000000L; // AD9851 Clock(32MHz * 6)
const unsigned long TWO_E32 = 4294967295L; // 2^32
const byte DDS_CMD = B00000001; // AD9851 Command
//---------- Memory Assign -------------------
long Dds_Dat = 0; // DDS Data
//---------- Initialization Program ---------------
void setup(){
pinMode(SW_TX,INPUT_PULLUP); // Input pin set
pinMode(SW_CH1,INPUT_PULLUP);
pinMode(SW_CH2,INPUT_PULLUP);
pinMode(SW_CH3,INPUT_PULLUP);
pinMode(DDS_RST,OUTPUT); // Output pin set
pinMode(FQ_UD,OUTPUT);
pinMode(W_CLK,OUTPUT);
pinMode(DATA,OUTPUT);
Fnc_Dds_Int(); // DDS Initial
}
//---------- Main program ---------------
void loop() {
if(digitalRead(SW_CH1) == LOW){
Dds_Dat = FRQ_CH1;
}
else if(digitalRead(SW_CH2) == LOW){
Dds_Dat = FRQ_CH2;
}
else if(digitalRead(SW_CH3) == LOW){
Dds_Dat = FRQ_CH3;
}
else{
Dds_Dat = FRQ_CH0;
}
if(digitalRead(SW_TX) == HIGH){ // Rx?
Dds_Dat = 0L;
}
Fnc_Dds(Dds_Dat);
delay(100);
}
//---------- Function DDS Initialization ---------------
void Fnc_Dds_Int(){
digitalWrite(DDS_RST,HIGH);
delay(1);
digitalWrite(DDS_RST,LOW);
digitalWrite(W_CLK,HIGH);
digitalWrite(W_CLK,LOW);
digitalWrite(FQ_UD,HIGH);
digitalWrite(FQ_UD,LOW);
}
//---------- Function DDS set ---------------
void Fnc_Dds(double frquency){
unsigned long wrk = frquency * TWO_E32 / DDS_CLK;
digitalWrite(FQ_UD,LOW);
shiftOut(DATA,W_CLK,LSBFIRST,wrk);
shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 8));
shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 16));
shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 24));
shiftOut(DATA,W_CLK,LSBFIRST,DDS_CMD); // AD9851 command
digitalWrite(FQ_UD,HIGH);
}
回路図である。チャンネル切替方式に必要な所以外、書いてない。チェンネル切替が不要であれば、50.6Mhz(デフォルト)一波となる。送信切替は、接点入力/電圧入力可能。出力は、真空管ドライブ可能なレベルである。
基板サイズ 69 x 54
Program(スケッチ)
50Mhz AM 送信用水晶発振子の代替とすべく、チャンネル周波数を設定している。このプログラムでは、受信時、DDS発振を停止している。送受用DDSに変更も簡単だ。//////////////////////////////////////////////////////////////////////
// AD9851 DDS VFO Premixed type program ver.1.0
//
// Copyright(C)2014-2015.JA2GQP.All rights reserved.
// Crystal replacement
// 2015/8/26
// JA2GQP
//--------------------------------------------------------------------
// Function
// 1.ch0=50.6Mhz ch1=50.55Mhz ch2=50.62Mhz ch3=50.69Mhz
// 2.TX=chenel frequency RX=0Hz(off)
//////////////////////////////////////////////////////////////////////
//---------- Define Constant Value ----------
const byte DATA = 12; // DIO12
const byte W_CLK = 14; // DIO14
const byte FQ_UD = 15; // DIO15
const byte SW_CH1 = 9; // Channel 1
const byte SW_CH2 = 10; // 2
const byte SW_CH3 = 11; // 3
const byte SW_TX = 13; // TX Sw
const byte DDS_RST = 8; // DDS Reset
const long FRQ_CH0 = 50600000L; // CH0=50.6Mhz
const long FRQ_CH1 = 50550000L; // CH1=50.55Mhz
const long FRQ_CH2 = 50620000L; // CH2=50.62Mhz
const long FRQ_CH3 = 50690000L; // CH3=50.69Mhz
const unsigned long DDS_CLK = 192000000L; // AD9851 Clock(32MHz * 6)
const unsigned long TWO_E32 = 4294967295L; // 2^32
const byte DDS_CMD = B00000001; // AD9851 Command
//---------- Memory Assign -------------------
long Dds_Dat = 0; // DDS Data
//---------- Initialization Program ---------------
void setup(){
pinMode(SW_TX,INPUT_PULLUP); // Input pin set
pinMode(SW_CH1,INPUT_PULLUP);
pinMode(SW_CH2,INPUT_PULLUP);
pinMode(SW_CH3,INPUT_PULLUP);
pinMode(DDS_RST,OUTPUT); // Output pin set
pinMode(FQ_UD,OUTPUT);
pinMode(W_CLK,OUTPUT);
pinMode(DATA,OUTPUT);
Fnc_Dds_Int(); // DDS Initial
}
//---------- Main program ---------------
void loop() {
if(digitalRead(SW_CH1) == LOW){
Dds_Dat = FRQ_CH1;
}
else if(digitalRead(SW_CH2) == LOW){
Dds_Dat = FRQ_CH2;
}
else if(digitalRead(SW_CH3) == LOW){
Dds_Dat = FRQ_CH3;
}
else{
Dds_Dat = FRQ_CH0;
}
if(digitalRead(SW_TX) == HIGH){ // Rx?
Dds_Dat = 0L;
}
Fnc_Dds(Dds_Dat);
delay(100);
}
//---------- Function DDS Initialization ---------------
void Fnc_Dds_Int(){
digitalWrite(DDS_RST,HIGH);
delay(1);
digitalWrite(DDS_RST,LOW);
digitalWrite(W_CLK,HIGH);
digitalWrite(W_CLK,LOW);
digitalWrite(FQ_UD,HIGH);
digitalWrite(FQ_UD,LOW);
}
//---------- Function DDS set ---------------
void Fnc_Dds(double frquency){
unsigned long wrk = frquency * TWO_E32 / DDS_CLK;
digitalWrite(FQ_UD,LOW);
shiftOut(DATA,W_CLK,LSBFIRST,wrk);
shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 8));
shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 16));
shiftOut(DATA,W_CLK,LSBFIRST,(wrk >> 24));
shiftOut(DATA,W_CLK,LSBFIRST,DDS_CMD); // AD9851 command
digitalWrite(FQ_UD,HIGH);
}
登録:
投稿 (Atom)
















