JH7UBCブログ

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

Arduino Pro Mini 2.2インチTFT表示テスト

2021-04-27 21:08:10 | Arduino
 Arduino Pro Miniを使って、2.2インチTFT(SODIAL 2.2" TFT QVGA)の表示テストをしました。

 このTFTのコントローラーは、ILI9341で、SPIでコントロールします。

 Arduino Pro Mini(UNO)のSPIで使用するピンは、
 D10    SS
 D11    MOSI
 D12    MISO
 D13    SCK
ですが、他にRESETとDC/RSのためのピン出力が必要です。

 TFTとArduino Pro Mini(UNO)との接続は、次のようにします。

 TFT のピン番号    Arduino
 1  VCC                    3V3
 2  GND                   GND
 3  CS                      D10
 4  RESET               D8
 5  DC/RS                D9
 6  SDI/MOSI           D11
 7  SCK                    D13
 8  LED                    3V3
 9  SDO/MISO         D12

 接続回路図です。

 表示テストをするためにまず、ILI9341のライブラリをインストールします。
 Arduino IDEで、ツールのライブラリ管理を開き、「Adafruit ILI9341」を検索し、インストールします。
 次に、ファイル→スケッチ例→Adafruit ILI9341と進み、graphicstestを読み込みます。

 このスケッチのままでは動かないので、若干修正し(赤字の部分)、保存します。
 (こちらのサイトを参考にさせていただきました。)
// For the Adafruit shield, these are the default.
#define TFT_RST 8 // 追加
#define TFT_DC 9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

 ブレッドボードと表示の様子です。
 グラフィックスのサンプルが表示された後、下のようなテキスト表示サンプルが90°ずつ回転して表示されます。

 メモリの消費率は57%、変数は29%使われますが、カラー表示はたいへん見やすいです。

 Adafruitのフォントは、ちょっと荒っぽいです。Ucglib を使えばもっと滑らかな文字を表示することができます。
 

Si4735 SSB/CW RXを使って交信テスト

2021-04-23 15:15:32 | アマチュア無線
 先日試作したSi4735 SSB/CW RX と昨年製作したPIC12F1840 Si5351A BS170 7NHz TX (3W)を組み合わせて、7MHz CWの交信テストをしてみました。


 アンテナは、10mHのダイポールを使いました。

 TXの周波数を7.003MHzとして、CALスイッチをON。
 RXのダイヤルを回し、TXからの信号を受信します。周波数が7.003MHz付近で強力に受信できます。BFOスイッチをONにして、ダイヤルを回し、モニタした音の周波数ピッチを700Hzくらいに調節します。TXのCALスイッチをOFFにします。これで、準備OKです。

 メモリーキーヤーからCQを出しました。(リピート機能で繰り返してCQをだしました。)5,6回CQを出したところで応答がありました。

 Si4735 SSB/CW RXにはSメータを付けていませんので、耳Sで559のレポートを送りました。相手局からは、579のレポートをいただきました。交信テスト成功です。相手局は、群馬県嬬恋村の局でした。交信ありがとうございました。

 Si4735 RXを実際のCW交信に使用した感想を述べます。
1 無信号時のノイズは、小さくはないですが、実用上問題はないと思います。感度はまずまずです。

2 CW受信時は、BW(Band Width)は1.0KHzか0.5KHzが適当。

3 Si4735 SSB/CW RXの周波数表示は1KHz程度の誤差があり、バンドエッジでは注意が必要です。

4 送信時は、リレーOFFの状態からの信号の漏れをRXで受信していますが、S9+の信号で受信されます。AGCが動作します。従って受信状態になった時にその影響で受信感度が回復するまで約1秒かかります。

 以上、Si4735 SSB/CW RXを使ってCW交信をすることが可能であることが確認できました。

自作パソコンにWi-Fiカードを装着

2021-04-21 14:41:47 | パソコン
 先日自作したAMD Athlon 200GE CPUパソコンにWi-Fiカードを装着しました。
 Amazonから購入したのは、OKN Wi-Fi PCIe 無線ANカードで、セールの時に参考価格の半額で手に入れました。Wi-Fi6モジュールで、Bluetooth5.1対応です。

 届いた小さな箱には下の写真のようにWi-Fiモジュールの他に小さいプラスドライバー(これは結局使いませんでた)やWiFiとBluetooth用のドライバーが入ったCD、アンテナ、Bluetooth用の電源ケーブル(USBポートに接続します)などが入っていました。


 簡単な取説が入っていて、その手順でWi-Fiカードを取り付け、Bluetooth用の電源をUSBポートに接続しました。


 アンテナは、2本ついてきましたが、同じ物?
 5GHzと2.4GHzのどちらにも使えるのかな?
 後でアンテナを取り換えてテストしましたが、どちらに接続して同じでした。


 付属のCDから、Wi-FiとBluetooth用のドライバをインストールすると、Wi-FiのIDが見えました。5GHzと2.4GHz両方のパスワードを設定。

 各バンドの通信速度をFast.comで測定してみました。
 5GHzで92Mbps
 2.4GHzで74Mbps
でした。こんなものでしょうか。5GHz接続で使用しましょう。

 この後キーボードとマウスのワイアレス化をしたいと思います。

Si4735 HF SSB CW Recieverの試作

2021-04-15 12:34:24 | アマチュア無線
 昨年製作したJA2GQP設計のSi4735 DSPラジオ(評価用ボード)をハムバンドHF専用、SSB,CW専用にしたSi4735 HF SSB CW Recieverを試作しました。


筐体の大きさは、10cm×10cmで高さは5cmです。
内部の様子です。

 回路は、JA2GQPブログに掲載されている回路とほぼ同じですが、LDOは、TA48M033F(3.3V 0.5A)に変更しました。
 電源、AFアンプ基板とSi4735、Arduino Pro Mini基板に分けました。
 Arduino Pro Miniへのスケッチの書き込みは、右側に出ているピンヘッダにFT-232RL USBシリアル変換モジュールを接続して行います。

 パネル面です。

 表示は、OLEDです。周波数以外の数字は小さいのですが、表示が明るいので、視認性は良いです。が・・・、やはり年寄りには厳しいです。Hi
 周波数STEPは、メインダイヤルと兼用です。スイッチ付きのロータリーエンコーダを使いました。
 VOL+ VOL-のボタンは付けず、Si4735のヴォリュームは50固定として、AFアンプの前に10Kオームのボリュームを入れました。この方が実戦的だと思います。

 実際にアンテナに接続して受信テストをしてみました。感度的には、問題ありません。周波数は、最小STEPが1KHzですので、SSB,CWともまず目的信号におおまかに合わせて、BFOスイッチを押し、BFO周波数を変化させて聞きやすい音に調整します。また、混信状況に応じてBand Widthスイッチでバンド幅を調整します。AGCは、ON/OFFできますが、ONのままでOKだと思います。MODEボタンを押すたびに、USBとLSBが切り替えられます。

 参考までに以下にスケッチを掲載します。オリジナルは、PU2CLRのスケッチで、JA2GQP局のスケッチと合わせて若干の改良を加えました。試作段階ですので、まだバグがある可能性があります。
SI4735.h
SSD1306AsciiAvrI2c.h
patch_init.h
は、JA2GQP Download またはGitHubからダウンロードできます。

 周波数表示は、lcdnums14x24というフォントを使っていますが、数字と「:」と「.」のフォントしかありません。スペースのフォントがないので、「:」のフォントデータをすべて0x00に変更しておき、「:」を表示すると実際にはスペースが表示されるようにして対応しています。

---------------------------------------------------------------------
/*
Si4735 HF SSB CW Reciever
JH7UBC Keiji Hata
2021.4.13
オリジナルはPU2CLR 、その改良版JA2GQPのスケッチを改良
*/
#include <SI4735.h>
#include <SSD1306AsciiAvrI2c.h>
#include "Rotary.h"
#include "patch_init.h" // SSB patch for whole SSBRX initialization string

const uint16_t size_content = sizeof ssb_patch_content; // see ssb_patch_content in patch_full.h or patch_init.h

#define AM_FUNCTION 1
#define RESET_PIN 7

// Enconder PINs
#define ENCODER_PIN_A 2
#define ENCODER_PIN_B 3

// Buttons controllers
#define STEP_SWITCH 8 // STEP(1, 5 or 10 KHz)
#define BFO_SWITCH 9 // BFO(BFO or VFO)
#define VOL_DOWN 10 // Volume Down
#define VOL_UP 11 // Up
#define BAND_BUTTON_DOWN 12 // Band Down
#define BAND_BUTTON_UP 14 // Up
#define AGC_SWITCH 15 // AGC ON/OF
#define BANDWIDTH_BUTTON 16 // banddwith(1.2, 2.2, 3.0, 4.0, 0.5, 1.0 KHz)
#define MODE_SWITCH 17 // MODE (LSB/USB)

#define LSB 1
#define USB 2

bool bfoOn = false;
bool disableAgc = true;
int currentBFO = 0;

// Encoder control variables
volatile int encoderCount = 0;

// Some variables to check the SI4735 status
uint16_t currentFrequency;
uint8_t currentStep = 1;
uint8_t currentBFOStep = 50;

uint8_t bandwidthIdx = 2;
const char *bandwitdth[] = {"1.2", "2.2", "3.0", "4.0", "0.5", "1.0"};

typedef struct
{
uint16_t minimumFreq;
uint16_t maximumFreq;
uint16_t currentFreq;
uint16_t currentStep;
uint8_t currentSSB;
} Band;

Band band[] = {
{1800, 2000, 1900, 1, LSB}, //160m
{3500, 4000, 3535, 1, LSB}, //80m
{7000, 7200, 7045, 1, LSB}, //40m
{10100, 10150, 10130, 1, USB},//30m
{14000, 14350, 14100, 1, USB},//20m
{18068, 18168, 18110, 1, USB},//17m
{21000, 21450, 21150, 1, USB},//15m
{24890, 24990, 24930, 1, USB},//13m
// {27000, 27700, 27300, 1, USB},
{28000, 28500, 28200, 1, USB}};//10m

const int lastBand = (sizeof band / sizeof(Band)) - 1;
byte bandIdx = 0;
int currentFreqIdx = 2;//40m band

SI4735 si4735;
SSD1306AsciiAvrI2c oled;
Rotary encoder = Rotary(ENCODER_PIN_A, ENCODER_PIN_B);

//---------- Encorder procedure(INT) ---------------
void rotaryEncoder()
{
unsigned char result = encoder.process();
if (result){
if (result == DIR_CW){
encoderCount = 1;
}else{
encoderCount = -1;
}
}
}

void setup(){
// Encoder pins
pinMode(ENCODER_PIN_A, INPUT_PULLUP);
pinMode(ENCODER_PIN_B, INPUT_PULLUP);

pinMode(BANDWIDTH_BUTTON, INPUT_PULLUP);
pinMode(BAND_BUTTON_UP, INPUT_PULLUP);
pinMode(BAND_BUTTON_DOWN, INPUT_PULLUP);
pinMode(VOL_UP, INPUT_PULLUP);
pinMode(VOL_DOWN, INPUT_PULLUP);
pinMode(BFO_SWITCH, INPUT_PULLUP);
pinMode(AGC_SWITCH, INPUT_PULLUP);
pinMode(STEP_SWITCH, INPUT_PULLUP);
pinMode(MODE_SWITCH, INPUT_PULLUP);

attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_A), rotaryEncoder, CHANGE); // Encoder interrupt
attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_B), rotaryEncoder, CHANGE);

oled.begin(&Adafruit128x64, 0x3C); //OLED initialize

oled.setFont(font5x7);
oled.setCursor(10,3);
oled.print("Loading SSB patch");
si4735.getDeviceI2CAddress(RESET_PIN); // Looks for the I2C buss address and set it. Returns 0 if error
si4735.setup(RESET_PIN, AM_FUNCTION);
loadSSB();
delay(100);
oled.clear();
si4735.setTuneFrequencyAntennaCapacitor(1); // Set antenna tuning capacitor for SW.
si4735.setSSB(band[currentFreqIdx].minimumFreq, band[currentFreqIdx].maximumFreq, band[currentFreqIdx].currentFreq, band[currentFreqIdx].currentStep, band[currentFreqIdx].currentSSB);
delay(100);

//----- 初期画面表示 --------
currentFrequency = si4735.getFrequency();
showFrequency();
oled.setFont(font5x7);
oled.setCursor(60,4);
oled.print("STEP KHz");
showStep();
oled.setCursor(0,4);
oled.print("Mode");
showMode();
oled.setCursor(0,5);
oled.print("B W");
showBandwidth();
oled.setCursor(60,5);
oled.print("BFO");
showBFO();
oled.setCursor(0,6);
oled.print("AGC");
showAGC();
si4735.setVolume(50);
}

//------ SSB patch Load ------
void loadSSB()
{
si4735.queryLibraryId(); // Is it really necessary here? I will check it.
si4735.patchPowerUp();
delay(50);
si4735.downloadPatch(ssb_patch_content, size_content);
// Parameters
// AUDIOBW - SSB Audio bandwidth; 0 = 1.2KHz (default); 1=2.2KHz; 2=3KHz; 3=4KHz; 4=500Hz; 5=1KHz;
// SBCUTFLT SSB - side band cutoff filter for band passand low pass filter ( 0 or 1)
// AVC_DIVIDER - set 0 for SSB mode; set 3 for SYNC mode.
// AVCEN - SSB Automatic Volume Control (AVC) enable; 0=disable; 1=enable (default).
// SMUTESEL - SSB Soft-mute Based on RSSI or SNR (0 or 1).
// DSP_AFCDIS - DSP AFC Disable or enable; 0=SYNC MODE, AFC enable; 1=SSB MODE, AFC disable.
si4735.setSSBConfig(bandwidthIdx, 1, 0, 1, 0, 1);
}

//------ Frequency display ---------
void showFrequency()
{
unsigned long fr;
unsigned long sf_rx;
sf_rx = (float)currentFrequency * 1000.0;

oled.setFont(lcdnums14x24);
oled.setCursor(1,0);
fr = sf_rx / 1000000;
if (fr < 10)
oled.print(':'); // ':' is changed to ' ' in lcdnums14x24.h
oled.print(fr);
oled.print('.');
fr = (sf_rx % 1000000) / 1000;
if (fr < 100)
oled.print('0');
if (fr < 10)
oled.print('0');
oled.print(fr);
oled.print('.');
fr = (sf_rx % 1000) / 10;
if (fr < 10)
oled.print('0');
oled.print(fr);
}

//------ Step Display ---------
void showStep(){
oled.setFont(font5x7);
oled.setCursor(85,4);
if(currentStep == 1){
oled.print(" 1");
}else if(currentStep == 5){
oled.print(" 5");
}else{
oled.print("10");
}
}

//----- Mode Display -----
void showMode(){
oled.setFont(font5x7);
oled.setCursor(30,4);
if(band[currentFreqIdx].currentSSB == 1){
oled.print("LSB");
}else if(band[currentFreqIdx].currentSSB == 2){
oled.print("USB");
}
}

//------ Bandwidth Display ---------
void showBandwidth(){
oled.setFont(font5x7);
oled.setCursor(30,5);
oled.print(bandwitdth[bandwidthIdx]);
}

//------- BFO Displsy -------
void showBFO(){
oled.setFont(font5x7);
oled.setCursor(90, 5);
if(bfoOn == 1)
{
oled.print("ON ");
oled.setCursor(90,6);
oled.print(" ");
oled.setCursor(90,6);
oled.print(currentBFO);
}else{
oled.print("OFF");
oled.setCursor(90,6);
oled.print(" ");
}
}

//------ AGC Display --------
void showAGC(){
oled.setFont(font5x7);
si4735.getAutomaticGainControl();
oled.setCursor(30, 6);
oled.print((si4735.isAgcEnabled()) ? "ON " : "OFF");
}

//----- Status Display -----
void showStatus(){
showFrequency();
showMode();
showStep();
showBandwidth();
showBFO();
showAGC();
}

//------ BAND UP ------
void bandUp()
{
// save the current frequency for the band
band[currentFreqIdx].currentFreq = currentFrequency;
if (currentFreqIdx < lastBand)
{
currentFreqIdx++;
}
else
{
currentFreqIdx = 0;
}
// si4735.setTuneFrequencyAntennaCapacitor(1); // Set antenna tuning capacitor for SW.
si4735.setSSB(band[currentFreqIdx].minimumFreq, band[currentFreqIdx].maximumFreq, band[currentFreqIdx].currentFreq, band[currentFreqIdx].currentStep, band[currentFreqIdx].currentSSB);
currentStep = band[currentFreqIdx].currentStep;
delay(250);
currentFrequency = si4735.getCurrentFrequency();
showStatus();
}

//------- BAND DOWN -------
void bandDown()
{
// save the current frequency for the band
band[currentFreqIdx].currentFreq = currentFrequency;
if (currentFreqIdx > 0)
{
currentFreqIdx--;
}
else
{
currentFreqIdx = lastBand;
}
// si4735.setTuneFrequencyAntennaCapacitor(1); // Set antenna tuning capacitor for SW.
si4735.setSSB(band[currentFreqIdx].minimumFreq, band[currentFreqIdx].maximumFreq, band[currentFreqIdx].currentFreq, band[currentFreqIdx].currentStep, band[currentFreqIdx].currentSSB);
currentStep = band[currentFreqIdx].currentStep;
delay(250);
currentFrequency = si4735.getCurrentFrequency();
showStatus();
}

//------ MODE Change -------
void modeChange()
{
if(band[currentFreqIdx].currentSSB == 1)
{
band[currentFreqIdx].currentSSB = 2;
}else{
band[currentFreqIdx].currentSSB = 1;
}
band[currentFreqIdx].currentFreq = currentFrequency;
band[currentFreqIdx].currentStep = currentStep;
si4735.setSSB(band[currentFreqIdx].minimumFreq, band[currentFreqIdx].maximumFreq, band[currentFreqIdx].currentFreq, band[currentFreqIdx].currentStep, band[currentFreqIdx].currentSSB);
currentFrequency = si4735.getCurrentFrequency();
showStatus();
}

//------ main loop ----------
void loop()
{
char bfo_disp=0;
// Check if the encoder has moved.
if (encoderCount != 0)
{
if (bfoOn)
{
currentBFO = (encoderCount == 1) ? (currentBFO + currentBFOStep) : (currentBFO - currentBFOStep);
si4735.setSSBBfo(currentBFO);
if(currentBFO >= 1000){
currentBFO = currentBFO - 1000;
si4735.frequencyUp();
currentFrequency = si4735.getFrequency();
}
else if(currentBFO < 0){
currentBFO = currentBFO + 1000;
si4735.frequencyDown();
currentFrequency = si4735.getFrequency();
}
showBFO();
showFrequency();
}
else
{
if (encoderCount == 1)
si4735.frequencyUp();
else
si4735.frequencyDown();

// Show the current frequency only if it has changed
currentFrequency = si4735.getFrequency();
showFrequency();
}
encoderCount = 0;
}

//------ STEP switch -------
if (digitalRead(STEP_SWITCH) == LOW){
if(currentStep == 1){
currentStep = 5;
}else if(currentStep == 5){
currentStep = 10;
}else{
currentStep = 1;
}
si4735.setFrequencyStep(currentStep);
band[currentFreqIdx].currentStep = currentStep;
showStep();
while(digitalRead(STEP_SWITCH) == LOW);
}

//--------- Band UP -----------
if(digitalRead(BAND_BUTTON_UP) == LOW){
bandUp();
while(digitalRead(BAND_BUTTON_UP) == LOW);
}

//--------- Band DOWN ---------
if(digitalRead(BAND_BUTTON_DOWN) == LOW){
bandDown();
while(digitalRead(BAND_BUTTON_DOWN) == LOW);
}

//--------- BANDWIDTH switch ---------
if (digitalRead(BANDWIDTH_BUTTON) == LOW)
{
bandwidthIdx++;
if (bandwidthIdx > 5)
bandwidthIdx = 0;
si4735.setSSBAudioBandwidth(bandwidthIdx);
// If audio bandwidth selected is about 2 kHz or below, it is recommended to set Sideband Cutoff Filter to 0.
if (bandwidthIdx == 0 || bandwidthIdx == 4 || bandwidthIdx == 5)
si4735.setSBBSidebandCutoffFilter(0);
else
si4735.setSBBSidebandCutoffFilter(1);
showBandwidth();
while(digitalRead(BANDWIDTH_BUTTON) == LOW);
}

//------- AGC switch ---------
if (digitalRead(AGC_SWITCH) == LOW)
{
disableAgc = !disableAgc;
// siwtch on/off ACG; AGC Index = 0. It means Minimum attenuation (max gain)
si4735.setAutomaticGainControl(disableAgc, 1);
showAGC();
while(digitalRead(AGC_SWITCH) == LOW);
}

//------- BFO switch --------
if(digitalRead(BFO_SWITCH) == LOW)
{
bfoOn = !bfoOn;
showBFO();
while(digitalRead(BFO_SWITCH) == LOW);
}

//-------- MODE switch ------
if (digitalRead(MODE_SWITCH) == LOW)
{
modeChange();
while(digitalRead(MODE_SWITCH) == LOW);
}

delay(10);
}

 

KCJトップバンドコンテストの結果が発表されました

2021-04-02 08:44:03 | アマチュア無線
 去る2月13日(土)~14日(日)に行われた第37回KCJトップバンドコンテストの結果が発表されました。

 今回は、参加局331局と昨年より大幅に参加局が増えました。1.8MHz帯の拡張、これによりFT8の混信が避けられたこと、コロナ禍でスタンバイ局が増えたことなどによるのでしょうが、CWファンがたくさん参加したことは非常にうれしいことです。

 さて、当局JH7UBCの結果はと見るとシングルオペ部門で36位(269局中)でした。そういえば2月13日の23時過ぎに福島県沖で大きな地震があり、無線どころではないと早々とコンテストを切り上げたこと思い出しました。もう少し続けたらもうちょっと上位にいけたかもしれません。

 いずれにせよ、今回はトップバンドでの交信を十分に楽しめたコンテストでした。交信いただいた各局ありがとうございました。

4月14日追記

 その後、KCJからメールが来て、pdfで賞状をダウンロードしました。
まず、シングルオペ36位の賞状です。

 次に、福島県1位の賞状です。