無線機の製作記録の全てを公開してます。 https://sites.google.com/view/ja2gqpから必要なファイルをダウンロードできます。 このBlogは、詳細な説明は一切行っておらず、ある程度のスキルが要求されます。 質問に応じますが、カスタマイズは対応しません。尚、コメントは誰でも出来る様に変更しました。
2017年3月21日火曜日
RF Analyzer
何時もお世話になっている松浦OMのRF Analyzerを作った。このAnalyzerは、2.8"TFT(オリジナルは、2.2"TFT)を使用し、スタンドアーロンでSG、パワーメータ、周波数応答、アンテナアナライザなどの機能がある。今回、1ボードのユニバーサル基板で作り、ジャンクのHubケースに納めた。シールド対策を施した結果、ノイズフロアレベル-70dB(測定用ケーブルなしでの裸特性)となった。
2017年2月28日火曜日
スイッチング電源
2017年度クラブ製作講習会に当たり、色々検討した結果、スイッチング電源装置の試作を行う事にした。この電源は、半田付けが殆どなく、市販モジュール配線と板金加工で完成する。仕様は、固定出力13.8V(max10A)と可変出力2V~11V(max1A)を切替え、電圧・電流を表示。大きさ100x50x230、質量620g。
固定出力(max10A)の写真。AJDスイッチをoffすると、固定出力(13.8V)となる。表示器の最大電流は10Aである為、スイッチング電源の能力に余裕が有っても、最大10A表示となる。
可変出力(max1A)の写真。AJDスイッチをonすると、可変出力となる。可変範囲は2V~11V。
上から見た写真。小型に作った為、配線が窮屈となった。
回路図。
固定出力(max10A)の写真。AJDスイッチをoffすると、固定出力(13.8V)となる。表示器の最大電流は10Aである為、スイッチング電源の能力に余裕が有っても、最大10A表示となる。
可変出力(max1A)の写真。AJDスイッチをonすると、可変出力となる。可変範囲は2V~11V。
上から見た写真。小型に作った為、配線が窮屈となった。
回路図。
2017年1月24日火曜日
stm32duino
H/Wインストール(USBを使う場合)
USB規格ではD +に1.5kのプルアップ抵抗が必要だが、このボードは誤った値(R10 10kまたは、4.7k)となっている事が知られている。R10を1.5kまたは、1.8kに交換する事が必要である。但し、PCとのマージンの問題なので、通信が行えない場合のみ、改造すれば良い。
stm32duinoインストール
- Arduino IDE 1.6.9をここでダウンロードしてインストールする。
- IDEを実行し、ツールメニューでボードマネージャを選択し、使用可能なボードのリストからArduino Zeroを検索し、ARM CortexーM0+をインストールする。
- STM32のZIPファイルを含むファイルをダウンロード。
- 解凍してArduino_STM32フォルダを作成する。但し、フォルダ名は変更しない事。
- Arduino_STM32フォルダをMy Documents / Arduino / hardwareにコピーする。 (hardwareフォルダが存在しない場合は、作成する必要がある)
Arduino IDE 1.6.9を使う様に書いて有るが、IDE 1.8.1を 使っても問題は起きてない。(但し、全ての機能を試した訳でない)
Bootloader(書込みしない)
Bootloaderとは、スケッチをマイコンボードに書込み、ロードなどを行うstm32f103c8t6のF/Wである。PCからシリアルまたは、ST-LINKを使う場合、Bootloader書込みは不要。USBを使う場合、Bootloader書込みが必要となるが、Power onまたはReset後、スケッチがロードされる迄に数秒待たなければプログラムが動作しない為、USBは使えない。
stm32f103c8t6に書き込まれたオリジナルのF/Wを使えば良い。
BOOTスイッチ(基板上のDIP SW)
ST-LINK V2
BOOT0 0側BOOT1 0側
書込み/Power onまたはRESET時とも同じ設定でOK。但し、シリアルモニタ機能は使えない。
シリアル
書込み時BOOT0 1側
BOOT1 0側
Power onまたはRESET時
BOOT0 0側
BOOT1 0側
シリアルモニタ機能が使える。
USBアダプタ
ST-LINK V2
アダプタ stm32f103c8t6
2pin SWDIO SWDIO
4pin GND GND
6pin SWCLK SWCLK
8pin 3.3V 3.3V
シリアル
左側(CH340G) stm32f103c8t6
TX A9
RX A10
3.3V 3.3V
GND GND
右側(FT232RL) stm32f103c8t6
RX A9
TX A10
3.3V 3.3V
GND GND
スケッチ(Lチカ)
// the setup function runs once when you press reset or power the boardvoid setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(PC13, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(PC13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(PC13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
2016年12月9日金曜日
バリキャップ容量測定治具
近頃バリキャップの入手が難しくなってきている。そこで、バリキャップの代替をする為に、測定治具を作った。LC meterにアダプタを付加する方式で、既存のLC meterの改造を行わない事にした。ツマミが付いた部分が、バリキャップ測定治具である。
測定治具は、アダプタ方式にしたので、取付/取外しが容易な構造にした。
回路図
バリキャップ代替
手持品の代替として使えそうな物の、特性を測った。
測定治具は、アダプタ方式にしたので、取付/取外しが容易な構造にした。
回路図
バリキャップ代替
手持品の代替として使えそうな物の、特性を測った。
2016年11月17日木曜日
Nextion TFT
Nextion 3.2"TFTを入手した。 このLCDは、インテリジェントTFTで、制御機器(PC,マイコンなど)からのシリアル通信で画面コントロールが出来る。最もシンプルの構成は、Nextionのみで動作する。マイコンなどによる画面制御では、メモリ、表示速度など神経を使わなければ出来ないアプリケーションも多々ある。表示部を分散した事で、より自由度の高いプログラムングが出来るであろう。今回、スイッチ画像を作り、タッチパネル操作でLED点灯/消灯る事が出来た。
開発は、 Nextion Editor とNextionに書き込む為の、USBアダプタ又は、マイクロSDカードが必要。SDカードは必須でなく、USBアダプタでもNextionに書込み出来る。SDカードを使う方が、書込み時間が少なく、お薦めである。
Nextion資料は、ライブラリ 、命令セット。また購入先は、こちら またはAliexpress、e-Bayなど。
NextionとUNOを使ったLチカ。画面をタッチすると、UNOのDIO(13)に接続のLEDが点灯/消灯する。
int charflag=0;
void setup() {
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop() {
if (Serial.available()>1)
{
if (charflag)
{
char2=Serial.read();
if (char2==0) digitalWrite(13,HIGH);
else if (char2==0x01) digitalWrite(13,LOW);
charflag=0;
}
else
{
char1=Serial.read();
if(char1==0x65) charflag=1;
}
}
}
NextionのHMIファイル、ArduinoスケッチなどダウンロードサイトのNextionフォルダからDownload可能。
開発は、 Nextion Editor とNextionに書き込む為の、USBアダプタ又は、マイクロSDカードが必要。SDカードは必須でなく、USBアダプタでもNextionに書込み出来る。SDカードを使う方が、書込み時間が少なく、お薦めである。
Nextion資料は、ライブラリ 、命令セット。また購入先は、こちら またはAliexpress、e-Bayなど。
NextionとUNOを使ったLチカ。画面をタッチすると、UNOのDIO(13)に接続のLEDが点灯/消灯する。
スケッチ
int char1,char2;int charflag=0;
void setup() {
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop() {
if (Serial.available()>1)
{
if (charflag)
{
char2=Serial.read();
if (char2==0) digitalWrite(13,HIGH);
else if (char2==0x01) digitalWrite(13,LOW);
charflag=0;
}
else
{
char1=Serial.read();
if(char1==0x65) charflag=1;
}
}
}
NextionのHMIファイル、ArduinoスケッチなどダウンロードサイトのNextionフォルダからDownload可能。
2016年10月27日木曜日
si5351a_TFT_Ver3.1 VFO
JA2NKD松浦OM開発のAD9850_TFT_Ver3.1(Multi-Band対応)をsi5351aに移植した。今回、機能追加は行わなかったので、チップが異なる以外、全く同じである。このVFOは、EEPROM初期値設定を別スケッチで書込みを行っている。同OMのBlogを読んで、設定されたい。EEPROM初期値設定スケッチがバージョンアップされて齟齬が危惧される為、Download siteにvfo_v3_eepスケッチのコピーを保存した。 IDEは、1.6.12(最新版)を使った。
Arduino nano/UNO対応の回路図である。スイッチ入力がアナログポートを使ったレベルによる入力判定を行っている。
////////////////////////////////////////////////////////////////////////
// Author: Hans Summers, 2015
// Website: http://www.hanssummers.com
//
// A very very simple Si5351a demonstration
// using the Si5351a module kit http://www.hanssummers.com/synth
// Please also refer to SiLabs AN619 which describes all the registers to use
//----------------------------------------------------------------------
// Addered: JA2GQP,2016/8/18
////////////////////////////////////////////////////////////////////////
#define I2C_START 0x08
#define I2C_START_RPT 0x10
#define I2C_SLA_W_ACK 0x18
#define I2C_SLA_R_ACK 0x40
#define I2C_DATA_ACK 0x28
#define I2C_WRITE 0b11000000
#define I2C_READ 0b11000001
#define SI_CLK0_CONTROL 16 // Register definitions
#define SI_CLK1_CONTROL 17
#define SI_CLK2_CONTROL 18
#define SI_SYNTH_PLL_A 26
#define SI_SYNTH_PLL_B 34
#define SI_SYNTH_MS_0 42
#define SI_SYNTH_MS_1 50
#define SI_SYNTH_MS_2 58
#define SI_PLL_RESET 177
#define SI_R_DIV_1 0b00000000 // R-division ratio definitions
#define SI_R_DIV_2 0b00010000
#define SI_R_DIV_4 0b00100000
#define SI_R_DIV_8 0b00110000
#define SI_R_DIV_16 0b01000000
#define SI_R_DIV_32 0b01010000
#define SI_R_DIV_64 0b01100000
#define SI_R_DIV_128 0b01110000
#define SI_CLK_SRC_PLL_A 0b00000000
#define SI_CLK_SRC_PLL_B 0b00100000
#define XTAL_FREQ 25000000 // Crystal frequency for Hans' board
uint8_t i2cStart(){
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) ;
return (TWSR & 0xF8);
}
void i2cStop(){
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
while ((TWCR & (1<<TWSTO))) ;
}
uint8_t i2cByteSend(uint8_t data){
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) ;
return (TWSR & 0xF8);
}
uint8_t i2cByteRead(){
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) ;
return (TWDR);
}
uint8_t i2cSendRegister(uint8_t reg, uint8_t data){
uint8_t stts;
stts = i2cStart();
if (stts != I2C_START)
return 1;
stts = i2cByteSend(I2C_WRITE);
if (stts != I2C_SLA_W_ACK)
return 2;
stts = i2cByteSend(reg);
if (stts != I2C_DATA_ACK)
return 3;
stts = i2cByteSend(data);
if (stts != I2C_DATA_ACK)
return 4;
i2cStop();
return 0;
}
uint8_t i2cReadRegister(uint8_t reg, uint8_t *data){
uint8_t stts;
stts = i2cStart();
if (stts != I2C_START)
return 1;
stts = i2cByteSend(I2C_WRITE);
if (stts != I2C_SLA_W_ACK)
return 2;
stts = i2cByteSend(reg);
if (stts != I2C_DATA_ACK)
return 3;
stts = i2cStart();
if (stts != I2C_START_RPT)
return 4;
stts = i2cByteSend(I2C_READ);
if (stts != I2C_SLA_R_ACK)
return 5;
*data = i2cByteRead();
i2cStop();
return 0;
}
// Init TWI (I2C)
//
void i2cInit(){
TWBR = 92;
TWSR = 0;
TWDR = 0xFF;
//#ifdef ARDUINO_AVR_MEGA2560
// PRR0 = 0;
//#else
PRR = 0;
//#endif
}
////////////////////////////////////////////////////////////////////////
// Set up specified PLL with mult, num and denom
// mult is 15..90
// num is 0..1,048,575 (0xFFFFF)
// denom is 0..1,048,575 (0xFFFFF)
///////////////////////////////////////////////////////////////////////
void setupPLL(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom){
uint32_t P1; // PLL config register P1
uint32_t P2; // PLL config register P2
uint32_t P3; // PLL config register P3
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;
i2cSendRegister(pll + 0, (P3 & 0x0000FF00) >> 8);
i2cSendRegister(pll + 1, (P3 & 0x000000FF));
i2cSendRegister(pll + 2, (P1 & 0x00030000) >> 16);
i2cSendRegister(pll + 3, (P1 & 0x0000FF00) >> 8);
i2cSendRegister(pll + 4, (P1 & 0x000000FF));
i2cSendRegister(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
i2cSendRegister(pll + 6, (P2 & 0x0000FF00) >> 8);
i2cSendRegister(pll + 7, (P2 & 0x000000FF));
}
////////////////////////////////////////////////////////////////////////
// Set up MultiSynth with integer divider and R divider
// R divider is the bit value which is OR'ed onto the appropriate
// register, it is a #define in si5351a.h
////////////////////////////////////////////////////////////////////////
void setupMultisynth(uint8_t synth, uint32_t divider, uint8_t rDiv){
uint32_t P1; // Synth config register P1
uint32_t P2; // Synth config register P2
uint32_t P3; // Synth config register P3
P1 = 128 * divider - 512;
P2 = 0; // P2 = 0, P3 = 1 forces an integer value for the divider
P3 = 1;
i2cSendRegister(synth + 0, (P3 & 0x0000FF00) >> 8);
i2cSendRegister(synth + 1, (P3 & 0x000000FF));
i2cSendRegister(synth + 2, ((P1 & 0x00030000) >> 16) | rDiv);
i2cSendRegister(synth + 3, (P1 & 0x0000FF00) >> 8);
i2cSendRegister(synth + 4, (P1 & 0x000000FF));
i2cSendRegister(synth + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
i2cSendRegister(synth + 6, (P2 & 0x0000FF00) >> 8);
i2cSendRegister(synth + 7, (P2 & 0x000000FF));
}
////////////////////////////////////////////////////////////////////////
// Switches off Si5351a output
// Example: si5351aOutputOff(SI_CLK0_CONTROL);
// will switch off output CLK0
////////////////////////////////////////////////////////////////////////
void si5351aOutputOff(uint8_t clk){
i2cSendRegister(clk, 0x80); // Refer to SiLabs AN619 to see
//bit values - 0x80 turns off the output stage
}
////////////////////////////////////////////////////////////////////////
// Set CLK0 output ON and to the specified frequency
// Frequency is in the range 1MHz to 150MHz
// Example: si5351aSetFrequency(10000000);
// will set output CLK0 to 10MHz
//
// This example sets up PLL A
// and MultiSynth 0
// and produces the output on CLK0
////////////////////////////////////////////////////////////////////////
void si5351aSetFrequency(uint32_t frequency){
uint32_t pllFreq;
uint32_t xtalFreq = XTAL_FREQ;
uint32_t l;
float f;
uint8_t mult;
uint32_t num;
uint32_t denom;
uint32_t divider;
divider = 900000000 / frequency; // Calculate the division ratio. 900,000,000 is the maximum internal
// PLL frequency: 900MHz
if (divider % 2) divider--; // Ensure an even integer
//division ratio
pllFreq = divider * frequency; // Calculate the pllFrequency:
//the divider * desired output frequency
mult = pllFreq / xtalFreq; // Determine the multiplier to
//get to the required pllFrequency
l = pllFreq % xtalFreq; // It has three parts:
f = l; // mult is an integer that must be in the range 15..90
f *= 1048575; // num and denom are the fractional parts, the numerator and denominator
f /= xtalFreq; // each is 20 bits (range 0..1048575)
num = f; // the actual multiplier is mult + num / denom
denom = 1048575; // For simplicity we set the denominator to the maximum 1048575
// Set up PLL A with the calculated multiplication ratio
setupPLL(SI_SYNTH_PLL_A, mult, num, denom);
// Set up MultiSynth divider 0, with the calculated divider.
// The final R division stage can divide by a power of two, from 1..128.
// reprented by constants SI_R_DIV1 to SI_R_DIV128 (see si5351a.h header file)
// If you want to output frequencies below 1MHz, you have to use the
// final R division stage
setupMultisynth(SI_SYNTH_MS_0, divider, SI_R_DIV_1);
// Reset the PLL. This causes a glitch in the output. For small changes to
// the parameters, you don't need to reset the PLL, and there is no glitch
// i2cSendRegister(SI_PLL_RESET, 0xA0); // 2016/10/23 JA2GQP
// Finally switch on the CLK0 output (0x4F)
// and set the MultiSynth0 input to be PLL A
i2cSendRegister(SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);
}
//////////////////////////////////////////////////////////////////////// << JA2GQP >>
// Power strength
// Example: SetPower(1);
// The setting range is from 1 to 4
////////////////////////////////////////////////////////////////////////
void SetPower(byte power){
switch(power){
case 1:
i2cSendRegister(SI_CLK0_CONTROL,76); // CLK0 drive strength = 2mA; power level ~ -10dB
break;
case 2:
i2cSendRegister(SI_CLK0_CONTROL,77); // CLK0 drive strength = 4mA; power level ~ -6dB
break;
case 3:
i2cSendRegister(SI_CLK0_CONTROL,78); // CLK0 drive strength = 6mA; power level ~ -3dB
break;
case 4:
i2cSendRegister(SI_CLK0_CONTROL,79); // CLK0 drive strength = 8mA; power level := 0dB
break;
default:
i2cSendRegister(SI_CLK0_CONTROL,76); // CLK0 drive strength = 2mA; power level ~ -10dB
break;
}
}
// Multi Band DDS VFO Ver3.1
// JA2NKD 2016.10.19
// Aruduino IDE 1.6.12
// Arduino nano/UNO
//
// <Rotary.h> https://github.com/brianlow/Rotary
// <EF_AD9850.h> http://forum.arduino.cc/index.php?topic=77483.0
// "Ucglib.h" https://github.com/olikraus/ucglib
// "si5351a.h" https://sites.google.com/site/ja2gqp/
//---------------------------------------------------------------------------------
// si5351a transplant 2016/10/23 JA2GQP
// (si5351a.h is original hedder file.)
//---------------------------------------------------------------------------------
//---------- Library include ----------
#include "si5351a.h" // 2016/10/23 JA2GQP
#include <SPI.h>
#include <EEPROM.h>
#include <Rotary.h>
//#include <EF_AD9850.h> // 2016/10/23 JA2GQP
#include "Ucglib.h"
/*
* Hardware SPI Pins:
* Arduino nano sclk=13, data=11
*/
// I/O setting
const byte __CS=10;
const byte __DC=9;
const byte __RST=8;
const byte modeout1=7; // 2016/10/24 JA2GQP
const byte modeout2=12; //
const byte bandout1=4; //
const byte bandout2=5; //
const byte bandout3=6; //
const byte txsw=A3; //
const byte meterin=A0; //
const byte analogsw=A1; //
// EF_AD9850 AD9850(ddsclock,ddsfqup,ddsreset,ddsdata); // 2016/10/23 JA2GQP
Rotary r=Rotary(2,3);
Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);
//---------- Variable setting ----------
long romf[4];
long freq =7100000;
long freqmax=7200000;
long freqmin=7000000;
long freqold=0;
long freqrit=0;
String freqt=String(freq);
long ifshift = 0;
long ifshiftLSB =8998500; // VFO>frequency USB/LSB is turn over
long ifshiftUSB =9001500;
long ifshiftCW =8999200;
long ifshiftAM =9000000;
long txshiftLSB =8998500;
long txshiftUSB =9001500;
long txshiftCW =9000000;
long txshiftAM =9000000;
long ddsfreq = 0;
long ddsfreqb; // 2016/10/23 JA2GQP
char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1;
int ddsstep=2;
int rit=0;
int fstep=100;
int steprom=1;
int fmode=3;
int fmodeold=1;
int flagrit=0;
int fritold=0;
int flagmode=0;
int meterval1=0;
int tmeterval=0;
int romadd=0;
int analogdata=0;
int band=0;
int bandmax=8;
//---------- Initialization Program ----------------------
void setup() {
i2cInit(); // I2c initialaz 2016/10/23 JA2GQP
delay(100);
ucg.begin(UCG_FONT_MODE_TRANSPARENT);
//ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
ucg.setRotate270();
pinMode (bandout1,OUTPUT);
pinMode (bandout2,OUTPUT);
pinMode (bandout3,OUTPUT);
pinMode(txsw,INPUT_PULLUP);
pinMode(modeout1,OUTPUT);
pinMode(modeout2,OUTPUT);
PCICR |=(1<<PCIE2);
PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
sei();
// AD9850.init(); // 2016/10/23 JA2GQP
// AD9850.reset(); // 2016/10/23 JA2GQP
band=EEPROM.read(0x01);
romadd=0x010+(band*0x10);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
banddataout();
screen01();
chlcd();
if (fmode==0){fmode=3;}
else{fmode=fmode-1;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
}
//---------- Main program ---------------------------------
void loop() {
analogdata=analogRead(analogsw);
// ucg.setPrintPos(12,157);
// ucg.setColor(255,255,255);
// ucg.print(analogdata);
if (analogdata<50){
setstep();
} else if (analogdata<300){
modeset();
} else if (analogdata<600){
setrit();
}else if (analogdata<750){
bandcall();
}else if (analogdata<980){
bandwrite();
}
if (digitalRead(txsw)==LOW){txset();}
if (flagrit==1){
if (freqrit == fritold){
meter();
}
if (freqrit!=fritold){
ddswrite();
ritlcd();
fritold=freqrit;
}
}
else{
if (freq == freqold){
meter();
}
ddswrite();
freqt=String(freq);
freqlcd();
freqold=freq;
}
}
//---------- Function DDS set --------------- 2016/10/23 JA2GQP
void Fnc_Dds(long frequency){
if(ddsfreq != ddsfreqb){
si5351aSetFrequency(frequency);
SetPower(1);
ddsfreqb = ddsfreq;
}
}
//---------- meter --------------------------
void meter(){
meterval1=analogRead(meterin);
meterval1=meterval1/50;
if (meterval1>15){meterval1=15;}
int sx1=sx1+(meterval1*17);
sx1=sx1+41;
int sx2=0;
sx2=sx2+(40+((15-meterval1)*17));
ucg.setFont(ucg_font_fub35_tr);
ucg.setColor(0,0,0);
ucg.drawBox(sx1,180,sx2,16);
ucg.setPrintPos(40,200);
for(int i=1;i<=meterval1;i++){
if (i<=9){
ucg.setColor(0,255,255);
ucg.print("-");
}
else{
ucg.setColor(255,0,0);
ucg.print("-");
}
}
}
//---------- Encoder Interrupt -----------------------
ISR(PCINT2_vect) {
if (flagrit==1){
unsigned char result = r.process();
if(result) {
if(result == DIR_CW){
freqrit=freqrit+fstep;
if (freqrit>=10000){
freqrit=10000;
}
}
else{
freqrit=freqrit-fstep;
if (freqrit<=-10000){
freqrit=-10000;
}
}
}
}
else{
unsigned char result = r.process();
if(result) {
if(result == DIR_CW){
freq=freq+fstep;
if (freq>=freqmax){freq=freqmax;}
}
else{
freq=freq-fstep;
if (freq<=freqmin){freq=freqmin;}
}
}
}
}
//------------ On Air -----------------------------
void txset(){
noInterrupts();
if (fmode==0){ddsfreq=freq+txshiftLSB;}
if (fmode==1){ddsfreq=freq+txshiftUSB;}
if (fmode==2){ddsfreq=freq+txshiftCW;}
if (fmode==3){ddsfreq=freq+txshiftAM;}
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("ON AIR");
while(digitalRead(txsw) == LOW){
meter();
}
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30); //45
ddswrite();
interrupts();
}
//------------- Mode change(LSB-USB-CW-AM) ------------
void modeset(){
ucg.setFont(ucg_font_fub17_tr);
ucg.setPrintPos(82,82);
ucg.setColor(0,0,0);
ucg.print("USB");
ucg.setPrintPos(12,82);
ucg.print("LSB");
ucg.setPrintPos(82,112);
ucg.print("A M");
ucg.setPrintPos(12,112);
ucg.print("C W");
if (fmode==0){
ifshift=ifshiftUSB;
ucg.setColor(255,255,0);
ucg.setPrintPos(82,82);
ucg.print("USB");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,LOW);
}
if(fmode==1){
ifshift=ifshiftCW;
ucg.setPrintPos(12,112);
ucg.setColor(255,255,0);
ucg.print("C W");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,HIGH);
}
if (fmode==2){
ifshift=ifshiftAM;
ucg.setPrintPos(82,112);
ucg.setColor(255,255,0);
ucg.print("A M");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,HIGH);
}
if (fmode==3){
ifshift=ifshiftLSB;
ucg.setPrintPos(12,82);
ucg.setColor(255,255,0);
ucg.print("LSB");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,LOW);
}
fmode=fmode+1;
if (fmode==4){fmode=0;}
ddswrite();
while(analogRead(analogsw) <1000);
}
//------------ Rit SET ------------------------------
void setrit(){
if(flagrit==0){
flagrit=1;
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(190,110);
ucg.setColor(255,0,0);
ucg.print("RIT");
ritlcd();
}
else {
flagrit=0;
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS Out 2016/10/23 JA2GQP
freqt=String(freq);
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(190,110);
ucg.setColor(255,255,255);
ucg.print("RIT");
ucg.setColor(0,0,0);
ucg.drawRBox(222,92,91,21,3);
freqrit=0;
}
while(analogRead(analogsw) <1000);
}
//----------- Rit screen ----------------------
void ritlcd(){
noInterrupts();
ucg.setColor(0,0,0);
ucg.drawBox(222,92,91,21);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,255,255);
ucg.setPrintPos(230,110);
ucg.print(freqrit);
interrupts();
}
//-------------- encorder frequency step set -----------
void setstep(){
noInterrupts();
if (fstep==10000){
fstep=10;
}
else{
fstep=fstep * 10;
}
steplcd();
while(analogRead(analogsw) < 1000);
interrupts();
}
//------------- Step Screen ---------------------------
void steplcd(){
ucg.setColor(0,0,0);
ucg.drawRBox(221,61,93,23,3);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,255,255);
ucg.setPrintPos(220,80);
if (fstep==10){ucg.print(" 10Hz");}
if (fstep==100){ucg.print(" 100Hz");}
if (fstep==1000){ucg.print(" 1KHz");}
if (fstep==10000){ucg.print(" 10KHz");}
}
//----------- Main frequency screen -------------------
void freqlcd(){
ucg.setFont(ucg_font_fub35_tn);
int mojisuu=(freqt.length());
if(freq<100){
ucg.setColor(0,0,0);
ucg.drawBox(217,9,28,36);
}
if(f10 !=(freqt.charAt(mojisuu-2))){
ucg.setColor(0,0,0);
ucg.drawBox(245,9,28,36);
ucg.setPrintPos(245,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-2));
f10 = (freqt.charAt(mojisuu-2));
}
/*
if(freq<10){
ucg.setColor(0,0,0);
ucg.drawBox(245,9,28,36);
}
if(f1 !=(freqt.charAt(mojisuu-1))){
ucg.setColor(0,0,0);
ucg.drawBox(273,9,28,36);
ucg.setPrintPos(273,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-1));
f1 = (freqt.charAt(mojisuu-1));
}
*/
if(freq<1000){
ucg.setColor(0,0,0);
ucg.drawBox(202,9,15,36);
}
if(f100 !=(freqt.charAt(mojisuu-3))){
ucg.setColor(0,0,0);
ucg.drawBox(217,9,28,36);
ucg.setPrintPos(217,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-3));
f100 = (freqt.charAt(mojisuu-3));
}
if(freq>=1000){
ucg.setPrintPos(202,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
if(freq<10000){
ucg.setColor(0,0,0);
ucg.drawBox(146,9,28,36);
}
if(f1k !=(freqt.charAt(mojisuu-4))){
ucg.setColor(0,0,0);
ucg.drawBox(174,9,28,36);
ucg.setPrintPos(174,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-4));
f1k = (freqt.charAt(mojisuu-4));
}
if(freq<100000){
ucg.setColor(0,0,0);
ucg.drawBox(118,9,28,36);
}
if(f10k !=(freqt.charAt(mojisuu-5))){
ucg.setColor(0,0,0);
ucg.drawBox(146,9,28,36);
ucg.setPrintPos(146,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-5));
f10k = (freqt.charAt(mojisuu-5));
}
if(freq<1000000){
ucg.setColor(0,0,0);
ucg.drawBox(103,9,15,36);
}
if(f100k !=(freqt.charAt(mojisuu-6))){
ucg.setColor(0,0,0);
ucg.drawBox(118,9,28,36);
ucg.setPrintPos(118,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-6));
f100k = (freqt.charAt(mojisuu-6));
}
if(freq>=1000000){
ucg.setPrintPos(103,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
if(freq<10000000){
ucg.setColor(0,0,0);
ucg.drawBox(47,9,28,36);
}
if(fmega !=(freqt.charAt(mojisuu-7))){
ucg.setColor(0,0,0);
ucg.drawBox(75,9,28,36);
ucg .setPrintPos(75,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-7));
fmega = (freqt.charAt(mojisuu-7));
}
if(freq<100000000){
ucg.setColor(0,0,0);
ucg.drawBox(19,9,28,36);
}
if (f10m !=(freqt.charAt(mojisuu-8))){
ucg.setColor(0,0,0);
ucg.drawBox(47,9,28,36);
ucg .setPrintPos(47,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-8));
f10m = (freqt.charAt(mojisuu-8));
}
/*
ucg.setPrintPos(19,45);
if(freq>=100000000){
if(f100m !=(freqt.charAt(0))){
ucg.setColor(0,0,0);
ucg.drawBox(19,9,28,36);
ucg .setPrintPos(19,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(0));
f100m = (freqt.charAt(0));
}
}
*/
}
//----------- Basic Screen -------------------------
void screen01(){
ucg.setColor(255,255,255);
ucg.drawRFrame(1,1,314,55,5);
ucg.drawRFrame(2,2,312,53,5);
ucg.setColor(50,50,50);
ucg.drawRBox(5,60,60,25,3);
ucg.drawRBox(75,60,60,25,3);
ucg.drawRBox(5,90,60,25,3);
ucg.drawRBox(75,90,60,25,3);
ucg.setFont(ucg_font_fub17_tr);
ucg.setPrintPos(12,82);
ucg.setColor(0,0,0);
ucg.print("LSB");
ucg.setPrintPos(82,82);
ucg.print("USB");
ucg.setPrintPos(12,112);
ucg.print("C W");
ucg.setPrintPos(82,112);
ucg.print("A M");
ucg.setColor(255,255,255);
ucg.drawRFrame(220,60,95,25,3);
ucg.drawRFrame(220,90,95,25,3);
ucg.setFont(ucg_font_fub11_tr);
ucg.setColor(255,255,255);
ucg.setPrintPos(175,80);
ucg.print("STEP");
ucg.setPrintPos(190,110);
ucg.setColor(255,255,255);
ucg.print("RIT");
ucg.setColor(100,100,100);
ucg.setPrintPos(10,210);
ucg.print(" S: 1-----3-------6-------9---Over--------");
ucg.setPrintPos(10,177);
ucg.print(" P: 1-----3-----5-----------10--------------");
ucg.setPrintPos(10,230);
ucg.setColor(235,0,200);
ucg.print(" Home Blew DDS-VFO Ver3.1 JA2NKD");
ucg.setFont(ucg_font_fub35_tr);
ucg.setColor(0,255,0);
// ucg.setPrintPos(19,45);
// ucg.print("4");
// ucg.setPrintPos(47,45);
// ucg.print("3");
// ucg.setPrintPos(75,45);
// ucg.print("7");
// ucg.setPrintPos(103,45);
// ucg.print(".");
ucg.setPrintPos(273,45);
ucg.print("0");
}
//---------- DDS Frequency write -----------
void ddswrite(){
if (flagrit==0){
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
if(flagrit==1){
ddsfreq=freq+ifshift+freqrit;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
}
//---------- Band data call from eeprom ----------
void bandcall(){
band=band+1;
if (band>(bandmax-1)){band=0;}
romadd=0x010+(band*0x010);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (fmode >=1 ){
fmode=fmode-1;
}else if (fmode==0){
fmode=3;
}
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
banddataout();
chlcd();
}
//---------- Band data write to eeprom ----------
void bandwrite(){
romadd=0x010+(band*0x010);
// for (int i=0;i<3;i++){
eepwrite(freq,romadd);
// }
EEPROM.write(0x001,band);
EEPROM.write(romadd+12,fmode);
if (fstep==10){steprom=1;}
if (fstep==100){steprom=2;}
if (fstep==1000){steprom=3;}
if (fstep==10000){steprom=4;}
EEPROM.write(romadd+13,steprom);
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("Complete!!");
delay (500);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30);
//ucg.drawBox(41,145,270,16);
}
//---------- EEPROM Write(4byte) subroutine ----------
void eepwrite(unsigned long f0,int epadd){
for (int i=0; i<=3;i++){
EEPROM.write(epadd+i,f0%256);
f0=f0/256;
}
}
//---------- EEPROM Read(4byte) subroutin ----------
unsigned long eepread(int epadd){
unsigned long f0=0;
for (int i=3; i >=0 ;i--){
f0=f0*256+EEPROM.read(epadd+i);
}
return f0;
}
//---------- Band data output I/O ----------
void banddataout(){
digitalWrite(bandout1,LOW);
digitalWrite(bandout2,LOW);
digitalWrite(bandout3,LOW);
if (band==0){}
if (band==1){
digitalWrite( bandout1,HIGH);
}
if (band==2){
digitalWrite(bandout2,HIGH);
}
if (band==3){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
}
if (band==4){
digitalWrite(bandout3,HIGH);
}
if (band==5){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==6){
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==7){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
}
//---------- Band No.(Chanel No.) write to LCD ----------
void chlcd(){
ucg.setColor(0,0,0);
ucg.drawBox(5,120,80,20);
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(12,137);
ucg.setColor(255,255,255);
ucg.print("CH: ");
ucg.print(band+1);
}
Arduino nano/UNO対応の回路図である。スイッチ入力がアナログポートを使ったレベルによる入力判定を行っている。
ヘッダーファイル
si5351a.hは、スケッチと同じフォルダーに入れる事。Download siteにヘッダーファイル、スケッチ、vfo_v3_eepを保存した。////////////////////////////////////////////////////////////////////////
// Author: Hans Summers, 2015
// Website: http://www.hanssummers.com
//
// A very very simple Si5351a demonstration
// using the Si5351a module kit http://www.hanssummers.com/synth
// Please also refer to SiLabs AN619 which describes all the registers to use
//----------------------------------------------------------------------
// Addered: JA2GQP,2016/8/18
////////////////////////////////////////////////////////////////////////
#define I2C_START 0x08
#define I2C_START_RPT 0x10
#define I2C_SLA_W_ACK 0x18
#define I2C_SLA_R_ACK 0x40
#define I2C_DATA_ACK 0x28
#define I2C_WRITE 0b11000000
#define I2C_READ 0b11000001
#define SI_CLK0_CONTROL 16 // Register definitions
#define SI_CLK1_CONTROL 17
#define SI_CLK2_CONTROL 18
#define SI_SYNTH_PLL_A 26
#define SI_SYNTH_PLL_B 34
#define SI_SYNTH_MS_0 42
#define SI_SYNTH_MS_1 50
#define SI_SYNTH_MS_2 58
#define SI_PLL_RESET 177
#define SI_R_DIV_1 0b00000000 // R-division ratio definitions
#define SI_R_DIV_2 0b00010000
#define SI_R_DIV_4 0b00100000
#define SI_R_DIV_8 0b00110000
#define SI_R_DIV_16 0b01000000
#define SI_R_DIV_32 0b01010000
#define SI_R_DIV_64 0b01100000
#define SI_R_DIV_128 0b01110000
#define SI_CLK_SRC_PLL_A 0b00000000
#define SI_CLK_SRC_PLL_B 0b00100000
#define XTAL_FREQ 25000000 // Crystal frequency for Hans' board
uint8_t i2cStart(){
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) ;
return (TWSR & 0xF8);
}
void i2cStop(){
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
while ((TWCR & (1<<TWSTO))) ;
}
uint8_t i2cByteSend(uint8_t data){
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) ;
return (TWSR & 0xF8);
}
uint8_t i2cByteRead(){
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))) ;
return (TWDR);
}
uint8_t i2cSendRegister(uint8_t reg, uint8_t data){
uint8_t stts;
stts = i2cStart();
if (stts != I2C_START)
return 1;
stts = i2cByteSend(I2C_WRITE);
if (stts != I2C_SLA_W_ACK)
return 2;
stts = i2cByteSend(reg);
if (stts != I2C_DATA_ACK)
return 3;
stts = i2cByteSend(data);
if (stts != I2C_DATA_ACK)
return 4;
i2cStop();
return 0;
}
uint8_t i2cReadRegister(uint8_t reg, uint8_t *data){
uint8_t stts;
stts = i2cStart();
if (stts != I2C_START)
return 1;
stts = i2cByteSend(I2C_WRITE);
if (stts != I2C_SLA_W_ACK)
return 2;
stts = i2cByteSend(reg);
if (stts != I2C_DATA_ACK)
return 3;
stts = i2cStart();
if (stts != I2C_START_RPT)
return 4;
stts = i2cByteSend(I2C_READ);
if (stts != I2C_SLA_R_ACK)
return 5;
*data = i2cByteRead();
i2cStop();
return 0;
}
// Init TWI (I2C)
//
void i2cInit(){
TWBR = 92;
TWSR = 0;
TWDR = 0xFF;
//#ifdef ARDUINO_AVR_MEGA2560
// PRR0 = 0;
//#else
PRR = 0;
//#endif
}
////////////////////////////////////////////////////////////////////////
// Set up specified PLL with mult, num and denom
// mult is 15..90
// num is 0..1,048,575 (0xFFFFF)
// denom is 0..1,048,575 (0xFFFFF)
///////////////////////////////////////////////////////////////////////
void setupPLL(uint8_t pll, uint8_t mult, uint32_t num, uint32_t denom){
uint32_t P1; // PLL config register P1
uint32_t P2; // PLL config register P2
uint32_t P3; // PLL config register P3
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;
i2cSendRegister(pll + 0, (P3 & 0x0000FF00) >> 8);
i2cSendRegister(pll + 1, (P3 & 0x000000FF));
i2cSendRegister(pll + 2, (P1 & 0x00030000) >> 16);
i2cSendRegister(pll + 3, (P1 & 0x0000FF00) >> 8);
i2cSendRegister(pll + 4, (P1 & 0x000000FF));
i2cSendRegister(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
i2cSendRegister(pll + 6, (P2 & 0x0000FF00) >> 8);
i2cSendRegister(pll + 7, (P2 & 0x000000FF));
}
////////////////////////////////////////////////////////////////////////
// Set up MultiSynth with integer divider and R divider
// R divider is the bit value which is OR'ed onto the appropriate
// register, it is a #define in si5351a.h
////////////////////////////////////////////////////////////////////////
void setupMultisynth(uint8_t synth, uint32_t divider, uint8_t rDiv){
uint32_t P1; // Synth config register P1
uint32_t P2; // Synth config register P2
uint32_t P3; // Synth config register P3
P1 = 128 * divider - 512;
P2 = 0; // P2 = 0, P3 = 1 forces an integer value for the divider
P3 = 1;
i2cSendRegister(synth + 0, (P3 & 0x0000FF00) >> 8);
i2cSendRegister(synth + 1, (P3 & 0x000000FF));
i2cSendRegister(synth + 2, ((P1 & 0x00030000) >> 16) | rDiv);
i2cSendRegister(synth + 3, (P1 & 0x0000FF00) >> 8);
i2cSendRegister(synth + 4, (P1 & 0x000000FF));
i2cSendRegister(synth + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
i2cSendRegister(synth + 6, (P2 & 0x0000FF00) >> 8);
i2cSendRegister(synth + 7, (P2 & 0x000000FF));
}
////////////////////////////////////////////////////////////////////////
// Switches off Si5351a output
// Example: si5351aOutputOff(SI_CLK0_CONTROL);
// will switch off output CLK0
////////////////////////////////////////////////////////////////////////
void si5351aOutputOff(uint8_t clk){
i2cSendRegister(clk, 0x80); // Refer to SiLabs AN619 to see
//bit values - 0x80 turns off the output stage
}
////////////////////////////////////////////////////////////////////////
// Set CLK0 output ON and to the specified frequency
// Frequency is in the range 1MHz to 150MHz
// Example: si5351aSetFrequency(10000000);
// will set output CLK0 to 10MHz
//
// This example sets up PLL A
// and MultiSynth 0
// and produces the output on CLK0
////////////////////////////////////////////////////////////////////////
void si5351aSetFrequency(uint32_t frequency){
uint32_t pllFreq;
uint32_t xtalFreq = XTAL_FREQ;
uint32_t l;
float f;
uint8_t mult;
uint32_t num;
uint32_t denom;
uint32_t divider;
divider = 900000000 / frequency; // Calculate the division ratio. 900,000,000 is the maximum internal
// PLL frequency: 900MHz
if (divider % 2) divider--; // Ensure an even integer
//division ratio
pllFreq = divider * frequency; // Calculate the pllFrequency:
//the divider * desired output frequency
mult = pllFreq / xtalFreq; // Determine the multiplier to
//get to the required pllFrequency
l = pllFreq % xtalFreq; // It has three parts:
f = l; // mult is an integer that must be in the range 15..90
f *= 1048575; // num and denom are the fractional parts, the numerator and denominator
f /= xtalFreq; // each is 20 bits (range 0..1048575)
num = f; // the actual multiplier is mult + num / denom
denom = 1048575; // For simplicity we set the denominator to the maximum 1048575
// Set up PLL A with the calculated multiplication ratio
setupPLL(SI_SYNTH_PLL_A, mult, num, denom);
// Set up MultiSynth divider 0, with the calculated divider.
// The final R division stage can divide by a power of two, from 1..128.
// reprented by constants SI_R_DIV1 to SI_R_DIV128 (see si5351a.h header file)
// If you want to output frequencies below 1MHz, you have to use the
// final R division stage
setupMultisynth(SI_SYNTH_MS_0, divider, SI_R_DIV_1);
// Reset the PLL. This causes a glitch in the output. For small changes to
// the parameters, you don't need to reset the PLL, and there is no glitch
// i2cSendRegister(SI_PLL_RESET, 0xA0); // 2016/10/23 JA2GQP
// Finally switch on the CLK0 output (0x4F)
// and set the MultiSynth0 input to be PLL A
i2cSendRegister(SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);
}
//////////////////////////////////////////////////////////////////////// << JA2GQP >>
// Power strength
// Example: SetPower(1);
// The setting range is from 1 to 4
////////////////////////////////////////////////////////////////////////
void SetPower(byte power){
switch(power){
case 1:
i2cSendRegister(SI_CLK0_CONTROL,76); // CLK0 drive strength = 2mA; power level ~ -10dB
break;
case 2:
i2cSendRegister(SI_CLK0_CONTROL,77); // CLK0 drive strength = 4mA; power level ~ -6dB
break;
case 3:
i2cSendRegister(SI_CLK0_CONTROL,78); // CLK0 drive strength = 6mA; power level ~ -3dB
break;
case 4:
i2cSendRegister(SI_CLK0_CONTROL,79); // CLK0 drive strength = 8mA; power level := 0dB
break;
default:
i2cSendRegister(SI_CLK0_CONTROL,76); // CLK0 drive strength = 2mA; power level ~ -10dB
break;
}
}
スケッチ
//----------------------------------------------------------------------------------// Multi Band DDS VFO Ver3.1
// JA2NKD 2016.10.19
// Aruduino IDE 1.6.12
// Arduino nano/UNO
//
// <Rotary.h> https://github.com/brianlow/Rotary
// <EF_AD9850.h> http://forum.arduino.cc/index.php?topic=77483.0
// "Ucglib.h" https://github.com/olikraus/ucglib
// "si5351a.h" https://sites.google.com/site/ja2gqp/
//---------------------------------------------------------------------------------
// si5351a transplant 2016/10/23 JA2GQP
// (si5351a.h is original hedder file.)
//---------------------------------------------------------------------------------
//---------- Library include ----------
#include "si5351a.h" // 2016/10/23 JA2GQP
#include <SPI.h>
#include <EEPROM.h>
#include <Rotary.h>
//#include <EF_AD9850.h> // 2016/10/23 JA2GQP
#include "Ucglib.h"
/*
* Hardware SPI Pins:
* Arduino nano sclk=13, data=11
*/
// I/O setting
const byte __CS=10;
const byte __DC=9;
const byte __RST=8;
const byte modeout1=7; // 2016/10/24 JA2GQP
const byte modeout2=12; //
const byte bandout1=4; //
const byte bandout2=5; //
const byte bandout3=6; //
const byte txsw=A3; //
const byte meterin=A0; //
const byte analogsw=A1; //
// EF_AD9850 AD9850(ddsclock,ddsfqup,ddsreset,ddsdata); // 2016/10/23 JA2GQP
Rotary r=Rotary(2,3);
Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);
//---------- Variable setting ----------
long romf[4];
long freq =7100000;
long freqmax=7200000;
long freqmin=7000000;
long freqold=0;
long freqrit=0;
String freqt=String(freq);
long ifshift = 0;
long ifshiftLSB =8998500; // VFO>frequency USB/LSB is turn over
long ifshiftUSB =9001500;
long ifshiftCW =8999200;
long ifshiftAM =9000000;
long txshiftLSB =8998500;
long txshiftUSB =9001500;
long txshiftCW =9000000;
long txshiftAM =9000000;
long ddsfreq = 0;
long ddsfreqb; // 2016/10/23 JA2GQP
char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1;
int ddsstep=2;
int rit=0;
int fstep=100;
int steprom=1;
int fmode=3;
int fmodeold=1;
int flagrit=0;
int fritold=0;
int flagmode=0;
int meterval1=0;
int tmeterval=0;
int romadd=0;
int analogdata=0;
int band=0;
int bandmax=8;
//---------- Initialization Program ----------------------
void setup() {
i2cInit(); // I2c initialaz 2016/10/23 JA2GQP
delay(100);
ucg.begin(UCG_FONT_MODE_TRANSPARENT);
//ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
ucg.setRotate270();
pinMode (bandout1,OUTPUT);
pinMode (bandout2,OUTPUT);
pinMode (bandout3,OUTPUT);
pinMode(txsw,INPUT_PULLUP);
pinMode(modeout1,OUTPUT);
pinMode(modeout2,OUTPUT);
PCICR |=(1<<PCIE2);
PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
sei();
// AD9850.init(); // 2016/10/23 JA2GQP
// AD9850.reset(); // 2016/10/23 JA2GQP
band=EEPROM.read(0x01);
romadd=0x010+(band*0x10);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
banddataout();
screen01();
chlcd();
if (fmode==0){fmode=3;}
else{fmode=fmode-1;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
}
//---------- Main program ---------------------------------
void loop() {
analogdata=analogRead(analogsw);
// ucg.setPrintPos(12,157);
// ucg.setColor(255,255,255);
// ucg.print(analogdata);
if (analogdata<50){
setstep();
} else if (analogdata<300){
modeset();
} else if (analogdata<600){
setrit();
}else if (analogdata<750){
bandcall();
}else if (analogdata<980){
bandwrite();
}
if (digitalRead(txsw)==LOW){txset();}
if (flagrit==1){
if (freqrit == fritold){
meter();
}
if (freqrit!=fritold){
ddswrite();
ritlcd();
fritold=freqrit;
}
}
else{
if (freq == freqold){
meter();
}
ddswrite();
freqt=String(freq);
freqlcd();
freqold=freq;
}
}
//---------- Function DDS set --------------- 2016/10/23 JA2GQP
void Fnc_Dds(long frequency){
if(ddsfreq != ddsfreqb){
si5351aSetFrequency(frequency);
SetPower(1);
ddsfreqb = ddsfreq;
}
}
//---------- meter --------------------------
void meter(){
meterval1=analogRead(meterin);
meterval1=meterval1/50;
if (meterval1>15){meterval1=15;}
int sx1=sx1+(meterval1*17);
sx1=sx1+41;
int sx2=0;
sx2=sx2+(40+((15-meterval1)*17));
ucg.setFont(ucg_font_fub35_tr);
ucg.setColor(0,0,0);
ucg.drawBox(sx1,180,sx2,16);
ucg.setPrintPos(40,200);
for(int i=1;i<=meterval1;i++){
if (i<=9){
ucg.setColor(0,255,255);
ucg.print("-");
}
else{
ucg.setColor(255,0,0);
ucg.print("-");
}
}
}
//---------- Encoder Interrupt -----------------------
ISR(PCINT2_vect) {
if (flagrit==1){
unsigned char result = r.process();
if(result) {
if(result == DIR_CW){
freqrit=freqrit+fstep;
if (freqrit>=10000){
freqrit=10000;
}
}
else{
freqrit=freqrit-fstep;
if (freqrit<=-10000){
freqrit=-10000;
}
}
}
}
else{
unsigned char result = r.process();
if(result) {
if(result == DIR_CW){
freq=freq+fstep;
if (freq>=freqmax){freq=freqmax;}
}
else{
freq=freq-fstep;
if (freq<=freqmin){freq=freqmin;}
}
}
}
}
//------------ On Air -----------------------------
void txset(){
noInterrupts();
if (fmode==0){ddsfreq=freq+txshiftLSB;}
if (fmode==1){ddsfreq=freq+txshiftUSB;}
if (fmode==2){ddsfreq=freq+txshiftCW;}
if (fmode==3){ddsfreq=freq+txshiftAM;}
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("ON AIR");
while(digitalRead(txsw) == LOW){
meter();
}
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30); //45
ddswrite();
interrupts();
}
//------------- Mode change(LSB-USB-CW-AM) ------------
void modeset(){
ucg.setFont(ucg_font_fub17_tr);
ucg.setPrintPos(82,82);
ucg.setColor(0,0,0);
ucg.print("USB");
ucg.setPrintPos(12,82);
ucg.print("LSB");
ucg.setPrintPos(82,112);
ucg.print("A M");
ucg.setPrintPos(12,112);
ucg.print("C W");
if (fmode==0){
ifshift=ifshiftUSB;
ucg.setColor(255,255,0);
ucg.setPrintPos(82,82);
ucg.print("USB");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,LOW);
}
if(fmode==1){
ifshift=ifshiftCW;
ucg.setPrintPos(12,112);
ucg.setColor(255,255,0);
ucg.print("C W");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,HIGH);
}
if (fmode==2){
ifshift=ifshiftAM;
ucg.setPrintPos(82,112);
ucg.setColor(255,255,0);
ucg.print("A M");
digitalWrite(modeout1,HIGH);
digitalWrite(modeout2,HIGH);
}
if (fmode==3){
ifshift=ifshiftLSB;
ucg.setPrintPos(12,82);
ucg.setColor(255,255,0);
ucg.print("LSB");
digitalWrite(modeout1,LOW);
digitalWrite(modeout2,LOW);
}
fmode=fmode+1;
if (fmode==4){fmode=0;}
ddswrite();
while(analogRead(analogsw) <1000);
}
//------------ Rit SET ------------------------------
void setrit(){
if(flagrit==0){
flagrit=1;
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(190,110);
ucg.setColor(255,0,0);
ucg.print("RIT");
ritlcd();
}
else {
flagrit=0;
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS Out 2016/10/23 JA2GQP
freqt=String(freq);
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(190,110);
ucg.setColor(255,255,255);
ucg.print("RIT");
ucg.setColor(0,0,0);
ucg.drawRBox(222,92,91,21,3);
freqrit=0;
}
while(analogRead(analogsw) <1000);
}
//----------- Rit screen ----------------------
void ritlcd(){
noInterrupts();
ucg.setColor(0,0,0);
ucg.drawBox(222,92,91,21);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,255,255);
ucg.setPrintPos(230,110);
ucg.print(freqrit);
interrupts();
}
//-------------- encorder frequency step set -----------
void setstep(){
noInterrupts();
if (fstep==10000){
fstep=10;
}
else{
fstep=fstep * 10;
}
steplcd();
while(analogRead(analogsw) < 1000);
interrupts();
}
//------------- Step Screen ---------------------------
void steplcd(){
ucg.setColor(0,0,0);
ucg.drawRBox(221,61,93,23,3);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,255,255);
ucg.setPrintPos(220,80);
if (fstep==10){ucg.print(" 10Hz");}
if (fstep==100){ucg.print(" 100Hz");}
if (fstep==1000){ucg.print(" 1KHz");}
if (fstep==10000){ucg.print(" 10KHz");}
}
//----------- Main frequency screen -------------------
void freqlcd(){
ucg.setFont(ucg_font_fub35_tn);
int mojisuu=(freqt.length());
if(freq<100){
ucg.setColor(0,0,0);
ucg.drawBox(217,9,28,36);
}
if(f10 !=(freqt.charAt(mojisuu-2))){
ucg.setColor(0,0,0);
ucg.drawBox(245,9,28,36);
ucg.setPrintPos(245,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-2));
f10 = (freqt.charAt(mojisuu-2));
}
/*
if(freq<10){
ucg.setColor(0,0,0);
ucg.drawBox(245,9,28,36);
}
if(f1 !=(freqt.charAt(mojisuu-1))){
ucg.setColor(0,0,0);
ucg.drawBox(273,9,28,36);
ucg.setPrintPos(273,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-1));
f1 = (freqt.charAt(mojisuu-1));
}
*/
if(freq<1000){
ucg.setColor(0,0,0);
ucg.drawBox(202,9,15,36);
}
if(f100 !=(freqt.charAt(mojisuu-3))){
ucg.setColor(0,0,0);
ucg.drawBox(217,9,28,36);
ucg.setPrintPos(217,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-3));
f100 = (freqt.charAt(mojisuu-3));
}
if(freq>=1000){
ucg.setPrintPos(202,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
if(freq<10000){
ucg.setColor(0,0,0);
ucg.drawBox(146,9,28,36);
}
if(f1k !=(freqt.charAt(mojisuu-4))){
ucg.setColor(0,0,0);
ucg.drawBox(174,9,28,36);
ucg.setPrintPos(174,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-4));
f1k = (freqt.charAt(mojisuu-4));
}
if(freq<100000){
ucg.setColor(0,0,0);
ucg.drawBox(118,9,28,36);
}
if(f10k !=(freqt.charAt(mojisuu-5))){
ucg.setColor(0,0,0);
ucg.drawBox(146,9,28,36);
ucg.setPrintPos(146,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-5));
f10k = (freqt.charAt(mojisuu-5));
}
if(freq<1000000){
ucg.setColor(0,0,0);
ucg.drawBox(103,9,15,36);
}
if(f100k !=(freqt.charAt(mojisuu-6))){
ucg.setColor(0,0,0);
ucg.drawBox(118,9,28,36);
ucg.setPrintPos(118,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-6));
f100k = (freqt.charAt(mojisuu-6));
}
if(freq>=1000000){
ucg.setPrintPos(103,45);
ucg.setColor(0,255,0);
ucg.print(".");
}
if(freq<10000000){
ucg.setColor(0,0,0);
ucg.drawBox(47,9,28,36);
}
if(fmega !=(freqt.charAt(mojisuu-7))){
ucg.setColor(0,0,0);
ucg.drawBox(75,9,28,36);
ucg .setPrintPos(75,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-7));
fmega = (freqt.charAt(mojisuu-7));
}
if(freq<100000000){
ucg.setColor(0,0,0);
ucg.drawBox(19,9,28,36);
}
if (f10m !=(freqt.charAt(mojisuu-8))){
ucg.setColor(0,0,0);
ucg.drawBox(47,9,28,36);
ucg .setPrintPos(47,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(mojisuu-8));
f10m = (freqt.charAt(mojisuu-8));
}
/*
ucg.setPrintPos(19,45);
if(freq>=100000000){
if(f100m !=(freqt.charAt(0))){
ucg.setColor(0,0,0);
ucg.drawBox(19,9,28,36);
ucg .setPrintPos(19,45);
ucg.setColor(0,255,0);
ucg.print(freqt.charAt(0));
f100m = (freqt.charAt(0));
}
}
*/
}
//----------- Basic Screen -------------------------
void screen01(){
ucg.setColor(255,255,255);
ucg.drawRFrame(1,1,314,55,5);
ucg.drawRFrame(2,2,312,53,5);
ucg.setColor(50,50,50);
ucg.drawRBox(5,60,60,25,3);
ucg.drawRBox(75,60,60,25,3);
ucg.drawRBox(5,90,60,25,3);
ucg.drawRBox(75,90,60,25,3);
ucg.setFont(ucg_font_fub17_tr);
ucg.setPrintPos(12,82);
ucg.setColor(0,0,0);
ucg.print("LSB");
ucg.setPrintPos(82,82);
ucg.print("USB");
ucg.setPrintPos(12,112);
ucg.print("C W");
ucg.setPrintPos(82,112);
ucg.print("A M");
ucg.setColor(255,255,255);
ucg.drawRFrame(220,60,95,25,3);
ucg.drawRFrame(220,90,95,25,3);
ucg.setFont(ucg_font_fub11_tr);
ucg.setColor(255,255,255);
ucg.setPrintPos(175,80);
ucg.print("STEP");
ucg.setPrintPos(190,110);
ucg.setColor(255,255,255);
ucg.print("RIT");
ucg.setColor(100,100,100);
ucg.setPrintPos(10,210);
ucg.print(" S: 1-----3-------6-------9---Over--------");
ucg.setPrintPos(10,177);
ucg.print(" P: 1-----3-----5-----------10--------------");
ucg.setPrintPos(10,230);
ucg.setColor(235,0,200);
ucg.print(" Home Blew DDS-VFO Ver3.1 JA2NKD");
ucg.setFont(ucg_font_fub35_tr);
ucg.setColor(0,255,0);
// ucg.setPrintPos(19,45);
// ucg.print("4");
// ucg.setPrintPos(47,45);
// ucg.print("3");
// ucg.setPrintPos(75,45);
// ucg.print("7");
// ucg.setPrintPos(103,45);
// ucg.print(".");
ucg.setPrintPos(273,45);
ucg.print("0");
}
//---------- DDS Frequency write -----------
void ddswrite(){
if (flagrit==0){
ddsfreq=freq+ifshift;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
if(flagrit==1){
ddsfreq=freq+ifshift+freqrit;
// AD9850.wr_serial(0x00,ddsfreq); // 2016/10/23 JA2GQP
Fnc_Dds(ddsfreq); // DDS out 2016/10/24 JA2GQP
}
}
//---------- Band data call from eeprom ----------
void bandcall(){
band=band+1;
if (band>(bandmax-1)){band=0;}
romadd=0x010+(band*0x010);
for (int i=0; i<3;i++){
romf[i]=eepread((romadd+4*i));
}
freq = romf[0];
freqmin = romf[1];
freqmax = romf[2];
fmode = EEPROM.read(romadd+12);
steprom = EEPROM.read(romadd+13);
if (fmode >=1 ){
fmode=fmode-1;
}else if (fmode==0){
fmode=3;
}
if (steprom==1){fstep=10;}
if (steprom==2){fstep=100;}
if (steprom==3){fstep=1000;}
if (steprom==4){fstep=10000;}
modeset();
steplcd();
freqt=String(freq);
freqlcd();
banddataout();
chlcd();
}
//---------- Band data write to eeprom ----------
void bandwrite(){
romadd=0x010+(band*0x010);
// for (int i=0;i<3;i++){
eepwrite(freq,romadd);
// }
EEPROM.write(0x001,band);
EEPROM.write(romadd+12,fmode);
if (fstep==10){steprom=1;}
if (fstep==100){steprom=2;}
if (fstep==1000){steprom=3;}
if (fstep==10000){steprom=4;}
EEPROM.write(romadd+13,steprom);
ucg.setPrintPos(110,140);
ucg.setFont(ucg_font_fub17_tr);
ucg.setColor(255,0,0);
ucg.print("Complete!!");
delay (500);
ucg.setColor(0,0,0);
ucg.drawBox(100,120,250,30);
//ucg.drawBox(41,145,270,16);
}
//---------- EEPROM Write(4byte) subroutine ----------
void eepwrite(unsigned long f0,int epadd){
for (int i=0; i<=3;i++){
EEPROM.write(epadd+i,f0%256);
f0=f0/256;
}
}
//---------- EEPROM Read(4byte) subroutin ----------
unsigned long eepread(int epadd){
unsigned long f0=0;
for (int i=3; i >=0 ;i--){
f0=f0*256+EEPROM.read(epadd+i);
}
return f0;
}
//---------- Band data output I/O ----------
void banddataout(){
digitalWrite(bandout1,LOW);
digitalWrite(bandout2,LOW);
digitalWrite(bandout3,LOW);
if (band==0){}
if (band==1){
digitalWrite( bandout1,HIGH);
}
if (band==2){
digitalWrite(bandout2,HIGH);
}
if (band==3){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
}
if (band==4){
digitalWrite(bandout3,HIGH);
}
if (band==5){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==6){
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
if (band==7){
digitalWrite(bandout1,HIGH);
digitalWrite(bandout2,HIGH);
digitalWrite(bandout3,HIGH);
}
}
//---------- Band No.(Chanel No.) write to LCD ----------
void chlcd(){
ucg.setColor(0,0,0);
ucg.drawBox(5,120,80,20);
ucg.setFont(ucg_font_fub11_tr);
ucg.setPrintPos(12,137);
ucg.setColor(255,255,255);
ucg.print("CH: ");
ucg.print(band+1);
}
2016年9月18日日曜日
6 pole Crystal filter
今まで、G3UUR回路で水晶発振子分類のみ行っていたが、パラメータを求めるプログラムを探した所、フィルタのシュミレーションまで出来るDishal203が見つかった。G3UUR methodによる水晶発振子パラメータをDishal203を使って求め、6poleクリスタルフィルタを作った。水晶の選別とDishal203へのパラメータを正しく入力すれば、無調整で計算値に近似した特性が得られる事が判った。
switch ON(F1)、switch off(F2)を以降の説明で表す事とする。 この回路で注意すべき点は、33pFを使うが実装前にコンデンサ容量を実測(小数点第一位までの読み取り精度が必要)の事。製作したチェッカーは、実測値35.2pFであった。(470pFは、測定の必要なし)コンデンサの測定は、単体で行う事。Webの記事で基板などに実装時の容量と記した記事も見受けられるが、実装時の容量をCswとして入力すると、帯域巾が目標値より狭くなる傾向がある。
G3UUR methodによる水晶発振子チェッカー製作例。電源電圧9V(006P)で使っている。
水晶発振子チェッカーに周波数カウンタ(最少分解能1Hz程度)を繋ぎ、switch F1側(ON)とswitch F2側(off)の周波数を1Hz単位まで読み取る。更に、水晶発振子の容量を0.1pF単位まで読み取る。水晶発振子の選別は、F1周波数を許容差30Hz以内(目標帯域巾の1/100位)、1グループに纏める。許容差100Hzで選別などの記事もあるが、無調整では上手く出来ないであろう。また、許容差100Hzを超えるものは、選外とした方が良い。
Csw値(33pF単体で測定した値)、水晶発振子の静電容量(0.1pF単位まで必要)、F1(SW CLOSE)周波数、F2(SW OPEN)周波数を入力し、Calculateを選び演算する。(470pFは、そのまま入力する)この演算は、6個の水晶発振子全て行い、Lm(mH),Cm(fF),fs(kHz)を記録する。更に、6個のCp(pF),Lm(mH),Cm(fF),fs(kHz)平均値を求め、記録する。
Lm(mH),fs(kHz),Cp(pF)の各々の平均値を入力する。帯域巾B3db(kHz) 2.7、PB ripple(0..3db) 0.1,# of xtals(2..14) 6を各々入力する。各々の値を入力後、Calculateを選び演算する。また、フィルタ特性の数値データは、show Tableを選べば表示出来る。
FRMSによる実測スペクトル。計算したフィルタの入出力インピーダンスは、512.2Ωであった。FRMSの入出力インピーダンスが50Ωの為、2kΩのVR(約462Ω)をFRMS入出力に繋ぎ、抵抗マッチングさせた。抵抗による疑似マッチングにより、約10dBの損失がある。
フィルタ回路図。値は全て計算値。コンデンサは、実測し、合成容量で最大誤差0.3pF以内で実装。
基板サイズ 48 x 27
switch ON(F1)、switch off(F2)を以降の説明で表す事とする。 この回路で注意すべき点は、33pFを使うが実装前にコンデンサ容量を実測(小数点第一位までの読み取り精度が必要)の事。製作したチェッカーは、実測値35.2pFであった。(470pFは、測定の必要なし)コンデンサの測定は、単体で行う事。Webの記事で基板などに実装時の容量と記した記事も見受けられるが、実装時の容量をCswとして入力すると、帯域巾が目標値より狭くなる傾向がある。
G3UUR methodによる水晶発振子チェッカー製作例。電源電圧9V(006P)で使っている。
水晶発振子チェッカーに周波数カウンタ(最少分解能1Hz程度)を繋ぎ、switch F1側(ON)とswitch F2側(off)の周波数を1Hz単位まで読み取る。更に、水晶発振子の容量を0.1pF単位まで読み取る。水晶発振子の選別は、F1周波数を許容差30Hz以内(目標帯域巾の1/100位)、1グループに纏める。許容差100Hzで選別などの記事もあるが、無調整では上手く出来ないであろう。また、許容差100Hzを超えるものは、選外とした方が良い。
Csw値(33pF単体で測定した値)、水晶発振子の静電容量(0.1pF単位まで必要)、F1(SW CLOSE)周波数、F2(SW OPEN)周波数を入力し、Calculateを選び演算する。(470pFは、そのまま入力する)この演算は、6個の水晶発振子全て行い、Lm(mH),Cm(fF),fs(kHz)を記録する。更に、6個のCp(pF),Lm(mH),Cm(fF),fs(kHz)平均値を求め、記録する。
Lm(mH),fs(kHz),Cp(pF)の各々の平均値を入力する。帯域巾B3db(kHz) 2.7、PB ripple(0..3db) 0.1,# of xtals(2..14) 6を各々入力する。各々の値を入力後、Calculateを選び演算する。また、フィルタ特性の数値データは、show Tableを選べば表示出来る。
FRMSによる実測スペクトル。計算したフィルタの入出力インピーダンスは、512.2Ωであった。FRMSの入出力インピーダンスが50Ωの為、2kΩのVR(約462Ω)をFRMS入出力に繋ぎ、抵抗マッチングさせた。抵抗による疑似マッチングにより、約10dBの損失がある。
フィルタ回路図。値は全て計算値。コンデンサは、実測し、合成容量で最大誤差0.3pF以内で実装。
基板サイズ 48 x 27
登録:
投稿 (Atom)











