TS-830無線機 DDS VFO
TS-830は水晶発振10MHz基準に各周波数をPLL制御で構成されています。ただし、VFOがアナログ発振(バリコン可変)なので周波数が時間とともにズレます。
以前作ったことがあるDDS VFOが使えないか調べたら詳しい内容の記事がありました【http://jf1vru.web.fc2.com/vfo/ddsvfo7.html】
使い慣れたArduino NanoとAD9850使いDDS出力をアンプしLPFを通しDDS_VFO出力します(オシロスコープで出力を内部VFOと同じ出力にVR調整)
パネルVFOスイッチによりMvfoSW信号がリレーをOFF/ON、リレーOFFで+9VがVFO切替信号に接続(内部VFO)、リレーONでDDS_VFO出力が本体に接続(外部VFO)。
現在TS-830は受信専用機として使用しています。エンコーダは30年前購入したネミコン製MKE-500-2(現在は製造中止?)
回路図
#include <Rotary.h> // https://github.com/brianlow/Rotary
#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <EF_AD9850.h>
// EF_AD9850(CLK,FQ_UP,RESET,DATA)
EF_AD9850 AD9850(9, 10, 11, 8);
//アドレス0x27 16文字2行の液晶
LiquidCrystal_I2C lcd(0x27, 16, 2);
Rotary r = Rotary(2, 3); // Rotary encoder for frequency connects to interrupt pins
#define MvfoSW A0
#define RitSW A1
#define StepSW A2
#define HoldSW A3
int CwMode = 4;
int TxMode = 5;
int Relay = 6;
//long unsigned int freq = 1000; // Set initial frequency.
long freq = 5500000; //VFO 5.5 - 6 MHZ
//long unsigned int freqOld = freq;
long freqOld = freq;
char disp_buf[16];
char disp_buf2[16];
long stepf = 100; //1Hz 10Hz 100Hz
long ritf = 0;
long ritfOld = 0;
int cw = 0 ; //cw ssb
int tx = 0 ; //send
int rl = 0 ; //relay
int wr = 0 ; //ad9850 write
int offset = 1 ; //dds_frequency offset
void updateDisplay() {
if (freq < 1000) {
sprintf(disp_buf, "%10ld", freq);
}
else if (freq < 1000000) {
int freqL = freq % 1000;
int freqM = freq / 1000;
sprintf(disp_buf, "%6d,%03d", freqM, freqL);
}
else {
int freqL = freq % 1000;
int freqM = (freq / 1000) % 1000;
int freqH = freq / 1000000;
sprintf(disp_buf, "%2d,%03d,%03d", freqH, freqM, freqL);
}
lcd.setCursor(3, 1);
lcd.print(disp_buf);
lcd.print("Hz");
}
//encoder interrupt
ISR(PCINT2_vect) { //rx holdsw_off
if (digitalRead(HoldSW) == HIGH && digitalRead(TxMode) == HIGH){
if (digitalRead(RitSW) == HIGH ){ //rit off
unsigned char result = r.process();
if (result) {
if (result == DIR_CW) {
if ((freq + stepf) <= 6000000) freq += stepf;
} else {
if ((freq - stepf) >= 5500000) freq -= stepf;
}
if (freq <= 1) freq = 1;
if (freq >= 6000000) freq = 6000000;
}
}
if (digitalRead(RitSW) == LOW ){ //rit on
unsigned char result = r.process();
if (result) {
if (result == DIR_CW) {
if ((ritf + stepf) <= 10000) ritf += stepf;
} else {
if ((ritf - stepf) >= -10000) ritf -= stepf;
}
if (ritf >= 10000) ritf = 10000;
if (ritf <= -10000) ritf = -10000;
}
}
}
}
void setup() {
pinMode(2, INPUT); // Pins for interrupt-driven rotary encoder and push buttons
pinMode(3, INPUT);
pinMode(MvfoSW, INPUT_PULLUP);
pinMode(RitSW, INPUT_PULLUP);
pinMode(StepSW, INPUT_PULLUP);
pinMode(HoldSW, INPUT_PULLUP);
pinMode(CwMode, INPUT_PULLUP);
pinMode(TxMode, INPUT_PULLUP);
pinMode(Relay, OUTPUT);
// Configure interrupt and enable for rotary encoder.
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("AD9850");
lcd.setCursor(0, 1);
lcd.print("DDS VFO");
delay(2000);
lcd.clear();
lcd.setCursor (0, 0);
lcd.print("RX");
lcd.setCursor (0, 1);
lcd.print("SSB");
// Initialise the AD9850 module.
AD9850.init();
AD9850.reset();
AD9850.wr_serial(0x00, freq+offset);
updateDisplay();
}
void loop() {
if (digitalRead(CwMode) == HIGH){ //ssb
if(cw=10000){
lcd.setCursor(0, 1);
lcd.print(" ");
cw=0;
}
cw=cw+1;
}
if (digitalRead(TxMode) == HIGH){ //rx
if(tx=10000) {
lcd.setCursor(0, 0);
lcd.print(" ");
tx=0;
}
tx=tx+1;
}
if (digitalRead(MvfoSW) == LOW){ //main vfo
if(rl=10000) {
digitalWrite(Relay, HIGH);
rl=0;
}
rl=rl+1;
}
if (digitalRead(MvfoSW) == HIGH){ //dds vfo
if(rl=10000) {
digitalWrite(Relay, LOW);
rl=0;
}
rl=rl+1;
}
if (digitalRead(StepSW) == LOW){ //dds 100hz
stepf = 100;
}
if (digitalRead(StepSW) == HIGH){ //dds 10hz
stepf = 10;
}
if (digitalRead(TxMode) == LOW ){ //send
delay(50);
if (digitalRead(CwMode) == LOW ){ //cw
lcd.setCursor(0, 1);
lcd.print("CW ");
lcd.setCursor(0, 0);
lcd.print("SEND");
AD9850.wr_serial(0x00, freq+offset+800 ); // freq+800
while(digitalRead(TxMode) == LOW){
if(wr=10000) { //ad9850 write 1/10000
AD9850.wr_serial(0x00, freq+offset+800);
wr=0;
}
wr=wr+1;
}
AD9850.wr_serial(0x00, freq+offset );
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(" ");
delay(50);
}
if (digitalRead(CwMode) == HIGH ){ //ssb
lcd.setCursor(0, 1);
lcd.print("SSB ");
lcd.setCursor(0, 0);
lcd.print("SEND");
AD9850.wr_serial(0x00, freq+offset ); // freq+800
while(digitalRead(TxMode) == LOW){
if(wr=10000) { //ad9850 write 1/10000
AD9850.wr_serial(0x00, freq+offset );
wr=0;
}
wr=wr+1;
}
AD9850.wr_serial(0x00, freq+offset );
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(" ");
delay(50);
}
}
if (digitalRead(RitSW) == LOW && digitalRead(TxMode) == HIGH){ //rx rit_on
lcd.setCursor (13, 0);
lcd.print("RIT");
stepf = 1; //1HZ
while(digitalRead(RitSW) == LOW && digitalRead(TxMode) == HIGH){
if (ritfOld != ritf) {
AD9850.wr_serial(0x00, freq+offset+ritf);
ritfOld=ritf;
lcd.setCursor (3, 0);
sprintf(disp_buf2, "%10ld", ritf);
lcd.print(disp_buf2);
lcd.print("RIT");
}
if(wr=10000) { //ad9850 write 1/10000
AD9850.wr_serial(0x00, freq+offset+ritf);
wr=0;
}
wr=wr+1;
}
ritf = ritfOld;
ritfOld = ritfOld-1;
freq = freqOld;
freqOld = freqOld-1;
lcd.clear();
}
if (freqOld != freq) {
AD9850.wr_serial(0x00, freq+offset);
updateDisplay();
freqOld = freq;
}
if(wr=10000) { //ad9850 write 1/10000
AD9850.wr_serial(0x00, freq+offset);
wr=0;
}
wr=wr+1;
}
0 件のコメント:
コメントを投稿