周辺デバイスコントロールにI2C使用のVFO PCBを作った。このVFO PCBは、拡張性を高める為、多くのI/O端子を引出した。PCBパターン引き回し上、アナログ専用ポートのA6を入力ポートに割り付けてしまった。正常動作させる為、アナログ専用ポートA6からアナログ/デジタルのA2に再割り当てを行った。また、PCB動作確認用に6m AMチャンネル切替式VFOスケッチを作り、H/Wチェックを行った。
回路図
回路図である。I/O端子を殆ど使ってないので、拡張用予備端子になっている。
PCB部品面
PCB小型化(50x50)の為、Arduinoボードとsi5351aボードで隠れた所迄、部品を実装している。左側のランドは、未使用のI/O端子である。Arduinoとsi5351aユニット実装
標準高さのピンソケットにArduino nanoとsi5351aユニットを実装した様子である。半固定抵抗は、Sメータレベル調整用である。A6からA2へ改造
Arduino nanoには、A6,A7端子があるがアナログ専用となっている。その為、PCB裏面(操作面側)のA6パターンをカットし、ジャンパーでA2に改造した。今回は、この方法で対応する事にしたが、アナログ信号を読み取って、しきい値判断によるデジタル化による判断方式などがある。
スケッチ
PCBチェックの為にスケッチを書いた。簡単で実用的な6m AMチャンネル切替式VFOにした。チャンネルは、50.500、50.550、50.600、50.620の切替式で、現在のチャンネルのメモリーする。使ったOLED128x32と小型だが、Sメータ表示が出来る。必要なファイルは、si5351 VFOフォルダからダウンロードできる。
//////////////////////////////////////////////////////////////////////
// si5351a 6m AM VFO program ver.1.0
// Copyright(C)2019.JA2GQP.All rights reserved.
//
// 2019/3/19
// JA2GQP
//////////////////////////////////////////////////////////////////////
#include "src/si5351.h" // https://github.com/etherkit/Si5351Arduino, v2.1.0
#include "src/SSD1306AsciiAvrI2c.h" // https://github.com/greiman/SSD1306Ascii
#include <EEPROM.h>
//---------- Set I/O Device ---------------------
Si5351 si5351(0x60); // Si5351 I2C address
SSD1306AsciiAvrI2c oled;
//---------- Define Constant Value ----------
#define SW_CH A0 // CH SW
#define SW_TX A2 // TX SW
#define PIN_SM A7 // S-meter voltage input
////////////////////////////////
// Channel Frequency
////////////////////////////////
#define CH1_FRQ 50500000L // Channel 1 Frequency
#define CH2_FRQ 50550000L // 2
#define CH3_FRQ 50600000L // 3
#define CH4_FRQ 50620000L // 4
////////////////////////////////
// etc
////////////////////////////////
#define CH1 1 // Channel 1
#define CH2 2 // Channel 2
#define CH3 3 // Channel 3
#define CH4 4 // Channel 4
#define MAX_CHN 4 // Max Channel
#define INT_END 73 // Initial end code
#define IF_FRQ 10700000L // IF Frequency 10.7MHz
#define OLED_ADR 0x3C // OLED Address
//---------- EEPROM Memory Address -----------------------
#define EEP_INT 0x00 // Eep Init(1byte*1)
#define EEP_CHN 0x01 // Channel(1byte*1)
//---------- Memory Assign -------------------
unsigned long Vfo_Dat = 0; // VFO Data
unsigned long Vfo_Datb = 0; // old
unsigned long If_Dat;
unsigned long Frq_Dat; // Frequency Data
byte Byt_Chn = CH1; // Channel SW
byte Flg_Tx = 0; // TX Flag
byte Flg_Txb = 1; // old
unsigned int Val_SM = 0; // S-Meter Data
unsigned int Val_SMb = 0; // old
//---------- Initialization Program ---------------
void setup(){
si5351.init(SI5351_CRYSTAL_LOAD_8PF,0,0);//crystal 25.000 MHz, correction 0
si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_4MA);//Drive lebel 4mA set
oled.begin(&Adafruit128x32, OLED_ADR);
pinMode(SW_TX,INPUT_PULLUP);
pinMode(SW_CH,INPUT_PULLUP);
if(EEPROM.read(EEP_INT) != INT_END){ // Eep initialaz
delay(10);
Eep_Init();
}
Byt_Chn = EEPROM.read(EEP_CHN); // Channel
CH_Set();
Disp_Comm1();
}
//---------- Main program ---------------
void loop() {
if(digitalRead(SW_TX) == HIGH){ // RX ?
if((digitalRead(SW_CH) == LOW)){ // CH SW On?
CH_Switch();
CH_Set();
}
Flg_Tx = 0;
If_Dat = IF_FRQ;
}
else{ // TX
Flg_Tx = 1; // Yes,TX Flag set
If_Dat = 0; // If_Dat 0 set
}
Vfo_Dat = Frq_Dat + If_Dat;
if(Vfo_Dat != Vfo_Datb){ // Frequency update?
si5351.set_freq(Vfo_Dat * SI5351_FREQ_MULT,SI5351_CLK0);
Vfo_Datb = Vfo_Dat;
}
if(Flg_Tx != Flg_Txb){
Disp_Comm1();
Flg_Txb = Flg_Tx;
}
Val_SM = analogRead(PIN_SM);
if ((abs(Val_SM - Val_SMb)) > 3) { // if needed draw S-meter
Disp_SM();
Val_SMb = Val_SM;
}
}
//---------- Channel Data Set & Display Frequency ---------
void CH_Set(){
oled.setFont(lcdnums14x24);
oled.setCursor(1, 0);
switch(Byt_Chn){
case CH1:
Frq_Dat = CH1_FRQ;
oled.print("01:50.500");
break;
case CH2:
Frq_Dat = CH2_FRQ;
oled.print("02:50.550");
break;
case CH3:
Frq_Dat = CH3_FRQ;
oled.print("03:50.600");
break;
case CH4:
Frq_Dat = CH4_FRQ;
oled.print("04:50.620");
break;
default:
break;
}
EEPROM.write(EEP_CHN,Byt_Chn);
}
//---------- Display Common1(TX/RX) ---------
void Disp_Comm1(){
oled.setCursor(2, 3);
oled.setFont(labels);
if(Flg_Tx == 1)
oled.print("2"); // "2" is "TX" in labels.h
else
oled.print("1"); // "1" is "RX" in labels.h
}
//---------- CH SW Check ----------------------
void CH_Switch(){
Byt_Chn++;
while(digitalRead(SW_CH) == LOW)
;
if(Byt_Chn > MAX_CHN)
Byt_Chn = CH1;
}
//---------- Display S-Meter -------------------
void Disp_SM() {
uint8_t a = 0;
uint8_t m = 0;
a = (Val_SM + 3) / 113; // 1024 / 9 characters for S = 1,3,5,7,8,9,+10,+20,+30
oled.setFont(pixels);
oled.setCursor(25, 3);
for (m = 0; m < a; m++)
if (m < 6)
oled.print('7'); // '5' - hollow rectangle, 6px
else
oled.print('8'); // '6' - filled rectangle, 6px
for (m = a; m < 9; m++)
oled.print('.'); // '.' 1px
}
//---------- EEProm Initialization -----------------
void Eep_Init(){
EEPROM.write(EEP_INT,INT_END); // Init end set(73)
EEPROM.write(EEP_CHN,CH1); // Init end set(73)
}