位相制御のVFO [VFO]
pico版のuSDXwp目指している途中で、位相制御のVFO部分だけをnanoで作ってみました。Si5351のライブラリーを使ったのでスケッチはとてもシンプルになりました。
しかし問題が二つあります。一つは予想できたことですがコンパイル後の実行ファイルが大きくなって、ATmega168のnanoではフラッシュメモリ少なくてインストールできません。ATmega328が必要です。
もう一つは、PLLの周波数が600〜900MHzの範囲である必要があって、位相差を指定するためにはSi5351の基準発信周波数の整数倍でないといけない制約があります。
27MHzなら27x23=621MHz 位相差の制御は7ビットなので 621/128=4.851MHzが最小の周波数になります。
25MHzなら25x24=600MHz 600/128=4.69MHzMHzです。したがって3.5MHzでは使えません。
周波数表示は0.91のOLEDです。
ロータリーエンコーダーのプッシュスイッチで周波数のステップ数を変更しています。(1kHz、100Hz、10Hzです)
再生できない場合、ダウンロードは🎥こちら
回路図とスケッチを載せておきます。
---------------------------------------------------------------------------------------
-----------------------------------------------------------------------
私は27MHzで作りましたが、25MHzの場合はSi5351初期化で、
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27003411, 0); 二つ目の引数を0(デフォルトで25MHzが指定されます)にしてください。(赤文字の部分、このスケッチでは周波数の補正をしています)
しかし問題が二つあります。一つは予想できたことですがコンパイル後の実行ファイルが大きくなって、ATmega168のnanoではフラッシュメモリ少なくてインストールできません。ATmega328が必要です。
もう一つは、PLLの周波数が600〜900MHzの範囲である必要があって、位相差を指定するためにはSi5351の基準発信周波数の整数倍でないといけない制約があります。
27MHzなら27x23=621MHz 位相差の制御は7ビットなので 621/128=4.851MHzが最小の周波数になります。
25MHzなら25x24=600MHz 600/128=4.69MHzMHzです。したがって3.5MHzでは使えません。
周波数表示は0.91のOLEDです。
ロータリーエンコーダーのプッシュスイッチで周波数のステップ数を変更しています。(1kHz、100Hz、10Hzです)
再生できない場合、ダウンロードは🎥こちら
回路図とスケッチを載せておきます。
---------------------------------------------------------------------------------------
/*
位相制御VFO 2023年2月13日 JR3XNW
Etherkit Si5351 - Arduino Library https://github.com/etherkit/Si5351Arduino
*/
#include
#include
#include
#include
SSD1306AsciiAvrI2c oled;
Rotary r = Rotary(2, 3);
Si5351 si5351;
//////////////////////////
// ステップスイッチ
//////////////////////////
#define SW_STEP 4 // 周波数ステップ
//////////////////////////
// レジスターのセット
//////////////////////////
unsigned long FREQ = 7000000; //
unsigned long long FREQ_ULL = 700000000ULL; //0.01Hzまでの設定・64ビットのデータ型
unsigned long long pll_freq = 75600000000ULL; //0.01Hzまでの設定・64ビットのデータ型
const long LOW_FREQ = 7000000; // 下限周波数
const long HI_FREQ = 7200000; // 上限周波数
unsigned long FREQ_OLD = FREQ; // old frequency
int STEP = 1000; // STEP(default)
int phase; //90°位相差設定
//////////////////////////
// Rotary Encoder 外部割込み処理ルーチン
//////////////////////////
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); //VFOの下限と上限を超えないように
FREQ_ULL = FREQ * 100ULL;
}
//////////////////////////
//STEP SWが押された時の処理
//////////////////////////
void Fnc_Stp()
{
if(STEP == 10){
STEP = 1000;
}
else{
STEP /= 10;
}
delay(10);
Step_Disp(STEP);
while(digitalRead(SW_STEP) == LOW){
delay(10);
}
}
//////////////////////////
// setup
//////////////////////////
void setup()
{
r.begin();//ロータリーエンコーダ初期化
attachInterrupt(0,rotary_encoder,CHANGE); //外部割込み設定
attachInterrupt(1,rotary_encoder,CHANGE);
pinMode(SW_STEP,INPUT_PULLUP); //STEP SW 入力に設定しプルアップ
oled.begin(&Adafruit128x32, 0x3C); //OLED初期化
Wire.begin();
// Si5351初期化
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27003411, 0); //二つ目の引数はSi5351の基準発信周波数(補正値を加えている)25MHzの場合は0(デフォルト)
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_4MA); //出力2mAはおよそ3dBm/8mAはおよそ10dBmの出力・3段階の設定
oled.setFont(font8x8);
oled.setCursor(6,3);
oled.print("step:");
Freq_Set();
Freq_Disp(FREQ); //周波数表示
Step_Disp(STEP); //STEP表示
}
//////////////////////////
// loop
//////////////////////////
void loop()
{
if(digitalRead(SW_STEP) == LOW){Fnc_Stp();} //STEP SWが押されたら、周波数STEPを変更
if(FREQ != FREQ_OLD){
Freq_Set();
Freq_Disp(FREQ);
FREQ_OLD = FREQ;
}
delay(10);
}
//////////////////////////
// 周波数設定
//////////////////////////
void Freq_Set(){
// Set CLK0 and CLK1
si5351.set_freq_manual(FREQ_ULL, pll_freq, SI5351_CLK0);
si5351.set_freq_manual(FREQ_ULL, pll_freq, SI5351_CLK1);
phase = pll_freq / FREQ_ULL + 0.5; //PLL周波数/発信周波数 90°の位相差設定数値 四捨五入
si5351.set_phase(SI5351_CLK0, 0);
si5351.set_phase(SI5351_CLK1, phase); //90°の位相差
// 位相が揃う前にPLLをリセットする
si5351.pll_reset(SI5351_PLLA);
delay(10);
}
//////////////////////////
/// 周波数表示
//////////////////////////
void Freq_Disp(unsigned long Fre){
String freqt = String(Fre);
oled.setFont(lcdnums14x24);
oled.setCursor(0,0);
oled.print(freqt.substring(0,1) + "." + freqt.substring(1,4) + "." + freqt.substring(4));
}
//////////////////////////
// ステップ数表示
//////////////////////////
void Step_Disp(int Stp){
oled.setFont(font8x8);
oled.setCursor(46,3);
if(Stp == 1000){
oled.print(" 1K");
}else if(Stp == 100){
oled.print("100");
}else{
oled.print(" 10");
}
}
-----------------------------------------------------------------------
私は27MHzで作りましたが、25MHzの場合はSi5351初期化で、
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27003411, 0); 二つ目の引数を0(デフォルトで25MHzが指定されます)にしてください。(赤文字の部分、このスケッチでは周波数の補正をしています)
コメント 0