JH7UBCブログ

アマチュア無線 電子工作 家庭菜園など趣味のブログです

CYTECのデジタルQRPパワーメーターの製作

2020-02-21 09:40:54 | 電子工作
2015年、CYTEC社が公開しているデジタルQRPパワー・メーターを製作しました。
回路図、説明書、PIC用HEXファイルなどは、CYTECのホームページからダウンロードできます。(貴重なデータを公開してくださっているCYTEC社に感謝です。)
勉強も兼ねてユニバーサル基板に回路を組みました。
PIC16F88へのHEXファイルの書き込みには自作のPICライタを使用しました。
回路図では、LCDのコントラスト調整は固定抵抗ですが、10KΩの半固定抵抗を使用しました。
LCD表示器を装着した状態です。
ここまで出来たら、ログアンプAD8307を校正します。説明書にあるDC1V法で校正しました。
上に見える基板が1V電源です。この回路も公開されています。
説明書の通り、右側の半固定ボリュームを回して、3.7dBmと表示するように調整しました。
ケースに入れ、いつものようにテプラでレタリングをしました。ケースは秋月電子のSK-16です。
電源は、電池(006P)と外部電源の両方が使えるようにしました。電流は40mAです。
このままでは、最大17dBm(50mW)までしか測定できませんので、-20dBのアッテネータも製作しました。(この回路も公開されています。)
18Ωの抵抗は手持ちが1/6W型しかなかったためそれを使いましたが、後日2W型と交換しました。
このデジタルQRPパワーメーターは、QRP送信機の調整や発振回路のチェックなどに使用しています。
以上紹介しました、SG、周波数カウンタ、QRPパワーメーターは、無線機の製作をする場合の必需品ですね。
皆さんも作ってみてはいかがですか。

PIC周波数カウンタ

2020-02-20 14:39:48 | 電子工作

 周波数カウンタは、2014年にPIC16F88版とPIC16F648A版を製作しました。 

上にちょこんと乗っている方です。

内部の様子です。
この周波数カウンタは、「電子工作etc」というwebサイトの「周波数カウンタV7」の回路とプログラムと回路を参考にさせていただきました。(現在このサイトは見えなくなっているようです。)
ソースプログラムは、C言語で書かれていましたが、アセンブラに移植しました。
PIC16F88周波数カウンタの回路図です。
PIC16F648A周波数カウンタの回路図です。

PIC16F648A周波数カウンタのアセンブラソースリストは、こちらです。
MPLAB IDEでコンパイルしてPICに書き込みます。

この周波数カウンタは、現在でも使用可能で、ときどき使いますが、LCDの画面が小さいのとバックライトがないので、ちょっと見ずらいです。

そこで、2017年、LEDを使ってもっと見やすい周波数カウンタを作ることにしました。
LEDは、ダイナミック点灯として、まずPIC16F883で周波数カウンタを試作しましたが、周波数測定のための割込みとLED点灯のための割込みがかちあい、特定の周波数で測定誤差が出てしまいました。
この問題を解決するために、周波数測定用にPIC16F628Aを使い、表示部にPIC16F883を使った周波数カウンタを製作しました。

内部です。
この周波数カウンタでは、下の図のようにPIC16F628Aで測定した周波数の値をシリアル通信でPIC16F883に送り、PIC16F883でLEDに表示します。


 PIC16F628A周波数測定部の回路図です。
PIC16F628Aのアセンブラソースリストは、こちら

PIC16F883周波数表示部の回路図です。
PIC16F883のアセンブラソースリストは、こちら

この周波数カウンタの測定上限は約50MHzです。
精度は数PPM(1MHzで数Hzの誤差)です。

なお、この周波数カウンタの仕組みは、JH7UBCホームページのこちらをご覧ください。
アマチュアの実験用としては、十分使えると思います。
LED表示で大変見やすく、当局もこの周波数カウンタを常用しています。


AD9850DDS簡易SG

2020-02-19 15:34:42 | 電子工作

 退職して間もなく9年になります。退職してから電子工作を楽しむ時間が多くなりました。けっこうたくさんの工作をして、製作したものはJH7UBCホームページに掲載しています。

 また、製作過程などはYahooのJH7UBCブログに掲載していましたが、Yahooブログの消滅とともに記事も消えてしましました。

 そこで、製作したものの中で実用になっているもの(現に使用しているもの)をいくつか紹介します。

 まず、AD9850DDSをPIC16F88でコントロールしたSG(Signal Generator)を紹介します。このSGは、2015年に製作して、受信機の調整や各種調整などに活躍しています。

STEPボタンを押すと1MHz→100KHz→10KHz→1KHz→100Hz→10Hz→1MHzと循環します。
STEPの初期値は、1MHzです。

回路図です。

AD9850DDSの出力を広帯域アンプLM7171で増幅しています。
出力はボリュームで調整でき、50Ω負荷のとき、1MHzで最大9.17dBm(8.3mW)です。

RF領域では、周波数が上がると出力は徐々に下がります。
低周波領域では、100Hz以上はほぼフラットで、100Hz以下では徐々に出力が低下します。
このSGを出力ボリュームを最小にして、IC756PROに接続するとSメータが50MHzまで9+5dB振れます。
10Hz~約50MHzがこのSGの実用範囲と考えます。

RF領域の周波数特性です。OUT1は、AD9850DDSの出力、OUT2は、LM7171の出力です。(共に50Ω負荷)

PIC16F88のプログラミングはアセンブラで行っています。

参考までに、ソースリストはこちらです。

なお、AD9850DDSのコントロールの方法は、JH7UBCホームページのこちらに記載してあります。

他のPICやArduinoでも十分制御できると思います。

 


Digital Sound CW(DSCW)

2020-02-18 12:30:23 | アマチュア無線

 当局JH7UBCは、FCWA(福島CW愛好会)で毎週水曜日の21時から行っているCWによる交信会のキー局を務めています。

 20時50分ころから3.520MHz付近をワッチして、空いている周波数で、調整符号を出します。

 VVV VVV VVV DE JH7UBC JH7UBC QRV FER CP FCWA QRX 2100 QSX 3520 AS(3520の部分は、実際に使用する周波数ですので、その時に応じて変わることがあります。) を21時まで繰り返し送信します。

 この調整送信は、愛用の縦振電鍵HK-808を使い、打鍵のウォームアップを兼ねています。

 この交信会は、縦振電鍵の練習、和文の練習になっており、週1回の交信会ですが、CWの技術を維持するのに一役かっています。

 実は、この交信会の時には、耳による受信に加えCWの解読・送信ソフト「Digital Sound(DSCW)」を併用しています。(DSCWのダウンロードはこちら

 これまでは、受信時のみ利用し、受信の確認と自分の送信が正しく行われているかの確認に使っていました。

 DSCWには送信機能があります。(画面の右側)

 送信機能を利用するためには、インタフェースが必要です。このインターフェースにはUSBIF4CWが利用できます。私の手元にはこの代替えとして使えるAMD-USB-CQというインターエースがあり、これで試してみました。

 DSCWの初期設定で、COM設定で「USBIF4CW」を選択することによって、送信ウインドウに入力した文字が送信されます。

あらかじめ、macroに登録しておいた送信文を使うことにより、効率的な送信(交信)を行うことができます。

 DSCWのマニュアルにもインターフェースの作り方が記載してありますが、以前CTESTWIN用に作成したインターフェース(製作記事はJH7UBCホームページのこちら)とほぼ同じなので、それを使ってみました。

 このインターフェースは、USBシリアル変換ケーブルを介してパソコンに接続します。

 DSCWの初期設定からCOM設定で、USBシリアル変換器のCOM番号を指定することにより送信可能になります。

 AMD-USB-CQ、CTESTWINインターフェースのどちらでも送信できることを確認しました。

 これらのインターフェースをリグのKEY端子に接続してしまうと、縦振電鍵を使用することができなくなります。それでは、ちょっと困ります。

 そこで、2つの回路からそれぞれキーイングできるように2つの入力を単純にパラレル接続する下の写真のような回路を作りました。

 これで、リグをDSCW、縦振電鍵そしてパドルの3つからキーイングできるようになりました。

 それぞれを臨機応変に利用して、交信会や普段の交信、コンテストなどを楽しみたいと思います。

 なお、毎週水曜日21時から3.520MHzで行っているFCWA(福島CW愛好会)に交信会に参加したい局は、こちらの要綱をよく読んで、コールをお願いします。

 

2月19日追記

 21時からの交信会の前に、調整符号を電文をDSCWで自動送信してみました。OKです。

 インターフェースは、CTESTWIN用を使いました。問題ありません。

 普通のCW交信やコンテストでも使えそうです。


ESP32 Si5351A 7MHz VFOの試作

2020-02-16 09:53:36 | ESP32

 ESP32の機能について一通りのテストができましたので、ロータリーエンコーダ、TFT表示、Si5351Aのコントロールを組み合わせて、7MHzのVFOを試作します。

 このVFOは、すでにSTM32で試作したスケッチを活用していますが、Si5351Aのコントロール部分は、今回改めてプログラムしました。

全体の回路図です。

 ブレッドボードです。

CLK0から7.01234MHzを出力しています。

 ロータリーエンコーダは、秋月電子で販売している安価なものです。

 スケッチを掲載します。試作ですので、参考までに。

 STEPボタンを押すと周波数STEPが10KHz→1KHz→100Hz→10Hz→10KHzと循環します。

 2.2"TFTの表示用ライブラリは、様々なフォントを使うことができるUcglib.hを利用しました。

-------------------------------------------------------

/*
 * ESP32 Si5351A 7MHz VFO
 * 2020.02.16
 * JH7UBC Keiji Hata
 */

//TFT関係の定義
#include
#include
#define __CS 5
#define __DC 17
#define __RST 16
// SDA(MOSI) 23 
// SCK 18
// VCC,LED 3V3

Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC, __CS, __RST);

//I2C
#include

//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
const 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;


//Rotary endoder関係の定義
#define ENC_A 12
#define ENC_B 13
volatile uint8_t old_value = 0x11;
volatile uint8_t value = 0;
volatile uint8_t D;
volatile int8_t count = 0;

//STEP関係の定義
#define SW_STEP 14
uint16_t STEP = 10000; //STEP 初期値

//VFO関係の定義
const uint32_t LOW_FREQ = 7000000; //下限周波数
const uint32_t HI_FREQ = 7200000; //上限周波数
uint32_t FREQ = 7000000; //VFO周波数初期値
uint32_t FREQ_OLD = FREQ; //周波数の前の値
int16_t df = 130; //周波数補正値(Hz)
String freqt = String(FREQ);
String fH_old = "";
String fM_old = "";
String fL_old = "";

//ROtary encoder 割込みサービスルーチン
void rotary(){
  value = (digitalRead(ENC_B)<<1) | digitalRead(ENC_A);
  if(old_value != value){
    D = ((old_value << 1) ^ value) & 3;
    if(D < 2){
      count += 1;
    }else{
      count -= 1;
    }
  if(count >= 4){
    FREQ += STEP;
    count = 0;
  }else if(count <= -4){
    FREQ -= STEP;
    count = 0;
  }
  FREQ = constrain(FREQ,LOW_FREQ,HI_FREQ); //VFOの下限と上限を超えないように
  old_value = value;
  }
}

//レジスタに1バイトデータを書き込む。
void Si5351_write(byte Reg , byte Data){
  Wire.beginTransmission(Si5351A_ADDR);
  Wire.write(Reg);
  Wire.write(Data);
  Wire.endTransmission();
}

//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,0x92); //Crystal Load Capasitance=8pF
  Si5351_write(PLL_RESET,0xA0); //Reset PLLA and PLLB
  Si5351_write(CLK0_CTRL,0x4F); //CLOCK0 Power up
  Si5351_write(OUTPUT_CTRL,0xFE); //Enable CLOCK0
}

void VFO_Set(uint32_t freqency){
  
//PLLのセット
  divider = 900000000 / freqency;
  if (divider % 2) divider--;
  PllFreq = divider * freqency;
  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;
  Parameter_write(MSNA_ADDR,P1,P2,P3);

//MultiSynth(分周器)のセット
  P1 = 128 * divider - 512;
  P2 = 0;
  P3 = 1;
  Parameter_write(MS0_ADDR,P1,P2,P3); 
}

//レジスタにパラメータP1,P2,P3を書き込む。
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)); 
}


//周波数表示
void Freq_Disp(long frequency){
  freqt = String(frequency);
  String fH = freqt.substring(0,1);
  String fM = freqt.substring(1,4);
  String fL = freqt.substring(4,6);
  ucg.setFont(ucg_font_fur35_tr);//Font設定
  
//MHzの表示
  if (fH != fH_old){
    ucg.setColor(0,0,0);
    ucg.drawBox(60,40,30,40);
    ucg.setColor(0,255,255);
    ucg.setPrintPos(60,80);
    ucg.print(fH);
    fH_old = fH;
  }

//KHzの表示
  if (fM != fM_old){
    ucg.setColor(0,0,0);
    ucg.drawBox(100,40,80,40);
    ucg.setColor(0,255,255);
    ucg.setPrintPos(100,80);
    ucg.print(fM);
    fM_old = fM;
  }

//Hzの表示
  if (fL != fL_old){
    ucg.setColor(0,0,0);
    ucg.drawBox(200,40,70,40);
    ucg.setColor(0,255,255);
    ucg.setPrintPos(200,80);
    ucg.print(fL);
    fL_old = fL;
  }
}

//STEP表示
void Step_Disp(){
  ucg.setFont(ucg_font_fur17_tr);
  ucg.setColor(0,0,0);
  ucg.drawBox(60,120,70,35);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(60,140);
  if (STEP == 10)ucg.print("10Hz");
  if (STEP == 100)ucg.print("100Hz");
  if (STEP == 1000)ucg.print("1KHz");
  if (STEP == 10000)ucg.print("10KHz");
}

//STEP切り替え
void Set_Step(){
  if (STEP == 10){
    STEP = 10000;
  }else{
    STEP /= 10;
  }
  delay(10);
  Step_Disp();
  while(digitalRead(SW_STEP) == LOW){
    delay(10);
  }
}
void setup(){
  //ロータリーエンコーダとSTEP使用ピンの設定とプルアップ
  pinMode(ENC_A, INPUT_PULLUP);
  pinMode(ENC_B, INPUT_PULLUP);
  pinMode(SW_STEP, INPUT_PULLUP);
  
  //ロータリーエンコーダ割込み設定
  attachInterrupt(ENC_A, rotary, CHANGE);
  attachInterrupt(ENC_B, rotary, CHANGE);

  Wire.begin();  //I2C初期化
  Si5351_init(); //Si5351Aの初期化

  //TFT初期化
  ucg.begin(UCG_FONT_MODE_TRANSPARENT);//透過モード
  ucg.clearScreen(); //画面クリア
  ucg.setRotate270(); //画面を270°回転

  //Titleの表示
  ucg.setFont(ucg_font_ncenB12_tr);
  ucg.setColor(0,0,255);
  ucg.setPrintPos(20,20);
  ucg.print("ESP32 Si5351A 7MHz VFO test");

  //周波数初期値表示
  Freq_Disp(FREQ);
  ucg.setPrintPos(85,80);
  ucg.print(".");
  ucg.setPrintPos(185,80);
  ucg.print(".");

//周波数STEPの表示
  ucg.setFont(ucg_font_fur17_tr);
  ucg.setColor(255,255,255);
  ucg.setPrintPos(60,115);
  ucg.print("STEP");
  Step_Disp();
  
  VFO_Set(FREQ + df);
  Freq_Disp(FREQ);
}

//Main program
void loop(){
  if(digitalRead(SW_STEP) == LOW)Set_Step();
  if(FREQ != FREQ_OLD){ //周波数FREQが変わったら、Si5351Aの周波数を変更
    VFO_Set(FREQ + df);
    Freq_Disp(FREQ);
    FREQ_OLD = FREQ; //変更された周波数を保存
  }
  delay(10); 
}

-------------------------------------------------------