TR-8200 1の8 外部VFOようやく完成


 い中、何とかこの休み中にとこちらの続きを。

 まずは残った部分の基板化検討。ちなみに各コネクタはすべて再利用品だったりします(^^;


 なんやかんやで基板化できたので、とりあえずケース内に仮留めして動作確認。


 実は動き出すまでにハンダ忘れ1件ハンダミス2件という体たらく…この程度の規模でこれでは、いけませんねぇ


 それはそれとして、このメータまわりの配線。


 あんまりいい案が思い浮かばないので、基板を貼り付けてしまいました。

 ちなみに各所の不細工なアルミテープは、元から空いてた穴から光が漏れ出るのを防ぐためのものです。


 それやこれやを経て、各基板の配置を決めて固定。
 制御基板はあとからソースを書き換えやすい(=USBケーブルを挿しやすい)ように、こんな向きにしてしまいました。
 一方出力基板はあとからシールドboxにいれることになっても大丈夫なように、配置に余裕を持たせてみました。できればその必要のないことを願ってますが。


 ダラダラとTR-8200との連絡ケーブルを作成し


 無事予定通り動き出しました。

 要調整のVFO出力レベルですが、結局元の通りでちょうどでした。
 ってこれ、考えてみたら当然ですよねぇ(^^;

 当分送信するつもりはない(そもそも免許されるかどうかも怪しい)んですが、気が向いたらダミー相手に送信してスプリアスをチェックしてみることにします。


 せっかくだからとつけてみたセンターメータ、実際に役に立つ機会はあんまりないかな。(1200じゃあるまいし)








 完成したらここに置いてみようと思ってたところへ設置して、室内アンテナでウォッチ中。
 しかし休日だからでしょうか、静かですねぇ。こんな田舎ではアンテナを外に出さないとダメってこともあるんでしょうけど。
 それにしてもメインで聞こえるCQ、次回どこそこでというアナウンスに追随できるのは便利ですねぇ(今さら)


 そのようなわけでお恥ずかしながら、今回の回路図はこちら。
 図面化には次の方々のツールやパーツを利用させていただきました。ありがとうございます。
回路図エディタBSch3V - 水魚堂さん
BSch3V用パーツライブラリ - 下間さん
BSch3V Arduino ライブラリ - OStanさん

 続いてこちらもお恥ずかしいソース(スケッチ)を。
 ご覧いただいてお分かりの通り、ほとんどオリジナルから変わってません。大きく変わっているのは「表示周波数と発振周波数は別」という概念を導入したところくらいです。その部分について記述が3箇所あるのがスマートではないんですが…ま、そのあたりはいずれまた。

/*
* Arduino Si5351A 7MHz VFO OLED Display
* 2020.12.29
* JH7UBC Keiji Hata
* 
* Modified for TR-8200
* by Sugi JI3KDH
* June 4 - June 11, 2023
*/

#include <Wire.h>
#include <SSD1306AsciiAvrI2c.h>
#include <Rotary.h>

SSD1306AsciiAvrI2c oled;
Rotary r = Rotary(2, 3);

//initialize digital pin output
const int LED_PIN = 13;
void setup_LED() {
  pinMode(LED_PIN, OUTPUT);
}

//initialize Si5351A
#define Si5351A_ADDR 0x60
#define MSNA_ADDR 26
#define MSNB_ADDR 34
#define MS0_ADDR 42
#define MS1_ADDR 50
#define MS2_ADDR 58
#define CLK0_CTRL 16
#define CLK1_CTRL 17
#define CLK2_CTRL 18
#define OUTPUT_CTRL 3
#define XTAL_LOAD_C 183
#define PLL_RESET 177
uint32_t XtalFreq = 25000000;
uint32_t divider;
uint32_t PllFreq;
uint8_t mult;
uint32_t num;
uint32_t denom;
uint32_t l;
float f;
uint32_t P1;
uint32_t P2;
uint32_t P3;
char PLL;
uint8_t PLL_ADDR;
uint8_t MS_ADDR;

//frequency STEP
#define SW_STEP 4 //frequency STEP button

//setting frequencies
const long LOW_FREQ = 431000000; //freq low limit
const long HI_FREQ = 439980000; //freq high limit
unsigned long FREQ = 433000000; //freq default
unsigned long FREQ_OLD = FREQ; //freq previous value
unsigned long FREQ_OUT = FREQ / 3 - 10700000 - 124433400; //freq output for TR-8200
int dF = 194; //freq delta-f
unsigned long STEP = 20000; //STEP default

//Rotary Encoder external break-in routine
void rotary_encoder(){
unsigned char result = r.process();
if(result){
if(result == DIR_CW){
FREQ = FREQ + STEP;
}else{
FREQ = FREQ - STEP;
}
}
FREQ = constrain(FREQ,LOW_FREQ,HI_FREQ); //bandwidth limits
}

//when STEP SW is turned ON
void Fnc_Stp()
{
if(STEP == 20000){
STEP = 1000000;
digitalWrite(LED_PIN, HIGH);   //turn the LED on (HIGH is the voltage level)
}
else{
STEP = 20000;
digitalWrite(LED_PIN, LOW);    //turn the LED off by making the voltage LOW
}
delay(10);
Step_Disp(STEP);
while(digitalRead(SW_STEP) == LOW){
delay(10);
}
}

void setup() {
r.begin(); //initial setting for rotaly encorder
attachInterrupt(0,rotary_encoder,CHANGE); //external breakin setting
attachInterrupt(1,rotary_encoder,CHANGE);
pinMode(SW_STEP,INPUT_PULLUP); //set as input for STEP SW with pullup
oled.begin(&Adafruit128x64, 0x3C); //OLED initiarize

Si5351_init(); //Si5351A initiarize
FREQ_OUT = FREQ / 3 - 10700000 - 124433400 ; //freq output for TR-8200
PLL_Set('A',FREQ_OUT + dF); //default freq setting for VFO
MS_Set(0);

//default screen settings
oled.setFont(font5x7);
oled.setCursor(5,0);
oled.print("Arduino Si5351A VFO");
oled.setFont(font5x7);
oled.setCursor(5,7);
oled.print("STEP");
Freq_Disp(FREQ); //freq display
Step_Disp(STEP); //STEP display
Freq_out_Disp(FREQ_OUT); //freq_out display
}

//Main program
void loop() {
if(digitalRead(SW_STEP) == LOW){Fnc_Stp();} //change STEP when STEP SW on
if(FREQ != FREQ_OLD){ //change freq of Si5351A when FREQ is changed
FREQ_OUT = FREQ / 3 - 10700000 - 124433400;
PLL_Set('A',FREQ_OUT + dF);
MS_Set(0);
Freq_Disp(FREQ); //displaying freq
Freq_out_Disp(FREQ_OUT);
FREQ_OLD = FREQ; //saving chagned freq
}
delay(10);
}

//freq display
void Freq_Disp(unsigned long Fre){
String freqt = String(Fre);
oled.setFont(CalBlk36);
oled.setCursor(3,2);
oled.print(freqt.substring(0,3) + "." + freqt.substring(3,5) + " ");
}

//freq_out display
void Freq_out_Disp(unsigned long Fre_out){
String freqt_out = String(Fre_out);
if (freqt_out.substring(0,1) != "1"){
  freqt_out = " " + freqt_out;
}
else{
  ;
}
oled.setFont(font5x7);
oled.setCursor(70,7);
oled.print(freqt_out.substring(0,2) + "." + freqt_out.substring(2));
}

//step display
void Step_Disp(int Stp){
oled.setFont(font5x7);
oled.setCursor(30,7);
if(Stp == 20000){
oled.print(" 20k");
}else{
oled.print(" 1M ");
}
}

//set 1 byte to register
void Si5351_write(byte Reg , byte Data){
Wire.beginTransmission(Si5351A_ADDR);
Wire.write(Reg);
Wire.write(Data);
Wire.endTransmission();
}


//initiarize Si5351A
void Si5351_init(){
Si5351_write(OUTPUT_CTRL,0xFF); //Disable Output
Si5351_write(CLK0_CTRL,0x80); //CLOCK0 Power down
Si5351_write(CLK1_CTRL,0x80); //CLOCK1 Power down
Si5351_write(CLK2_CTRL,0x80); //CLOCK2 Power down
Si5351_write(XTAL_LOAD_C,0x80); //Crystal Load Capasitance=8pF
Si5351_write(PLL_RESET,0xA0); //Reset PLLA and PLLB
Si5351_write(CLK0_CTRL,0x4F); //CLOCK0 Power up 8mA
Si5351_write(CLK1_CTRL,0x4F); //CLOCK1 Power up
Si5351_write(CLK2_CTRL,0x4F); //CLOCK2 Power up
Si5351_write(OUTPUT_CTRL,0xFE); //Enable CLOCK0
}

//setting PLL
void PLL_Set(char Pll,uint32_t Frequency){
divider = 900000000 / Frequency;
if (divider % 2) divider--;
PllFreq = divider * Frequency;
mult = PllFreq / XtalFreq;
l = PllFreq % XtalFreq;
f = l;
f *= 1048575;
f /= XtalFreq;
num = f;
denom = 1048575;
P1 = (uint32_t)(128 * ((float)num /(float)denom));
P1 = (uint32_t)(128 * (uint32_t)(mult) + P1 - 512);
P2 = (uint32_t)(128 * ((float)num / (float)denom));
P2 = (uint32_t)(128 * num -denom * P2);
P3=denom;

if (Pll == 'A'){
PLL_ADDR = MSNA_ADDR;
}else{
PLL_ADDR = MSNB_ADDR;
}
Parameter_write(PLL_ADDR,P1,P2,P3);
}

//setting MultiSynth (bunshuuki)
void MS_Set(uint8_t MS_No){
P1 = 128 * divider - 512;
P2 = 0;
P3 = 1;
switch(MS_No){
case 0:
MS_ADDR = MS0_ADDR;
break;
case 1:
MS_ADDR = MS1_ADDR;
break;
case 2:
MS_ADDR = MS2_ADDR;
break;
default:
MS_ADDR = MS0_ADDR;
}
Parameter_write(MS_ADDR,P1,P2,P3);
}

//write paramators P1,P2,P3 into register
void Parameter_write(uint8_t REG_ADDR,uint32_t Pa1,uint32_t Pa2,uint32_t Pa3)
{
Si5351_write(REG_ADDR + 0,(Pa3 & 0x0000FF00) >> 8);
Si5351_write(REG_ADDR + 1,(Pa3 & 0x000000FF));
Si5351_write(REG_ADDR + 2,(Pa1 & 0x00030000) >> 16);
Si5351_write(REG_ADDR + 3,(Pa1 & 0x0000FF00) >> 8);
Si5351_write(REG_ADDR + 4,(Pa1 & 0x000000FF));
Si5351_write(REG_ADDR + 5,((Pa3 & 0x000F0000) >> 12) | ((Pa2 & 0X000F0000) >> 16));
Si5351_write(REG_ADDR + 6,(Pa2 & 0x0000FF00) >> 8);
Si5351_write(REG_ADDR + 7,(Pa2 & 0x000000FF));
}

 今後について

1) TR-8200用外部VFOとして
・電源OFF直前の周波数を再現したい…ArduinoのEEPROMを使えばいいんですが、ここには書き込み回数の制限があるので闇雲に書き込むわけにいきません。例えばボタン長押しで記憶させるとか、状態が一時間続いたら保存するとか…いろいろと方法はありそうですが思いつく限りではいずれもあんまりスマートではないですねぇ

2) 他機種の外部VFOとして
・実はVFO-20/30/40が接続できる機種なら、ほぼこのまま使えるのではないかと睨んでます。まずコネクタの仕様が同じらしいことと、周波数も似たような感じなので、ソースの書き換えだけでいけそう。さしあたって手元のTR-1300なんかで試してみても面白いかも
・SSB/CW機に接続するならRITやスプリットの機能も欲しいところですが、そうなると物理的なスイッチの増設も必要になってくるかな
・外部VFO入力のない水晶式無線機の場合、どこにどう注入するかという問題もありますが、それよりも送受で別の周波数というのが結構高めなハードルです。ただこのSi5351Aには完全に独立した出力が二つあるので、さほど難しい問題でもないのかなという印象です。もちろんPLL部分の記述をまるで理解してない自分がやるには相当難しいんですが(^^;;


 ところでしばらくウォッチしてたところ、8200のフロントパネル上部が異常に熱を持っていることに気づきました。
 原因はここに使われてるパイロットランプの模様。どうもあとから手を入れられてるようで、抵抗を介して6V3Wという電球が使われてました。
 どうりで明るくてキレイだなと感じたわけですが


 異常な発熱はあんまりよろしくないのでLED化してしまいました。
 電球色のものを3本使ったこともあり、そんなに違和感なくできているのでは? と悦に入っております。

コメント(4)

24c32などのEEPROMを増設してみてはどうでしょうか?

 ありがとうございます。

 最初いただいたコメントを拝見したとき「外付けにしても書き込み回数に限度あるのは一緒やしなあ」と思ったんですよ。
 でもよくよく考えたら外付けにした場合、限度に達したらそのチップだけ交換すればいいし、そうでなくても読み書きするアドレスを順繰りにしていけば延命は可能かなと思い直しました。

 そして…それやこれやを考えるうちに、自分的にちょっと面白そうなことを思いついてしまいまして。
 というのも、問題になりそうな書き込みのタイミングを「電源が切れたとき」にすればいいんやないかと。そのためには小さなバッテリをつないでおいて、電源が切れた瞬間に書き込みをしてからシャットダウン。
 こうすれば書き込み回数の制限に達することはまずなさそうですし、機能的にも満足できそう。

 そのような事例がすでにあるかもですので、ボチボチ調べてみることにします。例によっていつになるやら、ですが。

あっその手がありましたか!
それならスーパーキャパシタで実用化できそうですね!

┌-------->Vct
--->l----->VCC
_____|C___>GND

...上の落書きのような感じでどうですか?

 数秒間(5秒くらい?)はArduino全体に供給する必要があるので、スーパーキャパシタではちょっと足りないように思いますが、いずれにしましてもまずはいろいろと調べてみることにします。

コメントする

この記事について

このページは、ji3kdhが2023年7月17日(月) 15:15に書いた記事です。

ひとつ前の記事は「TR-8200 1の7 外部VFOのフロントパネル加工」です。

次の記事は「久しぶりにBillboard Live Osakaへ」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。