VFOをどうするか。。。
これが、肝となっている。10MHzのトランシーバを”アナログ”で作ろうと思っているので構成はスーパーヘテロダインとなる。デバイスとしてはICを使おうと考えていて、往年のTA7358を使ってみようと思っている。
となると、VFOをどうするかが問題となるのだが、「トランシーバ製作入門」ではLC発振を3MHzとしてIFを7.2MHzとしている。
これに倣えば低い周波数でLOを供給できればよいので、アナデバのAD9833が候補に挙がってくる。以前7MHzの送信機を作ったときはAD9850で直接7MHzを供給させた。これを使い同じように10MHzを供給し、受信時には17MHzあるいは3MHzを供給すればよいのだが・・・なにか同じデバイスを使うのもつまらない。それに3MHzならばAD9833でいけそうだ。安いし。
AD9833VFO
IFを7.2MHzの4素子クリスタルのフィルターで帯域500Hz程度としたので供給周波数は2.9MHzとした。
出力波形(LowPass前)
AD9833の素の状態での出力波形。
2.9MHzを出力
ちなみに
10MHzを出力
やっぱり直接出力は難しいだろう。
出力波形(LowPass後)
3素子のLowPassフィルタ(回路図定数)を追加した。
2.9MHz近傍の波形
ここでちょっとわからなかったこと・・・。RBWを1kHzとしたら・・・
スケッチ 2024/12/25
元はAD7CさんのAD9850VFOのものをAD9833ライブラリとディスプレイにI2Cを使用した1602を使うための変更を施した。
/*
Main code by Richard Visokey AD7C - www.ad7c.com
Revision 2.0 - November 6th, 2013
https://www.instructables.com/Arduino-30MHZ-DDS-Signal-Generator-In-12/
*/
// Include the library code
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
#include <rotary.h>
//
#include <EEPROM.h>
#include <AD9833.h>
//https://github.com/Billwilliams1952/AD9833-Library-Arduino
//#include <digitalWriteFast.h>
//Setup some items
#define stepUpPin 5
#define stepDownPin 6
#define FNC_PIN 10
AD9833 gen(FNC_PIN);
Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses. Must be interrupt pins.
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16 chars and 2 line display
int_fast32_t rx=2902600; // Base (starting) frequency of VFO. This only loads once. To force load again see ForceFreq variable below.
int_fast32_t rx2=0; // variable to hold the updated frequency
int_fast32_t rxd=0; //for actual freq dysplay
int_fast32_t increment = 100; // starting VFO update increment in HZ.
int_fast32_t iffreq = 7197480; // Intermedite Frequency - Amount to subtract (-) from base frequency. ********************************************
int buttonstate = 0;
int buttonstate2 = 0;
String hertz = "100 Hz";
int hertzPosition = 4;
byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Placeholders
String freq; // string to hold the frequency
int_fast32_t timepassed = millis(); // int to hold the arduino miilis since startup
int memstatus = 1; // value to notify if memory is current or old. 0=old, 1=current.
int ForceFreq = 0; // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory. YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET!
void setup() {
pinMode(stepUpPin,INPUT); // Connect to a button that goes to GND on push
pinMode(stepDownPin,INPUT);
digitalWrite(stepUpPin,HIGH);
digitalWrite(stepDownPin,HIGH);
lcd.begin();
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
lcd.setCursor(hertzPosition,1);
lcd.print(hertz);
// Load the stored frequency
if (ForceFreq == 0) {
freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6));
rxd = freq.toInt();
rx=rxd-iffreq;
}
// Wave generate
gen.Begin();
gen.ApplySignal(SINE_WAVE,REG0,0);
gen.EnableOutput(true);
}
void loop() {
// Update the display and frequency if the new Freq NEQ the old Freq
if (rx != rx2){
showFreq();
gen.SetFrequency(REG0,rx);
rx2 = rx;
}
// Rotate through the rate of tuning as you hold down the button
buttonstate = digitalRead(stepUpPin);
if(buttonstate == LOW) {
setincrement();
};
// Rotate through the rate of tuning as you hold down the button
buttonstate2 = digitalRead(stepDownPin);
if(buttonstate2 == LOW) {
setincrement2();
};
// Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change.
if(memstatus == 0){
if(timepassed+2000 < millis()){
storeMEM();
}
}
}
// Interrupt routine to catch the rotary encoder
ISR(PCINT2_vect) {
unsigned char result = r.process();
if (result) {
if (result == DIR_CW){rx=rx+increment;}
else {rx=rx-increment;};
if (rx >=10000000){rx=rx2;}; // UPPER VFO LIMIT
if (rx <=0000000){rx=rx2;}; // LOWER VFO LIMIT
}
}
void setincrement(){
if(increment == 10){increment = 50; hertz = "50 Hz"; hertzPosition=5;}
else if (increment == 50){increment = 100; hertz = "100 Hz"; hertzPosition=4;}
else if (increment == 100){increment = 500; hertz="500 Hz"; hertzPosition=4;}
else if (increment == 500){increment = 1000; hertz="1 Khz"; hertzPosition=6;}
else if (increment == 1000){increment = 2500; hertz="2.5 Khz"; hertzPosition=4;}
else if (increment == 2500){increment = 5000; hertz="5 Khz"; hertzPosition=6;}
else if (increment == 5000){increment = 10000; hertz="10 Khz"; hertzPosition=5;}
else if (increment == 10000){increment = 100000; hertz="100 Khz"; hertzPosition=4;}
else if (increment == 100000){increment = 1000000; hertz="1 Mhz"; hertzPosition=6;}
else{increment = 10; hertz = "10 Hz"; hertzPosition=5;};
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(hertzPosition,1);
lcd.print(hertz);
delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed.
};
void setincrement2(){
if(increment == 1000000){increment = 100000; hertz = "100 khz"; hertzPosition=4;}
else if (increment == 100000){increment = 10000; hertz="10 Khz"; hertzPosition=5;}
else if (increment == 10000){increment = 5000; hertz="5 Khz"; hertzPosition=6;}
else if (increment == 5000){increment = 2500; hertz="2.5 Khz"; hertzPosition=4;}
else if (increment == 2500){increment = 1000; hertz="1 Khz"; hertzPosition=6;}
else if (increment == 1000){increment = 500; hertz="500 Hz"; hertzPosition=4;}
else if (increment == 500){increment = 100; hertz = "100 Hz"; hertzPosition=4;}
else if (increment == 100){increment = 50; hertz="50 Hz"; hertzPosition=5;}
else if (increment == 50){increment = 10; hertz="10 Hz"; hertzPosition=5;}
else{increment = 1000000; hertz = "1 Mhz"; hertzPosition=6;};
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(hertzPosition,1);
lcd.print(hertz);
delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed.
};
void showFreq(){
rxd=rx+iffreq;
millions = int(rxd/1000000);
hundredthousands = ((rxd/100000)%10);
tenthousands = ((rxd/10000)%10);
thousands = ((rxd/1000)%10);
hundreds = ((rxd/100)%10);
tens = ((rxd/10)%10);
ones = ((rxd/1)%10);
lcd.setCursor(0,0);
lcd.print(" ");
if (millions > 9){lcd.setCursor(1,0);}
else{lcd.setCursor(2,0);}
lcd.print(millions);
lcd.print(",");
lcd.print(hundredthousands);
lcd.print(tenthousands);
lcd.print(thousands);
lcd.print(".");
lcd.print(hundreds);
lcd.print(tens);
lcd.print(ones);
lcd.print(" KHz ");
timepassed = millis();
memstatus = 0; // Trigger memory write
};
void storeMEM(){
//Write each frequency section to a EPROM slot. Yes, it's cheating but it works!
EEPROM.write(0,millions);
EEPROM.write(1,hundredthousands);
EEPROM.write(2,tenthousands);
EEPROM.write(3,thousands);
EEPROM.write(4,hundreds);
EEPROM.write(5,tens);
EEPROM.write(6,ones);
memstatus = 1; // Let program know memory has been written
};
0 件のコメント:
コメントを投稿